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.2 (Berkeley) 03/10/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 *fts; 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; 53 char *ep; 54 55 rflag = 0; 56 while ((ch = getopt(argc, argv, "R")) != EOF) 57 switch((char)ch) { 58 case 'R': 59 rflag = 1; 60 break; 61 case '?': 62 default: 63 usage(); 64 } 65 argv += optind; 66 argc -= optind; 67 68 if (argc < 2) 69 usage(); 70 71 flags = *argv; 72 if (*flags >= '0' && *flags <= '7') { 73 oflags = (int)strtol(flags, &ep, 8); 74 if (oflags < 0 || *ep) 75 err("invalid flags: %s", flags); 76 oct = 1; 77 } else { 78 if ((set = setflags(flags)) == NULL) 79 err("invalid flags: %s", flags); 80 oct = 0; 81 } 82 83 retval = 0; 84 if (rflag) { 85 if (!(fts = fts_open(++argv, 86 oct ? FTS_NOSTAT|FTS_PHYSICAL : FTS_PHYSICAL, 0))) 87 err("%s", strerror(errno)); 88 while (p = fts_read(fts)) 89 switch(p->fts_info) { 90 case FTS_D: 91 break; 92 case FTS_DNR: 93 case FTS_ERR: 94 case FTS_NS: 95 err("%s: %s", p->fts_path, strerror(errno)); 96 default: 97 if (chflags(p->fts_accpath, oct ? oflags : 98 getflags(set, p->fts_statp->st_flags))) 99 error(p->fts_path); 100 break; 101 } 102 exit(retval); 103 } 104 if (oct) { 105 while (*++argv) 106 if (chflags(*argv, oflags)) 107 error(*argv); 108 } else 109 while (*++argv) 110 if (lstat(*argv, &sb) || 111 chflags(*argv, getflags(set, sb.st_flags))) 112 error(*argv); 113 exit(retval); 114 } 115 116 /* 117 * These are analogous to the setmode/getmode routines in the C library. 118 */ 119 void * 120 setflags(cp) 121 char *cp; 122 { 123 register CMDS *fset; 124 register char *arg; 125 126 fset = &cmds; 127 fset->clrbits = 0; 128 fset->setbits = 0; 129 while (cp) { 130 while ((arg = strsep(&cp, ",")) != NULL && *arg == '\0') 131 /* void */; 132 if (!strcasecmp(arg, "dump")) 133 fset->clrbits |= NODUMP; 134 else if (!strcasecmp(arg, "nodump")) 135 fset->setbits |= NODUMP; 136 else 137 return (NULL); 138 } 139 return (fset); 140 } 141 142 int 143 getflags(fset, oflags) 144 register CMDS *fset; 145 register int oflags; 146 { 147 148 oflags &= ~fset->clrbits; 149 oflags |= fset->setbits; 150 return (oflags); 151 } 152 153 #if __STDC__ 154 #include <stdarg.h> 155 #else 156 #include <varargs.h> 157 #endif 158 159 void 160 #if __STDC__ 161 err(const char *fmt, ...) 162 #else 163 err(fmt, va_alist) 164 char *fmt; 165 va_dcl 166 #endif 167 { 168 va_list ap; 169 #if __STDC__ 170 va_start(ap, fmt); 171 #else 172 va_start(ap); 173 #endif 174 (void)fprintf(stderr, "chflags: "); 175 (void)vfprintf(stderr, fmt, ap); 176 va_end(ap); 177 (void)fprintf(stderr, "\n"); 178 exit(1); 179 /* NOTREACHED */ 180 } 181 182 void 183 error(name) 184 char *name; 185 { 186 (void)fprintf(stderr, "chflags: %s: %s.\n", name, strerror(errno)); 187 retval = 1; 188 } 189 190 void 191 usage() 192 { 193 (void)fprintf(stderr, "usage: chflags [-R] flags file ...\n"); 194 exit(1); 195 } 196