⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zooadd.c

📁 一个很好的压缩与解压程序
💻 C
📖 第 1 页 / 共 2 页
字号:
#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 + -