sel_subs.c revision 1.4 1 1.1 jtc /*-
2 1.1 jtc * Copyright (c) 1992 Keith Muller.
3 1.1 jtc * Copyright (c) 1992, 1993
4 1.1 jtc * The Regents of the University of California. All rights reserved.
5 1.1 jtc *
6 1.1 jtc * This code is derived from software contributed to Berkeley by
7 1.1 jtc * Keith Muller of the University of California, San Diego.
8 1.1 jtc *
9 1.1 jtc * Redistribution and use in source and binary forms, with or without
10 1.1 jtc * modification, are permitted provided that the following conditions
11 1.1 jtc * are met:
12 1.1 jtc * 1. Redistributions of source code must retain the above copyright
13 1.1 jtc * notice, this list of conditions and the following disclaimer.
14 1.1 jtc * 2. Redistributions in binary form must reproduce the above copyright
15 1.1 jtc * notice, this list of conditions and the following disclaimer in the
16 1.1 jtc * documentation and/or other materials provided with the distribution.
17 1.1 jtc * 3. All advertising materials mentioning features or use of this software
18 1.1 jtc * must display the following acknowledgement:
19 1.1 jtc * This product includes software developed by the University of
20 1.1 jtc * California, Berkeley and its contributors.
21 1.1 jtc * 4. Neither the name of the University nor the names of its contributors
22 1.1 jtc * may be used to endorse or promote products derived from this software
23 1.1 jtc * without specific prior written permission.
24 1.1 jtc *
25 1.1 jtc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 1.1 jtc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 1.1 jtc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 1.1 jtc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 1.1 jtc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 1.1 jtc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 1.1 jtc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 1.1 jtc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 1.1 jtc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 1.1 jtc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 1.1 jtc * SUCH DAMAGE.
36 1.1 jtc */
37 1.1 jtc
38 1.1 jtc #ifndef lint
39 1.2 jtc /*static char sccsid[] = "from: @(#)sel_subs.c 8.1 (Berkeley) 5/31/93";*/
40 1.4 mycroft static char *rcsid = "$Id: sel_subs.c,v 1.4 1994/09/23 11:35:11 mycroft Exp $";
41 1.1 jtc #endif /* not lint */
42 1.1 jtc
43 1.1 jtc #include <sys/types.h>
44 1.1 jtc #include <sys/time.h>
45 1.1 jtc #include <sys/stat.h>
46 1.1 jtc #include <sys/param.h>
47 1.1 jtc #include <pwd.h>
48 1.1 jtc #include <grp.h>
49 1.1 jtc #include <stdio.h>
50 1.1 jtc #include <ctype.h>
51 1.1 jtc #include <string.h>
52 1.1 jtc #include <strings.h>
53 1.1 jtc #include <unistd.h>
54 1.1 jtc #include <stdlib.h>
55 1.1 jtc #include "pax.h"
56 1.1 jtc #include "sel_subs.h"
57 1.1 jtc #include "extern.h"
58 1.1 jtc
59 1.1 jtc static int str_sec __P((register char *, time_t *));
60 1.1 jtc static int usr_match __P((register ARCHD *));
61 1.1 jtc static int grp_match __P((register ARCHD *));
62 1.1 jtc static int trng_match __P((register ARCHD *));
63 1.1 jtc
64 1.1 jtc static TIME_RNG *trhead = NULL; /* time range list head */
65 1.1 jtc static TIME_RNG *trtail = NULL; /* time range list tail */
66 1.1 jtc static USRT **usrtb = NULL; /* user selection table */
67 1.1 jtc static GRPT **grptb = NULL; /* group selection table */
68 1.1 jtc
69 1.1 jtc /*
70 1.1 jtc * Routines for selection of archive members
71 1.1 jtc */
72 1.1 jtc
73 1.1 jtc /*
74 1.1 jtc * sel_chk()
75 1.1 jtc * check if this file matches a specfied uid, gid or time range
76 1.1 jtc * Return:
77 1.1 jtc * 0 if this archive member should be processed, 1 if it should be skipped
78 1.1 jtc */
79 1.1 jtc
80 1.1 jtc #if __STDC__
81 1.1 jtc int
82 1.1 jtc sel_chk(register ARCHD *arcn)
83 1.1 jtc #else
84 1.1 jtc int
85 1.1 jtc sel_chk(arcn)
86 1.1 jtc register ARCHD *arcn;
87 1.1 jtc #endif
88 1.1 jtc {
89 1.1 jtc if (((usrtb != NULL) && usr_match(arcn)) ||
90 1.1 jtc ((grptb != NULL) && grp_match(arcn)) ||
91 1.1 jtc ((trhead != NULL) && trng_match(arcn)))
92 1.1 jtc return(1);
93 1.1 jtc return(0);
94 1.1 jtc }
95 1.1 jtc
96 1.1 jtc /*
97 1.1 jtc * User/group selection routines
98 1.1 jtc *
99 1.1 jtc * Routines to handle user selection of files based on the file uid/gid. To
100 1.1 jtc * add an entry, the user supplies either then name or the uid/gid starting with
101 1.1 jtc * a # on the command line. A \# will eascape the #.
102 1.1 jtc */
103 1.1 jtc
104 1.1 jtc /*
105 1.1 jtc * usr_add()
106 1.1 jtc * add a user match to the user match hash table
107 1.1 jtc * Return:
108 1.1 jtc * 0 if added ok, -1 otherwise;
109 1.1 jtc */
110 1.1 jtc
111 1.1 jtc #if __STDC__
112 1.1 jtc int
113 1.1 jtc usr_add(register char *str)
114 1.1 jtc #else
115 1.1 jtc int
116 1.1 jtc usr_add(str)
117 1.1 jtc register char *str;
118 1.1 jtc #endif
119 1.1 jtc {
120 1.1 jtc register u_int indx;
121 1.1 jtc register USRT *pt;
122 1.1 jtc register struct passwd *pw;
123 1.1 jtc register uid_t uid;
124 1.1 jtc
125 1.1 jtc /*
126 1.1 jtc * create the table if it doesn't exist
127 1.1 jtc */
128 1.1 jtc if ((str == NULL) || (*str == '\0'))
129 1.1 jtc return(-1);
130 1.1 jtc if ((usrtb == NULL) &&
131 1.1 jtc ((usrtb = (USRT **)calloc(USR_TB_SZ, sizeof(USRT *))) == NULL)) {
132 1.1 jtc warn(1, "Unable to allocate memory for user selection table");
133 1.1 jtc return(-1);
134 1.1 jtc }
135 1.1 jtc
136 1.1 jtc /*
137 1.1 jtc * figure out user spec
138 1.1 jtc */
139 1.1 jtc if (str[0] != '#') {
140 1.1 jtc /*
141 1.1 jtc * it is a user name, \# escapes # as first char in user name
142 1.1 jtc */
143 1.1 jtc if ((str[0] == '\\') && (str[1] == '#'))
144 1.1 jtc ++str;
145 1.1 jtc if ((pw = getpwnam(str)) == NULL) {
146 1.1 jtc warn(1, "Unable to find uid for user: %s", str);
147 1.1 jtc return(-1);
148 1.1 jtc }
149 1.1 jtc uid = (uid_t)pw->pw_uid;
150 1.1 jtc } else
151 1.1 jtc # ifdef NET2_STAT
152 1.1 jtc uid = (uid_t)atoi(str+1);
153 1.1 jtc # else
154 1.1 jtc uid = (uid_t)strtoul(str+1, (char **)NULL, 10);
155 1.1 jtc # endif
156 1.1 jtc endpwent();
157 1.1 jtc
158 1.1 jtc /*
159 1.1 jtc * hash it and go down the hash chain (if any) looking for it
160 1.1 jtc */
161 1.1 jtc indx = ((unsigned)uid) % USR_TB_SZ;
162 1.1 jtc if ((pt = usrtb[indx]) != NULL) {
163 1.1 jtc while (pt != NULL) {
164 1.1 jtc if (pt->uid == uid)
165 1.1 jtc return(0);
166 1.1 jtc pt = pt->fow;
167 1.1 jtc }
168 1.1 jtc }
169 1.1 jtc
170 1.1 jtc /*
171 1.1 jtc * uid is not yet in the table, add it to the front of the chain
172 1.1 jtc */
173 1.1 jtc if ((pt = (USRT *)malloc(sizeof(USRT))) != NULL) {
174 1.1 jtc pt->uid = uid;
175 1.1 jtc pt->fow = usrtb[indx];
176 1.1 jtc usrtb[indx] = pt;
177 1.1 jtc return(0);
178 1.1 jtc }
179 1.1 jtc warn(1, "User selection table out of memory");
180 1.1 jtc return(-1);
181 1.1 jtc }
182 1.1 jtc
183 1.1 jtc /*
184 1.1 jtc * usr_match()
185 1.1 jtc * check if this files uid matches a selected uid.
186 1.1 jtc * Return:
187 1.1 jtc * 0 if this archive member should be processed, 1 if it should be skipped
188 1.1 jtc */
189 1.1 jtc
190 1.1 jtc #if __STDC__
191 1.1 jtc static int
192 1.1 jtc usr_match(register ARCHD *arcn)
193 1.1 jtc #else
194 1.1 jtc static int
195 1.1 jtc usr_match(arcn)
196 1.1 jtc register ARCHD *arcn;
197 1.1 jtc #endif
198 1.1 jtc {
199 1.1 jtc register USRT *pt;
200 1.1 jtc
201 1.1 jtc /*
202 1.1 jtc * hash and look for it in the table
203 1.1 jtc */
204 1.1 jtc pt = usrtb[((unsigned)arcn->sb.st_uid) % USR_TB_SZ];
205 1.1 jtc while (pt != NULL) {
206 1.1 jtc if (pt->uid == arcn->sb.st_uid)
207 1.1 jtc return(0);
208 1.1 jtc pt = pt->fow;
209 1.1 jtc }
210 1.1 jtc
211 1.1 jtc /*
212 1.1 jtc * not found
213 1.1 jtc */
214 1.1 jtc return(1);
215 1.1 jtc }
216 1.1 jtc
217 1.1 jtc /*
218 1.1 jtc * grp_add()
219 1.1 jtc * add a group match to the group match hash table
220 1.1 jtc * Return:
221 1.1 jtc * 0 if added ok, -1 otherwise;
222 1.1 jtc */
223 1.1 jtc
224 1.1 jtc #if __STDC__
225 1.1 jtc int
226 1.1 jtc grp_add(register char *str)
227 1.1 jtc #else
228 1.1 jtc int
229 1.1 jtc grp_add(str)
230 1.1 jtc register char *str;
231 1.1 jtc #endif
232 1.1 jtc {
233 1.1 jtc register u_int indx;
234 1.1 jtc register GRPT *pt;
235 1.1 jtc register struct group *gr;
236 1.1 jtc register gid_t gid;
237 1.1 jtc
238 1.1 jtc /*
239 1.1 jtc * create the table if it doesn't exist
240 1.1 jtc */
241 1.1 jtc if ((str == NULL) || (*str == '\0'))
242 1.1 jtc return(-1);
243 1.1 jtc if ((grptb == NULL) &&
244 1.1 jtc ((grptb = (GRPT **)calloc(GRP_TB_SZ, sizeof(GRPT *))) == NULL)) {
245 1.1 jtc warn(1, "Unable to allocate memory fo group selection table");
246 1.1 jtc return(-1);
247 1.1 jtc }
248 1.1 jtc
249 1.1 jtc /*
250 1.1 jtc * figure out user spec
251 1.1 jtc */
252 1.1 jtc if (str[0] != '#') {
253 1.1 jtc /*
254 1.1 jtc * it is a group name, \# escapes # as first char in group name
255 1.1 jtc */
256 1.1 jtc if ((str[0] == '\\') && (str[1] == '#'))
257 1.1 jtc ++str;
258 1.1 jtc if ((gr = getgrnam(str)) == NULL) {
259 1.1 jtc warn(1,"Cannot determine gid for group name: %s", str);
260 1.1 jtc return(-1);
261 1.1 jtc }
262 1.1 jtc gid = (gid_t)gr->gr_gid;
263 1.1 jtc } else
264 1.1 jtc # ifdef NET2_STAT
265 1.1 jtc gid = (gid_t)atoi(str+1);
266 1.1 jtc # else
267 1.1 jtc gid = (gid_t)strtoul(str+1, (char **)NULL, 10);
268 1.1 jtc # endif
269 1.1 jtc endgrent();
270 1.1 jtc
271 1.1 jtc /*
272 1.1 jtc * hash it and go down the hash chain (if any) looking for it
273 1.1 jtc */
274 1.1 jtc indx = ((unsigned)gid) % GRP_TB_SZ;
275 1.1 jtc if ((pt = grptb[indx]) != NULL) {
276 1.1 jtc while (pt != NULL) {
277 1.1 jtc if (pt->gid == gid)
278 1.1 jtc return(0);
279 1.1 jtc pt = pt->fow;
280 1.1 jtc }
281 1.1 jtc }
282 1.1 jtc
283 1.1 jtc /*
284 1.1 jtc * gid not in the table, add it to the front of the chain
285 1.1 jtc */
286 1.1 jtc if ((pt = (GRPT *)malloc(sizeof(GRPT))) != NULL) {
287 1.1 jtc pt->gid = gid;
288 1.1 jtc pt->fow = grptb[indx];
289 1.1 jtc grptb[indx] = pt;
290 1.1 jtc return(0);
291 1.1 jtc }
292 1.1 jtc warn(1, "Group selection table out of memory");
293 1.1 jtc return(-1);
294 1.1 jtc }
295 1.1 jtc
296 1.1 jtc /*
297 1.1 jtc * grp_match()
298 1.1 jtc * check if this files gid matches a selected gid.
299 1.1 jtc * Return:
300 1.1 jtc * 0 if this archive member should be processed, 1 if it should be skipped
301 1.1 jtc */
302 1.1 jtc
303 1.1 jtc #if __STDC__
304 1.1 jtc static int
305 1.1 jtc grp_match(register ARCHD *arcn)
306 1.1 jtc #else
307 1.1 jtc static int
308 1.1 jtc grp_match(arcn)
309 1.1 jtc register ARCHD *arcn;
310 1.1 jtc #endif
311 1.1 jtc {
312 1.1 jtc register GRPT *pt;
313 1.1 jtc
314 1.1 jtc /*
315 1.1 jtc * hash and look for it in the table
316 1.1 jtc */
317 1.1 jtc pt = grptb[((unsigned)arcn->sb.st_gid) % GRP_TB_SZ];
318 1.1 jtc while (pt != NULL) {
319 1.1 jtc if (pt->gid == arcn->sb.st_gid)
320 1.1 jtc return(0);
321 1.1 jtc pt = pt->fow;
322 1.1 jtc }
323 1.1 jtc
324 1.1 jtc /*
325 1.1 jtc * not found
326 1.1 jtc */
327 1.1 jtc return(1);
328 1.1 jtc }
329 1.1 jtc
330 1.1 jtc /*
331 1.1 jtc * Time range selection routines
332 1.1 jtc *
333 1.1 jtc * Routines to handle user selection of files based on the modification and/or
334 1.1 jtc * inode change time falling within a specified time range (the non-standard
335 1.1 jtc * -T flag). The user may specify any number of different file time ranges.
336 1.1 jtc * Time ranges are checked one at a time until a match is found (if at all).
337 1.1 jtc * If the file has a mtime (and/or ctime) which lies within one of the time
338 1.1 jtc * ranges, the file is selected. Time ranges may have a lower and/or a upper
339 1.1 jtc * value. These ranges are inclusive. When no time ranges are supplied to pax
340 1.1 jtc * with the -T option, all members in the archive will be selected by the time
341 1.1 jtc * range routines. When only a lower range is supplied, only files with a
342 1.1 jtc * mtime (and/or ctime) equal to or younger are selected. When only a upper
343 1.1 jtc * range is supplied, only files with a mtime (and/or ctime) equal to or older
344 1.1 jtc * are selected. When the lower time range is equal to the upper time range,
345 1.1 jtc * only files with a mtime (or ctime) of exactly that time are selected.
346 1.1 jtc */
347 1.1 jtc
348 1.1 jtc /*
349 1.1 jtc * trng_add()
350 1.1 jtc * add a time range match to the time range list.
351 1.1 jtc * This is a non-standard pax option. Lower and upper ranges are in the
352 1.1 jtc * format: [yy[mm[dd[hh]]]]mm[.ss] and are comma separated.
353 1.1 jtc * Time ranges are based on current time, so 1234 would specify a time of
354 1.1 jtc * 12:34 today.
355 1.1 jtc * Return:
356 1.1 jtc * 0 if the time range was added to the list, -1 otherwise
357 1.1 jtc */
358 1.1 jtc
359 1.1 jtc #if __STDC__
360 1.1 jtc int
361 1.1 jtc trng_add(register char *str)
362 1.1 jtc #else
363 1.1 jtc int
364 1.1 jtc trng_add(str)
365 1.1 jtc register char *str;
366 1.1 jtc #endif
367 1.1 jtc {
368 1.1 jtc register TIME_RNG *pt;
369 1.1 jtc register char *up_pt = NULL;
370 1.1 jtc register char *stpt;
371 1.1 jtc register char *flgpt;
372 1.1 jtc register int dot = 0;
373 1.1 jtc
374 1.1 jtc /*
375 1.1 jtc * throw out the badly formed time ranges
376 1.1 jtc */
377 1.1 jtc if ((str == NULL) || (*str == '\0')) {
378 1.1 jtc warn(1, "Empty time range string");
379 1.1 jtc return(-1);
380 1.1 jtc }
381 1.1 jtc
382 1.1 jtc /*
383 1.1 jtc * locate optional flags suffix /{cm}.
384 1.1 jtc */
385 1.4 mycroft if ((flgpt = strrchr(str, '/')) != NULL)
386 1.1 jtc *flgpt++ = '\0';
387 1.1 jtc
388 1.1 jtc for (stpt = str; *stpt != '\0'; ++stpt) {
389 1.1 jtc if ((*stpt >= '0') && (*stpt <= '9'))
390 1.1 jtc continue;
391 1.1 jtc if ((*stpt == ',') && (up_pt == NULL)) {
392 1.1 jtc *stpt = '\0';
393 1.1 jtc up_pt = stpt + 1;
394 1.1 jtc dot = 0;
395 1.1 jtc continue;
396 1.1 jtc }
397 1.1 jtc
398 1.1 jtc /*
399 1.1 jtc * allow only one dot per range (secs)
400 1.1 jtc */
401 1.1 jtc if ((*stpt == '.') && (!dot)) {
402 1.1 jtc ++dot;
403 1.1 jtc continue;
404 1.1 jtc }
405 1.1 jtc warn(1, "Improperly specified time range: %s", str);
406 1.1 jtc goto out;
407 1.1 jtc }
408 1.1 jtc
409 1.1 jtc /*
410 1.1 jtc * allocate space for the time range and store the limits
411 1.1 jtc */
412 1.1 jtc if ((pt = (TIME_RNG *)malloc(sizeof(TIME_RNG))) == NULL) {
413 1.1 jtc warn(1, "Unable to allocate memory for time range");
414 1.1 jtc return(-1);
415 1.1 jtc }
416 1.1 jtc
417 1.1 jtc /*
418 1.1 jtc * by default we only will check file mtime, but usee can specify
419 1.1 jtc * mtime, ctime (inode change time) or both.
420 1.1 jtc */
421 1.1 jtc if ((flgpt == NULL) || (*flgpt == '\0'))
422 1.1 jtc pt->flgs = CMPMTME;
423 1.1 jtc else {
424 1.1 jtc pt->flgs = 0;
425 1.1 jtc while (*flgpt != '\0') {
426 1.1 jtc switch(*flgpt) {
427 1.1 jtc case 'M':
428 1.1 jtc case 'm':
429 1.1 jtc pt->flgs |= CMPMTME;
430 1.1 jtc break;
431 1.1 jtc case 'C':
432 1.1 jtc case 'c':
433 1.1 jtc pt->flgs |= CMPCTME;
434 1.1 jtc break;
435 1.1 jtc default:
436 1.1 jtc warn(1, "Bad option %c with time range %s",
437 1.1 jtc *flgpt, str);
438 1.1 jtc goto out;
439 1.1 jtc }
440 1.1 jtc ++flgpt;
441 1.1 jtc }
442 1.1 jtc }
443 1.1 jtc
444 1.1 jtc /*
445 1.1 jtc * start off with the current time
446 1.1 jtc */
447 1.1 jtc pt->low_time = pt->high_time = time((time_t *)NULL);
448 1.1 jtc if (*str != '\0') {
449 1.1 jtc /*
450 1.1 jtc * add lower limit
451 1.1 jtc */
452 1.1 jtc if (str_sec(str, &(pt->low_time)) < 0) {
453 1.1 jtc warn(1, "Illegal lower time range %s", str);
454 1.1 jtc (void)free((char *)pt);
455 1.1 jtc goto out;
456 1.1 jtc }
457 1.1 jtc pt->flgs |= HASLOW;
458 1.1 jtc }
459 1.1 jtc
460 1.1 jtc if ((up_pt != NULL) && (*up_pt != '\0')) {
461 1.1 jtc /*
462 1.1 jtc * add upper limit
463 1.1 jtc */
464 1.1 jtc if (str_sec(up_pt, &(pt->high_time)) < 0) {
465 1.1 jtc warn(1, "Illegal upper time range %s", up_pt);
466 1.1 jtc (void)free((char *)pt);
467 1.1 jtc goto out;
468 1.1 jtc }
469 1.1 jtc pt->flgs |= HASHIGH;
470 1.1 jtc
471 1.1 jtc /*
472 1.1 jtc * check that the upper and lower do not overlap
473 1.1 jtc */
474 1.1 jtc if (pt->flgs & HASLOW) {
475 1.1 jtc if (pt->low_time > pt->high_time) {
476 1.1 jtc warn(1, "Upper %s and lower %s time overlap",
477 1.1 jtc up_pt, str);
478 1.1 jtc (void)free((char *)pt);
479 1.1 jtc return(-1);
480 1.1 jtc }
481 1.1 jtc }
482 1.1 jtc }
483 1.1 jtc
484 1.1 jtc pt->fow = NULL;
485 1.1 jtc if (trhead == NULL) {
486 1.1 jtc trtail = trhead = pt;
487 1.1 jtc return(0);
488 1.1 jtc }
489 1.1 jtc trtail->fow = pt;
490 1.1 jtc trtail = pt;
491 1.1 jtc return(0);
492 1.1 jtc
493 1.1 jtc out:
494 1.1 jtc warn(1, "Time range format is: [yy[mm[dd[hh]]]]mm[.ss][/[c][m]]");
495 1.1 jtc return(-1);
496 1.1 jtc }
497 1.1 jtc
498 1.1 jtc /*
499 1.1 jtc * trng_match()
500 1.1 jtc * check if this files mtime/ctime falls within any supplied time range.
501 1.1 jtc * Return:
502 1.1 jtc * 0 if this archive member should be processed, 1 if it should be skipped
503 1.1 jtc */
504 1.1 jtc
505 1.1 jtc #if __STDC__
506 1.1 jtc static int
507 1.1 jtc trng_match(register ARCHD *arcn)
508 1.1 jtc #else
509 1.1 jtc static int
510 1.1 jtc trng_match(arcn)
511 1.1 jtc register ARCHD *arcn;
512 1.1 jtc #endif
513 1.1 jtc {
514 1.1 jtc register TIME_RNG *pt;
515 1.1 jtc
516 1.1 jtc /*
517 1.1 jtc * have to search down the list one at a time looking for a match.
518 1.1 jtc * remember time range limits are inclusive.
519 1.1 jtc */
520 1.1 jtc pt = trhead;
521 1.1 jtc while (pt != NULL) {
522 1.1 jtc switch(pt->flgs & CMPBOTH) {
523 1.1 jtc case CMPBOTH:
524 1.1 jtc /*
525 1.1 jtc * user wants both mtime and ctime checked for this
526 1.1 jtc * time range
527 1.1 jtc */
528 1.1 jtc if (((pt->flgs & HASLOW) &&
529 1.1 jtc (arcn->sb.st_mtime < pt->low_time) &&
530 1.1 jtc (arcn->sb.st_ctime < pt->low_time)) ||
531 1.1 jtc ((pt->flgs & HASHIGH) &&
532 1.1 jtc (arcn->sb.st_mtime > pt->high_time) &&
533 1.1 jtc (arcn->sb.st_ctime > pt->high_time))) {
534 1.1 jtc pt = pt->fow;
535 1.1 jtc continue;
536 1.1 jtc }
537 1.1 jtc break;
538 1.1 jtc case CMPCTME:
539 1.1 jtc /*
540 1.1 jtc * user wants only ctime checked for this time range
541 1.1 jtc */
542 1.1 jtc if (((pt->flgs & HASLOW) &&
543 1.1 jtc (arcn->sb.st_ctime < pt->low_time)) ||
544 1.1 jtc ((pt->flgs & HASHIGH) &&
545 1.1 jtc (arcn->sb.st_ctime > pt->high_time))) {
546 1.1 jtc pt = pt->fow;
547 1.1 jtc continue;
548 1.1 jtc }
549 1.1 jtc break;
550 1.1 jtc case CMPMTME:
551 1.1 jtc default:
552 1.1 jtc /*
553 1.1 jtc * user wants only mtime checked for this time range
554 1.1 jtc */
555 1.1 jtc if (((pt->flgs & HASLOW) &&
556 1.1 jtc (arcn->sb.st_mtime < pt->low_time)) ||
557 1.1 jtc ((pt->flgs & HASHIGH) &&
558 1.1 jtc (arcn->sb.st_mtime > pt->high_time))) {
559 1.1 jtc pt = pt->fow;
560 1.1 jtc continue;
561 1.1 jtc }
562 1.1 jtc break;
563 1.1 jtc }
564 1.1 jtc break;
565 1.1 jtc }
566 1.1 jtc
567 1.1 jtc if (pt == NULL)
568 1.1 jtc return(1);
569 1.1 jtc return(0);
570 1.1 jtc }
571 1.1 jtc
572 1.1 jtc /*
573 1.1 jtc * str_sec()
574 1.1 jtc * Convert a time string in the format of [yy[mm[dd[hh]]]]mm[.ss] to gmt
575 1.1 jtc * seconds. Tval already has current time loaded into it at entry.
576 1.1 jtc * Return:
577 1.1 jtc * 0 if converted ok, -1 otherwise
578 1.1 jtc */
579 1.1 jtc
580 1.1 jtc #if __STDC__
581 1.1 jtc static int
582 1.1 jtc str_sec(register char *str, time_t *tval)
583 1.1 jtc #else
584 1.1 jtc static int
585 1.1 jtc str_sec(str, tval)
586 1.1 jtc register char *str;
587 1.1 jtc time_t *tval;
588 1.1 jtc #endif
589 1.1 jtc {
590 1.1 jtc register struct tm *lt;
591 1.1 jtc register char *dot = NULL;
592 1.1 jtc
593 1.1 jtc lt = localtime(tval);
594 1.4 mycroft if ((dot = strchr(str, '.')) != NULL) {
595 1.1 jtc /*
596 1.1 jtc * seconds (.ss)
597 1.1 jtc */
598 1.1 jtc *dot++ = '\0';
599 1.1 jtc if (strlen(dot) != 2)
600 1.1 jtc return(-1);
601 1.1 jtc if ((lt->tm_sec = ATOI2(dot)) > 61)
602 1.1 jtc return(-1);
603 1.1 jtc } else
604 1.1 jtc lt->tm_sec = 0;
605 1.1 jtc
606 1.1 jtc switch (strlen(str)) {
607 1.1 jtc case 10:
608 1.1 jtc /*
609 1.1 jtc * year (yy)
610 1.1 jtc * watch out for year 2000
611 1.1 jtc */
612 1.1 jtc if ((lt->tm_year = ATOI2(str)) < 69)
613 1.1 jtc lt->tm_year += 100;
614 1.1 jtc str += 2;
615 1.1 jtc /* FALLTHROUGH */
616 1.1 jtc case 8:
617 1.1 jtc /*
618 1.1 jtc * month (mm)
619 1.1 jtc * watch out months are from 0 - 11 internally
620 1.1 jtc */
621 1.1 jtc if ((lt->tm_mon = ATOI2(str)) > 12)
622 1.1 jtc return(-1);
623 1.1 jtc --lt->tm_mon;
624 1.1 jtc str += 2;
625 1.1 jtc /* FALLTHROUGH */
626 1.1 jtc case 6:
627 1.1 jtc /*
628 1.1 jtc * day (dd)
629 1.1 jtc */
630 1.1 jtc if ((lt->tm_mday = ATOI2(str)) > 31)
631 1.1 jtc return(-1);
632 1.1 jtc str += 2;
633 1.1 jtc /* FALLTHROUGH */
634 1.1 jtc case 4:
635 1.1 jtc /*
636 1.1 jtc * hour (hh)
637 1.1 jtc */
638 1.1 jtc if ((lt->tm_hour = ATOI2(str)) > 23)
639 1.1 jtc return(-1);
640 1.1 jtc str += 2;
641 1.1 jtc /* FALLTHROUGH */
642 1.1 jtc case 2:
643 1.1 jtc /*
644 1.1 jtc * minute (mm)
645 1.1 jtc */
646 1.1 jtc if ((lt->tm_min = ATOI2(str)) > 59)
647 1.1 jtc return(-1);
648 1.1 jtc break;
649 1.1 jtc default:
650 1.1 jtc return(-1);
651 1.1 jtc }
652 1.1 jtc /*
653 1.1 jtc * convert broken-down time to GMT clock time seconds
654 1.1 jtc */
655 1.1 jtc if ((*tval = mktime(lt)) == -1)
656 1.1 jtc return(-1);
657 1.1 jtc return(0);
658 1.1 jtc }
659