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