📄 zooadd.c
字号:
#ifndef LINT
/* derived from: zooadd.c 2.34 88/08/15 10:53:11 */
static char sccsid[]="$Source: /usr/home/dhesi/zoo/RCS/zooadd.c,v $\n\
$Id: zooadd.c,v 1.10 91/07/08 23:48:39 dhesi Exp $";
#endif /* LINT */
/*
Copyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
(C) Copyright 1988 Rahul Dhesi -- All rights reserved
(C) Copyright 1991 Rahul Dhesi -- All rights reserved
*/
#include "options.h"
/* Adds files specified in parameter-list to archive zoo_path. */
#define LONGEST 20 /* assumed length of longest filename */
#include "zoomem.h" /* to define MAXADD */
#include "zoo.h"
#include "zooio.h"
#include "various.h"
#include "parse.h"
#include "debug.h"
#include "portable.h"
#include "zoofns.h"
#include "errors.i"
extern int break_hit;
extern int quiet;
void show_comment PARMS ((struct direntry *, ZOOFILE, int, char *));
void dosname PARMS ((char *, char *));
void modpath PARMS ((char *));
void opts_add PARMS ((char *, int *, int *, int *, int *, int *, int *,
int *, int *, int *, int *, int *, int *, int *, int *));
int ver_too_high PARMS ((struct zoo_header *));
void get_comment PARMS ((struct direntry *, ZOOFILE, char *));
void copyfields PARMS ((struct direntry *, struct tiny_header *));
void storefname PARMS ((struct direntry *, char *, int));
char *choosefname PARMS ((struct direntry *));
extern struct zoo_header zoo_header;
extern char file_leader[];
extern unsigned int crccode;
void zooadd(zoo_path, argc, argv, option)
char *zoo_path; /* pathname of zoo archive to add to */
int argc; /* how many filespecs supplied */
char **argv; /* array of pointers to filespecs */
char *option; /* option string */
{
char *whichname; /* which name to show user */
char **flist; /* list of ptrs to input fnames */
int fptr; /* will point to within flist */
ZOOFILE this_file; /* file to add */
char zoo_fname[LFNAMESIZE]; /* basename of archive itself */
char zoo_bak[LFNAMESIZE]; /* name of archive's backup */
char this_fname[LFNAMESIZE]; /* just filename of file to add */
char latest_name[LFNAMESIZE]; /* latest name in archive */
long last_old = 0L; /* last direntry in old chain */
ZOOFILE zoo_file; /* stream for open archive */
char *this_path; /* pathname of file to add */
#ifdef NOENUM
#define NEW_ZOO 1
#define OLD_ZOO 2
int zoo_status;
#else
enum {NEW_ZOO, OLD_ZOO} zoo_status; /* newly created or not */
#endif
long this_dir_offset; /* pointers to within archive */
long save_position; /* pointer to within archive */
long prev_pos; /* posn of prev file of same name */
struct direntry direntry; /* directory entry */
struct direntry dir2entry; /* spare */
int status; /* error status */
int success; /* successful addition of file? */
int addcount = 0; /* number added */
int update=0; /* only files already in archive */
int suppress=0; /* suppress compression */
int new=0; /* add only files not in archive */
int zootime = 0; /* just set archive time */
int add_comment = 0; /* add comment */
int add_global_comment = 0; /* archive comment */
int pack = 0; /* pack after adding */
int need_dir = 1; /* store directories too */
int delcount = 0; /* count of deleted entries */
int exit_status = 0; /* exit status to set */
unsigned int latest_date = 0; /* to set time on archive itself */
unsigned int latest_time = 0; /* .. same */
int move = 0; /* delete after adding to archive */
int longest; /* length of longest pathname added */
int firstfile = 1; /* first file being added? */
int z_fmt = 0; /* look for Z format files? */
int inargs = 0; /* read filenames from stdin? */
#ifndef PORTABLE
struct tiny_header tiny_header; /* for Z format archives */
#endif
unsigned this_version_no; /* version no. of old file */
unsigned high_vflag; /* version flag of old file */
unsigned high_version_no; /* highest version no of this file */
long high_pos; /* offset of file w/highest ver no */
unsigned int fgens; /* gens. to preserve -- file */
unsigned int zgens; /* gens. to preserve -- archive */
long oldcmtpos; /* to save old comment */
unsigned int oldcmtsiz; /* to save old comment */
int genson = 0; /* whether to turn generations on */
int use_lzh = 0; /* whether to use lzh compression */
/* on entry option points to first letter */
opts_add (option, &zootime, &quiet, &suppress, &move, &new, &pack,
&update, &add_comment, &z_fmt, &need_dir, &inargs, &genson,
&use_lzh, &add_global_comment);
/* POSSIBLE RACE CONDITION BETWEEN TESTING EXISTENCE AND CREATING FILE */
if (exists (zoo_path)) {
zoo_file = zooopen (zoo_path, Z_RDWR);
zoo_status = OLD_ZOO;
} else {
if (!zootime)
zoo_file = zoocreate (zoo_path);
else
zoo_file = NOFILE; /* don't create if just setting time */
zoo_status = NEW_ZOO;
}
if (zoo_file == NOFILE)
prterror ('f', could_not_open, zoo_path);
basename(zoo_path, zoo_fname); /* get basename of archive */
rootname (zoo_path, zoo_bak); /* name without extension */
strcat (zoo_bak, BACKUP_EXT); /* name of backup of this archive */
/* Now we prepare the archive for adding one or more files. If the archive
has just been created, we write the archive header */
addfname ("",0L,0,0,0,0); /* initialize table of files already in archive */
if (zoo_status == NEW_ZOO) { /* newly-created archive */
if (genson) /* if no generations needed */
zoo_header.vdata = (VFL_ON|GEN_DEFAULT); /* generations on */
fwr_zooh (&zoo_header, zoo_file);
zgens = GEN_DEFAULT;
zooseek (zoo_file, zoo_header.zoo_start, 0); /* seek to where data begins */
} else {
/* read header and rewrite with updated version numbers, preserving
header type */
rwheader (&zoo_header, zoo_file, 1);
zgens = zoo_header.vdata & VFL_GEN; /* get archive generations */
/* initialize latest_name to null string */
/* NOTE: latest_name is not currently used for anything, but
may be used in the future for inserting files into the
archive in alphabetic order. */
*latest_name = '\0';
/* Skip existing files but add them to a list. The variable last_old
gets the tail of the old chain of directory entries */
skip_files (zoo_file, &latest_date, &latest_time, &delcount,
latest_name, &last_old);
}
/* The file pointer is now positioned correctly to add a file to archive,
unless the null directory entry is too short. This will be fixed below. */
/* If we are just setting time, do it and run. */
if (zootime) {
#ifdef NIXTIME
zooclose (zoo_file);
setutime (zoo_path, latest_date, latest_time);
#else
settime (zoo_file, latest_date, latest_time);
zooclose (zoo_file);
#endif
prterror ('m', "Archive time adjusted.\n");
zooexit (0);
}
/* make list of files, excluding archive and its backup */
longest = LONGEST;
flist = (char **) ealloc(MAXADD);
if (!inargs) {
makelist(argc, argv, flist, MAXADD-2, zoo_fname, zoo_bak, ".", &longest);
/* ^^ ^^ ^^ exclude */
}
fptr = 0; /* ready to get filename (if makelist() was called) or to
begin adding filenames (if reading them from stdin) */
while (1) {
unsigned int this_date, this_time;
int INLIST; /* boolean */
int RECENT; /* boolean */
int danger; /* if update requested and disk copy is out of date */
if (inargs) {
again: /* loop back if filename was same as archive name or its backup */
this_path = getstdin(); /* pathname from stdin, in static area */
if (this_path != NULL) {
if (samefile (nameptr(zoo_fname),nameptr(this_path)) ||
samefile (nameptr(zoo_bak),nameptr(this_path)))
goto again; /* don't add archive to itself */
modpath (this_path);
/* if moving files, add to list for later deletion; if list overflows,
terminate addition loop and give warning message */
if (move) {
if (fptr >= MAXADD-2) {
prterror ('w', too_many_files, MAXADD-2);
this_path = NULL;
} else
flist[fptr++] = str_dup (this_path);
}
}
} else {
this_path = flist[fptr++];
}
/* exit the addition loop when no more pathnames are left */
if (this_path == NULL) {
/* in case stdin was being read, make sure flist is NULL-terminated */
flist[fptr] = NULL;
break;
}
basename (this_path, this_fname); /* get just filename for later */
this_file = zooopen(this_path, Z_READ);
if (this_file == NOFILE) {
prterror ('e', could_not_open, this_path);
exit_status++;
continue;
}
#ifndef PORTABLE
/* Test to see if this is a Z format file. We assume the file is Z format
if (a) tag is correct and (b) type is 1 and (c) embedded filename
is not longer than FNAMESIZE.
*/
if (z_fmt) {
zooread (this_file, (char *) &tiny_header, sizeof(tiny_header));
if (tiny_header.tinytag == TINYTAG && tiny_header.type == 1 &&
strlen (tiny_header.fname) <= FNAMESIZE)
/* ok */ ;
else {
zooclose (this_file);
prterror ('e', "File %s does not have Z format.\n", this_fname);
exit_status++;
continue;
}
}
#endif
/* get file time; also fix name */
#ifndef PORTABLE
if (z_fmt) {
direntry.date = tiny_header.date;
direntry.time = tiny_header.time;
strcpy (direntry.fname, tiny_header.fname);
direntry.dirlen = direntry.namlen = 0;
} else {
#endif
/* Get timstamp of file being added */
#ifdef GETUTIME
getutime (this_path, &direntry.date, &direntry.time);
#else
gettime (this_file, &direntry.date, &direntry.time);
#endif
/* save file attributes */
#ifdef FATTR
/* we expect getfattr() to set all attr. bits; currently
only the portable format is recognized */
{
# ifdef FATTR_FNAME
unsigned long getfattr PARMS ((char *);
direntry.fattr = getfattr (this_path);
# else
unsigned long getfattr PARMS ((ZOOFILE));
direntry.fattr = getfattr (this_file);
# endif /* FATTR_FNAME */
}
#else
direntry.fattr = NO_FATTR; /* none */
#endif /* FATTR */
#ifdef FOLD
str_lwr(this_fname);
#endif
dosname (this_fname, direntry.fname); /* MSDOS filename */
/*
Store long filename into direntry.lfname iff it is different from MSDOS
filename. Also store directory name if need_dir is true. Moved out of
zooadd() so zooadd() doesn't get too big for optimization.
*/
storefname (&direntry, this_path, need_dir);
#ifndef PORTABLE
}
#endif
#ifdef DEBUG
printf ("zooadd: direntry.lfname = [%s] direntry.dirname = [%s]\n",
direntry.lfname, direntry.dirname);
#endif
/* if update option, then we add file if it is already in the archive
AND the archived file is older */
/* The following logic was derived from a Karnaugh map so it may
be hard to understand. Essentially, if U=update requested,
N=new files requested, I=file is already in archive, and
R=file being archived is more recent than file already in
archive, then the boolean equation is:
add = U' (N' + I') + U (IR + I'N)
*/
/* Get the filename to use for this addition. */
whichname = choosefname(&direntry);
/* Get position in archive of any old file of same name, ignoring
any directory prefix if need_dir is not true. Also get its
date, time, version flag, and version number. */
prev_pos = inlist (fullpath (&direntry), &this_date, &this_time,
&this_version_no, &high_vflag, &high_version_no,
&high_pos, !need_dir);
/* define DBG_INLIST for debugging by printing values returned by inlist() */
#ifdef DBG_INLIST
printf ("FROM inlist(): prev_pos=%ld, high_pos=%ld\n", prev_pos, high_pos);
printf ("this_version_no=%u, high_vflag=%4x, high_version_no=%u\n",
this_version_no, high_vflag, high_version_no);
#endif
INLIST = prev_pos > 0; /* already in archive if positive value */
if (INLIST) {
int result;
result = cmpnum (direntry.date, direntry.time, this_date, this_time);
RECENT = result > 0;
danger = result < 0;
} else
danger = 0; /* And RECENT is undefined and should not be used */
if (
!update && (!new || !INLIST) ||
update && (INLIST && RECENT || !INLIST && new)
)
; /* then continue and add file */
else {
if (update && danger)
prterror ('w', "Archived copy of %s is newer.\n", whichname);
zooclose (this_file);
continue; /* cycle back, skip this file */
}
#ifdef CHEKDIR
/* Don't add if this is a directory */
if (isadir (this_file)) {
zooclose (this_file);
continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -