794 lines
20 KiB
C
794 lines
20 KiB
C
/************************************************************************
|
||
* *
|
||
* Copyright (c) 1984, Fred Fish *
|
||
* All Rights Reserved *
|
||
* *
|
||
* This software and/or documentation is protected by U.S. *
|
||
* Copyright Law (Title 17 United States Code). Unauthorized *
|
||
* reproduction and/or sales may result in imprisonment of up *
|
||
* to 1 year and fines of up to $10,000 (17 USC 506). *
|
||
* Copyright infringers may also be subject to civil liability. *
|
||
* *
|
||
************************************************************************
|
||
*/
|
||
|
||
|
||
/*
|
||
* FILE
|
||
*
|
||
* create.c functions for creating archive
|
||
*
|
||
* SCCS
|
||
*
|
||
* @(#)create.c 9.11 5/11/88
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
* Contains functions concerned primarily with creating new
|
||
* archives.
|
||
*
|
||
*/
|
||
|
||
#include "autoconfig.h"
|
||
|
||
#include <stdio.h>
|
||
#include <limits.h>
|
||
|
||
#if (unix || xenix)
|
||
# include <sys/types.h>
|
||
# include <sys/stat.h>
|
||
# include <fcntl.h>
|
||
#else
|
||
# include "sys.h" /* Header to fake stuff for non-unix */
|
||
#endif
|
||
|
||
#include "typedefs.h" /* Locally defined types */
|
||
#include "dbug.h"
|
||
#include "manifest.h" /* Manifest constants */
|
||
#include "config.h" /* Configuration file */
|
||
#include "errors.h" /* Error codes */
|
||
#include "blocks.h" /* Archive format */
|
||
#include "macros.h" /* Useful macros */
|
||
#include "finfo.h" /* File information structure */
|
||
#include "flags.h" /* Command line flags */
|
||
#include "bruinfo.h" /* Current invocation info */
|
||
#include "exeinfo.h" /* Runtime info */
|
||
|
||
|
||
/*
|
||
* External bru functions.
|
||
*/
|
||
|
||
extern VOID discard_zfile (); /* Discard the compressed version of file */
|
||
extern BOOLEAN compressfip (); /* Compress given file if compressable */
|
||
extern VOID addz (); /* Add a ".Z" extension to filename */
|
||
extern BOOLEAN confirmed (); /* Confirm action to be taken */
|
||
extern BOOLEAN copy (); /* Copy N characters */
|
||
extern BOOLEAN selected (); /* File passes selection criteria */
|
||
extern VOID bru_error (); /* Report an error to user */
|
||
extern VOID ar_close (); /* Flush buffers and close the archive */
|
||
extern VOID ar_open (); /* Open the archive */
|
||
extern VOID ar_write (); /* Logical write of current archive block */
|
||
extern VOID copyname (); /* Copy pathnames around */
|
||
extern VOID done (); /* Finish up and exit */
|
||
extern VOID free_list (); /* Free the list of links */
|
||
extern VOID reload (); /* Reload first volume for rescan */
|
||
extern VOID reset_times (); /* Reset atime and mtime of file */
|
||
extern VOID tohex (); /* Convert 32 bit integer to hex */
|
||
extern VOID tree_walk (); /* Walk tree */
|
||
extern VOID unresolved (); /* Complain about unresolved links */
|
||
extern VOID verbosity (); /* Give a verbosity message */
|
||
extern char *add_link (); /* Add linked file to list */
|
||
extern union blk *ar_next (); /* Get pointer to next archive block */
|
||
extern union blk *ar_seek (); /* Locate given logical block in archive */
|
||
extern VOID mark_archived (); /* Set the "has been archived" bit */
|
||
extern VOID clear_archived (); /* Clear the "has been archived" bit */
|
||
extern char *getlinkname();
|
||
|
||
#if HAVE_MEMSET
|
||
#define zeroblk(blkp) (void)memset((blkp)->bytes,0,ELEMENTS((blkp)->bytes))
|
||
#else
|
||
extern VOID zeroblk (); /* Zero an archive block */
|
||
#endif
|
||
|
||
/*
|
||
* System library interface functions.
|
||
*/
|
||
|
||
extern char *s_strcpy (); /* Copy strings */
|
||
extern int s_close (); /* Invoke library file close function */
|
||
extern int s_open (); /* Invoke library file open function */
|
||
extern int s_read (); /* Invoke library file read function */
|
||
extern int s_uname (); /* Invoke library function to get sys info */
|
||
extern int s_unlink (); /* Invoke library function to delete file */
|
||
|
||
/*
|
||
* Extern bru variables.
|
||
*/
|
||
|
||
extern struct cmd_flags flags; /* Flags given on command line */
|
||
extern struct exe_info einfo; /* Execution information */
|
||
extern struct bru_info info; /* Invocation information */
|
||
extern char *id; /* ID of bru */
|
||
extern char mode; /* Current mode (citdxh) */
|
||
extern char *label; /* Archive label string given by user */
|
||
extern struct finfo afile; /* The archive file */
|
||
|
||
|
||
/*
|
||
* Local function declarations.
|
||
*/
|
||
|
||
static VOID do_write (); /* Write file after tests applied */
|
||
static VOID winfo (); /* Write archive info block */
|
||
static VOID wheader (); /* Write a file header block */
|
||
static VOID markend (); /* Mark end of archive */
|
||
static VOID wfile (); /* Write a file to archive */
|
||
static VOID wcontents (); /* Write file contents to archive */
|
||
static VOID bldhdr (); /* Build a file header block */
|
||
static VOID check_intr (); /* Check for interrupt */
|
||
|
||
/*
|
||
* Stuff for signal handling.
|
||
*/
|
||
|
||
extern VOID sig_catch (); /* Set signal catch state */
|
||
extern VOID sig_push (); /* Push signal state */
|
||
extern VOID sig_pop (); /* Pop signal state */
|
||
extern BOOLEAN interrupt; /* Interrupt received */
|
||
|
||
|
||
/*
|
||
* NAME
|
||
*
|
||
* create main entry point for creating new archives
|
||
*
|
||
* SYNOPSIS
|
||
*
|
||
* VOID create ()
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
* This is the main entry point for creating new archives.
|
||
* It is called once all the command line options have been
|
||
* processed and common initialization has been performed.
|
||
*
|
||
*/
|
||
|
||
|
||
/*
|
||
* PSEUDO CODE
|
||
*
|
||
* Begin create
|
||
* Set current mode to create
|
||
* Open the archive file
|
||
* Save state of signal handling
|
||
* Catch signals
|
||
* Write the archive header block
|
||
* Walk directory tree, archiving each file
|
||
* Mark end of archive
|
||
* Restore previous signal handling state
|
||
* If not suppressing link warnings
|
||
* Complain about unresolved links
|
||
* End if
|
||
* Free the list of unresolved links
|
||
* Close the archive file
|
||
* End create
|
||
*
|
||
*/
|
||
|
||
VOID create ()
|
||
{
|
||
SIGTYPE prevINT;
|
||
SIGTYPE prevQUIT;
|
||
|
||
DBUG_ENTER ("create");
|
||
mode = 'c';
|
||
reload ("archive creation");
|
||
ar_open ();
|
||
sig_push (&prevINT, &prevQUIT);
|
||
sig_catch ();
|
||
winfo (&afile);
|
||
tree_walk (wfile);
|
||
markend (&afile);
|
||
sig_pop (&prevINT, &prevQUIT);
|
||
if (!flags.lflag) {
|
||
unresolved ();
|
||
}
|
||
free_list ();
|
||
ar_close ();
|
||
DBUG_VOID_RETURN;
|
||
}
|
||
|
||
|
||
/*
|
||
* FUNCTION
|
||
*
|
||
* wfile write a file to archive
|
||
*
|
||
* SYNOPSIS
|
||
*
|
||
* static VOID wfile (fip)
|
||
* struct finfo *fip;
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
* Given pathname to a file, writes that file to the archive.
|
||
* Each regular file written in the archive has a header block
|
||
* containing information about the file, and zero or more data
|
||
* blocks containing the actual file contents.
|
||
*
|
||
* Note that directories, block special files, character special
|
||
* files, and other special files only have a header block written.
|
||
* This is so those nodes can be restored with the proper attributes.
|
||
* This is a particular failing of the Unix "tar" utility.
|
||
*
|
||
* Note that the file must be opened with the O_NDELAY flag
|
||
* set or else character special files associated with communication
|
||
* lines will cause the open to block until the line has carrier
|
||
* present. See open(2) in the Unix Sys V User's Manual.
|
||
*
|
||
*/
|
||
|
||
|
||
/*
|
||
* PSEUDO CODE
|
||
*
|
||
* Begin wfile
|
||
* If bad arguments then
|
||
* Tell user about bug
|
||
* End if
|
||
* Check for interrupts
|
||
* If there is a file to write and is not "." or ".." then
|
||
* If this file is selected then
|
||
* If archiving confirmed then
|
||
* Committed, so write it to archive
|
||
* End if
|
||
* End if
|
||
* End if
|
||
* End wfile
|
||
*
|
||
*/
|
||
|
||
static VOID wfile (fip)
|
||
struct finfo *fip;
|
||
{
|
||
DBUG_ENTER ("wfile");
|
||
if (fip == NULL) {
|
||
bru_error (ERR_BUG, "wfile");
|
||
}
|
||
check_intr ();
|
||
DBUG_PRINT ("path", ("write \"%s\" to archive", fip -> fname));
|
||
if (*fip -> fname != EOS && !DOTFILE (fip -> fname)) {
|
||
/*
|
||
* Added for xfs - Don't archive big files unless -K and -Z set
|
||
*/
|
||
if (fip->statp->st_size > LONG_MAX ) {
|
||
if (!flags.Kflag) {
|
||
bru_error (ERR_NO_KFLAG,fip->fname);
|
||
DBUG_VOID_RETURN;
|
||
}
|
||
if (!flags.Zflag) {
|
||
bru_error (ERR_NO_ZFLAG,fip->fname);
|
||
DBUG_VOID_RETURN;
|
||
}
|
||
}
|
||
}
|
||
if (selected (fip)) {
|
||
if (confirmed ("c %s", fip)) {
|
||
do_write (fip);
|
||
}
|
||
}
|
||
DBUG_VOID_RETURN;
|
||
}
|
||
|
||
|
||
/*
|
||
* FUNCTION
|
||
*
|
||
* do_write committed to doing write so do it
|
||
*
|
||
* SYNOPSIS
|
||
*
|
||
* static VOID do_write (fip)
|
||
* struct finfo *fip;
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
* Once it has been decided to write a file to the archive,
|
||
* after applying all tests, this function is called to do
|
||
* the actual write.
|
||
*
|
||
* If the command line option -Z to store files in a compressed
|
||
* form has been given, the input file is compressed, and the
|
||
* resulting temporary compressed file is saved in the archive.
|
||
* For backwards compatibility with versions of bru that don't
|
||
* understand compressed files, the saved file name has a ".Z"
|
||
* extension appended to it, the standard name for compressed
|
||
* versions of files. The original file size is saved in an
|
||
* area that won't be seen by older versions of bru, and the
|
||
* compressed file size is stored in the normal size location.
|
||
* Thus, if an archive built by a new version of bru is read
|
||
* by an old version of bru, it will appear that all the files
|
||
* were compressed before archiving, and the files will be
|
||
* extracted as compressed files.
|
||
*
|
||
* This routine has been reorganized considerably in order to
|
||
* get file compression implemented, because the input file
|
||
* needs to be compressed BEFORE verbosity() is called. Plus
|
||
* verbosity() should not be called if we can't access or open
|
||
* the file for some reason, and the file is a file we will
|
||
* need to access and read.
|
||
*/
|
||
|
||
|
||
/*
|
||
* PSEUDO CODE
|
||
*
|
||
* Begin do_write
|
||
* If bad arguments then
|
||
* Tell user about bug
|
||
* End if
|
||
* If not a symbolic link then
|
||
* Set linked file name to NULL.
|
||
* End if
|
||
* If not directory and more than one link then
|
||
* Add link to list of linked files
|
||
* End if
|
||
* Do verbosity processing
|
||
* Set current file block to zero
|
||
* If is special file or linked to another file then
|
||
* Write header block only
|
||
* Else
|
||
* If file is accessible for read then
|
||
* Open the file for read
|
||
* If open failed then
|
||
* Report open error to user
|
||
* Else
|
||
* Write the header block to archive
|
||
* Write the file contents to archive
|
||
* If file close failed then
|
||
* Report close error to user
|
||
* End if
|
||
* Reset the file times
|
||
* If should mark file as archived then
|
||
* Set file archived bit
|
||
* Else if should mark file unarchived then
|
||
* Reset file archived bit
|
||
* Endif
|
||
* End if
|
||
* End if
|
||
* End if
|
||
* End do_write
|
||
*
|
||
*/
|
||
|
||
static VOID do_write (fip)
|
||
struct finfo *fip;
|
||
{
|
||
BOOLEAN fileok = FALSE;
|
||
char *savelinkname;
|
||
|
||
DBUG_ENTER ("do_write");
|
||
if (fip == NULL) {
|
||
bru_error (ERR_BUG, "do_write");
|
||
}
|
||
/* symbolic links that are hard linked to other symbolic links we
|
||
* have already seen are treated as just links. SGI seems to
|
||
* be one of the few vendors that even allows this */
|
||
savelinkname = fip->lname;
|
||
if(!IS_FLNK(fip->statp->st_mode) || (fip->statp->st_nlink>1 &&
|
||
getlinkname(fip))) {
|
||
fip->lname = NULL;
|
||
}
|
||
if (!IS_DIR (fip -> statp -> st_mode) && fip -> statp -> st_nlink > 1) {
|
||
fip -> lname = add_link (fip);
|
||
if(!fip->lname && IS_FLNK(fip->statp->st_mode))
|
||
fip->lname = savelinkname;
|
||
}
|
||
fileok = openandchkcompress(fip);
|
||
if (!IS_REG (fip -> statp -> st_mode) || fip -> lname != NULL) {
|
||
verbosity (fip);
|
||
fip -> flba = 0L;
|
||
wheader (fip);
|
||
} else if (fileok) {
|
||
if (fip->statp->st_size > LONG_MAX )
|
||
bru_error (ERR_OK_FLAG,fip->fname);
|
||
verbosity (fip);
|
||
fip -> flba = 0L;
|
||
wheader (fip);
|
||
wcontents (fip);
|
||
if (s_close (fip -> fildes) == SYS_ERROR) {
|
||
bru_error (ERR_CLOSE, fip -> fname);
|
||
}
|
||
discard_zfile (fip);
|
||
reset_times (fip);
|
||
if (flags.Asflag) {
|
||
mark_archived (fip);
|
||
} else if (flags.Acflag) {
|
||
clear_archived (fip);
|
||
}
|
||
}
|
||
DBUG_VOID_RETURN;
|
||
}
|
||
|
||
|
||
/*
|
||
* FUNCTION
|
||
*
|
||
* wheader build and write header block to archive
|
||
*
|
||
* SYNOPSIS
|
||
*
|
||
* static VOID wheader (fip)
|
||
* struct finfo *fip;
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
* Builds a header block and writes it to the archive.
|
||
*
|
||
*/
|
||
|
||
|
||
/*
|
||
* PSEUDO CODE
|
||
*
|
||
* Begin wheader
|
||
* If bad arguments then
|
||
* Warn user about bug
|
||
* End if
|
||
* Get next archive block
|
||
* Zero the block
|
||
* Copy the file name to block header
|
||
* If linked to another file then
|
||
* Copy the linked name to file header
|
||
* End if
|
||
* Build the rest of the file header
|
||
* Write the header block to archive
|
||
* End wheader
|
||
*
|
||
*/
|
||
|
||
static VOID wheader (fip)
|
||
struct finfo *fip;
|
||
{
|
||
register union blk *blkp;
|
||
|
||
DBUG_ENTER ("wheader");
|
||
if (fip == NULL) {
|
||
bru_error (ERR_BUG, "wheader");
|
||
}
|
||
blkp = ar_next ();
|
||
zeroblk (blkp);
|
||
copyname (blkp -> HD.h_name, fip -> fname);
|
||
if (IS_COMPRESSED (fip)) {
|
||
addz (blkp -> HD.h_name);
|
||
}
|
||
if (fip -> lname != NULL) {
|
||
copyname (blkp -> FH.f_lname, fip -> lname);
|
||
if (IS_COMPRESSED (fip)) {
|
||
addz (blkp -> FH.f_lname);
|
||
}
|
||
}
|
||
bldhdr (blkp, fip);
|
||
ar_write (fip, H_MAGIC);
|
||
DBUG_VOID_RETURN;
|
||
}
|
||
|
||
|
||
/*
|
||
* FUNCTION
|
||
*
|
||
* wcontents write contents of normal file to archive
|
||
*
|
||
* SYNOPSIS
|
||
*
|
||
* static VOID wcontents (fip)
|
||
* struct finfo *fip;
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
* This routine is responsible for writing the contents of a normal
|
||
* file to the archive.
|
||
*
|
||
* Note that each block is zeroed to assure that no junk is left
|
||
* laying around in it from it's last use. This is necessary because
|
||
* the data section is only part of the block (otherwise only the
|
||
* last block would require zeroing). The header is initialized
|
||
* by ar_write, which may not clear unused fields.
|
||
*
|
||
* BUGS
|
||
*
|
||
* In previous versions of bru, if the read failed or the file was
|
||
* truncated, the number of blocks in the archive did not match the
|
||
* number expected from the file size stored in the file header
|
||
* block. This caused problems when the archive was read because
|
||
* the header block of the following file was never found.
|
||
*
|
||
* The solution was to always write the correct number of blocks
|
||
* to the archive, regardless of whether or not their contents
|
||
* are correct. This fixes the previous problem and insures
|
||
* that as much as possible of the file is preserved. Note
|
||
* however, that the only error observed is when the archive
|
||
* is created. Once the archive is created, as far as it is
|
||
* concerned, all the internal data is correct.
|
||
*
|
||
* Another problem is what to do about files that grow while
|
||
* archiving. The solution implemented currently is simply to warn
|
||
* the user and discard any file additions. The file scanning
|
||
* routines could be made smarter about finding a data block when
|
||
* expecting a file header. This would allow the additional data
|
||
* to be archived.
|
||
*
|
||
*/
|
||
|
||
|
||
/*
|
||
* PSEUDO CODE
|
||
*
|
||
* Begin wcontents
|
||
* Initialize the file truncated flag to FALSE
|
||
* If the file information pointer is bad then
|
||
* Warn user about bug
|
||
* End if
|
||
* Get the number of bytes in the file to be archived
|
||
* If the file has anything in it at all then
|
||
* For each block of data to be archived
|
||
* Increment the file block number
|
||
* Get the next archive block
|
||
* Zero the block
|
||
* If only a partial block left to read then
|
||
* Read only the correct number of bytes
|
||
* End if
|
||
* Read data from file into block
|
||
* Write the block to the archive
|
||
* If read was not correct then
|
||
* Set the file has been truncated flag
|
||
* End if
|
||
* End for
|
||
* If last read returned with error condition then
|
||
* Warn user about read error
|
||
* End if
|
||
* If the file was truncated then
|
||
* Warn user about truncation
|
||
* Else
|
||
* Attempt to read some more data from file
|
||
* If successful then
|
||
* Warn user that the file grew while archiving
|
||
* End if
|
||
* End if
|
||
* End if
|
||
* End wcontents
|
||
*
|
||
*/
|
||
|
||
static VOID wcontents (fip)
|
||
struct finfo *fip;
|
||
{
|
||
register off_t bytes;
|
||
register int iobytes;
|
||
register UINT rbytes;
|
||
register union blk *blkp;
|
||
auto char testbuf[DATASIZE];
|
||
register BOOLEAN truncated;
|
||
register int fildes;
|
||
char *fname;
|
||
|
||
DBUG_ENTER ("wcontents");
|
||
truncated = FALSE;
|
||
if (fip == NULL) {
|
||
bru_error (ERR_BUG, "wcontents");
|
||
}
|
||
if (IS_COMPRESSED (fip)) {
|
||
bytes = fip -> zsize;
|
||
fildes = fip -> zfildes;
|
||
fname = fip -> zfname;
|
||
} else {
|
||
bytes = fip -> statp -> st_size;
|
||
fildes = fip -> fildes;
|
||
fname = fip -> fname;
|
||
}
|
||
DBUG_PRINT ("rbytes", ("read and save %ld bytes from '%s'", bytes, fname));
|
||
if (bytes > 0) {
|
||
for (rbytes = DATASIZE; bytes > 0; bytes -= rbytes) {
|
||
fip -> flba++;
|
||
blkp = ar_next ();
|
||
zeroblk (blkp);
|
||
if (bytes < DATASIZE) {
|
||
rbytes = bytes;
|
||
}
|
||
iobytes = s_read (fildes, blkp -> FD, rbytes);
|
||
ar_write (fip, D_MAGIC);
|
||
if (iobytes != rbytes) {
|
||
truncated = TRUE;
|
||
}
|
||
}
|
||
if (iobytes == SYS_ERROR) {
|
||
bru_error (ERR_READ, fname);
|
||
}
|
||
if (truncated) {
|
||
bru_error (ERR_FTRUNC, fname);
|
||
} else {
|
||
iobytes = s_read (fildes, testbuf, DATASIZE);
|
||
if (iobytes > 0) {
|
||
bru_error (ERR_FGREW, fname);
|
||
}
|
||
}
|
||
}
|
||
DBUG_VOID_RETURN;
|
||
}
|
||
|
||
|
||
/*
|
||
* FUNCTION
|
||
*
|
||
* bldhdr do grunge work for building a file header
|
||
*
|
||
* SYNOPSIS
|
||
*
|
||
* static VOID bldhdr (blkp, fip)
|
||
* register union blk *blkp;
|
||
* register struct finfo *fip;
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
* Does the actual work of building each field in the file
|
||
* header block.
|
||
*
|
||
* Note that if the file is a directory, the size in the file
|
||
* header block is set to zero, since we don't actually archive
|
||
* any of the contents of directory files.
|
||
*
|
||
*/
|
||
|
||
static VOID bldhdr (blkp, fip)
|
||
register union blk *blkp;
|
||
register struct finfo *fip;
|
||
{
|
||
DBUG_ENTER ("bldhdr");
|
||
if (fip == NULL || blkp == NULL) {
|
||
bru_error (ERR_BUG, "bldhdr");
|
||
}
|
||
TOHEX (blkp -> HD.h_magic, H_MAGIC);
|
||
TOHEX (blkp -> FH.f_mode, fip -> statp -> st_mode);
|
||
TOHEX (blkp -> FH.f_ino, fip -> statp -> st_ino);
|
||
TOHEX (blkp -> FH.f_dev, fip -> statp -> st_dev);
|
||
TOHEX (blkp -> FH.f_rdev, fip -> statp -> st_rdev);
|
||
TOHEX (blkp -> FH.f_nlink, fip -> statp -> st_nlink);
|
||
TOHEX (blkp -> FH.f_uid, fip -> statp -> st_uid);
|
||
TOHEX (blkp -> FH.f_gid, fip -> statp -> st_gid);
|
||
if (IS_REG (fip -> statp -> st_mode)) {
|
||
if (IS_COMPRESSED (fip)) {
|
||
TOHEX (blkp -> FH.f_size, fip -> zsize);
|
||
/*
|
||
* Added for xfs
|
||
*/
|
||
if (fip -> statp -> st_size > LONG_MAX)
|
||
TOHEX (blkp -> FH.f_xsize, -1);
|
||
else
|
||
TOHEX (blkp -> FH.f_xsize, fip -> statp -> st_size);
|
||
} else {
|
||
if (fip -> statp -> st_size > LONG_MAX)
|
||
TOHEX (blkp -> FH.f_size, -1);
|
||
else
|
||
TOHEX (blkp -> FH.f_size, fip -> statp -> st_size);
|
||
}
|
||
} else {
|
||
TOHEX (blkp -> FH.f_size, 0L);
|
||
}
|
||
TOHEX (blkp -> FH.f_atime, fip -> statp -> st_atime);
|
||
TOHEX (blkp -> FH.f_mtime, fip -> statp -> st_mtime);
|
||
TOHEX (blkp -> FH.f_ctime, fip -> statp -> st_ctime);
|
||
TOHEX (blkp -> FH.f_flags, fip -> fi_flags);
|
||
TOHEX (blkp -> FH.f_fibprot, fip -> fib_Protection);
|
||
(VOID) s_strcpy (blkp -> FH.f_fibcomm, fip -> fib_Comment);
|
||
DBUG_VOID_RETURN;
|
||
}
|
||
|
||
|
||
/*
|
||
* FUNCTION
|
||
*
|
||
* winfo write the archive header block
|
||
*
|
||
* SYNOPSIS
|
||
*
|
||
* static VOID winfo (afip)
|
||
* register struct finfo *afip;
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
* Builds and writes the archive header block, which is
|
||
* the first block in the archive. This block contains
|
||
* useful information about the archive.
|
||
*
|
||
*/
|
||
|
||
static VOID winfo (afip)
|
||
register struct finfo *afip;
|
||
{
|
||
register union blk *blkp;
|
||
|
||
DBUG_ENTER ("winfo");
|
||
if (afip == NULL) {
|
||
bru_error (ERR_BUG, "winfo");
|
||
}
|
||
blkp = ar_seek (0L, 0);
|
||
zeroblk (blkp);
|
||
TOHEX (blkp -> AH.a_uid, info.bru_uid);
|
||
TOHEX (blkp -> AH.a_gid, info.bru_gid);
|
||
copyname (blkp -> AH.a_name, afile.fname);
|
||
if (flags.Lflag) {
|
||
if (!copy (blkp -> AH.a_label, label, BLABELSIZE)) {
|
||
bru_error (ERR_LABEL, label);
|
||
}
|
||
}
|
||
(VOID) s_strcpy (blkp -> AH.a_id, id);
|
||
if (s_uname (&blkp -> AH.a_host) == SYS_ERROR) {
|
||
bru_error (ERR_UNAME);
|
||
}
|
||
ar_write (afip, A_MAGIC);
|
||
DBUG_VOID_RETURN;
|
||
}
|
||
|
||
|
||
/*
|
||
* FUNCTION
|
||
*
|
||
* markend mark the end of the archive with a terminator block
|
||
*
|
||
* SYNOPSIS
|
||
*
|
||
* static VOID markend (afip)
|
||
* struct finfo *afip;
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
* Marks the end of the archive by writing a terminator block.
|
||
*
|
||
*/
|
||
|
||
static VOID markend (afip)
|
||
struct finfo *afip;
|
||
{
|
||
register union blk *blkp;
|
||
|
||
DBUG_ENTER ("markend");
|
||
if (afip == NULL) {
|
||
bru_error (ERR_BUG, "afip");
|
||
}
|
||
blkp = ar_next ();
|
||
zeroblk (blkp);
|
||
ar_write (afip, T_MAGIC);
|
||
DBUG_VOID_RETURN;
|
||
}
|
||
|
||
|
||
/*
|
||
* FUNCTION
|
||
*
|
||
* check_intr check for an interrupt received
|
||
*
|
||
* SYNOPSIS
|
||
*
|
||
* static VOID check_intr ()
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
* Checks to see if an interrupt was received while signals
|
||
* were being caught. If so, marks the end of the archive
|
||
* and cleans up and exits.
|
||
*
|
||
*/
|
||
|
||
static VOID check_intr ()
|
||
{
|
||
if (interrupt) {
|
||
DBUG_PRINT ("sig", ("interrupt recognized"));
|
||
einfo.warnings++;
|
||
markend (&afile);
|
||
ar_close ();
|
||
done ();
|
||
}
|
||
}
|