1 #ifndef LINT
2 /* derived from: zooadd2.c 2.14 88/01/27 10:40:32 */
3 static char sccsid[]="$Id: zooadd2.c,v 1.5 91/07/04 13:33:55 dhesi Exp $";
4 #endif /* LINT */
5 
6 /*
7 Copyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
8 (C) Copyright 1988 Rahul Dhesi -- All rights reserved
9 */
10 #include "options.h"
11 #include "zoo.h"
12 #ifndef	OK_STDIO
13 #include <stdio.h>
14 #define	OK_STDIO
15 #endif
16 #include "various.h"
17 #include "zooio.h"
18 #include "zoofns.h"
19 #include "errors.i"
20 #include "assert.h"
21 #include "debug.h"
22 #include "parse.h"
23 
24 /*
25 Miscellaneous routines to support zooadd().
26 */
27 
28 /****************
29 This function is called with zoo_file positioned to the first
30 directory entry in an archive.  It skips past all existing files,
31 counts the number of deleted files, saves the latest data and time
32 encountered, and adds all filenames encountered to a global list. The
33 long filename is added if available, else the MSDOS filename is
34 added.
35 */
36 
skip_files(zoo_file,latest_date,latest_time,delcount,latest_name,latest_pos)37 void skip_files (zoo_file, latest_date, latest_time, delcount,
38                   latest_name, latest_pos)
39 ZOOFILE zoo_file;
40 unsigned int *latest_date, *latest_time;
41 int *delcount;
42 char latest_name[];
43 long *latest_pos;
44 {
45    long save_offset, next_ptr;
46    struct direntry direntry;
47    struct direntry *drp = &direntry;
48 
49    *latest_pos = 0L;
50    do {
51       /* read a directory entry */
52       save_offset = zootell (zoo_file);     /* save pos'n of this dir entry */
53       readdir (&direntry, zoo_file, 1);   /* read directory entry */
54       if (drp->next == 0L) {                 /* END OF CHAIN */
55          zooseek (zoo_file, save_offset, 0);      /* back up */
56          break;                                 /* EXIT on end of chain */
57       } else
58          *latest_pos = save_offset;
59       /* remember most recent date and time, for files not marked deleted */
60       if (!drp->deleted)
61          if (drp->date > *latest_date ||
62             (drp->date == *latest_date && drp->time > *latest_time)) {
63                *latest_date = drp->date;
64                *latest_time = drp->time;
65          }
66       next_ptr = drp->next;            /* ptr to next dir entry */
67       if (drp->deleted)
68          ++(*delcount);                      /* count deleted entries */
69       /* add name of file and position of direntry into global list */
70       /* but only if the entry is not deleted */
71       if (!drp->deleted) {
72 #ifdef FOLD
73 			/* IS THIS REALLY NEEDED?  IF SO, WHAT ABOUT drp->lfname? */
74          str_lwr(drp->fname);
75 #endif
76 			/* add full pathname to global list */
77 			strcpy (latest_name, fullpath (drp));
78          addfname (latest_name, save_offset, drp->date, drp->time,
79 							drp->vflag, drp->version_no);
80       }
81       zooseek (zoo_file, next_ptr, 0);   /* ..seek to next dir entry */
82    } while (next_ptr != 0L);              /* loop terminates on null ptr */
83 }
84 
85 /*******************/
86 /* kill_files() deletes all files in the supplied list of pointers to
87 filenames */
88 
kill_files(flist,pathlength)89 int kill_files (flist, pathlength)
90 char *flist[];                      /* list of ptrs to input fnames */
91 int pathlength;                     /* length of longest pathname */
92 {
93    int status = 0;
94    int fptr;
95    prterror ('M', "-----\nErasing added files...\n");
96    for (fptr = 0;  flist[fptr] != NULL; fptr++) {
97 #ifdef CHEKUDIR
98 				if (isuadir(flist[fptr]))
99 					continue;
100 #else /* CHEKUDIR */
101 # ifdef CHEKDIR
102 				if (isfdir(flist[fptr]))
103 					continue;
104 # endif /* CHEKDIR */
105 #endif /* CHEKUDIR */
106       prterror ('m', "%-*s -- ", pathlength, flist[fptr]);
107       if (unlink (flist[fptr]) == 0) {
108          prterror ('M', "erased\n");
109       } else {
110          prterror ('w', "Could not erase %s.\n", flist[fptr]);
111          status = 1;
112       }
113    }
114    return (status);
115 }
116 
117 #ifndef PORTABLE
118 /*******************/
copyfields(drp,thp)119 void copyfields (drp, thp)
120 struct direntry *drp;
121 struct tiny_header *thp;
122 {
123    drp->org_size = thp->org_size;
124    drp->file_crc = thp->file_crc;
125    drp->size_now = thp->size_now;
126    drp->major_ver = thp->major_ver;
127    drp->minor_ver = thp->minor_ver;
128 }
129 #endif
130 
131 /*******************/
132 /* processes option switches for zooadd() */
opts_add(option,zootime,quiet,suppress,move,new,pack,update,add_comment,z_fmt,need_dir,inargs,genson,use_lzh,arch_cmnt)133 void opts_add (option, zootime, quiet, suppress, move, new, pack,
134           update, add_comment, z_fmt, need_dir, inargs, genson,
135 			 use_lzh, arch_cmnt)
136 char *option;
137 int *zootime, *quiet, *suppress, *move, *new, *pack,
138    *update, *add_comment, *z_fmt, *need_dir, *inargs,
139 	*genson, *use_lzh, *arch_cmnt;
140 
141 {
142    if (*option == 'T') {
143       (*zootime)++;
144       option++;
145       while (*option) {
146          switch (*option) {
147             case 'q': (*quiet)++; break;
148             default:
149                prterror ('f', inv_option, *option);
150          }
151       option++;
152       }
153    }
154 
155    while (*option) {
156       switch (*option) {
157          case 'a': break;
158 			case 'h': (*use_lzh)++; break;         /* use lzh compression */
159          case 'f': (*suppress)++; break;        /* suppress compression */
160          case 'M': (*move)++; break;            /* delete files after adding them */
161          case 'n': (*new)++; break;             /* add only files not in archive */
162          case 'P': (*pack)++; break;            /* pack after adding */
163          case 'u': (*update)++;   break;        /* add only files already in archive */
164          case 'q': (*quiet)++; break;           /* be quiet */
165          case 'c': (*add_comment)++; break;     /* add comment */
166          case ':': *need_dir = 0; break;        /* don't store directories */
167          case 'I': (*inargs)++; break;        	/* get filenames from stdin */
168          case 'C': (*arch_cmnt)++; break;			/* do an archive comment */
169 /* #ifdef PORTABLE */ /* avoid Turbo C warning about unused param */
170          case 'z': (*z_fmt)++; break;           /* look for Z format files */
171 /* #endif */
172 			case '+':
173 						*genson = 1;  break;
174 			case '-':
175 						*genson = 0;  break;
176          default:
177             prterror ('f', inv_option, *option);
178       }
179       option++;
180    } /* end while */
181 	if (*suppress && *use_lzh)
182 		prterror ('f', "\"f\" and \"h\" can't both be used\n");
183 }
184 
185 /*
186 Stores long filename into direntry.lfname iff it is different from MSDOS
187 filename.  Also stores directory name if need_dir is true.  Moved out of
188 zooadd() so zooadd() doesn't get too big for optimization.
189 */
storefname(direntry,this_path,need_dir)190 void storefname (direntry, this_path, need_dir)
191 struct direntry *direntry;
192 char *this_path;
193 int need_dir;
194 {
195    struct path_st path_st;
196    parse (&path_st, this_path);
197    direntry->lfname[0] = '\0';
198    direntry->namlen = 0;
199 #ifdef SPECMOD
200    specfname (path_st.lfname);
201    specdir (path_st.dir);
202 #endif
203    if (strcmp(path_st.lfname,direntry->fname) != 0) {
204          strcpy (direntry->lfname, path_st.lfname); /* full filename */
205          direntry->namlen = strlen(direntry->lfname) + 1;
206    }
207    if (need_dir) {
208       strcpy (direntry->dirname, path_st.dir);   /* directory name */
209       direntry->dirlen = strlen(direntry->dirname) + 1;
210       if (direntry->dirlen == 1) /* don't store trailing null alone */
211          direntry->dirlen = 0;
212    } else {
213       direntry->dirname[0] = '\0';
214       direntry->dirlen = 0;
215    }
216 }
217 
218 /*
219 Function getsdtin() gets a pathname from standard input, cleans
220 it if necessary by removing any following blanks/tabs and other
221 junk, and returns it in a static area that is overwritten by each
222 call.
223 */
getstdin()224 char *getstdin()
225 {
226 	char *chptr;									/* temp pointer */
227 	static char tempname[PATHSIZE];
228 	do {
229 		if (fgets (tempname, PATHSIZE, stdin) == NULL)
230 			return (NULL);
231 		/* remove trailing blank, tab, newline */
232 		for (chptr = tempname; *chptr != '\0';  chptr++) {
233 			if (
234 	/* PURIFY means remove trailing blanks/tabs and all subsequent chars */
235 #ifdef PURIFY
236 					*chptr == '\t' || *chptr == ' ' ||
237 #endif
238 					*chptr == '\n'						/* always remove trailing \n */
239 				)
240 			{
241 
242 				*chptr = '\0';
243 				break;
244 			}
245 		}
246 	} while (*tempname == '\0');				/* get a nonempty line */
247 #ifdef FOLD
248 	str_lwr (tempname);
249 #endif
250 	return (tempname);
251 }
252 
253 /*
254 Function newdir() adds some default information to a directory entry.
255 This will be a new directory entry added to an archive.
256 */
newdir(direntry)257 void newdir (direntry)
258 register struct direntry *direntry;
259 {
260 #ifdef GETTZ
261 	long mstonix();
262 	long gettz();
263 	long t;
264 #endif
265    direntry->zoo_tag = ZOO_TAG;
266    direntry->type = 2;                  /* type is now 2 */
267 #ifdef GETTZ
268 	t = mstonix (direntry->date, direntry->time);
269 	direntry->tz = gettz(t) / (15 * 60); /* seconds => 15-min units */
270 #else
271    direntry->tz = NO_TZ;                /* timezone unknown */
272 #endif
273    direntry->struc = 0;                 /* unstructured file */
274    direntry->system_id = SYSID_NIX;     /* identify **IX filesystem */
275 	direntry->vflag = VFL_ON|VFL_LAST;	 /* latest version */
276 	direntry->version_no = 1;					/* begin with version 1 */
277 	/* 1 for namlen, 1 for dirlen, 2 for system id, 3 for attributes,
278 		1 for version flag and 2 for version number */
279    direntry->var_dir_len = direntry->dirlen + direntry->namlen + 10;
280 }
281