1 /* 2 * Copyright (c) 1992 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1992 The Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)chflags.c 5.3 (Berkeley) 06/01/92"; 16 #endif /* not lint */ 17 18 #include <sys/types.h> 19 #include <sys/stat.h> 20 #include <errno.h> 21 #include <fts.h> 22 #include <unistd.h> 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <string.h> 26 27 typedef struct cmdset { 28 long clrbits; 29 long setbits; 30 } CMDS; 31 CMDS cmds; 32 int retval; 33 34 void err __P((const char *, ...)); 35 void error __P((char *)); 36 int getflags __P((CMDS *, int)); 37 void *setflags __P((char *)); 38 void usage __P((void)); 39 40 int 41 main(argc, argv) 42 int argc; 43 char *argv[]; 44 { 45 register FTS *ftsp; 46 register FTSENT *p; 47 register long oflags; 48 register int oct; 49 register char *flags; 50 struct stat sb; 51 void *set; 52 int ch, rflag, hflag, Hflag; 53 char *ep; 54 int fts_options; 55 56 rflag = hflag = Hflag = 0; 57 fts_options = FTS_PHYSICAL; 58 while ((ch = getopt(argc, argv, "HRh")) != EOF) 59 switch((char)ch) { 60 case 'H': 61 Hflag = 1; 62 fts_options |= FTS_COMFOLLOW; 63 break; 64 case 'R': 65 rflag = 1; 66 break; 67 case 'h': 68 hflag = 1; 69 fts_options &= ~FTS_PHYSICAL; 70 fts_options |= FTS_LOGICAL; 71 break; 72 case '?': 73 default: 74 usage(); 75 } 76 argv += optind; 77 argc -= optind; 78 79 if (argc < 2) 80 usage(); 81 82 flags = *argv; 83 if (*flags >= '0' && *flags <= '7') { 84 oflags = (int)strtol(flags, &ep, 8); 85 if (oflags < 0 || *ep) 86 err("invalid flags: %s", flags); 87 oct = 1; 88 } else { 89 if ((set = setflags(flags)) == NULL) 90 err("invalid flags: %s", flags); 91 oct = 0; 92 } 93 94 retval = 0; 95 if (oct) 96 fts_options |= FTS_NOSTAT; 97 if (!(ftsp = fts_open(++argv, fts_options , 0))) 98 err("%s", strerror(errno)); 99 while (p = fts_read(ftsp)) 100 switch(p->fts_info) { 101 case FTS_D: 102 if (!rflag) 103 fts_set(ftsp, p, FTS_SKIP); 104 break; 105 case FTS_DNR: 106 case FTS_ERR: 107 case FTS_NS: 108 err("%s: %s", p->fts_path, strerror(errno)); 109 default: 110 if (p->fts_info == FTS_SL && 111 !(hflag || 112 (Hflag && p->fts_level == FTS_ROOTLEVEL))) 113 continue; 114 if (chflags(p->fts_accpath, oct ? oflags : 115 getflags(set, p->fts_statp->st_flags))) 116 error(p->fts_path); 117 break; 118 } 119 exit(retval); 120 } 121 122 /* 123 * These are analogous to the setmode/getmode routines in the C library. 124 */ 125 void * 126 setflags(cp) 127 char *cp; 128 { 129 register CMDS *fset; 130 register char *arg; 131 132 fset = &cmds; 133 fset->clrbits = 0; 134 fset->setbits = 0; 135 while (cp) { 136 while ((arg = strsep(&cp, ",")) != NULL && *arg == '\0') 137 /* void */; 138 if (!strcasecmp(arg, "dump")) 139 fset->clrbits |= NODUMP; 140 else if (!strcasecmp(arg, "nodump")) 141 fset->setbits |= NODUMP; 142 else 143 return (NULL); 144 } 145 return (fset); 146 } 147 148 int 149 getflags(fset, oflags) 150 register CMDS *fset; 151 register int oflags; 152 { 153 154 oflags &= ~fset->clrbits; 155 oflags |= fset->setbits; 156 return (oflags); 157 } 158 159 #if __STDC__ 160 #include <stdarg.h> 161 #else 162 #include <varargs.h> 163 #endif 164 165 void 166 #if __STDC__ 167 err(const char *fmt, ...) 168 #else 169 err(fmt, va_alist) 170 char *fmt; 171 va_dcl 172 #endif 173 { 174 va_list ap; 175 #if __STDC__ 176 va_start(ap, fmt); 177 #else 178 va_start(ap); 179 #endif 180 (void)fprintf(stderr, "chflags: "); 181 (void)vfprintf(stderr, fmt, ap); 182 va_end(ap); 183 (void)fprintf(stderr, "\n"); 184 exit(1); 185 /* NOTREACHED */ 186 } 187 188 void 189 error(name) 190 char *name; 191 { 192 (void)fprintf(stderr, "chflags: %s: %s.\n", name, strerror(errno)); 193 retval = 1; 194 } 195 196 void 197 usage() 198 { 199 (void)fprintf(stderr, "usage: chflags [-HRh] flags file ...\n"); 200 exit(1); 201 } 202