Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

426 lines
16 KiB

/*
$Log: S:\gfs32\libgfs\wfwrite.c_v $
*
* Rev 1.1 19 Apr 1995 16:35:24 RWR
* Make sure WIN32_LEAN_AND_MEAN is defined (explicitly or via GFSINTRN.H)
* Also surround local include files with quotes instead of angle brackets
*
* Rev 1.0 06 Apr 1995 14:02:44 HEIDI
* Initial entry
*
* Rev 1.0 28 Mar 1995 15:53:22 JAR
* Initial entry
*/
/*
Copyright 1989, 1990, 1991 by Wang Laboratories Inc.
Permission to use, copy, modify, and distribute this
software and its documentation for any purpose and without
fee is hereby granted, provided that the above copyright
notice appear in all copies and that both that copyright
notice and this permission notice appear in supporting
documentation, and that the name of WANG not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
WANG makes no representations about the suitability of
this software for any purpose. It is provided "as is"
without express or implied warranty.
*/
/*
* SccsId: @(#)Source wfwrite.c 1.28@(#)
*
* GFS: WIFF write handling routines
*
* Routines:
* long wfwrite(fct, buf, numbytes, pgnum, done )
*
*/
/*LINTLIBRARY*/
#define GFS_CORE
#include "gfsintrn.h"
#include <stdio.h>
#include <errno.h>
#include "gfs.h"
#include "gfct.h"
#include "rtbk.h"
#include "hdbk.h"
#if (SYSBYTEORDER == II)
extern void FAR PASCAL swaphdbk();
extern void FAR PASCAL swapdbt();
extern void FAR PASCAL swapdbcb();
#endif
long FAR PASCAL wfwrite(fct, buf, numbytes, pgnum, done ) /*errno_KEY*/
char FAR *buf, done;
u_long numbytes;
u_short pgnum;
struct _gfct FAR *fct;
{
int rc = (int) 0;
int pmt_cnt = (int) ROOT_PMTS;
int bytes_written = (int) 0;
int getdbt();
int first_one;
char FAR *p_wrtbuf;
long byte_cnt = (long) 0;
long fp;
unsigned bytes_to_write = (unsigned) 0;
struct _rtbk FAR *p_rtbk;
struct _pmt FAR *p_pmt;
struct _pmte FAR *p_pmte;
struct _hdbk FAR *p_hdbk;
struct _dbt FAR *p_dbt, FAR *nxt_dbt, FAR *free_dbt;
struct _dbcb FAR *p_dbcb, FAR *prv_dbcb;
struct gfsinfo FAR *p_info;
/* simplify addressing */
p_rtbk = fct->u.wif.root_in_mem;
p_pmt = fct->u.wif.pmt_in_mem;
p_wrtbuf = (char FAR *) fct->u.wif.RWbuf;
p_pmte = (struct _pmte FAR *) &p_pmt->first_pmte;
p_hdbk = fct->u.wif.hdbk_in_mem;
p_info = &fct->uinfo;
/* for now, insure sequential page writing,
later, we'll allow the writing of any page */
if (pgnum != p_rtbk->full_pages) {
errno = (int) EINVALID_PAGE;
return( (long) -1 );
}
/* see if we've already started writing this page */
p_dbt = (struct _dbt FAR *) &p_hdbk->first_dbt;
if (!(fct->PAGE_STATUS & (char) PAGE_INIT)) {
fct->PAGE_STATUS |= (char) PAGE_INIT;
/* seek to end of file */
fp = lseek(fct->fildes, (long) 0, (int) 2);
if (fp < (int) 0)
return ( (long) -1);
/* initialize the_hdbk */
(void) memset( (char FAR *) p_hdbk, (int) NULL, (int) 4 * K );
p_hdbk->type = (u_short) GFS_TEXT;
switch ((int) p_info->img_cmpr.type) {
case UNCOMPRESSED:
if (p_info->fill_order == (u_long) LOWTOHIGH)
p_hdbk->compression = (u_short) 3;
else
p_hdbk->compression = (u_short) 6;
break;
case CCITT_GRP3_NO_EOLS:
if (p_info->fill_order == (u_long) LOWTOHIGH) {
if (p_info->img_cmpr.opts.grp3 & (u_long) DATA_ALIGNED)
p_hdbk->compression = (u_short) 11;
else
p_hdbk->compression = (u_short) 10;
}
else {
if (p_info->img_cmpr.opts.grp3 & (u_long) DATA_ALIGNED)
p_hdbk->compression = (u_short) 15;
else
p_hdbk->compression = (u_short) 20;
}
break;
case CCITT_GRP3_FACS:
{
register u_long grp3opts = p_info->img_cmpr.opts.grp3;
if (p_info->fill_order == (u_long) LOWTOHIGH) {
if (grp3opts & (u_long) GRP3_EOLS_BYTEBOUNDED) {
if (grp3opts & LEAD_EOL)
p_hdbk->compression = (u_short) 9;
else
p_hdbk->compression = (u_short) 8;
} else {
if (grp3opts & LEAD_EOL)
p_hdbk->compression = (u_short) 7;
else
p_hdbk->compression = (u_short) 4;
}
} else {
if (grp3opts & (u_long) GRP3_EOLS_BYTEBOUNDED) {
if (grp3opts & LEAD_EOL)
p_hdbk->compression = (u_short) 19;
else
p_hdbk->compression = (u_short) 14;
} else {
if (grp3opts & LEAD_EOL)
p_hdbk->compression = (u_short) 13;
else
p_hdbk->compression = (u_short) 12;
}
}
break;
}
case CCITT_GRP4_FACS:
if (p_info->fill_order == (u_long) LOWTOHIGH)
p_hdbk->compression = (u_short) 5;
else
p_hdbk->compression = (u_short) 2;
break;
case LZW:
errno = (int) EINVALID_COMPRESSION;
return ((long) -1);
case PACKBITS:
if (p_info->fill_order == (u_long) LOWTOHIGH)
p_hdbk->compression = (u_short) 65;
else
p_hdbk->compression = (u_short) 64;
break;
default:
errno = (int) EINVALID_COMPRESSION;
return ((long) -1);
}
p_hdbk->db_size = p_info->_file.fmt.wiff.db_size;
p_hdbk->horiz_res = (u_short) p_info->horiz_res[0];
p_hdbk->vert_res = (u_short) p_info->vert_res[0];
p_hdbk->horiz_size = (u_short) p_info->horiz_size;
p_hdbk->vert_size = (u_short) p_info->vert_size;
p_hdbk->bits_pixel = (u_short) p_info->bits_per_sample[0];
p_hdbk->scan_dir =
(u_short) p_info->origin;
switch ( (int) p_info->rotation ) {
case DEGREES_0:
p_hdbk->rotation = (u_short) 0;
break;
case DEGREES_90:
p_hdbk->rotation = (u_short) 1;
break;
case DEGREES_180:
p_hdbk->rotation = (u_short) 2;
break;
case DEGREES_270:
p_hdbk->rotation = (u_short) 3;
break;
default:
errno = (int) EINVALID_ROTATION;
return ( (long) -1 );
}
p_hdbk->reflection =
(u_short) p_info->reflection;
/* now initialize the first dbt */
p_dbt->first_free = (u_short) 0;
p_dbt->entries = (u_short) HDR_CNT;
p_dbt->pu.prev_dbt = p_dbt->nu.next_dbt
= (struct _dbt FAR *) NULL;
}
/* find the first dbt with a free entry */
while( (char) TRUE) {
p_dbcb = (struct _dbcb FAR *) &p_dbt->first_dbcb;
if (p_dbt->first_free < (u_short) (p_dbt->entries) )
break;
if (p_dbt->nu.next_dbt == (struct _dbt FAR *) NULL) {
rc = getdbt((struct _gfct FAR *) fct,
(struct _dbt FAR *) p_dbt);
if (rc < 0)
return( (int) -1);
}
p_dbt = p_dbt->nu.next_dbt;
p_dbcb = (struct _dbcb FAR *) &p_dbt->first_dbcb;
} /* end while */
/* get first free dbcb entry in_dbt */
p_dbcb += (int) p_dbt->first_free;
/* for each block of data (db_size) build a_dbcb and write data */
for (;;) {
if (numbytes <= p_hdbk->db_size)
break;
(void) memcpy( (char FAR *) p_wrtbuf,
(char FAR *) buf,
(int) (p_hdbk->db_size) );
buf += (int) p_hdbk->db_size;
bytes_to_write = (unsigned) p_hdbk->db_size;
bytes_written = write(fct->fildes,
(char FAR *) p_wrtbuf,
(unsigned) (p_hdbk->db_size) );
if (bytes_written == (int) -1) {
/* some error handling goes here */
return( (int) -1);
}
byte_cnt += (long) bytes_to_write;
p_dbcb->blk_offset = (u_long) fct->u.wif.block_cnt;
fct->u.wif.block_cnt += (u_long)
(p_hdbk->db_size / ( 4 * K ) );
p_dbcb->blk_cnt = (u_long) p_hdbk->db_size;
p_dbcb->data_cnt = (u_long) p_hdbk->db_size;
p_dbcb->compression = (u_short) p_hdbk->compression;
prv_dbcb = p_dbcb;
prv_dbcb->nu.next_dbcb = ++p_dbcb;
p_dbt->first_free++;
if (((unsigned long)byte_cnt + p_hdbk->db_size) >
(unsigned long) numbytes )
break;
if (p_dbt->first_free > (u_short)
(p_dbt->entries) ) {
rc = getdbt((struct _gfct FAR *) fct,
(struct _dbt FAR *) p_dbt);
if (rc < 0)
return( (int) -1);
p_dbt = p_dbt->nu.next_dbt;
p_dbcb = (struct _dbcb FAR *) &p_dbt->first_dbcb;
}
}
bytes_to_write = (unsigned) (numbytes - byte_cnt);
if (bytes_to_write > (unsigned) 0) {
(void) memset( (char FAR *) p_wrtbuf,
(int) NULL,
(int) (p_hdbk->db_size) );
(void) memcpy( (char FAR *) p_wrtbuf,
(char FAR *) buf,
(int) bytes_to_write );
bytes_written = write(fct->fildes,
(char FAR *) p_wrtbuf,
(unsigned) (p_hdbk->db_size) );
if (bytes_written == (int) -1) {
/* some error handling goes here */
return( (int) -1);
}
byte_cnt += (long) bytes_to_write;
p_dbcb->blk_offset = (u_long) fct->u.wif.block_cnt;
fct->u.wif.block_cnt += (u_long)
(p_hdbk->db_size / ( 4 * K ) );
p_dbcb->blk_cnt = (u_long) p_hdbk->db_size;
p_dbcb->data_cnt = (u_long) bytes_to_write;
p_dbcb->compression = (u_short) p_hdbk->compression;
p_dbt->first_free++;
prv_dbcb = p_dbcb;
}
if (!done) {
if (p_dbt->first_free > (u_short)
(p_dbt->entries) ) {
rc = getdbt((struct _gfct FAR *) fct,
(struct _dbt FAR *) p_dbt);
if (rc < 0)
return( (int) -1);
p_dbt = p_dbt->nu.next_dbt;
p_dbcb = (struct _dbcb FAR *) &p_dbt->first_dbcb;
}
prv_dbcb->nu.next_dbcb = ++p_dbcb;
return( byte_cnt );
} else
prv_dbcb->nu.next_dbcb = (struct _dbcb FAR *) NULL;
/* if page is complete (done = TRUE)
make an entry in the next free pmt
write the hdbk (and associates) to disk
update the rtbk to reflect page addition
otherwise,
exit routine. */
/* first, let's update the page mapping table for this entry */
/* find the first pmt with a free entry */
pmt_cnt = (int) ROOT_PMTS;
while((char) TRUE) {
/* First check to see if we need to build another pmt,
if we do, build it an' break out after insuring we're
pointing to it properly. */
if ((p_pmt->first_free == pmt_cnt) &&
(p_pmt->nu.next_pmt == (struct _pmt FAR *) NULL)) {
p_pmt->first_free = (u_short) pmt_cnt;
p_pmt->entries = (u_short) pmt_cnt;
p_pmt->nu.next_pmt = (struct _pmt FAR *)
calloc( (unsigned) 1, (unsigned) 4 * K);
if (p_pmt->nu.next_pmt == (struct _pmt FAR *) NULL) {
errno = (int) ENOMEM;
return( (int) -1);
}
p_pmt->nu.next_pmt->first_free = (u_short) 0;
pmt_cnt = (int) OTHER_PMTS;
p_pmt->nu.next_pmt->entries = (u_short) pmt_cnt;
p_pmt = p_pmt->nu.next_pmt;
break;
}
/* We don't need another one, let's see if the current one
just happens to be full !! If it is, point to the next
one (it'd better damn well be there or we're all messed
up !!!), otherwise we're gonna break out and use the
current one !!!! */
else if ((p_pmt->first_free == p_pmt->entries) &&
(p_pmt->nu.next_pmt != (struct _pmt FAR *) NULL)) {
p_pmt = p_pmt->nu.next_pmt;
pmt_cnt = (int) OTHER_PMTS;
}
else
break;
} /* end while */
p_pmte = (struct _pmte FAR *) &p_pmt->first_pmte;
p_pmte += p_pmt->first_free;
p_pmt->first_free++;
p_pmte->first_full = (u_long) fct->u.wif.block_cnt;
/* now, time to blast out the_hdbk to disk */
p_hdbk = fct->u.wif.hdbk_in_mem;
#if (SYSBYTEORDER == II)
(void) swaphdbk((struct _hdbk FAR *) p_hdbk);
#endif
nxt_dbt = p_dbt = (struct _dbt FAR *) &p_hdbk->first_dbt;
first_one = (int) TRUE;
do {
p_dbt = free_dbt = nxt_dbt;
if (p_dbt->nu.next_dbt != (struct _dbt FAR *) NULL) {
nxt_dbt = p_dbt->nu.next_dbt;
nxt_dbt->pu.prv_blk = (u_long)
(fct->u.wif.block_cnt);
p_dbt->nu.nxt_blk = (u_long)
(fct->u.wif.block_cnt + 1);
}
else
nxt_dbt = (struct _dbt FAR *) NULL;
#if (SYSBYTEORDER == II)
(void) swapdbcb((struct _dbcb FAR *) &(p_dbt->first_dbcb),
(long) p_dbt->entries);
(void) swapdbt((struct _dbt FAR *) p_dbt);
#endif
bytes_written = write(fct->fildes,
(char FAR *) p_hdbk,
(unsigned) (4 * K) );
if (bytes_written < (int) 0) {
/* some error handling goes here */
return( (int) -1);
}
if (first_one) {
first_one = (int) FALSE;
p_dbt->nu.next_dbt = (struct _dbt FAR *) NULL;
} else
free( (char FAR *) free_dbt);
++fct->u.wif.block_cnt;
p_hdbk = (struct _hdbk FAR *) nxt_dbt;
} while (nxt_dbt != (struct _dbt FAR *) NULL);
/* finally, update the root block to reflect changes */
p_rtbk->full_pages++;
fct->ROOT_STATUS = (char) TRUE;
fct->PAGE_STATUS = (char) FALSE;
return( byte_cnt );
}
/* get new dbt when needed .... */
int getdbt(fct, p_dbt) /*errno_KEY*/
struct _gfct FAR *fct;
struct _dbt FAR *p_dbt;
{
p_dbt->first_free = (u_short) p_dbt->entries;
p_dbt->nu.next_dbt = (struct _dbt FAR *)
calloc( (unsigned) 1, (unsigned) 4 * K);
if (p_dbt->nu.next_dbt == (struct _dbt FAR *) NULL) {
errno = (int) ENOMEM;
return( (int) -1);
}
p_dbt->nu.next_dbt->pu.prev_dbt = p_dbt;
p_dbt->nu.next_dbt->first_free = (u_short) 0;
p_dbt->nu.next_dbt->entries = (u_short) DBT_CNT;
return ( (int) 0 );
}