sel_subs.c revision 46684
11556Srgrimes/*- 21556Srgrimes * Copyright (c) 1992 Keith Muller. 31556Srgrimes * Copyright (c) 1992, 1993 41556Srgrimes * The Regents of the University of California. All rights reserved. 51556Srgrimes * 61556Srgrimes * This code is derived from software contributed to Berkeley by 71556Srgrimes * Keith Muller of the University of California, San Diego. 81556Srgrimes * 91556Srgrimes * Redistribution and use in source and binary forms, with or without 101556Srgrimes * modification, are permitted provided that the following conditions 111556Srgrimes * are met: 121556Srgrimes * 1. Redistributions of source code must retain the above copyright 131556Srgrimes * notice, this list of conditions and the following disclaimer. 141556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 151556Srgrimes * notice, this list of conditions and the following disclaimer in the 161556Srgrimes * documentation and/or other materials provided with the distribution. 171556Srgrimes * 3. All advertising materials mentioning features or use of this software 181556Srgrimes * must display the following acknowledgement: 191556Srgrimes * This product includes software developed by the University of 201556Srgrimes * California, Berkeley and its contributors. 211556Srgrimes * 4. Neither the name of the University nor the names of its contributors 221556Srgrimes * may be used to endorse or promote products derived from this software 231556Srgrimes * without specific prior written permission. 241556Srgrimes * 251556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 261556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 271556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 281556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 291556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 301556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 311556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 321556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 331556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 341556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 351556Srgrimes * SUCH DAMAGE. 361556Srgrimes */ 371556Srgrimes 381556Srgrimes#ifndef lint 3936049Scharnier#if 0 4036049Scharnierstatic char sccsid[] = "@(#)sel_subs.c 8.1 (Berkeley) 5/31/93"; 4136049Scharnier#endif 4236049Scharnierstatic const char rcsid[] = 4346684Skris "$Id: sel_subs.c,v 1.9 1998/05/15 06:27:46 charnier Exp $"; 441556Srgrimes#endif /* not lint */ 451556Srgrimes 461556Srgrimes#include <sys/types.h> 471556Srgrimes#include <sys/time.h> 481556Srgrimes#include <sys/stat.h> 491556Srgrimes#include <pwd.h> 501556Srgrimes#include <grp.h> 511556Srgrimes#include <stdio.h> 521556Srgrimes#include <string.h> 531556Srgrimes#include <strings.h> 541556Srgrimes#include <unistd.h> 551556Srgrimes#include <stdlib.h> 561556Srgrimes#include "pax.h" 571556Srgrimes#include "sel_subs.h" 581556Srgrimes#include "extern.h" 591556Srgrimes 601556Srgrimesstatic int str_sec __P((register char *, time_t *)); 611556Srgrimesstatic int usr_match __P((register ARCHD *)); 621556Srgrimesstatic int grp_match __P((register ARCHD *)); 631556Srgrimesstatic int trng_match __P((register ARCHD *)); 641556Srgrimes 651556Srgrimesstatic TIME_RNG *trhead = NULL; /* time range list head */ 661556Srgrimesstatic TIME_RNG *trtail = NULL; /* time range list tail */ 671556Srgrimesstatic USRT **usrtb = NULL; /* user selection table */ 681556Srgrimesstatic GRPT **grptb = NULL; /* group selection table */ 691556Srgrimes 701556Srgrimes/* 711556Srgrimes * Routines for selection of archive members 721556Srgrimes */ 731556Srgrimes 741556Srgrimes/* 751556Srgrimes * sel_chk() 7646684Skris * check if this file matches a specified uid, gid or time range 771556Srgrimes * Return: 781556Srgrimes * 0 if this archive member should be processed, 1 if it should be skipped 791556Srgrimes */ 801556Srgrimes 811556Srgrimes#if __STDC__ 821556Srgrimesint 831556Srgrimessel_chk(register ARCHD *arcn) 841556Srgrimes#else 851556Srgrimesint 861556Srgrimessel_chk(arcn) 871556Srgrimes register ARCHD *arcn; 881556Srgrimes#endif 891556Srgrimes{ 901556Srgrimes if (((usrtb != NULL) && usr_match(arcn)) || 911556Srgrimes ((grptb != NULL) && grp_match(arcn)) || 921556Srgrimes ((trhead != NULL) && trng_match(arcn))) 931556Srgrimes return(1); 941556Srgrimes return(0); 951556Srgrimes} 961556Srgrimes 971556Srgrimes/* 981556Srgrimes * User/group selection routines 991556Srgrimes * 1001556Srgrimes * Routines to handle user selection of files based on the file uid/gid. To 1011556Srgrimes * add an entry, the user supplies either then name or the uid/gid starting with 10246684Skris * a # on the command line. A \# will escape the #. 1031556Srgrimes */ 1041556Srgrimes 1051556Srgrimes/* 1061556Srgrimes * usr_add() 1071556Srgrimes * add a user match to the user match hash table 1081556Srgrimes * Return: 1091556Srgrimes * 0 if added ok, -1 otherwise; 1101556Srgrimes */ 1111556Srgrimes 1121556Srgrimes#if __STDC__ 1131556Srgrimesint 1141556Srgrimesusr_add(register char *str) 1151556Srgrimes#else 1161556Srgrimesint 1171556Srgrimesusr_add(str) 1181556Srgrimes register char *str; 1191556Srgrimes#endif 1201556Srgrimes{ 1211556Srgrimes register u_int indx; 1221556Srgrimes register USRT *pt; 1231556Srgrimes register struct passwd *pw; 1241556Srgrimes register uid_t uid; 1251556Srgrimes 1261556Srgrimes /* 1271556Srgrimes * create the table if it doesn't exist 1281556Srgrimes */ 1291556Srgrimes if ((str == NULL) || (*str == '\0')) 1301556Srgrimes return(-1); 1311556Srgrimes if ((usrtb == NULL) && 1321556Srgrimes ((usrtb = (USRT **)calloc(USR_TB_SZ, sizeof(USRT *))) == NULL)) { 13328904Ssos pax_warn(1, "Unable to allocate memory for user selection table"); 1341556Srgrimes return(-1); 1351556Srgrimes } 1361556Srgrimes 1371556Srgrimes /* 1381556Srgrimes * figure out user spec 1391556Srgrimes */ 1401556Srgrimes if (str[0] != '#') { 1411556Srgrimes /* 1421556Srgrimes * it is a user name, \# escapes # as first char in user name 1431556Srgrimes */ 1441556Srgrimes if ((str[0] == '\\') && (str[1] == '#')) 1451556Srgrimes ++str; 1461556Srgrimes if ((pw = getpwnam(str)) == NULL) { 14728904Ssos pax_warn(1, "Unable to find uid for user: %s", str); 1481556Srgrimes return(-1); 1491556Srgrimes } 1501556Srgrimes uid = (uid_t)pw->pw_uid; 1511556Srgrimes } else 1521556Srgrimes# ifdef NET2_STAT 1531556Srgrimes uid = (uid_t)atoi(str+1); 1541556Srgrimes# else 1551556Srgrimes uid = (uid_t)strtoul(str+1, (char **)NULL, 10); 1561556Srgrimes# endif 1571556Srgrimes endpwent(); 1581556Srgrimes 1591556Srgrimes /* 1601556Srgrimes * hash it and go down the hash chain (if any) looking for it 1611556Srgrimes */ 1621556Srgrimes indx = ((unsigned)uid) % USR_TB_SZ; 1631556Srgrimes if ((pt = usrtb[indx]) != NULL) { 1641556Srgrimes while (pt != NULL) { 1651556Srgrimes if (pt->uid == uid) 1661556Srgrimes return(0); 1671556Srgrimes pt = pt->fow; 1681556Srgrimes } 1691556Srgrimes } 1701556Srgrimes 1711556Srgrimes /* 1721556Srgrimes * uid is not yet in the table, add it to the front of the chain 1731556Srgrimes */ 1741556Srgrimes if ((pt = (USRT *)malloc(sizeof(USRT))) != NULL) { 1751556Srgrimes pt->uid = uid; 1761556Srgrimes pt->fow = usrtb[indx]; 1771556Srgrimes usrtb[indx] = pt; 1781556Srgrimes return(0); 1791556Srgrimes } 18028904Ssos pax_warn(1, "User selection table out of memory"); 1811556Srgrimes return(-1); 1821556Srgrimes} 1831556Srgrimes 1841556Srgrimes/* 1851556Srgrimes * usr_match() 1861556Srgrimes * check if this files uid matches a selected uid. 1871556Srgrimes * Return: 1881556Srgrimes * 0 if this archive member should be processed, 1 if it should be skipped 1891556Srgrimes */ 1901556Srgrimes 1911556Srgrimes#if __STDC__ 1921556Srgrimesstatic int 1931556Srgrimesusr_match(register ARCHD *arcn) 1941556Srgrimes#else 1951556Srgrimesstatic int 1961556Srgrimesusr_match(arcn) 1971556Srgrimes register ARCHD *arcn; 1981556Srgrimes#endif 1991556Srgrimes{ 2001556Srgrimes register USRT *pt; 2011556Srgrimes 2021556Srgrimes /* 2031556Srgrimes * hash and look for it in the table 2041556Srgrimes */ 2051556Srgrimes pt = usrtb[((unsigned)arcn->sb.st_uid) % USR_TB_SZ]; 2061556Srgrimes while (pt != NULL) { 2071556Srgrimes if (pt->uid == arcn->sb.st_uid) 2081556Srgrimes return(0); 2091556Srgrimes pt = pt->fow; 2101556Srgrimes } 2111556Srgrimes 2121556Srgrimes /* 2131556Srgrimes * not found 2141556Srgrimes */ 2151556Srgrimes return(1); 2161556Srgrimes} 2171556Srgrimes 2181556Srgrimes/* 2191556Srgrimes * grp_add() 2201556Srgrimes * add a group match to the group match hash table 2211556Srgrimes * Return: 2221556Srgrimes * 0 if added ok, -1 otherwise; 2231556Srgrimes */ 2241556Srgrimes 2251556Srgrimes#if __STDC__ 2261556Srgrimesint 2271556Srgrimesgrp_add(register char *str) 2281556Srgrimes#else 2291556Srgrimesint 2301556Srgrimesgrp_add(str) 2311556Srgrimes register char *str; 2321556Srgrimes#endif 2331556Srgrimes{ 2341556Srgrimes register u_int indx; 2351556Srgrimes register GRPT *pt; 2361556Srgrimes register struct group *gr; 2371556Srgrimes register gid_t gid; 2381556Srgrimes 2391556Srgrimes /* 2401556Srgrimes * create the table if it doesn't exist 2411556Srgrimes */ 2421556Srgrimes if ((str == NULL) || (*str == '\0')) 2431556Srgrimes return(-1); 2441556Srgrimes if ((grptb == NULL) && 2451556Srgrimes ((grptb = (GRPT **)calloc(GRP_TB_SZ, sizeof(GRPT *))) == NULL)) { 24628904Ssos pax_warn(1, "Unable to allocate memory fo group selection table"); 2471556Srgrimes return(-1); 2481556Srgrimes } 2491556Srgrimes 2501556Srgrimes /* 2511556Srgrimes * figure out user spec 2521556Srgrimes */ 2531556Srgrimes if (str[0] != '#') { 2541556Srgrimes /* 2551556Srgrimes * it is a group name, \# escapes # as first char in group name 2561556Srgrimes */ 2571556Srgrimes if ((str[0] == '\\') && (str[1] == '#')) 2581556Srgrimes ++str; 2591556Srgrimes if ((gr = getgrnam(str)) == NULL) { 26028904Ssos pax_warn(1,"Cannot determine gid for group name: %s", str); 2611556Srgrimes return(-1); 2621556Srgrimes } 2631556Srgrimes gid = (gid_t)gr->gr_gid; 2641556Srgrimes } else 2651556Srgrimes# ifdef NET2_STAT 2661556Srgrimes gid = (gid_t)atoi(str+1); 2671556Srgrimes# else 2681556Srgrimes gid = (gid_t)strtoul(str+1, (char **)NULL, 10); 2691556Srgrimes# endif 2701556Srgrimes endgrent(); 2711556Srgrimes 2721556Srgrimes /* 2731556Srgrimes * hash it and go down the hash chain (if any) looking for it 2741556Srgrimes */ 2751556Srgrimes indx = ((unsigned)gid) % GRP_TB_SZ; 2761556Srgrimes if ((pt = grptb[indx]) != NULL) { 2771556Srgrimes while (pt != NULL) { 2781556Srgrimes if (pt->gid == gid) 2791556Srgrimes return(0); 2801556Srgrimes pt = pt->fow; 2811556Srgrimes } 2821556Srgrimes } 2831556Srgrimes 2841556Srgrimes /* 2851556Srgrimes * gid not in the table, add it to the front of the chain 2861556Srgrimes */ 2871556Srgrimes if ((pt = (GRPT *)malloc(sizeof(GRPT))) != NULL) { 2881556Srgrimes pt->gid = gid; 2891556Srgrimes pt->fow = grptb[indx]; 2901556Srgrimes grptb[indx] = pt; 2911556Srgrimes return(0); 2921556Srgrimes } 29328904Ssos pax_warn(1, "Group selection table out of memory"); 2941556Srgrimes return(-1); 2951556Srgrimes} 2961556Srgrimes 2971556Srgrimes/* 2981556Srgrimes * grp_match() 2991556Srgrimes * check if this files gid matches a selected gid. 3001556Srgrimes * Return: 3011556Srgrimes * 0 if this archive member should be processed, 1 if it should be skipped 3021556Srgrimes */ 3031556Srgrimes 3041556Srgrimes#if __STDC__ 3051556Srgrimesstatic int 3061556Srgrimesgrp_match(register ARCHD *arcn) 3071556Srgrimes#else 3081556Srgrimesstatic int 3091556Srgrimesgrp_match(arcn) 3101556Srgrimes register ARCHD *arcn; 3111556Srgrimes#endif 3121556Srgrimes{ 3131556Srgrimes register GRPT *pt; 3141556Srgrimes 3151556Srgrimes /* 3161556Srgrimes * hash and look for it in the table 3171556Srgrimes */ 3181556Srgrimes pt = grptb[((unsigned)arcn->sb.st_gid) % GRP_TB_SZ]; 3191556Srgrimes while (pt != NULL) { 3201556Srgrimes if (pt->gid == arcn->sb.st_gid) 3211556Srgrimes return(0); 3221556Srgrimes pt = pt->fow; 3231556Srgrimes } 3241556Srgrimes 3251556Srgrimes /* 3261556Srgrimes * not found 3271556Srgrimes */ 3281556Srgrimes return(1); 3291556Srgrimes} 3301556Srgrimes 3311556Srgrimes/* 3321556Srgrimes * Time range selection routines 3331556Srgrimes * 3341556Srgrimes * Routines to handle user selection of files based on the modification and/or 3351556Srgrimes * inode change time falling within a specified time range (the non-standard 3361556Srgrimes * -T flag). The user may specify any number of different file time ranges. 3371556Srgrimes * Time ranges are checked one at a time until a match is found (if at all). 3381556Srgrimes * If the file has a mtime (and/or ctime) which lies within one of the time 3391556Srgrimes * ranges, the file is selected. Time ranges may have a lower and/or a upper 3401556Srgrimes * value. These ranges are inclusive. When no time ranges are supplied to pax 3411556Srgrimes * with the -T option, all members in the archive will be selected by the time 3421556Srgrimes * range routines. When only a lower range is supplied, only files with a 3431556Srgrimes * mtime (and/or ctime) equal to or younger are selected. When only a upper 3441556Srgrimes * range is supplied, only files with a mtime (and/or ctime) equal to or older 3451556Srgrimes * are selected. When the lower time range is equal to the upper time range, 3461556Srgrimes * only files with a mtime (or ctime) of exactly that time are selected. 3471556Srgrimes */ 3481556Srgrimes 3491556Srgrimes/* 3501556Srgrimes * trng_add() 3511556Srgrimes * add a time range match to the time range list. 3521556Srgrimes * This is a non-standard pax option. Lower and upper ranges are in the 3531556Srgrimes * format: [yy[mm[dd[hh]]]]mm[.ss] and are comma separated. 3541556Srgrimes * Time ranges are based on current time, so 1234 would specify a time of 3551556Srgrimes * 12:34 today. 3561556Srgrimes * Return: 3571556Srgrimes * 0 if the time range was added to the list, -1 otherwise 3581556Srgrimes */ 3591556Srgrimes 3601556Srgrimes#if __STDC__ 3611556Srgrimesint 3621556Srgrimestrng_add(register char *str) 3631556Srgrimes#else 3641556Srgrimesint 3651556Srgrimestrng_add(str) 3661556Srgrimes register char *str; 3671556Srgrimes#endif 3681556Srgrimes{ 3691556Srgrimes register TIME_RNG *pt; 3701556Srgrimes register char *up_pt = NULL; 3711556Srgrimes register char *stpt; 3721556Srgrimes register char *flgpt; 3731556Srgrimes register int dot = 0; 3741556Srgrimes 3751556Srgrimes /* 3761556Srgrimes * throw out the badly formed time ranges 3771556Srgrimes */ 3781556Srgrimes if ((str == NULL) || (*str == '\0')) { 37928904Ssos pax_warn(1, "Empty time range string"); 3801556Srgrimes return(-1); 3811556Srgrimes } 3821556Srgrimes 3831556Srgrimes /* 3841556Srgrimes * locate optional flags suffix /{cm}. 3851556Srgrimes */ 3861556Srgrimes if ((flgpt = rindex(str, '/')) != NULL) 3871556Srgrimes *flgpt++ = '\0'; 3881556Srgrimes 3891556Srgrimes for (stpt = str; *stpt != '\0'; ++stpt) { 3901556Srgrimes if ((*stpt >= '0') && (*stpt <= '9')) 3911556Srgrimes continue; 3921556Srgrimes if ((*stpt == ',') && (up_pt == NULL)) { 3931556Srgrimes *stpt = '\0'; 3941556Srgrimes up_pt = stpt + 1; 3951556Srgrimes dot = 0; 3961556Srgrimes continue; 3971556Srgrimes } 3981556Srgrimes 3991556Srgrimes /* 4001556Srgrimes * allow only one dot per range (secs) 4011556Srgrimes */ 4021556Srgrimes if ((*stpt == '.') && (!dot)) { 4031556Srgrimes ++dot; 4041556Srgrimes continue; 4051556Srgrimes } 40628904Ssos pax_warn(1, "Improperly specified time range: %s", str); 4071556Srgrimes goto out; 4081556Srgrimes } 4091556Srgrimes 4101556Srgrimes /* 4111556Srgrimes * allocate space for the time range and store the limits 4121556Srgrimes */ 4131556Srgrimes if ((pt = (TIME_RNG *)malloc(sizeof(TIME_RNG))) == NULL) { 41428904Ssos pax_warn(1, "Unable to allocate memory for time range"); 4151556Srgrimes return(-1); 4161556Srgrimes } 4171556Srgrimes 4181556Srgrimes /* 4191556Srgrimes * by default we only will check file mtime, but usee can specify 4201556Srgrimes * mtime, ctime (inode change time) or both. 4211556Srgrimes */ 4221556Srgrimes if ((flgpt == NULL) || (*flgpt == '\0')) 4231556Srgrimes pt->flgs = CMPMTME; 4241556Srgrimes else { 4251556Srgrimes pt->flgs = 0; 4261556Srgrimes while (*flgpt != '\0') { 4271556Srgrimes switch(*flgpt) { 4281556Srgrimes case 'M': 4291556Srgrimes case 'm': 4301556Srgrimes pt->flgs |= CMPMTME; 4311556Srgrimes break; 4321556Srgrimes case 'C': 4331556Srgrimes case 'c': 4341556Srgrimes pt->flgs |= CMPCTME; 4351556Srgrimes break; 4361556Srgrimes default: 43728904Ssos pax_warn(1, "Bad option %c with time range %s", 4381556Srgrimes *flgpt, str); 4391556Srgrimes goto out; 4401556Srgrimes } 4411556Srgrimes ++flgpt; 4421556Srgrimes } 4431556Srgrimes } 4441556Srgrimes 4451556Srgrimes /* 4461556Srgrimes * start off with the current time 4471556Srgrimes */ 4481556Srgrimes pt->low_time = pt->high_time = time((time_t *)NULL); 4491556Srgrimes if (*str != '\0') { 4501556Srgrimes /* 4511556Srgrimes * add lower limit 4521556Srgrimes */ 4531556Srgrimes if (str_sec(str, &(pt->low_time)) < 0) { 45428904Ssos pax_warn(1, "Illegal lower time range %s", str); 4551556Srgrimes (void)free((char *)pt); 4561556Srgrimes goto out; 4571556Srgrimes } 4581556Srgrimes pt->flgs |= HASLOW; 4591556Srgrimes } 4601556Srgrimes 4611556Srgrimes if ((up_pt != NULL) && (*up_pt != '\0')) { 4621556Srgrimes /* 4631556Srgrimes * add upper limit 4641556Srgrimes */ 4651556Srgrimes if (str_sec(up_pt, &(pt->high_time)) < 0) { 46628904Ssos pax_warn(1, "Illegal upper time range %s", up_pt); 4671556Srgrimes (void)free((char *)pt); 4681556Srgrimes goto out; 4691556Srgrimes } 4701556Srgrimes pt->flgs |= HASHIGH; 4711556Srgrimes 4721556Srgrimes /* 4731556Srgrimes * check that the upper and lower do not overlap 4741556Srgrimes */ 4751556Srgrimes if (pt->flgs & HASLOW) { 4761556Srgrimes if (pt->low_time > pt->high_time) { 47728904Ssos pax_warn(1, "Upper %s and lower %s time overlap", 4781556Srgrimes up_pt, str); 4791556Srgrimes (void)free((char *)pt); 4801556Srgrimes return(-1); 4811556Srgrimes } 4821556Srgrimes } 4831556Srgrimes } 4841556Srgrimes 4851556Srgrimes pt->fow = NULL; 4861556Srgrimes if (trhead == NULL) { 4871556Srgrimes trtail = trhead = pt; 4881556Srgrimes return(0); 4891556Srgrimes } 4901556Srgrimes trtail->fow = pt; 4911556Srgrimes trtail = pt; 4921556Srgrimes return(0); 4931556Srgrimes 4941556Srgrimes out: 49528904Ssos pax_warn(1, "Time range format is: [yy[mm[dd[hh]]]]mm[.ss][/[c][m]]"); 4961556Srgrimes return(-1); 4971556Srgrimes} 4981556Srgrimes 4991556Srgrimes/* 5001556Srgrimes * trng_match() 5011556Srgrimes * check if this files mtime/ctime falls within any supplied time range. 5021556Srgrimes * Return: 5031556Srgrimes * 0 if this archive member should be processed, 1 if it should be skipped 5041556Srgrimes */ 5051556Srgrimes 5061556Srgrimes#if __STDC__ 5071556Srgrimesstatic int 5081556Srgrimestrng_match(register ARCHD *arcn) 5091556Srgrimes#else 5101556Srgrimesstatic int 5111556Srgrimestrng_match(arcn) 5121556Srgrimes register ARCHD *arcn; 5131556Srgrimes#endif 5141556Srgrimes{ 5151556Srgrimes register TIME_RNG *pt; 5161556Srgrimes 5171556Srgrimes /* 5181556Srgrimes * have to search down the list one at a time looking for a match. 5191556Srgrimes * remember time range limits are inclusive. 5201556Srgrimes */ 5211556Srgrimes pt = trhead; 5221556Srgrimes while (pt != NULL) { 5231556Srgrimes switch(pt->flgs & CMPBOTH) { 5241556Srgrimes case CMPBOTH: 5251556Srgrimes /* 5261556Srgrimes * user wants both mtime and ctime checked for this 5271556Srgrimes * time range 5281556Srgrimes */ 5291556Srgrimes if (((pt->flgs & HASLOW) && 5301556Srgrimes (arcn->sb.st_mtime < pt->low_time) && 5311556Srgrimes (arcn->sb.st_ctime < pt->low_time)) || 5321556Srgrimes ((pt->flgs & HASHIGH) && 5331556Srgrimes (arcn->sb.st_mtime > pt->high_time) && 5341556Srgrimes (arcn->sb.st_ctime > pt->high_time))) { 5351556Srgrimes pt = pt->fow; 5361556Srgrimes continue; 5371556Srgrimes } 5381556Srgrimes break; 5391556Srgrimes case CMPCTME: 5401556Srgrimes /* 5411556Srgrimes * user wants only ctime checked for this time range 5421556Srgrimes */ 5431556Srgrimes if (((pt->flgs & HASLOW) && 5441556Srgrimes (arcn->sb.st_ctime < pt->low_time)) || 5451556Srgrimes ((pt->flgs & HASHIGH) && 5461556Srgrimes (arcn->sb.st_ctime > pt->high_time))) { 5471556Srgrimes pt = pt->fow; 5481556Srgrimes continue; 5491556Srgrimes } 5501556Srgrimes break; 5511556Srgrimes case CMPMTME: 5521556Srgrimes default: 5531556Srgrimes /* 5541556Srgrimes * user wants only mtime checked for this time range 5551556Srgrimes */ 5561556Srgrimes if (((pt->flgs & HASLOW) && 5571556Srgrimes (arcn->sb.st_mtime < pt->low_time)) || 5581556Srgrimes ((pt->flgs & HASHIGH) && 5591556Srgrimes (arcn->sb.st_mtime > pt->high_time))) { 5601556Srgrimes pt = pt->fow; 5611556Srgrimes continue; 5621556Srgrimes } 5631556Srgrimes break; 5641556Srgrimes } 5651556Srgrimes break; 5661556Srgrimes } 5671556Srgrimes 5681556Srgrimes if (pt == NULL) 5691556Srgrimes return(1); 5701556Srgrimes return(0); 5711556Srgrimes} 5721556Srgrimes 5731556Srgrimes/* 5741556Srgrimes * str_sec() 5751556Srgrimes * Convert a time string in the format of [yy[mm[dd[hh]]]]mm[.ss] to gmt 5761556Srgrimes * seconds. Tval already has current time loaded into it at entry. 5771556Srgrimes * Return: 5781556Srgrimes * 0 if converted ok, -1 otherwise 5791556Srgrimes */ 5801556Srgrimes 5811556Srgrimes#if __STDC__ 5821556Srgrimesstatic int 5831556Srgrimesstr_sec(register char *str, time_t *tval) 5841556Srgrimes#else 5851556Srgrimesstatic int 5861556Srgrimesstr_sec(str, tval) 5871556Srgrimes register char *str; 5881556Srgrimes time_t *tval; 5891556Srgrimes#endif 5901556Srgrimes{ 5911556Srgrimes register struct tm *lt; 5921556Srgrimes register char *dot = NULL; 5931556Srgrimes 5941556Srgrimes lt = localtime(tval); 5951556Srgrimes if ((dot = index(str, '.')) != NULL) { 5961556Srgrimes /* 5971556Srgrimes * seconds (.ss) 5981556Srgrimes */ 5991556Srgrimes *dot++ = '\0'; 6001556Srgrimes if (strlen(dot) != 2) 6011556Srgrimes return(-1); 6021556Srgrimes if ((lt->tm_sec = ATOI2(dot)) > 61) 6031556Srgrimes return(-1); 6041556Srgrimes } else 6051556Srgrimes lt->tm_sec = 0; 6061556Srgrimes 6071556Srgrimes switch (strlen(str)) { 6081556Srgrimes case 10: 6091556Srgrimes /* 6101556Srgrimes * year (yy) 6111556Srgrimes * watch out for year 2000 6121556Srgrimes */ 6131556Srgrimes if ((lt->tm_year = ATOI2(str)) < 69) 6141556Srgrimes lt->tm_year += 100; 6151556Srgrimes str += 2; 6161556Srgrimes /* FALLTHROUGH */ 6171556Srgrimes case 8: 6181556Srgrimes /* 6191556Srgrimes * month (mm) 6201556Srgrimes * watch out months are from 0 - 11 internally 6211556Srgrimes */ 6221556Srgrimes if ((lt->tm_mon = ATOI2(str)) > 12) 6231556Srgrimes return(-1); 6241556Srgrimes --lt->tm_mon; 6251556Srgrimes str += 2; 6261556Srgrimes /* FALLTHROUGH */ 6271556Srgrimes case 6: 6281556Srgrimes /* 6291556Srgrimes * day (dd) 6301556Srgrimes */ 6311556Srgrimes if ((lt->tm_mday = ATOI2(str)) > 31) 6321556Srgrimes return(-1); 6331556Srgrimes str += 2; 6341556Srgrimes /* FALLTHROUGH */ 6351556Srgrimes case 4: 6361556Srgrimes /* 6371556Srgrimes * hour (hh) 6381556Srgrimes */ 6391556Srgrimes if ((lt->tm_hour = ATOI2(str)) > 23) 6401556Srgrimes return(-1); 6411556Srgrimes str += 2; 6421556Srgrimes /* FALLTHROUGH */ 6431556Srgrimes case 2: 6441556Srgrimes /* 6451556Srgrimes * minute (mm) 6461556Srgrimes */ 6471556Srgrimes if ((lt->tm_min = ATOI2(str)) > 59) 6481556Srgrimes return(-1); 6491556Srgrimes break; 6501556Srgrimes default: 6511556Srgrimes return(-1); 6521556Srgrimes } 6531556Srgrimes /* 6541556Srgrimes * convert broken-down time to GMT clock time seconds 6551556Srgrimes */ 6561556Srgrimes if ((*tval = mktime(lt)) == -1) 6571556Srgrimes return(-1); 6581556Srgrimes return(0); 6591556Srgrimes} 660