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 1995-2003 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* 28*7c478bd9Sstevel@tonic-gate * module: 29*7c478bd9Sstevel@tonic-gate * main.c 30*7c478bd9Sstevel@tonic-gate * 31*7c478bd9Sstevel@tonic-gate * purpose: 32*7c478bd9Sstevel@tonic-gate * argument handling and top level dispatch 33*7c478bd9Sstevel@tonic-gate * 34*7c478bd9Sstevel@tonic-gate * contents: 35*7c478bd9Sstevel@tonic-gate * main argument handling and main loop 36*7c478bd9Sstevel@tonic-gate * usage (static) print out usage message 37*7c478bd9Sstevel@tonic-gate * confirm prompt the user for a confirmation and get it 38*7c478bd9Sstevel@tonic-gate * nomem fatal error handler for malloc failures 39*7c478bd9Sstevel@tonic-gate * findfiles (static) locate our baseline and rules files 40*7c478bd9Sstevel@tonic-gate * cleanup (static) unlock baseline and delete temp file 41*7c478bd9Sstevel@tonic-gate * check_access (static) do we have adequate access to a file/directory 42*7c478bd9Sstevel@tonic-gate * whoami (static) get uid/gid/umask 43*7c478bd9Sstevel@tonic-gate */ 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate #include <unistd.h> 48*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 49*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 50*7c478bd9Sstevel@tonic-gate #include <stdio.h> 51*7c478bd9Sstevel@tonic-gate #include <string.h> 52*7c478bd9Sstevel@tonic-gate #include <ctype.h> 53*7c478bd9Sstevel@tonic-gate #include <errno.h> 54*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate #include "filesync.h" 57*7c478bd9Sstevel@tonic-gate #include "database.h" 58*7c478bd9Sstevel@tonic-gate #include "messages.h" 59*7c478bd9Sstevel@tonic-gate #include "debug.h" 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate /* 62*7c478bd9Sstevel@tonic-gate * local routines in this module: 63*7c478bd9Sstevel@tonic-gate */ 64*7c478bd9Sstevel@tonic-gate static errmask_t findfiles(); /* find rule and baseline files */ 65*7c478bd9Sstevel@tonic-gate static void cleanup(int); /* cleanup locks and temps */ 66*7c478bd9Sstevel@tonic-gate static errmask_t check_access(char *, int *); /* check access to file */ 67*7c478bd9Sstevel@tonic-gate static void whoami(); /* gather information about me */ 68*7c478bd9Sstevel@tonic-gate static void usage(void); /* general usage */ 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate /* 72*7c478bd9Sstevel@tonic-gate * globals exported to the rest of the program 73*7c478bd9Sstevel@tonic-gate */ 74*7c478bd9Sstevel@tonic-gate bool_t opt_mtime; /* preserve modification times on propagations */ 75*7c478bd9Sstevel@tonic-gate bool_t opt_notouch; /* don't actually make any changes */ 76*7c478bd9Sstevel@tonic-gate bool_t opt_quiet; /* disable reconciliation command output */ 77*7c478bd9Sstevel@tonic-gate bool_t opt_verbose; /* enable analysis descriptions */ 78*7c478bd9Sstevel@tonic-gate side_t opt_force; /* designated winner for conflicts */ 79*7c478bd9Sstevel@tonic-gate side_t opt_oneway; /* one way only propagation */ 80*7c478bd9Sstevel@tonic-gate side_t opt_onesided; /* permit one-sided evaluation */ 81*7c478bd9Sstevel@tonic-gate bool_t opt_everything; /* everything must agree (modes/uid/gid) */ 82*7c478bd9Sstevel@tonic-gate bool_t opt_yes; /* pre-confirm massive deletions are OK */ 83*7c478bd9Sstevel@tonic-gate bool_t opt_acls; /* always scan for acls on all files */ 84*7c478bd9Sstevel@tonic-gate bool_t opt_errors; /* simulate errors on specified files */ 85*7c478bd9Sstevel@tonic-gate bool_t opt_halt; /* halt on propagation errors */ 86*7c478bd9Sstevel@tonic-gate dbgmask_t opt_debug; /* debug mask */ 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate uid_t my_uid; /* default UID for files I create */ 89*7c478bd9Sstevel@tonic-gate gid_t my_gid; /* default GID for files I create */ 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate static char *file_rules; /* name of rules file */ 92*7c478bd9Sstevel@tonic-gate static char *file_base; /* name of baseline file */ 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate static int new_baseline; /* are we creating a new baseline */ 95*7c478bd9Sstevel@tonic-gate static int new_rules; /* are we creating a new rules file */ 96*7c478bd9Sstevel@tonic-gate static int my_umask; /* default UMASK for files I create */ 97*7c478bd9Sstevel@tonic-gate static int lockfd; /* file descriptor for locking baseline */ 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate static char *rlist[MAX_RLIST]; 100*7c478bd9Sstevel@tonic-gate static int num_restrs = 0; 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate /* 103*7c478bd9Sstevel@tonic-gate * routine: 104*7c478bd9Sstevel@tonic-gate * main 105*7c478bd9Sstevel@tonic-gate * 106*7c478bd9Sstevel@tonic-gate * purpose: 107*7c478bd9Sstevel@tonic-gate * argument processing and primary dispatch 108*7c478bd9Sstevel@tonic-gate * 109*7c478bd9Sstevel@tonic-gate * returns: 110*7c478bd9Sstevel@tonic-gate * error codes per filesync.1 (ERR_* in filesync.h) 111*7c478bd9Sstevel@tonic-gate * 112*7c478bd9Sstevel@tonic-gate * notes: 113*7c478bd9Sstevel@tonic-gate * read filesync.1 in order to understand the argument processing 114*7c478bd9Sstevel@tonic-gate * 115*7c478bd9Sstevel@tonic-gate * most of the command line options just set some opt_ global 116*7c478bd9Sstevel@tonic-gate * variable that is later looked at by the code that actually 117*7c478bd9Sstevel@tonic-gate * implements the features. Only file names are really processed 118*7c478bd9Sstevel@tonic-gate * in this routine. 119*7c478bd9Sstevel@tonic-gate */ 120*7c478bd9Sstevel@tonic-gate void 121*7c478bd9Sstevel@tonic-gate main(int argc, char **argv) 122*7c478bd9Sstevel@tonic-gate { int i; 123*7c478bd9Sstevel@tonic-gate int c; 124*7c478bd9Sstevel@tonic-gate errmask_t errs = ERR_OK; 125*7c478bd9Sstevel@tonic-gate int do_prune = 0; 126*7c478bd9Sstevel@tonic-gate char *srcname = 0; 127*7c478bd9Sstevel@tonic-gate char *dstname = 0; 128*7c478bd9Sstevel@tonic-gate struct base *bp; 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate /* keep the error messages simple */ 131*7c478bd9Sstevel@tonic-gate argv[0] = "filesync"; 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate /* gather together all of the options */ 134*7c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "AaehmnqvyD:E:r:s:d:f:o:")) != EOF) 135*7c478bd9Sstevel@tonic-gate switch (c) { 136*7c478bd9Sstevel@tonic-gate case 'a': /* always scan for acls */ 137*7c478bd9Sstevel@tonic-gate opt_acls = TRUE; 138*7c478bd9Sstevel@tonic-gate break; 139*7c478bd9Sstevel@tonic-gate case 'e': /* everything agrees */ 140*7c478bd9Sstevel@tonic-gate opt_everything = TRUE; 141*7c478bd9Sstevel@tonic-gate break; 142*7c478bd9Sstevel@tonic-gate case 'h': /* halt on error */ 143*7c478bd9Sstevel@tonic-gate opt_halt = TRUE; 144*7c478bd9Sstevel@tonic-gate break; 145*7c478bd9Sstevel@tonic-gate case 'm': /* preserve modtimes */ 146*7c478bd9Sstevel@tonic-gate opt_mtime = TRUE; 147*7c478bd9Sstevel@tonic-gate break; 148*7c478bd9Sstevel@tonic-gate case 'n': /* notouch */ 149*7c478bd9Sstevel@tonic-gate opt_notouch = TRUE; 150*7c478bd9Sstevel@tonic-gate break; 151*7c478bd9Sstevel@tonic-gate case 'q': /* quiet */ 152*7c478bd9Sstevel@tonic-gate opt_quiet = TRUE; 153*7c478bd9Sstevel@tonic-gate break; 154*7c478bd9Sstevel@tonic-gate case 'v': /* verbose */ 155*7c478bd9Sstevel@tonic-gate opt_verbose = TRUE; 156*7c478bd9Sstevel@tonic-gate break; 157*7c478bd9Sstevel@tonic-gate case 'y': /* yes */ 158*7c478bd9Sstevel@tonic-gate opt_yes = TRUE; 159*7c478bd9Sstevel@tonic-gate break; 160*7c478bd9Sstevel@tonic-gate case 'D': /* debug options */ 161*7c478bd9Sstevel@tonic-gate if (!isdigit(optarg[0])) { 162*7c478bd9Sstevel@tonic-gate dbg_usage(); 163*7c478bd9Sstevel@tonic-gate exit(ERR_INVAL); 164*7c478bd9Sstevel@tonic-gate } 165*7c478bd9Sstevel@tonic-gate opt_debug |= strtol(optarg, (char **) NULL, 0); 166*7c478bd9Sstevel@tonic-gate break; 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate case 'E': /* error simulation */ 169*7c478bd9Sstevel@tonic-gate if (dbg_set_error(optarg)) { 170*7c478bd9Sstevel@tonic-gate err_usage(); 171*7c478bd9Sstevel@tonic-gate exit(ERR_INVAL); 172*7c478bd9Sstevel@tonic-gate } 173*7c478bd9Sstevel@tonic-gate opt_errors = TRUE; 174*7c478bd9Sstevel@tonic-gate break; 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate case 'f': /* force conflict resolution */ 177*7c478bd9Sstevel@tonic-gate switch (optarg[0]) { 178*7c478bd9Sstevel@tonic-gate case 's': 179*7c478bd9Sstevel@tonic-gate opt_force = OPT_SRC; 180*7c478bd9Sstevel@tonic-gate break; 181*7c478bd9Sstevel@tonic-gate case 'd': 182*7c478bd9Sstevel@tonic-gate opt_force = OPT_DST; 183*7c478bd9Sstevel@tonic-gate break; 184*7c478bd9Sstevel@tonic-gate case 'o': 185*7c478bd9Sstevel@tonic-gate opt_force = OPT_OLD; 186*7c478bd9Sstevel@tonic-gate break; 187*7c478bd9Sstevel@tonic-gate case 'n': 188*7c478bd9Sstevel@tonic-gate opt_force = OPT_NEW; 189*7c478bd9Sstevel@tonic-gate break; 190*7c478bd9Sstevel@tonic-gate default: 191*7c478bd9Sstevel@tonic-gate fprintf(stderr, 192*7c478bd9Sstevel@tonic-gate gettext(ERR_badopt), 193*7c478bd9Sstevel@tonic-gate c, optarg); 194*7c478bd9Sstevel@tonic-gate errs |= ERR_INVAL; 195*7c478bd9Sstevel@tonic-gate break; 196*7c478bd9Sstevel@tonic-gate } 197*7c478bd9Sstevel@tonic-gate break; 198*7c478bd9Sstevel@tonic-gate 199*7c478bd9Sstevel@tonic-gate case 'o': /* one way propagation */ 200*7c478bd9Sstevel@tonic-gate switch (optarg[0]) { 201*7c478bd9Sstevel@tonic-gate case 's': 202*7c478bd9Sstevel@tonic-gate opt_oneway = OPT_SRC; 203*7c478bd9Sstevel@tonic-gate break; 204*7c478bd9Sstevel@tonic-gate case 'd': 205*7c478bd9Sstevel@tonic-gate opt_oneway = OPT_DST; 206*7c478bd9Sstevel@tonic-gate break; 207*7c478bd9Sstevel@tonic-gate default: 208*7c478bd9Sstevel@tonic-gate fprintf(stderr, 209*7c478bd9Sstevel@tonic-gate gettext(ERR_badopt), 210*7c478bd9Sstevel@tonic-gate c, optarg); 211*7c478bd9Sstevel@tonic-gate errs |= ERR_INVAL; 212*7c478bd9Sstevel@tonic-gate break; 213*7c478bd9Sstevel@tonic-gate } 214*7c478bd9Sstevel@tonic-gate break; 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate case 'r': /* restricted reconciliation */ 217*7c478bd9Sstevel@tonic-gate if (num_restrs < MAX_RLIST) 218*7c478bd9Sstevel@tonic-gate rlist[ num_restrs++ ] = optarg; 219*7c478bd9Sstevel@tonic-gate else { 220*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(ERR_tomany), 221*7c478bd9Sstevel@tonic-gate MAX_RLIST); 222*7c478bd9Sstevel@tonic-gate errs |= ERR_INVAL; 223*7c478bd9Sstevel@tonic-gate } 224*7c478bd9Sstevel@tonic-gate break; 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate case 's': 227*7c478bd9Sstevel@tonic-gate if ((srcname = qualify(optarg)) == 0) 228*7c478bd9Sstevel@tonic-gate errs |= ERR_MISSING; 229*7c478bd9Sstevel@tonic-gate break; 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate case 'd': 232*7c478bd9Sstevel@tonic-gate if ((dstname = qualify(optarg)) == 0) 233*7c478bd9Sstevel@tonic-gate errs |= ERR_MISSING; 234*7c478bd9Sstevel@tonic-gate break; 235*7c478bd9Sstevel@tonic-gate 236*7c478bd9Sstevel@tonic-gate default: 237*7c478bd9Sstevel@tonic-gate case '?': 238*7c478bd9Sstevel@tonic-gate errs |= ERR_INVAL; 239*7c478bd9Sstevel@tonic-gate break; 240*7c478bd9Sstevel@tonic-gate } 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate if (opt_debug & DBG_MISC) 243*7c478bd9Sstevel@tonic-gate fprintf(stderr, "MISC: DBG=%s\n", showflags(dbgmap, opt_debug)); 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate /* if we have file names, we need a source and destination */ 246*7c478bd9Sstevel@tonic-gate if (optind < argc) { 247*7c478bd9Sstevel@tonic-gate if (srcname == 0) { 248*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(ERR_nosrc)); 249*7c478bd9Sstevel@tonic-gate errs |= ERR_INVAL; 250*7c478bd9Sstevel@tonic-gate } 251*7c478bd9Sstevel@tonic-gate if (dstname == 0) { 252*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(ERR_nodst)); 253*7c478bd9Sstevel@tonic-gate errs |= ERR_INVAL; 254*7c478bd9Sstevel@tonic-gate } 255*7c478bd9Sstevel@tonic-gate } 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate /* check for simple usage errors */ 258*7c478bd9Sstevel@tonic-gate if (errs & ERR_INVAL) { 259*7c478bd9Sstevel@tonic-gate usage(); 260*7c478bd9Sstevel@tonic-gate exit(errs); 261*7c478bd9Sstevel@tonic-gate } 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate /* locate our baseline and rules files */ 264*7c478bd9Sstevel@tonic-gate if (c = findfiles()) 265*7c478bd9Sstevel@tonic-gate exit(c); 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate /* figure out file creation defaults */ 268*7c478bd9Sstevel@tonic-gate whoami(); 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate /* read in our initial baseline */ 271*7c478bd9Sstevel@tonic-gate if (!new_baseline && (c = read_baseline(file_base))) 272*7c478bd9Sstevel@tonic-gate errs |= c; 273*7c478bd9Sstevel@tonic-gate 274*7c478bd9Sstevel@tonic-gate /* read in the rules file if we need or have rules */ 275*7c478bd9Sstevel@tonic-gate if (optind >= argc && new_rules) { 276*7c478bd9Sstevel@tonic-gate fprintf(stderr, ERR_nonames); 277*7c478bd9Sstevel@tonic-gate errs |= ERR_INVAL; 278*7c478bd9Sstevel@tonic-gate } else if (!new_rules) 279*7c478bd9Sstevel@tonic-gate errs |= read_rules(file_rules); 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate /* if anything has failed with our setup, go no further */ 282*7c478bd9Sstevel@tonic-gate if (errs) { 283*7c478bd9Sstevel@tonic-gate cleanup(errs); 284*7c478bd9Sstevel@tonic-gate exit(errs); 285*7c478bd9Sstevel@tonic-gate } 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate /* 288*7c478bd9Sstevel@tonic-gate * figure out whether or not we are willing to do a one-sided 289*7c478bd9Sstevel@tonic-gate * analysis (where we don't even look at the other side. This 290*7c478bd9Sstevel@tonic-gate * is an "I'm just curious what has changed" query, and we are 291*7c478bd9Sstevel@tonic-gate * only willing to do it if: 292*7c478bd9Sstevel@tonic-gate * we aren't actually going to do anything 293*7c478bd9Sstevel@tonic-gate * we have a baseline we can compare against 294*7c478bd9Sstevel@tonic-gate * otherwise, we are going to insist on being able to access 295*7c478bd9Sstevel@tonic-gate * both the source and destination. 296*7c478bd9Sstevel@tonic-gate */ 297*7c478bd9Sstevel@tonic-gate if (opt_notouch && !new_baseline) 298*7c478bd9Sstevel@tonic-gate opt_onesided = opt_oneway; 299*7c478bd9Sstevel@tonic-gate 300*7c478bd9Sstevel@tonic-gate /* 301*7c478bd9Sstevel@tonic-gate * there are two interested usage scenarios: 302*7c478bd9Sstevel@tonic-gate * file names specified 303*7c478bd9Sstevel@tonic-gate * create new rules for the specified files 304*7c478bd9Sstevel@tonic-gate * evaulate and reconcile only the specified files 305*7c478bd9Sstevel@tonic-gate * no file names specified 306*7c478bd9Sstevel@tonic-gate * use already existing rules 307*7c478bd9Sstevel@tonic-gate * consider restricting them to specified subdirs/files 308*7c478bd9Sstevel@tonic-gate */ 309*7c478bd9Sstevel@tonic-gate if (optind < argc) { 310*7c478bd9Sstevel@tonic-gate /* figure out what base pair we're working on */ 311*7c478bd9Sstevel@tonic-gate bp = add_base(srcname, dstname); 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate /* perverse default rules to avoid trouble */ 314*7c478bd9Sstevel@tonic-gate if (new_rules) { 315*7c478bd9Sstevel@tonic-gate errs |= add_ignore(0, SUFX_RULES); 316*7c478bd9Sstevel@tonic-gate errs |= add_ignore(0, SUFX_BASE); 317*7c478bd9Sstevel@tonic-gate } 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate /* create include rules for each file/dir arg */ 320*7c478bd9Sstevel@tonic-gate while (optind < argc) 321*7c478bd9Sstevel@tonic-gate errs |= add_include(bp, argv[ optind++ ]); 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate /* 324*7c478bd9Sstevel@tonic-gate * evaluate the specified base on each side, 325*7c478bd9Sstevel@tonic-gate * being careful to limit evaulation to new rules 326*7c478bd9Sstevel@tonic-gate */ 327*7c478bd9Sstevel@tonic-gate errs |= evaluate(bp, OPT_SRC, TRUE); 328*7c478bd9Sstevel@tonic-gate errs |= evaluate(bp, OPT_DST, TRUE); 329*7c478bd9Sstevel@tonic-gate } else { 330*7c478bd9Sstevel@tonic-gate /* note any possible evaluation restrictions */ 331*7c478bd9Sstevel@tonic-gate for (i = 0; i < num_restrs; i++) 332*7c478bd9Sstevel@tonic-gate errs |= add_restr(rlist[i]); 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate /* 335*7c478bd9Sstevel@tonic-gate * we can only prune the baseline file if we have done 336*7c478bd9Sstevel@tonic-gate * a complete (unrestricted) analysis. 337*7c478bd9Sstevel@tonic-gate */ 338*7c478bd9Sstevel@tonic-gate if (i == 0) 339*7c478bd9Sstevel@tonic-gate do_prune = 1; 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate /* evaulate each base on each side */ 342*7c478bd9Sstevel@tonic-gate for (bp = bases; bp; bp = bp->b_next) { 343*7c478bd9Sstevel@tonic-gate errs |= evaluate(bp, OPT_SRC, FALSE); 344*7c478bd9Sstevel@tonic-gate errs |= evaluate(bp, OPT_DST, FALSE); 345*7c478bd9Sstevel@tonic-gate } 346*7c478bd9Sstevel@tonic-gate } 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate /* if anything serious happened, skip reconciliation */ 349*7c478bd9Sstevel@tonic-gate if (errs & ERR_FATAL) { 350*7c478bd9Sstevel@tonic-gate cleanup(errs); 351*7c478bd9Sstevel@tonic-gate exit(errs); 352*7c478bd9Sstevel@tonic-gate } 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate /* analyze and deal with the differenecs */ 355*7c478bd9Sstevel@tonic-gate errs |= analyze(); 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate /* see if there is any dead-wood in the baseline */ 358*7c478bd9Sstevel@tonic-gate if (do_prune) { 359*7c478bd9Sstevel@tonic-gate c = prune(); 360*7c478bd9Sstevel@tonic-gate 361*7c478bd9Sstevel@tonic-gate if (c > 0 && opt_verbose) 362*7c478bd9Sstevel@tonic-gate fprintf(stdout, V_prunes, c); 363*7c478bd9Sstevel@tonic-gate } 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate /* print out a final summary */ 366*7c478bd9Sstevel@tonic-gate summary(); 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate /* update the rules and baseline files (if needed) */ 369*7c478bd9Sstevel@tonic-gate (void) umask(my_umask); 370*7c478bd9Sstevel@tonic-gate errs |= write_baseline(file_base); 371*7c478bd9Sstevel@tonic-gate errs |= write_rules(file_rules); 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate if (opt_debug & DBG_MISC) 374*7c478bd9Sstevel@tonic-gate fprintf(stderr, "MISC: EXIT=%s\n", showflags(errmap, errs)); 375*7c478bd9Sstevel@tonic-gate 376*7c478bd9Sstevel@tonic-gate /* just returning ERR_RESOLVABLE upsets some people */ 377*7c478bd9Sstevel@tonic-gate if (errs == ERR_RESOLVABLE && !opt_notouch) 378*7c478bd9Sstevel@tonic-gate errs = 0; 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate /* all done */ 381*7c478bd9Sstevel@tonic-gate cleanup(0); 382*7c478bd9Sstevel@tonic-gate exit(errs); 383*7c478bd9Sstevel@tonic-gate } 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate /* 387*7c478bd9Sstevel@tonic-gate * routine: 388*7c478bd9Sstevel@tonic-gate * usage 389*7c478bd9Sstevel@tonic-gate * 390*7c478bd9Sstevel@tonic-gate * purpose: 391*7c478bd9Sstevel@tonic-gate * print out a usage message 392*7c478bd9Sstevel@tonic-gate * 393*7c478bd9Sstevel@tonic-gate * parameters: 394*7c478bd9Sstevel@tonic-gate * none 395*7c478bd9Sstevel@tonic-gate * 396*7c478bd9Sstevel@tonic-gate * returns: 397*7c478bd9Sstevel@tonic-gate * none 398*7c478bd9Sstevel@tonic-gate * 399*7c478bd9Sstevel@tonic-gate * note: 400*7c478bd9Sstevel@tonic-gate * the -D and -E switches are for development/test/support 401*7c478bd9Sstevel@tonic-gate * use only and do not show up in the general usage message. 402*7c478bd9Sstevel@tonic-gate */ 403*7c478bd9Sstevel@tonic-gate static void 404*7c478bd9Sstevel@tonic-gate usage(void) 405*7c478bd9Sstevel@tonic-gate { 406*7c478bd9Sstevel@tonic-gate fprintf(stderr, "%s\t%s %s\n", gettext(ERR_usage), "filesync", 407*7c478bd9Sstevel@tonic-gate gettext(USE_simple)); 408*7c478bd9Sstevel@tonic-gate fprintf(stderr, "\t%s %s\n", "filesync", gettext(USE_all)); 409*7c478bd9Sstevel@tonic-gate fprintf(stderr, "\t-a .......... %s\n", gettext(USE_a)); 410*7c478bd9Sstevel@tonic-gate fprintf(stderr, "\t-e .......... %s\n", gettext(USE_e)); 411*7c478bd9Sstevel@tonic-gate fprintf(stderr, "\t-h .......... %s\n", gettext(USE_h)); 412*7c478bd9Sstevel@tonic-gate fprintf(stderr, "\t-m .......... %s\n", gettext(USE_m)); 413*7c478bd9Sstevel@tonic-gate fprintf(stderr, "\t-n .......... %s\n", gettext(USE_n)); 414*7c478bd9Sstevel@tonic-gate fprintf(stderr, "\t-q .......... %s\n", gettext(USE_q)); 415*7c478bd9Sstevel@tonic-gate fprintf(stderr, "\t-v .......... %s\n", gettext(USE_v)); 416*7c478bd9Sstevel@tonic-gate fprintf(stderr, "\t-y .......... %s\n", gettext(USE_y)); 417*7c478bd9Sstevel@tonic-gate fprintf(stderr, "\t-s dir ...... %s\n", gettext(USE_s)); 418*7c478bd9Sstevel@tonic-gate fprintf(stderr, "\t-d dir ...... %s\n", gettext(USE_d)); 419*7c478bd9Sstevel@tonic-gate fprintf(stderr, "\t-r dir ...... %s\n", gettext(USE_r)); 420*7c478bd9Sstevel@tonic-gate fprintf(stderr, "\t-f [sdon].... %s\n", gettext(USE_f)); 421*7c478bd9Sstevel@tonic-gate fprintf(stderr, "\t-o src/dst... %s\n", gettext(USE_o)); 422*7c478bd9Sstevel@tonic-gate } 423*7c478bd9Sstevel@tonic-gate 424*7c478bd9Sstevel@tonic-gate /* 425*7c478bd9Sstevel@tonic-gate * routine: 426*7c478bd9Sstevel@tonic-gate * confirm 427*7c478bd9Sstevel@tonic-gate * 428*7c478bd9Sstevel@tonic-gate * purpose: 429*7c478bd9Sstevel@tonic-gate * to confirm that the user is willing to do something dangerous 430*7c478bd9Sstevel@tonic-gate * 431*7c478bd9Sstevel@tonic-gate * parameters: 432*7c478bd9Sstevel@tonic-gate * warning message to be printed 433*7c478bd9Sstevel@tonic-gate * 434*7c478bd9Sstevel@tonic-gate * returns: 435*7c478bd9Sstevel@tonic-gate * void 436*7c478bd9Sstevel@tonic-gate * 437*7c478bd9Sstevel@tonic-gate * notes: 438*7c478bd9Sstevel@tonic-gate * if this is a "notouch" or if the user has pre-confirmed, 439*7c478bd9Sstevel@tonic-gate * we should not obtain the confirmation and just return that 440*7c478bd9Sstevel@tonic-gate * the user has confirmed. 441*7c478bd9Sstevel@tonic-gate */ 442*7c478bd9Sstevel@tonic-gate void 443*7c478bd9Sstevel@tonic-gate confirm(char *message) 444*7c478bd9Sstevel@tonic-gate { FILE *ttyi, *ttyo; 445*7c478bd9Sstevel@tonic-gate char ansbuf[ MAX_LINE ]; 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate /* if user pre-confirmed, we don't have to ask */ 448*7c478bd9Sstevel@tonic-gate if (opt_yes || opt_notouch) 449*7c478bd9Sstevel@tonic-gate return; 450*7c478bd9Sstevel@tonic-gate 451*7c478bd9Sstevel@tonic-gate ttyo = fopen("/dev/tty", "w"); 452*7c478bd9Sstevel@tonic-gate ttyi = fopen("/dev/tty", "r"); 453*7c478bd9Sstevel@tonic-gate if (ttyi == NULL || ttyo == NULL) 454*7c478bd9Sstevel@tonic-gate exit(ERR_OTHER); 455*7c478bd9Sstevel@tonic-gate 456*7c478bd9Sstevel@tonic-gate /* explain the problem and prompt for confirmation */ 457*7c478bd9Sstevel@tonic-gate fprintf(ttyo, message); 458*7c478bd9Sstevel@tonic-gate fprintf(ttyo, gettext(WARN_proceed)); 459*7c478bd9Sstevel@tonic-gate 460*7c478bd9Sstevel@tonic-gate /* if the user doesn't kill us, we can continue */ 461*7c478bd9Sstevel@tonic-gate (void) fgets(ansbuf, sizeof (ansbuf), ttyi); 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate /* close the files and return */ 464*7c478bd9Sstevel@tonic-gate (void) fclose(ttyi); 465*7c478bd9Sstevel@tonic-gate (void) fclose(ttyo); 466*7c478bd9Sstevel@tonic-gate } 467*7c478bd9Sstevel@tonic-gate 468*7c478bd9Sstevel@tonic-gate void 469*7c478bd9Sstevel@tonic-gate nomem(char *reason) 470*7c478bd9Sstevel@tonic-gate { 471*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(ERR_nomem), reason); 472*7c478bd9Sstevel@tonic-gate exit(ERR_OTHER); 473*7c478bd9Sstevel@tonic-gate } 474*7c478bd9Sstevel@tonic-gate 475*7c478bd9Sstevel@tonic-gate /* 476*7c478bd9Sstevel@tonic-gate * routine: 477*7c478bd9Sstevel@tonic-gate * findfiles 478*7c478bd9Sstevel@tonic-gate * 479*7c478bd9Sstevel@tonic-gate * purpose: 480*7c478bd9Sstevel@tonic-gate * to locate our baseline and rules files 481*7c478bd9Sstevel@tonic-gate * 482*7c478bd9Sstevel@tonic-gate * parameters: 483*7c478bd9Sstevel@tonic-gate * none 484*7c478bd9Sstevel@tonic-gate * 485*7c478bd9Sstevel@tonic-gate * returns: 486*7c478bd9Sstevel@tonic-gate * error mask 487*7c478bd9Sstevel@tonic-gate * settings of file_base and file_rules 488*7c478bd9Sstevel@tonic-gate * 489*7c478bd9Sstevel@tonic-gate * side-effects: 490*7c478bd9Sstevel@tonic-gate * in order to keep multiple filesyncs from running in parallel 491*7c478bd9Sstevel@tonic-gate * we put an advisory lock on the baseline file. If the baseline 492*7c478bd9Sstevel@tonic-gate * file does not exist we create one. The unlocking (and deletion 493*7c478bd9Sstevel@tonic-gate * of extraneous baselines) is handled in cleanup. 494*7c478bd9Sstevel@tonic-gate */ 495*7c478bd9Sstevel@tonic-gate static errmask_t 496*7c478bd9Sstevel@tonic-gate findfiles(void) /* find rule and baseline files */ 497*7c478bd9Sstevel@tonic-gate { char *s, *where; 498*7c478bd9Sstevel@tonic-gate char namebuf[MAX_PATH]; 499*7c478bd9Sstevel@tonic-gate int ret; 500*7c478bd9Sstevel@tonic-gate errmask_t errs = 0; 501*7c478bd9Sstevel@tonic-gate 502*7c478bd9Sstevel@tonic-gate /* figure out where the files should be located */ 503*7c478bd9Sstevel@tonic-gate s = getenv("FILESYNC"); 504*7c478bd9Sstevel@tonic-gate where = (s && *s) ? expand(s) : expand(DFLT_PRFX); 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate /* see if we got a viable name */ 507*7c478bd9Sstevel@tonic-gate if (where == 0) { 508*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(ERR_nofsync)); 509*7c478bd9Sstevel@tonic-gate return (ERR_FILES); 510*7c478bd9Sstevel@tonic-gate } 511*7c478bd9Sstevel@tonic-gate 512*7c478bd9Sstevel@tonic-gate /* try to form the name of the rules file */ 513*7c478bd9Sstevel@tonic-gate strcpy(namebuf, where); 514*7c478bd9Sstevel@tonic-gate strcat(namebuf, SUFX_RULES); 515*7c478bd9Sstevel@tonic-gate s = strdup(namebuf); 516*7c478bd9Sstevel@tonic-gate errs = check_access(namebuf, &new_rules); 517*7c478bd9Sstevel@tonic-gate 518*7c478bd9Sstevel@tonic-gate /* if we cannot find a proper rules file, look in the old place */ 519*7c478bd9Sstevel@tonic-gate if (new_rules && errs == 0) { 520*7c478bd9Sstevel@tonic-gate strcpy(namebuf, where); 521*7c478bd9Sstevel@tonic-gate strcat(namebuf, SUFX_OLD); 522*7c478bd9Sstevel@tonic-gate file_rules = strdup(namebuf); 523*7c478bd9Sstevel@tonic-gate errs = check_access(namebuf, &new_rules); 524*7c478bd9Sstevel@tonic-gate 525*7c478bd9Sstevel@tonic-gate /* if we couldn't find that either, go with new name */ 526*7c478bd9Sstevel@tonic-gate if (new_rules && errs == 0) 527*7c478bd9Sstevel@tonic-gate file_rules = s; 528*7c478bd9Sstevel@tonic-gate } else 529*7c478bd9Sstevel@tonic-gate file_rules = s; 530*7c478bd9Sstevel@tonic-gate 531*7c478bd9Sstevel@tonic-gate /* try to form the name of the baseline file */ 532*7c478bd9Sstevel@tonic-gate strcpy(namebuf, where); 533*7c478bd9Sstevel@tonic-gate strcat(namebuf, SUFX_BASE); 534*7c478bd9Sstevel@tonic-gate file_base = strdup(namebuf); 535*7c478bd9Sstevel@tonic-gate errs |= check_access(namebuf, &new_baseline); 536*7c478bd9Sstevel@tonic-gate 537*7c478bd9Sstevel@tonic-gate if (opt_debug & DBG_FILES) { 538*7c478bd9Sstevel@tonic-gate fprintf(stderr, "FILE: %s rules file: %s\n", 539*7c478bd9Sstevel@tonic-gate new_rules ? "new" : "existing", file_rules); 540*7c478bd9Sstevel@tonic-gate 541*7c478bd9Sstevel@tonic-gate fprintf(stderr, "FILE: %s base file: %s\n", 542*7c478bd9Sstevel@tonic-gate new_baseline ? "new" : "existing", file_base); 543*7c478bd9Sstevel@tonic-gate } 544*7c478bd9Sstevel@tonic-gate 545*7c478bd9Sstevel@tonic-gate /* 546*7c478bd9Sstevel@tonic-gate * in order to lock out other filesync programs we need some 547*7c478bd9Sstevel@tonic-gate * file we can lock. We do an advisory lock on the baseline 548*7c478bd9Sstevel@tonic-gate * file. If no baseline file exists, we create an empty one. 549*7c478bd9Sstevel@tonic-gate */ 550*7c478bd9Sstevel@tonic-gate if (new_baseline) 551*7c478bd9Sstevel@tonic-gate lockfd = creat(file_base, 0666); 552*7c478bd9Sstevel@tonic-gate else 553*7c478bd9Sstevel@tonic-gate lockfd = open(file_base, O_RDWR); 554*7c478bd9Sstevel@tonic-gate 555*7c478bd9Sstevel@tonic-gate if (lockfd < 0) { 556*7c478bd9Sstevel@tonic-gate fprintf(stderr, new_baseline ? ERR_creat : ERR_open, 557*7c478bd9Sstevel@tonic-gate TXT_base, file_base); 558*7c478bd9Sstevel@tonic-gate errs |= ERR_FILES; 559*7c478bd9Sstevel@tonic-gate } else { 560*7c478bd9Sstevel@tonic-gate ret = lockf(lockfd, F_TLOCK, 0L); 561*7c478bd9Sstevel@tonic-gate if (ret < 0) { 562*7c478bd9Sstevel@tonic-gate fprintf(stderr, ERR_lock, TXT_base, file_base); 563*7c478bd9Sstevel@tonic-gate errs |= ERR_FILES; 564*7c478bd9Sstevel@tonic-gate } else if (opt_debug & DBG_FILES) 565*7c478bd9Sstevel@tonic-gate fprintf(stderr, "FILE: locking baseline file %s\n", 566*7c478bd9Sstevel@tonic-gate file_base); 567*7c478bd9Sstevel@tonic-gate } 568*7c478bd9Sstevel@tonic-gate 569*7c478bd9Sstevel@tonic-gate return (errs); 570*7c478bd9Sstevel@tonic-gate } 571*7c478bd9Sstevel@tonic-gate 572*7c478bd9Sstevel@tonic-gate /* 573*7c478bd9Sstevel@tonic-gate * routine: 574*7c478bd9Sstevel@tonic-gate * cleanup 575*7c478bd9Sstevel@tonic-gate * 576*7c478bd9Sstevel@tonic-gate * purpose: 577*7c478bd9Sstevel@tonic-gate * to clean up temporary files and locking prior to exit 578*7c478bd9Sstevel@tonic-gate * 579*7c478bd9Sstevel@tonic-gate * paremeters: 580*7c478bd9Sstevel@tonic-gate * error mask 581*7c478bd9Sstevel@tonic-gate * 582*7c478bd9Sstevel@tonic-gate * returns: 583*7c478bd9Sstevel@tonic-gate * void 584*7c478bd9Sstevel@tonic-gate * 585*7c478bd9Sstevel@tonic-gate * notes: 586*7c478bd9Sstevel@tonic-gate * if there are no errors, the baseline file is assumed to be good. 587*7c478bd9Sstevel@tonic-gate * Otherwise, if we created a temporary baseline file (just for 588*7c478bd9Sstevel@tonic-gate * locking) we will delete it. 589*7c478bd9Sstevel@tonic-gate */ 590*7c478bd9Sstevel@tonic-gate static void 591*7c478bd9Sstevel@tonic-gate cleanup(errmask_t errmask) 592*7c478bd9Sstevel@tonic-gate { 593*7c478bd9Sstevel@tonic-gate /* unlock the baseline file */ 594*7c478bd9Sstevel@tonic-gate if (opt_debug & DBG_FILES) 595*7c478bd9Sstevel@tonic-gate fprintf(stderr, "FILE: unlock baseline file %s\n", file_base); 596*7c478bd9Sstevel@tonic-gate (void) lockf(lockfd, F_ULOCK, 0); 597*7c478bd9Sstevel@tonic-gate 598*7c478bd9Sstevel@tonic-gate /* see if we need to delete a temporary copy */ 599*7c478bd9Sstevel@tonic-gate if (errmask && new_baseline) { 600*7c478bd9Sstevel@tonic-gate if (opt_debug & DBG_FILES) 601*7c478bd9Sstevel@tonic-gate fprintf(stderr, "FILE: unlink temp baseline file %s\n", 602*7c478bd9Sstevel@tonic-gate file_base); 603*7c478bd9Sstevel@tonic-gate (void) unlink(file_base); 604*7c478bd9Sstevel@tonic-gate } 605*7c478bd9Sstevel@tonic-gate } 606*7c478bd9Sstevel@tonic-gate 607*7c478bd9Sstevel@tonic-gate /* 608*7c478bd9Sstevel@tonic-gate * routine: 609*7c478bd9Sstevel@tonic-gate * check_access 610*7c478bd9Sstevel@tonic-gate * 611*7c478bd9Sstevel@tonic-gate * purpose: 612*7c478bd9Sstevel@tonic-gate * to determine whether or not we can access an existing file 613*7c478bd9Sstevel@tonic-gate * or create a new one 614*7c478bd9Sstevel@tonic-gate * 615*7c478bd9Sstevel@tonic-gate * parameters: 616*7c478bd9Sstevel@tonic-gate * name of file (in a clobberable buffer) 617*7c478bd9Sstevel@tonic-gate * pointer to new file flag 618*7c478bd9Sstevel@tonic-gate * 619*7c478bd9Sstevel@tonic-gate * returns: 620*7c478bd9Sstevel@tonic-gate * error mask 621*7c478bd9Sstevel@tonic-gate * setting of the new file flag 622*7c478bd9Sstevel@tonic-gate * 623*7c478bd9Sstevel@tonic-gate * note: 624*7c478bd9Sstevel@tonic-gate * it is kind of a kluge that this routine clobbers the name, 625*7c478bd9Sstevel@tonic-gate * but it is only called from one place, it needs a modified 626*7c478bd9Sstevel@tonic-gate * copy of the name, and the one caller doesn't mind. 627*7c478bd9Sstevel@tonic-gate */ 628*7c478bd9Sstevel@tonic-gate static errmask_t 629*7c478bd9Sstevel@tonic-gate check_access(char *name, int *newflag) 630*7c478bd9Sstevel@tonic-gate { char *s; 631*7c478bd9Sstevel@tonic-gate 632*7c478bd9Sstevel@tonic-gate /* start out by asking for what we want */ 633*7c478bd9Sstevel@tonic-gate if (access(name, R_OK|W_OK) == 0) { 634*7c478bd9Sstevel@tonic-gate *newflag = 0; 635*7c478bd9Sstevel@tonic-gate return (0); 636*7c478bd9Sstevel@tonic-gate } 637*7c478bd9Sstevel@tonic-gate 638*7c478bd9Sstevel@tonic-gate /* if the problem is isn't non-existance, lose */ 639*7c478bd9Sstevel@tonic-gate if (errno != ENOENT) { 640*7c478bd9Sstevel@tonic-gate *newflag = 0; 641*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(ERR_rdwri), name); 642*7c478bd9Sstevel@tonic-gate return (ERR_FILES); 643*7c478bd9Sstevel@tonic-gate } 644*7c478bd9Sstevel@tonic-gate 645*7c478bd9Sstevel@tonic-gate /* 646*7c478bd9Sstevel@tonic-gate * the file doesn't exist, so there is still hope if we can 647*7c478bd9Sstevel@tonic-gate * write in the directory that should contain the file 648*7c478bd9Sstevel@tonic-gate */ 649*7c478bd9Sstevel@tonic-gate *newflag = 1; 650*7c478bd9Sstevel@tonic-gate 651*7c478bd9Sstevel@tonic-gate /* truncate the file name to its containing directory */ 652*7c478bd9Sstevel@tonic-gate for (s = name; s[1]; s++); 653*7c478bd9Sstevel@tonic-gate while (s > name && *s != '/') 654*7c478bd9Sstevel@tonic-gate s--; 655*7c478bd9Sstevel@tonic-gate if (s > name) 656*7c478bd9Sstevel@tonic-gate *s = 0; 657*7c478bd9Sstevel@tonic-gate else if (*s == '/') 658*7c478bd9Sstevel@tonic-gate s[1] = 0; 659*7c478bd9Sstevel@tonic-gate else 660*7c478bd9Sstevel@tonic-gate name = "."; 661*7c478bd9Sstevel@tonic-gate 662*7c478bd9Sstevel@tonic-gate /* then see if we have write access to the directory */ 663*7c478bd9Sstevel@tonic-gate if (access(name, W_OK) == 0) 664*7c478bd9Sstevel@tonic-gate return (0); 665*7c478bd9Sstevel@tonic-gate 666*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(ERR_dirwac), name); 667*7c478bd9Sstevel@tonic-gate return (ERR_FILES); 668*7c478bd9Sstevel@tonic-gate } 669*7c478bd9Sstevel@tonic-gate 670*7c478bd9Sstevel@tonic-gate /* 671*7c478bd9Sstevel@tonic-gate * routine: 672*7c478bd9Sstevel@tonic-gate * whoami 673*7c478bd9Sstevel@tonic-gate * 674*7c478bd9Sstevel@tonic-gate * purpose: 675*7c478bd9Sstevel@tonic-gate * to figure out who I am and what the default modes/ownership 676*7c478bd9Sstevel@tonic-gate * is on files that I create. 677*7c478bd9Sstevel@tonic-gate */ 678*7c478bd9Sstevel@tonic-gate static void 679*7c478bd9Sstevel@tonic-gate whoami() 680*7c478bd9Sstevel@tonic-gate { 681*7c478bd9Sstevel@tonic-gate my_uid = geteuid(); 682*7c478bd9Sstevel@tonic-gate my_gid = getegid(); 683*7c478bd9Sstevel@tonic-gate my_umask = umask(0); 684*7c478bd9Sstevel@tonic-gate 685*7c478bd9Sstevel@tonic-gate if (opt_debug & DBG_MISC) 686*7c478bd9Sstevel@tonic-gate fprintf(stderr, "MISC: my_uid=%ld, my_gid=%ld, my_umask=%03o\n", 687*7c478bd9Sstevel@tonic-gate my_uid, my_gid, my_umask); 688*7c478bd9Sstevel@tonic-gate } 689