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