2021-10-11 19:38:01 -03:00

270 lines
6.0 KiB
C
Executable File

/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
#ident "@(#)table.c 1.4 92/07/14 SMI" /* SVr4.0 1.9 */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <table.h>
#include <internal.h>
extern tbl_t TLtables[];
extern unsigned char TLinbuffer[];
static int TLinitialized = 0;
/*
Initialize all global data structures
*/
TLinit()
{
if( TLinitialized ) return;
Strncpy( TLtables, "", TL_MAXTABLES * sizeof( tbl_t ) );
TLinitialized = 1;
}
/* Get a new table id */
int
TLt_get()
{
register i;
register tbl_t *tptr = TLtables;
for( i = 0; i < TL_MAXTABLES; i++, tptr++ )
if( !(tptr->status & IN_USE) ) {
tptr->status |= IN_USE;
return( i );
}
return( -1 );
}
/* Free slot associated with tid */
void
TLt_unget( tid )
int tid;
{
if( tid >= 0 && tid < TL_MAXTABLES ) {
TLtables[ tid ].status = 0;
TLtables[ tid ].hiwater = 0;
}
}
int
TLt_init( tid )
int tid;
{
register tbl_t *tptr = TLtables + tid;
tptr->status &= ~MODIFIED;
return( TLe_init( tid ) );
}
int
TLt_open( tid, filename, descr, oflag, mode )
int tid, oflag, mode;
unsigned char *filename;
TLdesc_t *descr;
{
register tbl_t *tptr = TLtables + tid;
register rc;
struct stat buf;
/* Initialize Table entry */
if( (rc = TLt_init( tid )) != TLOK ) {
TLt_unget( tid );
return( rc );
}
/* stat the file before the open to determine whether or not it exists */
if( stat( (char *)filename, &buf ) == -1 ) {
if( errno == ENOENT ) {
tptr->file.mode = mode;
tptr->file.oflag = oflag;
tptr->file.fid = 0;
tptr->status |= FOUND_EOF;
} else {
TLt_unget( tid );
return( TLFAILED );
}
} else {
tptr->file.mode = buf.st_mode;
tptr->file.oflag = oflag;
/* Open the Table file */
if( (tptr->file.fid = open( (char *)filename, oflag, tptr->file.mode ))
== -1 ){
TLt_unget( tid );
return( TLFAILED );
}
}
/* Keep our own copy of the file name */
if( !(tptr->file.name = (unsigned char *)Malloc( Strlen(filename) + 1 ))){
TLt_unget( tid );
return( TLNOMEMORY );
}
Strcpy( tptr->file.name, filename );
/* Scan for Self-Describing Comments */
if( (rc = TLe_prolog( tid, descr )) != TLOK && rc != TLBADFS
&& rc != TLDIFFFORMAT )
TLt_unget( tid );
return( rc );
}
/* Compare 2 descriptions */
int
TLt_desccmp( a, b )
register TLdesc_t *a, *b;
{
if( a->td_fs != b->td_fs ) return( TLBADFS );
if( a->td_format && b->td_format && Strcmp( a->td_format, b->td_format ) )
return( TLDIFFFORMAT );
return( TLOK );
}
/* Free all memory associated with a table */
void
TLt_free( tid )
int tid;
{
register tbl_t *tptr = TLtables + tid;
register entry_t **eptr;
register count;
void TLe_free(), TLf_free(), TLd_free();
if( tptr->file.fid ) {
(void)close( tptr->file.fid );
tptr->file.fid = 0;
}
if( tptr->file.name ) {
Free( tptr->file.name );
tptr->file.name = NULL;
}
TLd_free( &(tptr->description) ); /* Description Structure */
TLf_free( &(tptr->fieldnames) ); /* Fieldnames Structure */
if( tptr->e_info.nentries ) {
for( count = tptr->e_info.nentries, eptr = ENTRYTAB(tid, 0); count > 0;
eptr++, count-- ) {
/*
if( *eptr ) {
*/
if( (*eptr)->status & IS_END ) count = 0;
TLe_free( *eptr );
Free( *eptr );
/*
}
*/
}
Free( tptr->e_table );
tptr->e_table = NULL;
}
tptr->e_info.nentries = 0;
tptr->e_info.size = 0;
}
/* Write out current notion of table into "the" file */
int
TLt_sync( tid )
int tid;
{
register tbl_t *tptr = TLtables + tid;
register fid, rc = TLOK, locked, count, oflag, seekaddr = 0;
unsigned char fname[ 30 ];
entry_t **eptr, *entry;
if( !(tptr->status & MODIFIED) ) return( TLOK );
/* Create temp file */
(void)sprintf( (char *)fname, "/var/tmp/TL%d", getpid() );
/*
* Check for -1 for failure. Also, enclose
* (fid=open()) in ()'s else assignment to fid doesn't get done
*/
if ( (fid = open( (char *)fname, O_RDWR|O_CREAT, 0666)) < 0 )
return( TLFAILED );
/* what if whole file has not been read in! */
if( tptr->e_info.nentries ) {
for( count = 0, eptr = ENTRYTAB(tid, 1); count < tptr->e_info.nentries;
eptr++, count++ ) {
if( ((*eptr)->status & IS_END) ) break;
else if( !((*eptr)->status & IS_BEGIN) ) {
if( (rc = TLe_write( fid, tid, (*eptr) )) < 0 )
goto out;
E_SEEKADDR((*eptr)) = seekaddr;
seekaddr += rc;
}
}
}
if( !(tptr->status & FOUND_EOF ) ) {
/* If EOF has not been seen, there are more entries in the file */
if( Lseek( tptr->file.fid, tptr->hiwater, 0 ) == -1 ) {
rc = TLFAILED;
goto out;
}
/*
ASSERT: All escapes of special characters that are in the
remainder of the file entries are intact. These entries
may be copied as-is.
*/
/* Get entry to the position AFTER this entry */
if( (rc = TLfl_getentry( tid, TLinbuffer, 2 * TL_MAXLINESZ )) < 0 ) {
if( rc == TLEOF ) {
/* This 'shouldn't' happen - i.e. this entry should've been
gotten before, but just in case ... */
tptr->status |= FOUND_EOF;
rc = TLBADENTRY;
}
goto out;
}
while( (rc = TLfl_getentry( tid, TLinbuffer, 2 * TL_MAXLINESZ )) > 0 )
if( Write( tptr->file.fid, TLinbuffer, rc ) <= 0 ) {
rc = TLFAILED;
goto out;
}
}
/* Readjust hiwater to reflect new version of the file */
if( seekaddr )
tptr->hiwater = seekaddr;
/* Create or truncate "table" file */
if( tptr->file.fid ) {
(void)close( tptr->file.fid );
oflag = tptr->file.oflag|O_TRUNC;
} else oflag = tptr->file.oflag|O_CREAT;
if( !(tptr->file.fid = open( (char *)tptr->file.name, oflag,
tptr->file.mode ) )){
rc = TLFAILED;
goto out;
}
if( TLfl_lock( tptr->file.fid ) == TLOK )
locked = TRUE;
else {
rc = TLFAILED;
goto out;
}
/* copy new file to old */
rc = TLfl_copy( tptr->file.fid, fid );
if( locked )
rc = TLfl_unlock( tptr->file.fid );
if( rc == TLOK )
tptr->status &= ~MODIFIED;
out:
(void)unlink( (char *)fname );
(void)close( fid );
return( rc );
}