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