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