1 /*- 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)create.c 5.14 (Berkeley) 06/25/90"; 10 #endif /* not lint */ 11 12 #include <sys/param.h> 13 #include <sys/stat.h> 14 #include <time.h> 15 #include <fts.h> 16 #include <dirent.h> 17 #include <errno.h> 18 #include <stdio.h> 19 #include "mtree.h" 20 21 #define LABEL \ 22 if (label++) \ 23 (void)putchar(' '); \ 24 25 int ftsoptions = FTS_PHYSICAL; 26 27 cwalk() 28 { 29 extern int dflag; 30 register FTS *t; 31 register FTSENT *p; 32 register int cnt, label, notset; 33 time_t clock; 34 uid_t uid; 35 gid_t gid; 36 mode_t mode; 37 int tabs, dsort(); 38 char *argv[2]; 39 char curp[MAXPATHLEN], *inotype(), *getlogin(), *rlink(); 40 41 if (!getwd(curp)) { 42 (void)fprintf(stderr, "mtree: %s\n", curp); 43 exit(1); 44 } 45 (void)time(&clock); 46 (void)printf("#\t fs: %s\n#\t by: %s\n#\tdate: %s\n", 47 curp, getlogin(), ctime(&clock)); 48 49 argv[0] = "."; 50 argv[1] = (char *)NULL; 51 if (!(t = ftsopen(argv, ftsoptions, dsort))) { 52 (void)fprintf(stderr, 53 "mtree: ftsopen: %s.\n", strerror(errno)); 54 exit(1); 55 } 56 while (p = ftsread(t)) { 57 switch(p->fts_info) { 58 case FTS_D: 59 if (dflag) 60 notset = 1; 61 else 62 notset = 63 statdir(t, p, &uid, &gid, &mode, &tabs); 64 if (!strcmp(p->fts_name, ".")) 65 continue; 66 break; 67 case FTS_DC: 68 (void)fprintf(stderr, 69 "mtree: directory cycle: %s.\n", p->fts_path); 70 continue; 71 case FTS_DNR: 72 (void)fprintf(stderr, 73 "mtree: %s: unable to read.\n", p->fts_path); 74 continue; 75 case FTS_DNX: 76 (void)fprintf(stderr, 77 "mtree: %s: unable to search.\n", p->fts_path); 78 continue; 79 case FTS_DP: 80 if (p->fts_level <= 0) 81 continue; 82 for (cnt = p->fts_level - 1; cnt-- > 0; ) 83 (void)putchar('\t'); 84 (void)printf("..\n"); 85 continue; 86 case FTS_ERR: 87 (void)fprintf(stderr, "mtree: %s: %s.\n", 88 p->fts_path, strerror(errno)); 89 continue; 90 case FTS_NS: 91 (void)fprintf(stderr, 92 "mtree: can't stat: %s.\n", p->fts_path); 93 continue; 94 default: 95 if (dflag) 96 continue; 97 } 98 99 for (cnt = p->fts_level - 1; cnt-- > 0; ) 100 (void)putchar('\t'); 101 (void)printf("%s", p->fts_name); 102 if (p->fts_info == FTS_D) 103 (void)putchar('\t'); 104 else { 105 if (tabs > 1 && p->fts_namelen < 8) 106 (void)putchar('\t'); 107 (void)putchar('\t'); 108 } 109 110 label = 0; 111 if (!S_ISREG(p->fts_statb.st_mode) || notset) { 112 LABEL; 113 (void)printf("type=%s", inotype(p->fts_statb.st_mode)); 114 } 115 if (p->fts_statb.st_uid != uid || notset) { 116 LABEL; 117 (void)printf("owner=%u", p->fts_statb.st_uid); 118 } 119 if (p->fts_statb.st_gid != gid || notset) { 120 LABEL; 121 (void)printf("group=%u", p->fts_statb.st_gid); 122 } 123 if ((p->fts_statb.st_mode & MBITS) != mode || notset) { 124 LABEL; 125 (void)printf("mode=%#o", p->fts_statb.st_mode & MBITS); 126 } 127 if (p->fts_statb.st_nlink != 1 || notset) { 128 LABEL; 129 (void)printf("nlink=%u", p->fts_statb.st_nlink); 130 } 131 LABEL; 132 (void)printf("size=%ld", p->fts_statb.st_size); 133 LABEL; 134 (void)printf("time=%ld", p->fts_statb.st_mtime); 135 136 if (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE) { 137 LABEL; 138 (void)printf("link=%s", rlink(p->fts_accpath)); 139 } 140 (void)putchar('\n'); 141 } 142 (void)ftsclose(t); 143 } 144 145 #define MAXGID 5000 146 #define MAXUID 5000 147 #define MAXMODE MBITS + 1 148 149 statdir(t, parent, puid, pgid, pmode, tabs) 150 FTS *t; 151 FTSENT *parent; 152 uid_t *puid; 153 gid_t *pgid; 154 mode_t *pmode; 155 int *tabs; 156 { 157 register FTSENT *p; 158 register gid_t gid; 159 register uid_t uid; 160 register mode_t mode; 161 gid_t savegid; 162 uid_t saveuid; 163 mode_t savemode; 164 u_short maxgid, maxuid, maxmode, g[MAXGID], u[MAXUID], m[MAXMODE]; 165 166 if (!(p = ftschildren(t))) { 167 if (errno) { 168 (void)fprintf(stderr, "mtree: %s: %s.\n", 169 RP(parent), strerror(errno)); 170 exit(1); 171 } 172 return(1); 173 } 174 175 bzero(g, sizeof(g)); 176 bzero(u, sizeof(u)); 177 bzero(m, sizeof(m)); 178 179 *tabs = 1; 180 maxuid = maxgid = maxmode = 0; 181 for (; p; p = p->fts_link) { 182 mode = p->fts_statb.st_mode & MBITS; 183 if (mode < MAXMODE && ++m[mode] > maxmode) { 184 savemode = mode; 185 maxmode = m[mode]; 186 } 187 gid = p->fts_statb.st_gid; 188 if (gid < MAXGID && ++g[gid] > maxgid) { 189 savegid = gid; 190 maxgid = g[gid]; 191 } 192 uid = p->fts_statb.st_uid; 193 if (uid < MAXUID && ++u[uid] > maxuid) { 194 saveuid = uid; 195 maxuid = u[uid]; 196 } 197 if (p->fts_namelen > 7) 198 *tabs = 2; 199 } 200 (void)printf("\n/set group=%u mode=%#o nlink=1 owner=%u type=file\n", 201 savegid, savemode, saveuid); 202 *puid = saveuid; 203 *pgid = savegid; 204 *pmode = savemode; 205 return(0); 206 } 207 208 dsort(p1, p2) 209 FTSENT **p1, **p2; 210 { 211 register FTSENT *a, *b; 212 213 a = *p1; 214 b = *p2; 215 216 if (S_ISDIR(a->fts_statb.st_mode)) { 217 if (!S_ISDIR(b->fts_statb.st_mode)) 218 return(1); 219 } else if (S_ISDIR(b->fts_statb.st_mode)) 220 return(-1); 221 return(strcmp(a->fts_name, b->fts_name)); 222 } 223