xref: /original-bsd/usr.sbin/mtree/create.c (revision e2bb50a5)
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