1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright (c) 1995 Sun Microsystems, Inc. All Rights Reserved 24*7c478bd9Sstevel@tonic-gate * 25*7c478bd9Sstevel@tonic-gate * module: 26*7c478bd9Sstevel@tonic-gate * rules.c 27*7c478bd9Sstevel@tonic-gate * 28*7c478bd9Sstevel@tonic-gate * purpose: 29*7c478bd9Sstevel@tonic-gate * to read and write the rules file and manage rules lists 30*7c478bd9Sstevel@tonic-gate * 31*7c478bd9Sstevel@tonic-gate * contents: 32*7c478bd9Sstevel@tonic-gate * reading rules file 33*7c478bd9Sstevel@tonic-gate * read_rules 34*7c478bd9Sstevel@tonic-gate * (static) read_command 35*7c478bd9Sstevel@tonic-gate * writing rules file 36*7c478bd9Sstevel@tonic-gate * write_rules 37*7c478bd9Sstevel@tonic-gate * (static) rw_header, rw_base 38*7c478bd9Sstevel@tonic-gate * adding rules 39*7c478bd9Sstevel@tonic-gate * add_ignore, add_include 40*7c478bd9Sstevel@tonic-gate * (static) add_rule 41*7c478bd9Sstevel@tonic-gate * adding/checking restrictions 42*7c478bd9Sstevel@tonic-gate * add_restr, check_restr 43*7c478bd9Sstevel@tonic-gate */ 44*7c478bd9Sstevel@tonic-gate #ident "%W% %E% SMI" 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate #include <stdio.h> 47*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 48*7c478bd9Sstevel@tonic-gate #include <string.h> 49*7c478bd9Sstevel@tonic-gate #include <time.h> 50*7c478bd9Sstevel@tonic-gate #include <ctype.h> 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate #include "filesync.h" 53*7c478bd9Sstevel@tonic-gate #include "database.h" 54*7c478bd9Sstevel@tonic-gate #include "messages.h" 55*7c478bd9Sstevel@tonic-gate #include "debug.h" 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate /* 58*7c478bd9Sstevel@tonic-gate * routines: 59*7c478bd9Sstevel@tonic-gate */ 60*7c478bd9Sstevel@tonic-gate static errmask_t rw_base(FILE *file, struct base *bp); 61*7c478bd9Sstevel@tonic-gate static errmask_t rw_header(FILE *file); 62*7c478bd9Sstevel@tonic-gate static errmask_t add_rule(struct base *, int, const char *); 63*7c478bd9Sstevel@tonic-gate static char *read_cmd(char *); 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate /* 66*7c478bd9Sstevel@tonic-gate * globals 67*7c478bd9Sstevel@tonic-gate */ 68*7c478bd9Sstevel@tonic-gate static int rules_added; 69*7c478bd9Sstevel@tonic-gate static int restr_added; 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate /* 72*7c478bd9Sstevel@tonic-gate * locals 73*7c478bd9Sstevel@tonic-gate */ 74*7c478bd9Sstevel@tonic-gate #define RULE_MAJOR 1 /* rules file format major rev */ 75*7c478bd9Sstevel@tonic-gate #define RULE_MINOR 1 /* rules file format minor rev */ 76*7c478bd9Sstevel@tonic-gate #define RULE_TAG "PACKINGRULES" /* magic string for rules files */ 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate /* 79*7c478bd9Sstevel@tonic-gate * routine: 80*7c478bd9Sstevel@tonic-gate * read_rules 81*7c478bd9Sstevel@tonic-gate * 82*7c478bd9Sstevel@tonic-gate * purpose: 83*7c478bd9Sstevel@tonic-gate * to read in the rules file 84*7c478bd9Sstevel@tonic-gate * 85*7c478bd9Sstevel@tonic-gate * parameters: 86*7c478bd9Sstevel@tonic-gate * name of rules file 87*7c478bd9Sstevel@tonic-gate * 88*7c478bd9Sstevel@tonic-gate * returns: 89*7c478bd9Sstevel@tonic-gate * error mask 90*7c478bd9Sstevel@tonic-gate * 91*7c478bd9Sstevel@tonic-gate * notes: 92*7c478bd9Sstevel@tonic-gate * later when I implement a proper (comment preserving) update 93*7c478bd9Sstevel@tonic-gate * function I'm going to wish I had figured out how to build the 94*7c478bd9Sstevel@tonic-gate * input functions for this function in a way that would make 95*7c478bd9Sstevel@tonic-gate * the more usable for that too. 96*7c478bd9Sstevel@tonic-gate */ 97*7c478bd9Sstevel@tonic-gate errmask_t 98*7c478bd9Sstevel@tonic-gate read_rules(char *name) 99*7c478bd9Sstevel@tonic-gate { FILE *file; 100*7c478bd9Sstevel@tonic-gate errmask_t errs = 0; 101*7c478bd9Sstevel@tonic-gate int flags; 102*7c478bd9Sstevel@tonic-gate int major, minor; 103*7c478bd9Sstevel@tonic-gate char *s, *s1, *s2; 104*7c478bd9Sstevel@tonic-gate struct base *bp; 105*7c478bd9Sstevel@tonic-gate char *errstr = "???"; 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate file = fopen(name, "r"); 108*7c478bd9Sstevel@tonic-gate if (file == NULL) { 109*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(ERR_open), gettext(TXT_rules), 110*7c478bd9Sstevel@tonic-gate name); 111*7c478bd9Sstevel@tonic-gate return (ERR_FILES); 112*7c478bd9Sstevel@tonic-gate } 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate lex_linenum = 0; 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate if (opt_debug & DBG_FILES) 117*7c478bd9Sstevel@tonic-gate fprintf(stderr, "FILE: READ RULES %s\n", name); 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate bp = &omnibase; /* default base before any others */ 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate while (!feof(file)) { 122*7c478bd9Sstevel@tonic-gate /* find the first token on the line */ 123*7c478bd9Sstevel@tonic-gate s = lex(file); 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate /* skip blank lines and comments */ 126*7c478bd9Sstevel@tonic-gate if (s == 0 || *s == 0 || *s == '#' || *s == '*') 127*7c478bd9Sstevel@tonic-gate continue; 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate /* see if the first token is a known keyword */ 130*7c478bd9Sstevel@tonic-gate if (strcmp(s, "BASE") == 0) { 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate /* get the source & destination tokens */ 133*7c478bd9Sstevel@tonic-gate errstr = gettext(TXT_srcdst); 134*7c478bd9Sstevel@tonic-gate s1 = lex(0); 135*7c478bd9Sstevel@tonic-gate if (s1 == 0) 136*7c478bd9Sstevel@tonic-gate goto bad; 137*7c478bd9Sstevel@tonic-gate s1 = strdup(s1); 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate s2 = lex(0); 140*7c478bd9Sstevel@tonic-gate if (s2 == 0) 141*7c478bd9Sstevel@tonic-gate goto bad; 142*7c478bd9Sstevel@tonic-gate s2 = strdup(s2); 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate /* creat the new base pair */ 145*7c478bd9Sstevel@tonic-gate bp = add_base(s1, s2); 146*7c478bd9Sstevel@tonic-gate bp->b_flags |= F_LISTED; 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate free(s1); 149*7c478bd9Sstevel@tonic-gate free(s2); 150*7c478bd9Sstevel@tonic-gate continue; 151*7c478bd9Sstevel@tonic-gate } 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate if (strcmp(s, "LIST") == 0) { 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate /* make sure we are associated with a real base */ 156*7c478bd9Sstevel@tonic-gate if (bp == &omnibase) { 157*7c478bd9Sstevel@tonic-gate errstr = gettext(TXT_nobase); 158*7c478bd9Sstevel@tonic-gate goto bad; 159*7c478bd9Sstevel@tonic-gate } 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate /* skip to the next token */ 162*7c478bd9Sstevel@tonic-gate s = lex(0); 163*7c478bd9Sstevel@tonic-gate errstr = gettext(TXT_noargs); 164*7c478bd9Sstevel@tonic-gate if (s == 0) 165*7c478bd9Sstevel@tonic-gate goto bad; 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate /* see if it is a program or a name */ 168*7c478bd9Sstevel@tonic-gate if (*s == '!') { 169*7c478bd9Sstevel@tonic-gate errs |= add_rule(bp, R_PROGRAM, 170*7c478bd9Sstevel@tonic-gate read_cmd(&s[1])); 171*7c478bd9Sstevel@tonic-gate } else { 172*7c478bd9Sstevel@tonic-gate do { 173*7c478bd9Sstevel@tonic-gate flags = wildcards(s) ? R_WILD : 0; 174*7c478bd9Sstevel@tonic-gate errs |= add_rule(bp, flags, s); 175*7c478bd9Sstevel@tonic-gate s = lex(0); 176*7c478bd9Sstevel@tonic-gate } while (s != 0); 177*7c478bd9Sstevel@tonic-gate } 178*7c478bd9Sstevel@tonic-gate continue; 179*7c478bd9Sstevel@tonic-gate } 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate if (strcmp(s, "IGNORE") == 0) { 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate /* skip to the next token */ 184*7c478bd9Sstevel@tonic-gate s = lex(0); 185*7c478bd9Sstevel@tonic-gate errstr = gettext(TXT_noargs); 186*7c478bd9Sstevel@tonic-gate if (s == 0) 187*7c478bd9Sstevel@tonic-gate goto bad; 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate flags = R_IGNORE; 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate /* see if it is a program or a name */ 192*7c478bd9Sstevel@tonic-gate if (*s == '!') { 193*7c478bd9Sstevel@tonic-gate errs |= add_rule(bp, R_PROGRAM|flags, 194*7c478bd9Sstevel@tonic-gate read_cmd(&s[1])); 195*7c478bd9Sstevel@tonic-gate } else { 196*7c478bd9Sstevel@tonic-gate do { 197*7c478bd9Sstevel@tonic-gate if (wildcards(s)) 198*7c478bd9Sstevel@tonic-gate flags |= R_WILD; 199*7c478bd9Sstevel@tonic-gate errs |= add_rule(bp, flags, s); 200*7c478bd9Sstevel@tonic-gate s = lex(0); 201*7c478bd9Sstevel@tonic-gate } while (s != 0); 202*7c478bd9Sstevel@tonic-gate } 203*7c478bd9Sstevel@tonic-gate continue; 204*7c478bd9Sstevel@tonic-gate } 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate if (strcmp(s, "VERSION") == 0 || strcmp(s, RULE_TAG) == 0) { 207*7c478bd9Sstevel@tonic-gate s = lex(0); 208*7c478bd9Sstevel@tonic-gate errstr = gettext(TXT_noargs); 209*7c478bd9Sstevel@tonic-gate if (s == 0) 210*7c478bd9Sstevel@tonic-gate goto bad; 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate major = strtol(s, &s1, 10); 213*7c478bd9Sstevel@tonic-gate errstr = gettext(TXT_badver); 214*7c478bd9Sstevel@tonic-gate if (*s1 != '.') 215*7c478bd9Sstevel@tonic-gate goto bad; 216*7c478bd9Sstevel@tonic-gate minor = strtol(&s1[1], 0, 10); 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate if (major != RULE_MAJOR || minor > RULE_MINOR) { 219*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(ERR_badver), 220*7c478bd9Sstevel@tonic-gate major, minor, gettext(TXT_rules), name); 221*7c478bd9Sstevel@tonic-gate errs |= ERR_FILES; 222*7c478bd9Sstevel@tonic-gate } 223*7c478bd9Sstevel@tonic-gate continue; 224*7c478bd9Sstevel@tonic-gate } 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate bad: /* log the error and continue processing to find others */ 227*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(ERR_badinput), 228*7c478bd9Sstevel@tonic-gate lex_linenum, errstr, name); 229*7c478bd9Sstevel@tonic-gate errs |= ERR_FILES; 230*7c478bd9Sstevel@tonic-gate } 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate 233*7c478bd9Sstevel@tonic-gate (void) fclose(file); 234*7c478bd9Sstevel@tonic-gate return (errs); 235*7c478bd9Sstevel@tonic-gate } 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate /* 238*7c478bd9Sstevel@tonic-gate * routine: 239*7c478bd9Sstevel@tonic-gate * read_cmd 240*7c478bd9Sstevel@tonic-gate * 241*7c478bd9Sstevel@tonic-gate * purpose: 242*7c478bd9Sstevel@tonic-gate * to lex a runnable command (! lines) into a buffer 243*7c478bd9Sstevel@tonic-gate * 244*7c478bd9Sstevel@tonic-gate * parameters: 245*7c478bd9Sstevel@tonic-gate * first token 246*7c478bd9Sstevel@tonic-gate * 247*7c478bd9Sstevel@tonic-gate * returns: 248*7c478bd9Sstevel@tonic-gate * pointer to a command line in a static buffer 249*7c478bd9Sstevel@tonic-gate * (it is assumed the caller will copy it promptly) 250*7c478bd9Sstevel@tonic-gate * 251*7c478bd9Sstevel@tonic-gate * notes: 252*7c478bd9Sstevel@tonic-gate * this is necessary because lex has already choped off 253*7c478bd9Sstevel@tonic-gate * the first token for us 254*7c478bd9Sstevel@tonic-gate */ 255*7c478bd9Sstevel@tonic-gate static char *read_cmd(char * s) 256*7c478bd9Sstevel@tonic-gate { 257*7c478bd9Sstevel@tonic-gate static char cmdbuf[ MAX_LINE ]; 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate cmdbuf[0] = 0; 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate do { 262*7c478bd9Sstevel@tonic-gate if (*s) { 263*7c478bd9Sstevel@tonic-gate strcat(cmdbuf, s); 264*7c478bd9Sstevel@tonic-gate strcat(cmdbuf, " "); 265*7c478bd9Sstevel@tonic-gate } 266*7c478bd9Sstevel@tonic-gate } while ((s = lex(0)) != 0); 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate return (cmdbuf); 269*7c478bd9Sstevel@tonic-gate } 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate /* 272*7c478bd9Sstevel@tonic-gate * routine: 273*7c478bd9Sstevel@tonic-gate * write_rules 274*7c478bd9Sstevel@tonic-gate * 275*7c478bd9Sstevel@tonic-gate * purpose: 276*7c478bd9Sstevel@tonic-gate * to rewrite the rules file, appending the new rules 277*7c478bd9Sstevel@tonic-gate * 278*7c478bd9Sstevel@tonic-gate * parameters: 279*7c478bd9Sstevel@tonic-gate * name of output file 280*7c478bd9Sstevel@tonic-gate * 281*7c478bd9Sstevel@tonic-gate * returns: 282*7c478bd9Sstevel@tonic-gate * error mask 283*7c478bd9Sstevel@tonic-gate * 284*7c478bd9Sstevel@tonic-gate */ 285*7c478bd9Sstevel@tonic-gate errmask_t 286*7c478bd9Sstevel@tonic-gate write_rules(char *name) 287*7c478bd9Sstevel@tonic-gate { FILE *newfile; 288*7c478bd9Sstevel@tonic-gate errmask_t errs = 0; 289*7c478bd9Sstevel@tonic-gate struct base *bp; 290*7c478bd9Sstevel@tonic-gate char tmpname[ MAX_PATH ]; 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate /* if no-touch is specified, we don't update files */ 293*7c478bd9Sstevel@tonic-gate if (opt_notouch || rules_added == 0) 294*7c478bd9Sstevel@tonic-gate return (0); 295*7c478bd9Sstevel@tonic-gate 296*7c478bd9Sstevel@tonic-gate /* create a temporary output file */ 297*7c478bd9Sstevel@tonic-gate sprintf(tmpname, "%s-TMP", name); 298*7c478bd9Sstevel@tonic-gate 299*7c478bd9Sstevel@tonic-gate /* create our output file */ 300*7c478bd9Sstevel@tonic-gate newfile = fopen(tmpname, "w+"); 301*7c478bd9Sstevel@tonic-gate if (newfile == NULL) { 302*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(ERR_creat), gettext(TXT_rules), 303*7c478bd9Sstevel@tonic-gate name); 304*7c478bd9Sstevel@tonic-gate return (ERR_FILES); 305*7c478bd9Sstevel@tonic-gate } 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate if (opt_debug & DBG_FILES) 308*7c478bd9Sstevel@tonic-gate fprintf(stderr, "FILE: UPDATE RULES %s\n", name); 309*7c478bd9Sstevel@tonic-gate 310*7c478bd9Sstevel@tonic-gate errs |= rw_header(newfile); 311*7c478bd9Sstevel@tonic-gate errs |= rw_base(newfile, &omnibase); 312*7c478bd9Sstevel@tonic-gate for (bp = bases; bp; bp = bp->b_next) 313*7c478bd9Sstevel@tonic-gate errs |= rw_base(newfile, bp); 314*7c478bd9Sstevel@tonic-gate 315*7c478bd9Sstevel@tonic-gate if (ferror(newfile)) { 316*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(ERR_write), gettext(TXT_rules), 317*7c478bd9Sstevel@tonic-gate tmpname); 318*7c478bd9Sstevel@tonic-gate errs |= ERR_FILES; 319*7c478bd9Sstevel@tonic-gate } 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate if (fclose(newfile)) { 322*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(ERR_fclose), gettext(TXT_rules), 323*7c478bd9Sstevel@tonic-gate tmpname); 324*7c478bd9Sstevel@tonic-gate errs |= ERR_FILES; 325*7c478bd9Sstevel@tonic-gate } 326*7c478bd9Sstevel@tonic-gate 327*7c478bd9Sstevel@tonic-gate /* now switch the new file for the old one */ 328*7c478bd9Sstevel@tonic-gate if (errs == 0) 329*7c478bd9Sstevel@tonic-gate if (rename(tmpname, name) != 0) { 330*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(ERR_rename), 331*7c478bd9Sstevel@tonic-gate gettext(TXT_rules), tmpname, name); 332*7c478bd9Sstevel@tonic-gate errs |= ERR_FILES; 333*7c478bd9Sstevel@tonic-gate } 334*7c478bd9Sstevel@tonic-gate 335*7c478bd9Sstevel@tonic-gate return (errs); 336*7c478bd9Sstevel@tonic-gate } 337*7c478bd9Sstevel@tonic-gate 338*7c478bd9Sstevel@tonic-gate /* 339*7c478bd9Sstevel@tonic-gate * routine: 340*7c478bd9Sstevel@tonic-gate * rw_header 341*7c478bd9Sstevel@tonic-gate * 342*7c478bd9Sstevel@tonic-gate * purpose: 343*7c478bd9Sstevel@tonic-gate * to write out a rules header 344*7c478bd9Sstevel@tonic-gate * 345*7c478bd9Sstevel@tonic-gate * parameters: 346*7c478bd9Sstevel@tonic-gate * FILE* for the output file 347*7c478bd9Sstevel@tonic-gate * 348*7c478bd9Sstevel@tonic-gate * returns: 349*7c478bd9Sstevel@tonic-gate * error mask 350*7c478bd9Sstevel@tonic-gate * 351*7c478bd9Sstevel@tonic-gate * notes: 352*7c478bd9Sstevel@tonic-gate */ 353*7c478bd9Sstevel@tonic-gate static errmask_t rw_header(FILE *file) 354*7c478bd9Sstevel@tonic-gate { 355*7c478bd9Sstevel@tonic-gate time_t now; 356*7c478bd9Sstevel@tonic-gate struct tm *local; 357*7c478bd9Sstevel@tonic-gate 358*7c478bd9Sstevel@tonic-gate /* figure out what time it is */ 359*7c478bd9Sstevel@tonic-gate (void) time(&now); 360*7c478bd9Sstevel@tonic-gate local = localtime(&now); 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate fprintf(file, "%s %d.%d\n", RULE_TAG, RULE_MAJOR, RULE_MINOR); 363*7c478bd9Sstevel@tonic-gate fprintf(file, "#\n"); 364*7c478bd9Sstevel@tonic-gate fprintf(file, "# filesync rules, last written by %s, %s", 365*7c478bd9Sstevel@tonic-gate cuserid((char *) 0), asctime(local)); 366*7c478bd9Sstevel@tonic-gate fprintf(file, "#\n"); 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate return (0); 369*7c478bd9Sstevel@tonic-gate } 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate /* 372*7c478bd9Sstevel@tonic-gate * routine: 373*7c478bd9Sstevel@tonic-gate * rw_base 374*7c478bd9Sstevel@tonic-gate * 375*7c478bd9Sstevel@tonic-gate * purpose: 376*7c478bd9Sstevel@tonic-gate * to write out the summary for one base-pair 377*7c478bd9Sstevel@tonic-gate * 378*7c478bd9Sstevel@tonic-gate * parameters: 379*7c478bd9Sstevel@tonic-gate * FILE * for the output file 380*7c478bd9Sstevel@tonic-gate * 381*7c478bd9Sstevel@tonic-gate * returns: 382*7c478bd9Sstevel@tonic-gate * error mask 383*7c478bd9Sstevel@tonic-gate * 384*7c478bd9Sstevel@tonic-gate * notes: 385*7c478bd9Sstevel@tonic-gate */ 386*7c478bd9Sstevel@tonic-gate static errmask_t rw_base(FILE *file, struct base *bp) 387*7c478bd9Sstevel@tonic-gate { struct rule *rp; 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate fprintf(file, "\n"); 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate /* global rules don't appear within a base */ 392*7c478bd9Sstevel@tonic-gate if (bp->b_ident) 393*7c478bd9Sstevel@tonic-gate fprintf(file, "BASE %s %s\n", noblanks(bp->b_src_spec), 394*7c478bd9Sstevel@tonic-gate noblanks(bp->b_dst_spec)); 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate for (rp = bp->b_includes; rp; rp = rp->r_next) 397*7c478bd9Sstevel@tonic-gate if (rp->r_flags & R_PROGRAM) 398*7c478bd9Sstevel@tonic-gate fprintf(file, "LIST !%s\n", rp->r_file); 399*7c478bd9Sstevel@tonic-gate else 400*7c478bd9Sstevel@tonic-gate fprintf(file, "LIST %s\n", noblanks(rp->r_file)); 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate for (rp = bp->b_excludes; rp; rp = rp->r_next) 403*7c478bd9Sstevel@tonic-gate if (rp->r_flags & R_PROGRAM) 404*7c478bd9Sstevel@tonic-gate fprintf(file, "IGNORE !%s\n", rp->r_file); 405*7c478bd9Sstevel@tonic-gate else 406*7c478bd9Sstevel@tonic-gate fprintf(file, "IGNORE %s\n", noblanks(rp->r_file)); 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate return (0); 409*7c478bd9Sstevel@tonic-gate } 410*7c478bd9Sstevel@tonic-gate 411*7c478bd9Sstevel@tonic-gate /* 412*7c478bd9Sstevel@tonic-gate * routine: 413*7c478bd9Sstevel@tonic-gate * add_rule 414*7c478bd9Sstevel@tonic-gate * 415*7c478bd9Sstevel@tonic-gate * purpose: 416*7c478bd9Sstevel@tonic-gate * to add a new rule 417*7c478bd9Sstevel@tonic-gate * 418*7c478bd9Sstevel@tonic-gate * parameters: 419*7c478bd9Sstevel@tonic-gate * pointer to list base 420*7c478bd9Sstevel@tonic-gate * rule flags 421*7c478bd9Sstevel@tonic-gate * associated name/arguments 422*7c478bd9Sstevel@tonic-gate * 423*7c478bd9Sstevel@tonic-gate * returns: 424*7c478bd9Sstevel@tonic-gate * error flags 425*7c478bd9Sstevel@tonic-gate * 426*7c478bd9Sstevel@tonic-gate * notes: 427*7c478bd9Sstevel@tonic-gate * we always copy the argument string because most of them 428*7c478bd9Sstevel@tonic-gate * were read from a file and are just in a transient buffer 429*7c478bd9Sstevel@tonic-gate */ 430*7c478bd9Sstevel@tonic-gate static errmask_t add_rule(struct base *bp, int flags, const char *args) 431*7c478bd9Sstevel@tonic-gate { struct rule *rp; 432*7c478bd9Sstevel@tonic-gate struct rule **list; 433*7c478bd9Sstevel@tonic-gate 434*7c478bd9Sstevel@tonic-gate rp = malloc(sizeof (struct rule)); 435*7c478bd9Sstevel@tonic-gate if (rp == 0) 436*7c478bd9Sstevel@tonic-gate nomem("rule struture"); 437*7c478bd9Sstevel@tonic-gate 438*7c478bd9Sstevel@tonic-gate /* initialize the new base */ 439*7c478bd9Sstevel@tonic-gate memset((void *) rp, 0, sizeof (struct rule)); 440*7c478bd9Sstevel@tonic-gate rp->r_flags = flags; 441*7c478bd9Sstevel@tonic-gate rp->r_file = strdup(args); 442*7c478bd9Sstevel@tonic-gate 443*7c478bd9Sstevel@tonic-gate /* figure out which list to put it on */ 444*7c478bd9Sstevel@tonic-gate if (flags&R_IGNORE) 445*7c478bd9Sstevel@tonic-gate list = &bp->b_excludes; 446*7c478bd9Sstevel@tonic-gate else if (flags&R_RESTRICT) 447*7c478bd9Sstevel@tonic-gate list = &bp->b_restrictions; 448*7c478bd9Sstevel@tonic-gate else 449*7c478bd9Sstevel@tonic-gate list = &bp->b_includes; 450*7c478bd9Sstevel@tonic-gate 451*7c478bd9Sstevel@tonic-gate while (*list) 452*7c478bd9Sstevel@tonic-gate list = &((*list)->r_next); 453*7c478bd9Sstevel@tonic-gate *list = rp; 454*7c478bd9Sstevel@tonic-gate 455*7c478bd9Sstevel@tonic-gate if (flags & R_NEW) 456*7c478bd9Sstevel@tonic-gate rules_added++; 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate if (opt_debug & DBG_RULE) { 459*7c478bd9Sstevel@tonic-gate fprintf(stderr, "RULE: base=%d, ", bp->b_ident); 460*7c478bd9Sstevel@tonic-gate fprintf(stderr, "flags=%s, ", 461*7c478bd9Sstevel@tonic-gate showflags(rflags, rp->r_flags)); 462*7c478bd9Sstevel@tonic-gate fprintf(stderr, "arg=%s\n", rp->r_file); 463*7c478bd9Sstevel@tonic-gate } 464*7c478bd9Sstevel@tonic-gate 465*7c478bd9Sstevel@tonic-gate return (0); 466*7c478bd9Sstevel@tonic-gate } 467*7c478bd9Sstevel@tonic-gate 468*7c478bd9Sstevel@tonic-gate /* 469*7c478bd9Sstevel@tonic-gate * routine: 470*7c478bd9Sstevel@tonic-gate * add_ignore, add_include 471*7c478bd9Sstevel@tonic-gate * 472*7c478bd9Sstevel@tonic-gate * purpose: 473*7c478bd9Sstevel@tonic-gate * wrappers for add_rule that permit outsiders (like main.c) 474*7c478bd9Sstevel@tonic-gate * not to know what is inside of a base, file, or list entry 475*7c478bd9Sstevel@tonic-gate * 476*7c478bd9Sstevel@tonic-gate * parameters: 477*7c478bd9Sstevel@tonic-gate * base under which rules should be added 478*7c478bd9Sstevel@tonic-gate * argument associated with rule 479*7c478bd9Sstevel@tonic-gate * 480*7c478bd9Sstevel@tonic-gate * returns: 481*7c478bd9Sstevel@tonic-gate * error flags 482*7c478bd9Sstevel@tonic-gate * 483*7c478bd9Sstevel@tonic-gate * notes: 484*7c478bd9Sstevel@tonic-gate * basically these routines figure out what the right 485*7c478bd9Sstevel@tonic-gate * flags are for a rule, and what list to put it on, 486*7c478bd9Sstevel@tonic-gate * and then call a common handler. 487*7c478bd9Sstevel@tonic-gate */ 488*7c478bd9Sstevel@tonic-gate errmask_t 489*7c478bd9Sstevel@tonic-gate add_ignore(struct base *bp, char *name) 490*7c478bd9Sstevel@tonic-gate { int flags = R_IGNORE | R_NEW; 491*7c478bd9Sstevel@tonic-gate 492*7c478bd9Sstevel@tonic-gate if (bp == 0) 493*7c478bd9Sstevel@tonic-gate bp = &omnibase; 494*7c478bd9Sstevel@tonic-gate 495*7c478bd9Sstevel@tonic-gate if (wildcards(name)) 496*7c478bd9Sstevel@tonic-gate flags |= R_WILD; 497*7c478bd9Sstevel@tonic-gate 498*7c478bd9Sstevel@tonic-gate return (add_rule(bp, flags, name)); 499*7c478bd9Sstevel@tonic-gate } 500*7c478bd9Sstevel@tonic-gate 501*7c478bd9Sstevel@tonic-gate errmask_t 502*7c478bd9Sstevel@tonic-gate add_include(struct base *bp, char *name) 503*7c478bd9Sstevel@tonic-gate { int flags = R_NEW; 504*7c478bd9Sstevel@tonic-gate 505*7c478bd9Sstevel@tonic-gate if (bp == 0) 506*7c478bd9Sstevel@tonic-gate bp = &omnibase; 507*7c478bd9Sstevel@tonic-gate 508*7c478bd9Sstevel@tonic-gate if (wildcards(name)) 509*7c478bd9Sstevel@tonic-gate flags |= R_WILD; 510*7c478bd9Sstevel@tonic-gate 511*7c478bd9Sstevel@tonic-gate bp->b_flags |= F_LISTED; 512*7c478bd9Sstevel@tonic-gate 513*7c478bd9Sstevel@tonic-gate return (add_rule(bp, flags, name)); 514*7c478bd9Sstevel@tonic-gate } 515*7c478bd9Sstevel@tonic-gate 516*7c478bd9Sstevel@tonic-gate /* 517*7c478bd9Sstevel@tonic-gate * routine: 518*7c478bd9Sstevel@tonic-gate * add_restr 519*7c478bd9Sstevel@tonic-gate * 520*7c478bd9Sstevel@tonic-gate * purpose: 521*7c478bd9Sstevel@tonic-gate * to add a restriction to a base 522*7c478bd9Sstevel@tonic-gate * 523*7c478bd9Sstevel@tonic-gate * parameters: 524*7c478bd9Sstevel@tonic-gate * address of base 525*7c478bd9Sstevel@tonic-gate * restriction string 526*7c478bd9Sstevel@tonic-gate * 527*7c478bd9Sstevel@tonic-gate * returns: 528*7c478bd9Sstevel@tonic-gate * error mask 529*7c478bd9Sstevel@tonic-gate * 530*7c478bd9Sstevel@tonic-gate * notes: 531*7c478bd9Sstevel@tonic-gate * a restriction is specified on the command line and 532*7c478bd9Sstevel@tonic-gate * tells us to limit our analysis/reconcilation to 533*7c478bd9Sstevel@tonic-gate * specified files and/or directories. We deal with 534*7c478bd9Sstevel@tonic-gate * these by adding a restriction rule to any base that 535*7c478bd9Sstevel@tonic-gate * looks like it might fit the restriction. We need to 536*7c478bd9Sstevel@tonic-gate * treat this as a rule because the restriction string 537*7c478bd9Sstevel@tonic-gate * may extend beyond the base directory and part-way into 538*7c478bd9Sstevel@tonic-gate * its tree ... meaning that individual file names under 539*7c478bd9Sstevel@tonic-gate * the base will have to be checked against the restriction. 540*7c478bd9Sstevel@tonic-gate */ 541*7c478bd9Sstevel@tonic-gate errmask_t 542*7c478bd9Sstevel@tonic-gate add_restr(char *restr) 543*7c478bd9Sstevel@tonic-gate { const char *s; 544*7c478bd9Sstevel@tonic-gate errmask_t errs = 0; 545*7c478bd9Sstevel@tonic-gate struct base *bp; 546*7c478bd9Sstevel@tonic-gate 547*7c478bd9Sstevel@tonic-gate for (bp = bases; bp; bp = bp->b_next) { 548*7c478bd9Sstevel@tonic-gate /* 549*7c478bd9Sstevel@tonic-gate * see if this restriction could apply to this base. 550*7c478bd9Sstevel@tonic-gate * It could match either the source or destination 551*7c478bd9Sstevel@tonic-gate * directory name for this base. If it matches neither 552*7c478bd9Sstevel@tonic-gate * then the restriction does not apply to this base. 553*7c478bd9Sstevel@tonic-gate */ 554*7c478bd9Sstevel@tonic-gate s = prefix(restr, bp->b_src_name); 555*7c478bd9Sstevel@tonic-gate if (s == 0) 556*7c478bd9Sstevel@tonic-gate s = prefix(restr, bp->b_dst_name); 557*7c478bd9Sstevel@tonic-gate if (s == 0) 558*7c478bd9Sstevel@tonic-gate continue; 559*7c478bd9Sstevel@tonic-gate 560*7c478bd9Sstevel@tonic-gate /* 561*7c478bd9Sstevel@tonic-gate * if there is more restriction string after the 562*7c478bd9Sstevel@tonic-gate * base, we will need to note the remainder of the 563*7c478bd9Sstevel@tonic-gate * string so that we can match individual files 564*7c478bd9Sstevel@tonic-gate * against it. 565*7c478bd9Sstevel@tonic-gate */ 566*7c478bd9Sstevel@tonic-gate if (*s == '/') 567*7c478bd9Sstevel@tonic-gate s++; 568*7c478bd9Sstevel@tonic-gate 569*7c478bd9Sstevel@tonic-gate errs |= add_rule(bp, R_RESTRICT, s); 570*7c478bd9Sstevel@tonic-gate restr_added++; 571*7c478bd9Sstevel@tonic-gate } 572*7c478bd9Sstevel@tonic-gate 573*7c478bd9Sstevel@tonic-gate return (errs); 574*7c478bd9Sstevel@tonic-gate } 575*7c478bd9Sstevel@tonic-gate 576*7c478bd9Sstevel@tonic-gate /* 577*7c478bd9Sstevel@tonic-gate * routine: 578*7c478bd9Sstevel@tonic-gate * check_restr 579*7c478bd9Sstevel@tonic-gate * 580*7c478bd9Sstevel@tonic-gate * purpose: 581*7c478bd9Sstevel@tonic-gate * to see if an argument falls within restrictions 582*7c478bd9Sstevel@tonic-gate * 583*7c478bd9Sstevel@tonic-gate * parameters: 584*7c478bd9Sstevel@tonic-gate * pointer to relevent base 585*7c478bd9Sstevel@tonic-gate * file name 586*7c478bd9Sstevel@tonic-gate * 587*7c478bd9Sstevel@tonic-gate * returns: 588*7c478bd9Sstevel@tonic-gate * TRUE name is within restrictions 589*7c478bd9Sstevel@tonic-gate * FALSE name is outside of restrictions 590*7c478bd9Sstevel@tonic-gate * MAYBE name is on the path to a restriction 591*7c478bd9Sstevel@tonic-gate * 592*7c478bd9Sstevel@tonic-gate * notes: 593*7c478bd9Sstevel@tonic-gate * if no restrictions have been specified, we evaluate 594*7c478bd9Sstevel@tonic-gate * everything. If any restrictions have been specified, 595*7c478bd9Sstevel@tonic-gate * we process only files that match one of the restrictions. 596*7c478bd9Sstevel@tonic-gate * 597*7c478bd9Sstevel@tonic-gate * add_restr has ensured that if the restriction includes 598*7c478bd9Sstevel@tonic-gate * a portion that must be matched by individual files under 599*7c478bd9Sstevel@tonic-gate * the base, that the restriction rule will contain that 600*7c478bd9Sstevel@tonic-gate * portion of the restriction which must be matched against 601*7c478bd9Sstevel@tonic-gate * individual file names. 602*7c478bd9Sstevel@tonic-gate */ 603*7c478bd9Sstevel@tonic-gate bool_t 604*7c478bd9Sstevel@tonic-gate check_restr(struct base *bp, const char *name) 605*7c478bd9Sstevel@tonic-gate { struct rule *rp; 606*7c478bd9Sstevel@tonic-gate 607*7c478bd9Sstevel@tonic-gate /* if there are no restrictions, everything is OK */ 608*7c478bd9Sstevel@tonic-gate if (restr_added == 0) 609*7c478bd9Sstevel@tonic-gate return (TRUE); 610*7c478bd9Sstevel@tonic-gate 611*7c478bd9Sstevel@tonic-gate /* now we have to run through the list */ 612*7c478bd9Sstevel@tonic-gate for (rp = bp->b_restrictions; rp; rp = rp->r_next) { 613*7c478bd9Sstevel@tonic-gate /* see if current path is under the restriction */ 614*7c478bd9Sstevel@tonic-gate if (prefix(name, rp->r_file)) 615*7c478bd9Sstevel@tonic-gate return (TRUE); 616*7c478bd9Sstevel@tonic-gate 617*7c478bd9Sstevel@tonic-gate /* see if current path is on the way to restr */ 618*7c478bd9Sstevel@tonic-gate if (prefix(rp->r_file, name)) 619*7c478bd9Sstevel@tonic-gate /* 620*7c478bd9Sstevel@tonic-gate * this is kinky, but walker really needs 621*7c478bd9Sstevel@tonic-gate * to know the difference between a directory 622*7c478bd9Sstevel@tonic-gate * that we are unreservedly scanning, and one 623*7c478bd9Sstevel@tonic-gate * that we are scanning only to find something 624*7c478bd9Sstevel@tonic-gate * beneath it. 625*7c478bd9Sstevel@tonic-gate */ 626*7c478bd9Sstevel@tonic-gate return (MAYBE); 627*7c478bd9Sstevel@tonic-gate } 628*7c478bd9Sstevel@tonic-gate 629*7c478bd9Sstevel@tonic-gate /* 630*7c478bd9Sstevel@tonic-gate * there are restrictions in effect and this file doesn't seem 631*7c478bd9Sstevel@tonic-gate * to meet any of them 632*7c478bd9Sstevel@tonic-gate */ 633*7c478bd9Sstevel@tonic-gate if (opt_debug & DBG_RULE) 634*7c478bd9Sstevel@tonic-gate fprintf(stderr, "RULE: FAIL RESTRICTION base=%d, file=%s\n", 635*7c478bd9Sstevel@tonic-gate bp->b_ident, name); 636*7c478bd9Sstevel@tonic-gate 637*7c478bd9Sstevel@tonic-gate return (FALSE); 638*7c478bd9Sstevel@tonic-gate } 639