1
0
Files
irix-657m-src/eoe/cmd/bru/extract.c
2022-09-29 17:59:04 +03:00

1062 lines
27 KiB
C
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/************************************************************************
* *
* 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
*
* extract.c contains routines specific to extracting files
*
* SCCS
*
* @(#)extract.c 9.11 5/11/88
*
* DESCRIPTION
*
* Contains routines specific to extracting files from bru archives.
*
*/
#include "autoconfig.h"
#include <stdio.h>
#if (unix || xenix)
# include <sys/types.h>
# include <sys/stat.h>
#else
# include "sys.h"
#endif
#include "typedefs.h"
#include "dbug.h"
#include "manifest.h"
#include "config.h"
#include "errors.h"
#include "blocks.h"
#include "macros.h"
#include "trees.h"
#include "finfo.h"
#include "flags.h"
#include "bruinfo.h"
#define DIR_MAGIC 0777 /* Default permissions for directories */
/* This is modified by umask */
dev_t saved_st_dev = 0;
/*
* External bru functions.
*/
extern BOOLEAN decompfip (); /* Decompress a file, saving to destination */
extern BOOLEAN openzfile (); /* Open a temp file for compressed file */
extern int setinfo ();
extern int s_mknod (); /* Make a directory, special, or other file */
extern BOOLEAN confirmed (); /* Confirm action */
extern union blk *ar_next (); /* Get pointer to next archive block */
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_read (); /* Read archive block */
extern VOID reload (); /* Reload first volume for rescan */
extern VOID done (); /* Finish up and exit */
extern BOOLEAN newdir (); /* Make a directory */
extern BOOLEAN mklink (); /* Make a link to a file */
extern BOOLEAN mksymlink (); /* Make a symbolic link to a file */
extern VOID scan (); /* Scan archive */
extern VOID verbosity (); /* Issue verbosity message */
extern BOOLEAN selected (); /* Apply selection criteria */
extern VOID finfo_init (); /* Initialize a finfo structure */
extern BOOLEAN file_access (); /* Check file for access */
extern BOOLEAN dir_access (); /* Check parent for access */
extern BOOLEAN out_of_date (); /* Existing file out of date */
extern BOOLEAN unconditional(); /* Unconditionally overwrite */
extern char *s_strrchr (); /* Find last given character in string */
extern int s_close (); /* Invoke library file close function */
extern int s_umask (); /* Invoke umask library function */
extern int s_creat (); /* Create a file */
extern VOID file_chown (); /* Change file owner and group */
extern int s_utime (); /* Set file access/modification times */
extern int s_chmod (); /* Change mode of a file */
extern int s_write (); /* Write data to file */
extern int s_unlink (); /* Remove a directory entry */
extern long s_time (); /* Get current time */
extern VOID mark_archived (); /* Set the "has been archived" bit */
extern VOID clear_archived (); /* Clear the "has been archived" bit */
extern char *getlinkname();
extern char *add_link();
/*
* External bru variables.
*/
extern struct bru_info info; /* Current invocation information */
extern struct cmd_flags flags; /* Command line flags */
extern char mode; /* Current mode (citdxh) */
/*
* Local functions.
*/
static VOID do_extract (); /* Actually do the extraction */
static VOID xfile (); /* Extract the file */
static VOID makelink (); /* Make link to existing file */
static BOOLEAN makedir (); /* Make a directory */
static BOOLEAN makeparent (); /* Make a parent directory */
static VOID makestat (); /* Make default stat buffer */
static VOID makespecial (); /* Make a special file */
static VOID xregfile (); /* Do extraction of regular file */
static VOID makefile (); /* Make first copy of file */
static VOID attributes (); /* Set attributes to match */
/*
* 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
*
* extract main entry point for extraction of file from archive
*
* SYNOPSIS
*
* VOID extract ()
*
* DESCRIPTION
*
* This is the main entry point for extracting files from a bru
* archive. It is called once all the command line options
* have been processed and common initialization has been
* performed.
*
*/
VOID extract ()
{
DBUG_ENTER ("extract");
mode = 'x';
reload ("extraction");
ar_open ();
scan (xfile);
ar_close ();
DBUG_VOID_RETURN;
}
/*
* NAME
*
* xfile control extraction of a single file
*
* SYNOPSIS
*
* static VOID xfile (blkp, fip)
* register union blk *blkp;
* register struct finfo *fip;
*
* DESCRIPTION
*
* Controls extraction of a single file from the archive.
* Blkp points to the file header block and fip points
* to a file information structure.
*
* There was initially some question about how to report
* files which are not extracted because there is an existing
* file which is more recent. Since files that ARE extracted
* are only reported if verbosity is enabled, by analogy, files
* that are NOT extracted are reported only if verbosity is
* enabled. The basic philosophy is to silently bring the existing
* hierarchy up to date by replacing missing files and
* superceding out of date files, without overwriting more
* recent files. If every file in a given class (regular,
* directory, block special, etc) is to be extracted regardless
* of modification date, bru must be explicitly told this via
* the -u (unconditional) flag.
*
*/
/*
* PSEUDO CODE
*
* Begin xfile
* Determine whether or not file is a directory
* If this file is to be extracted then
* If unconditional extraction or file out of date then
* If extraction confirmed then
* Issue verbosity message
* Do the extraction
* End if
* End if
* Else
* If file is not a directory and verbosity enabled
* Warn user that it was not extracted
* End if
* End if
* End if
* End xfile
*
*/
static VOID xfile (blkp, fip)
register union blk *blkp;
register struct finfo *fip;
{
register BOOLEAN is_directory;
struct stat64 alpha;
char tmp[256];
char *savelinkname;
DBUG_ENTER ("xfile");
is_directory = IS_DIR (fip -> statp -> st_mode);
if ((IS_STEM (fip) && is_directory) || IS_LEAF (fip) || IS_EXTENSION (fip)) {
/* change absolute path to relative path if -j flag specified */
if( (flags.jflag) && (*fip->fname == '/') ) {
if(strcmp(fip->fname, "/") == 0)
DBUG_VOID_RETURN;
strcpy(tmp, fip->fname);
strcpy(fip->fname, &tmp[1]);
}
if(flags.mflag) {
if(saved_st_dev != fip->statp->st_dev) {
if(access(fip->fname, 0)) {
DBUG_VOID_RETURN;
}
else {
stat64(fip->fname, &alpha);
if(alpha.st_dev == fip->statp->st_dev)
saved_st_dev = fip->statp->st_dev;
}
}
}
/* 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; the only way
* make this work (and remain compatible with older versions of
* bru both directions) on list and extract is to build the link
* table, same as on create and estimate... */
savelinkname = fip->lname;
if(!IS_FLNK(fip->statp->st_mode) || (fip->statp->st_nlink>1 &&
getlinkname(fip))) {
fip->lname = NULL;
}
if(!is_directory && fip->statp -> st_nlink > 1) {
fip->lname = add_link(fip);
if(!fip->lname && IS_FLNK(fip->statp->st_mode))
fip->lname = savelinkname;
}
if (unconditional (fip) || out_of_date (fip)) {
if (confirmed ("x %s", fip)) {
verbosity (fip);
do_extract (blkp, fip);
}
} else {
if (!is_directory && flags.vflag > 1) {
bru_error (ERR_SUPERSEDE, fip -> fname);
}
}
}
DBUG_VOID_RETURN;
}
/*
* FUNCTION
*
* makelink link file being extracted to an existing file
*
* SYNOPSIS
*
* static VOID makelink (blkp, fip)
* union blk *blkp;
* register struct finfo *fip;
*
* DESCRIPTION
*
* Links the file being extracted (file1) to the existing file
* (file2) that it is supposed to be linked to.
*
* Note that this will fail if file2 does not exist.
* In this case there is nothing else to be done since the file
* contents for file2 are not stored in the archived file1.
*
* Also note that any existing file1 is unlinked. If the
* new link cannot be made for some reason, the effective
* result is the deletion of any existing file1. This
* could be fixed by first linking an existing file1 to some
* temporary and then either unlinking or relinking it as
* necessary once the link between the new file1 and file2
* is established or denied respectively. Another way is
* to open the existing file1, unlink the existing file1,
* then either close file1 or copy it back to a new
* instance of file1 as necessary.
*
*/
/*
* PSEUDO CODE
*
* Begin makelink
* If file to be linked to does not exist then
* Tell user we can't make the link
* Else
* Unlink any existing file to be linked
* If the link to the target file is successful then
* Set the attributes of the link just made
* End if
* End if
* End makelink
*
*/
static VOID makelink (blkp, fip)
union blk *blkp;
register struct finfo *fip;
{
char tmp[256];
DBUG_ENTER ("makelink");
if(flags.jflag) {
if(!fip->lname) {
bru_error (ERR_MKLINK_J, fip->fname);
return;
}
if(strcmp(fip->lname, "") && *fip->lname == '/') {
strcpy(tmp, fip->lname);
strcpy(fip->lname, &tmp[1]);
}
if (!file_access (fip->lname, A_EXISTS, FALSE)) {
bru_error (ERR_MKLINK, fip->fname, fip->lname);
} else {
(VOID) s_unlink (fip->fname);
if (mklink (fip->lname, fip->fname)) {
attributes (fip);
}
}
}
else {
if (!file_access (blkp -> FH.f_lname, A_EXISTS, FALSE)) {
bru_error (ERR_MKLINK, blkp -> HD.h_name, blkp -> FH.f_lname);
} else {
(VOID) s_unlink (blkp -> HD.h_name);
if (mklink (blkp -> FH.f_lname, blkp -> HD.h_name)) {
attributes (fip);
}
}
}
DBUG_VOID_RETURN;
}
/*
* FUNCTION
*
* makefile extract a regular file
*
* SYNOPSIS
*
* static VOID makefile (blkp, fip)
* register union blk *blkp;
* register struct finfo *fip;
*
* DESCRIPTION
*
* Controls extract of a regular file by testing for
* for it's existance and/or writability. The file
* will only be extracted if it does not currently exist
* or if the user has write permission to overwrite an
* existing version.
*
*/
/*
* PSEUOD CODE
*
* Begin makefile
* If file does not exist then
* Go ahead and extract it from archive
* Else
* If file is not writable then
* Tell user he can't overwrite the file
* Else
* Go ahead and extract it from archive
* End if
* End if
* End makefile
*
*/
static VOID makefile (blkp, fip)
register union blk *blkp;
register struct finfo *fip;
{
DBUG_ENTER ("makefile");
if (!file_access (fip -> fname, A_EXISTS, FALSE)) {
xregfile (blkp, fip);
} else {
if (!file_access (fip -> fname, A_WRITE, FALSE)) {
bru_error (ERR_OVRWRT, fip -> fname);
} else {
xregfile (blkp, fip);
}
}
DBUG_VOID_RETURN;
}
/*
* FUNCTION
*
* xregfile extract a normal file from archive
*
* SYNOPSIS
*
* static VOID xregfile (blkp, fip)
* register union blk *blkp;
* register struct finfo *fip;
*
* DESCRIPTION
*
* This routine is responsible for extracting a normal file from
* an archive.
*
* Returns TRUE if file was created, FALSE otherwise.
* Note that return of TRUE does NOT indicate successful
* extraction, only that a file was created.
*
*/
/*
* PSEUDO CODE
*
* Begin xregfile
* Initialize the file truncated flag to FALSE
* Create the file being extracted
* If couldn't be created then
* Inform user
* Else
* Get number of bytes to extract
* If any bytes to extract then
* For each block to be extracted
* Seek to archive block
* Read the archive block
* If extracting a partial block then
* Only use that many bytes
* End if
* Write the bytes to the new file
* If write did not write requested number then
* Remember that the file was truncated
* End if
* End for
* If last write returned error then
* Notify user about write error
* End if
* If file was truncated then
* Warn user about truncation
* End if
* End if
* If file close get an error then
* Warn user about the close error
* End if
* Set the attributes of the extracted file
* End if
* End xregfile
*
*/
static VOID xregfile (blkp, fip)
register union blk *blkp;
register struct finfo *fip;
{
register off_t bytes;
register int iobytes;
register UINT wbytes;
register int fildes;
register BOOLEAN truncated = FALSE;
register BOOLEAN doextract = TRUE;
register char *fname;
DBUG_ENTER ("xregfile");
if (IS_COMPRESSED (fip)) {
if (openzfile (fip)) {
fname = fip -> zfname;
fildes = fip -> zfildes;
} else {
bru_error (ERR_ZXFAIL, fip -> fname);
doextract = FALSE;
}
} else {
fname = fip -> fname;
fildes = s_creat (fip -> fname, 0600);
if (fildes == SYS_ERROR) {
bru_error (ERR_CREAT, fip -> fname);
doextract = FALSE;
}
}
if (doextract) {
bytes = ZSIZE (fip);
if (bytes > 0) {
for (wbytes = DATASIZE; bytes > 0; bytes -= wbytes) {
blkp = ar_next ();
ar_read (fip);
if (bytes < DATASIZE) {
wbytes = bytes;
}
iobytes = s_write (fildes, blkp -> FD, wbytes);
if (iobytes != wbytes) {
truncated = TRUE;
}
}
if (iobytes == SYS_ERROR) {
bru_error (ERR_WRITE, fname);
}
if (truncated) {
bru_error (ERR_FTRUNC, fname);
}
}
if (s_close (fildes) == SYS_ERROR) {
bru_error (ERR_CLOSE, fname);
}
if (!IS_COMPRESSED (fip) || decompfip (fip)) {
attributes (fip);
}
}
DBUG_VOID_RETURN;
}
/*
* FUNCTION
*
* makespecial make a special file node
*
* SYNOPSIS
*
* static VOID makespecial (fip)
* register struct finfo *fip;
*
* DESCRIPTION
*
* Is reponsible for controlling creation of special files.
* If the special file being made already exists, it is
* unlinked first, then the new node is made.
*
* Adding code for 4.2 has complicated this routine, and made it
* very ugly. It is even worse than it ought to be, since it is
* currently impossible under 4.2 to chmod a symbolic link (although
* a symlink with mode 000 can still be read!), or to reset the access
* and modification times on a symbolic link. This is dealt with
* in attributes(), below.
*
*/
/*
* PSEUDO CODE
*
* Begin makespecial
* If the current file exists then
* Unlink the file
* End if
* If under 4.2, not a pyramid, and file is a fifo, then
* Just create a regular file
* Set the attributes of the new node
* Else if the file is a symbolic link then
* If cannot make the symbolic link then
* Inform the user
* Else
* Set the attributes of the new node
* Endif
* Else if the new node cannot be made then
* Inform the user
* Else
* Set attributes of the new node
* End if
* End makespecial
*
*/
static VOID makespecial (fip)
register struct finfo *fip;
{
char *tmpname;
DBUG_ENTER ("makespecial");
if (file_access (fip -> fname, A_EXISTS, FALSE)) {
(VOID) s_unlink (fip -> fname);
}
#if !HAVE_FIFOS
if (IS_FIFO (fip -> statp -> st_mode)) {
int fd;
fd = s_creat (fip -> fname, 0666); /* fudge it */
if (fd == SYS_ERROR) {
bru_error (ERR_MKFIFO, fip -> fname);
} else {
attributes (fip);
bru_error (ERR_FIFOTOREG, fip -> fname);
if (s_close (fd) == SYS_ERROR) {
bru_error (ERR_CLOSE, fip -> fname);
}
}
} else
#endif
if (IS_FLNK (fip -> statp -> st_mode)) {
if (! mksymlink (fip -> lname, fip -> fname) && ! flags.lflag) {
bru_error (ERR_MKSYMLINK, fip -> fname);
} else {
attributes (fip);
}
} else if (s_mknod (fip -> fname, (int) fip -> statp -> st_mode, (int) fip -> statp -> st_rdev) == SYS_ERROR) {
bru_error (ERR_MKNOD, fip -> fname);
} else {
attributes (fip);
}
DBUG_VOID_RETURN;
}
/*
* FUNCTION
*
* attributes set attributes of newly created file
*
* SYNOPSIS
*
* static VOID attributes (fip)
* register struct finfo *fip;
*
* DESCRIPTION
*
* Using stat buffer information recovered from archive
* header block, sets the attributes of the file.
*
* Under 4.2 BSD, it is impossible to reset the access and
* modification times of a symbolic link, or to change its
* mode with chmod. Both chmod and utimes go through the
* symbolic link to the real file, which is not what we want.
* Therefore, we add code for checking symbolic links.
*
*/
/*
* PSEUDO CODE
*
* Begin attributes
* If the mode cannot be set then
* Inform user that mode cannot be changed
* End if
* Change owner and group of the file
* If the access and modification times cannot be set then
* Inform the user about time error
* End if
* End attributes
*
*/
static VOID attributes (fip)
register struct finfo *fip;
{
register char *path;
register int s_mode;
register int s_owner;
register int s_group;
struct filetimes { /* 4.2 changed the stat buffer; st_atime */
time_t atime; /* is not contiguous to st_mtime, so we */
time_t mtime; /* build the structure explicitly before */
} t; /* handing it off to s_utime() */
DBUG_ENTER ("attributes");
path = fip -> fname;
s_mode = fip -> statp -> st_mode;
s_owner = fip -> statp -> st_uid;
s_group = fip -> statp -> st_gid;
if (s_owner != info.bru_uid && (info.bru_uid != 0 || flags.Cflag)) {
if (s_mode & S_ISUID) {
s_mode &= ~S_ISUID;
bru_error (ERR_SUID, path);
}
}
if (s_group != info.bru_gid && (info.bru_uid != 0 || flags.Cflag)) {
if (s_mode & S_ISGID) {
s_mode &= ~S_ISGID;
bru_error (ERR_SGID, path);
}
}
DBUG_PRINT ("attributes",
("file %s, owner %d, group %d", fip -> fname, s_owner, s_group));
DBUG_PRINT ("attributes", ("file %s, mode %#o", fip -> fname, s_mode));
if(!IS_FLNK (fip -> statp -> st_mode)) {
t.atime = fip -> statp -> st_atime;
t.mtime = fip -> statp -> st_mtime;
/* do in this order so when on sysV systems, the time
* and mode can be set correctly even if we are chown'ing
* the file to some other user. */
if(s_utime (fip -> fname, &t) == SYS_ERROR)
bru_error (ERR_STIMES, fip -> fname);
if(s_chmod (path, s_mode) == SYS_ERROR)
bru_error (ERR_SMODE, path);
file_chown (path, s_owner, s_group);
}
if (fip -> fi_flags & FI_AMIGA) {
(VOID) setinfo (fip);
if (flags.Asflag) {
mark_archived (fip);
} else if (flags.Acflag) {
clear_archived (fip);
}
}
DBUG_VOID_RETURN;
}
/*
* FUNCTION
*
* do_extract do the extraction
*
* SYNOPSIS
*
*
* static VOID do_extract (blkp, fip)
* register union blk *blkp;
* register struct finfo *fip;
*
* DESCRIPTION
*
* Once all tests have been met and it has been decided to extract
* the file, this routine is called to do the actual extraction.
* At this point, we are committed to doing the extraction and
* cannot be interrupted until done.
*
* Any missing parent directories will be created and then the
* file itself will be extracted.
*
* For directories, there is an explicit call to set the attributes
* since the makedir function cannot do this if the directory already
* exists. Thus directories which do not exist will have there
* attributes set when they are made by makedir, and again here.
* It is the case of existing directories that we only catch here.
*
*/
/*
* PSEUDO CODE
*
* Begin do_extract
* Save current signal processing stat
* Set up to catch signals
* Check for directory in which to extract file
* If no parent directory then
* Make a default stat buffer
* Make the parent directory
* End if
* If parent directory and parent accessible then
* If file to extract is a directory then
* Make the directory
* Set the directory attributes
* Else if file linked to another then
* Make the linkage
* Else if not a regular file then
* Make a special file
* Else
* Make the file
* End if
* End if
* Pop the saved signal processing state
* If interrupt came in while doing extraction
* Cleanup and exit
* End if
* End do_extract
*
*/
static VOID do_extract (blkp, fip)
register union blk *blkp;
register struct finfo *fip;
{
auto struct stat64 sbuf;
register BOOLEAN got_parent;
char *tmpname;
SIGTYPE prevINT;
SIGTYPE prevQUIT;
DBUG_ENTER ("do_extract");
sig_push (&prevINT, &prevQUIT);
sig_catch ();
got_parent = dir_access (fip -> fname, A_EXISTS, FALSE);
if (!got_parent) {
makestat (&sbuf);
got_parent = makeparent (&sbuf, fip -> fname);
}
if (got_parent) {
if (IS_DIR (fip -> statp -> st_mode)) {
(VOID) makedir (fip);
attributes (fip);
} else if (LINKED (blkp) && (!IS_FLNK (fip -> statp -> st_mode)) ||
fip->statp->st_nlink>1 && (tmpname=getlinkname(fip)) &&
strcmp(fip->fname, tmpname)) {
/* make hard link if not a symlink, or a symlink with st_nlink>1
* and this is the 2nd thru nth instance seen of the hardlink
* to the symlink during the backup. */
makelink (blkp, fip);
} else if (!IS_REG (fip -> statp -> st_mode)) {
/*
* blkp and fip are passed down from scan, which will already
* set up the link name in fip, so makespecial can just pass
* it on if a symbolic link has to be made. In other words,
* we don't need to do any special checking for that here.
*/
makespecial (fip);
} else {
makefile (blkp, fip);
}
}
sig_pop (&prevINT, &prevQUIT);
if (interrupt) {
done ();
}
DBUG_VOID_RETURN;
}
/*
* FUNCTION
*
* makeparent make a parent directory that does not exist
*
* SYNOPSIS
*
* static BOOLEAN makeparent (statp, name)
* struct stat64 *statp;
* char *name;
*
* DESCRIPTION
*
* Given pointer to a directory pathname in "name" and
* pointer to stat buffer in "statp", attempts to make
* the parent directory if one does not already exist.
*
* Note that the installation is recursive. That is,
* if the parent of the parent does not exist, it is
* made also, with the same attributes.
*
*/
/*
* PSEUDO CODE
*
* Begin makeparent
* If parent already exists then
* Result is TRUE
* Else
* Find where parent and child names join.
* If no parent name
* Tell user about bug
* Result is FALSE
* Else
* Split parent and child names
* Attempt to make grandparent recursively
* If attempt successful then
* Build a file info struct for parent
* Make the parent
* End if
* Rejoin parent and child names
* End if
* End if
* Return result
* End makeparent
*
*/
static BOOLEAN makeparent (statp, name)
struct stat64 *statp;
char *name;
{
register char *slash;
register BOOLEAN got_dir;
auto struct finfo pfile;
DBUG_ENTER ("makeparent");
if (dir_access (name, A_EXISTS, FALSE)) {
got_dir = TRUE;
} else {
slash = s_strrchr (name, '/');
if (slash == NULL) {
bru_error (ERR_BUG, "makeparent");
got_dir = FALSE;
} else {
if(slash != name) {
*slash = EOS;
if(got_dir = makeparent (statp, name)) {
finfo_init (&pfile, name, statp);
got_dir = makedir (&pfile);
}
*slash = '/';
}
else /* makedir called directly later if it's a dir; if
it isn't, we definitely do not want to mkdir! */
got_dir = 1; /* but makeparent still has to return true */
}
}
DBUG_RETURN (got_dir);
}
/*
* FUNCTION
*
* makedir make a directory
*
* SYNOPSIS
*
* static BOOLEAN makedir (fip)
* register struct finfo *fip;
*
* DESCRIPTION
*
* Attempts to make a directory if one does not already exist.
*
* Note that it is assumed that the parent has already
* been made by a call to makeparent. If not, then
* makedir will fail if no parent exists. Also, we need to
* verify that the user running bru has appropriate permission
* to write into the parent of the directory to be made, rather
* than depending upon the newdir/mkdir calls to enforce
* permissions.
*
* Also note that the attributes are set ONLY if the directory
* is made. This is because makedir may be called to ensure
* that parent directories exist in order to extract an archived
* directory. If the attributes were unconditionally set,
* parents would take on the attributes of the child directory
* being extracted from the archive. The actual directory
* being extracted has it attributes explicitly set elsewhere.
*
*/
/*
* PSEUDO CODE
*
* Begin makedir
* If the directory already exists then
* Result is TRUE
* Else if we can write in parent to make directory then
* Attempt to make the directory
* If directory node successfully made then
* Set attributes of directory
* End if
* Else
* Doesn't exist and can't make it, result is FALSE
* End if
* Return result
* End makedir
*
*/
static BOOLEAN makedir (fip)
register struct finfo *fip;
{
register BOOLEAN result;
DBUG_ENTER ("makedir");
if (file_access (fip -> fname, A_EXISTS, FALSE)) {
result = TRUE;
} else {
/* idiotic program; don't check permissions, just
* try to make the directory. */
result = newdir (fip);
if (result) {
attributes (fip);
}
}
DBUG_RETURN (result);
}
/*
* FUNCTION
*
* makestat make a default stat buffer
*
* SYNOPSIS
*
* static VOID makestat (statp)
* struct stat64 *statp;
*
* DESCRIPTION
*
* Makes a default stat buffer as appropriate for current user.
* This is typically used to set attributes of directories which
* must be made to install a file being extracted.
*
*/
/*
* PSEUDO CODE
*
* Begin makestat
* Get current time
* Get the mode word mask
* Restore the mode word mask
* Get the file mode and make it a directory
* Initialize the stat buffer mode
* Initialize the user id
* Initialize the group id
* Initialize the access time
* Initialize the modification time
* End makestat
*
*/
static VOID makestat (statp)
struct stat64 *statp;
{
register int mask;
register time_t now;
DBUG_ENTER ("makestat");
now = (time_t) s_time ((long *) 0);
mask = s_umask (0);
(VOID) s_umask (mask);
statp -> st_mode = (ushort) (S_IFDIR | (DIR_MAGIC & ~mask));
statp -> st_uid = info.bru_uid;
statp -> st_gid = info.bru_gid;
statp -> st_atime = now;
statp -> st_mtime = now;
DBUG_VOID_RETURN;
}