1 1.24 plunky /* $NetBSD: sel_subs.c,v 1.24 2011/08/31 16:24:54 plunky 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.24 plunky __RCSID("$NetBSD: sel_subs.c,v 1.24 2011/08/31 16:24:54 plunky 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.24 plunky uid = (uid_t)strtoul(str+1, 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.24 plunky gid = (gid_t)strtoul(str+1, 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.24 plunky pt->low_time = pt->high_time = time(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