AT&T free version, from Michael Rendell (michael@stretch.cs.mun.ca)
[unix-history] / usr / src / usr.sbin / mtree / create.c
CommitLineData
097163c4
KB
1/*
2 * Copyright (c) 1989 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 */
17
18#ifndef lint
38dde0cd 19static char sccsid[] = "@(#)create.c 5.5 (Berkeley) %G%";
097163c4
KB
20#endif /* not lint */
21
22#include <sys/types.h>
23#include <sys/stat.h>
24#include <dirent.h>
25#include <stdio.h>
38dde0cd 26#include <string.h>
097163c4
KB
27#include "mtree.h"
28
29cwalk(parent, tail)
30 ENTRY *parent;
31 register char *tail;
32{
33 extern ENTRY *root;
34 extern dev_t device;
35 extern int dflag, xflag, errno, alphasort();
36 extern char path[];
37 register ENTRY *centry, *level;
38 struct dirent *dp, **dir_list;
39 struct stat sbuf;
40 int cnt, dir_cnt;
41 char *emalloc(), *rlink();
42
43 *tail++ = '/';
44 dir_cnt = scandir(".", &dir_list, NULL, alphasort);
ca5705de 45 if (dir_cnt == -1 || xflag && lstat(".", &sbuf)) {
097163c4
KB
46 (void)fprintf(stderr, "mtree: %s: %s\n", path + 2,
47 strerror(errno));
48 exit(1);
49 }
50 device = sbuf.st_dev;
51 for (cnt = 0; cnt < dir_cnt; ++cnt) {
52 dp = dir_list[cnt];
53 if (dp->d_name[0] == '.' &&
54 (!dp->d_name[1] || dp->d_name[1] == '.' && !dp->d_name[2]))
55 continue;
56 bcopy(dp->d_name, tail, dp->d_namlen + 1);
ca5705de 57 if (lstat(dp->d_name, &sbuf)) {
097163c4
KB
58 (void)fprintf(stderr, "mtree: %s: %s\n",
59 path + 2, strerror(errno));
60 exit(1);
61 }
62 if (dflag && !S_ISDIR(sbuf.st_mode))
63 continue;
64
65 centry = (ENTRY *)emalloc(sizeof(ENTRY));
66 if (!(centry->name = strdup(dp->d_name)))
67 nomem();
68 centry->nlen = dp->d_namlen;
69
70 switch(sbuf.st_mode&S_IFMT) {
71 case S_IFDIR:
72 centry->info.type = F_DIR;
73 break;
74 case S_IFCHR:
75 centry->info.type = F_CHAR;
76 break;
77 case S_IFBLK:
78 centry->info.type = F_BLOCK;
79 break;
80 case S_IFREG:
81 centry->info.type = F_FILE;
82 break;
83 case S_IFLNK:
84 centry->info.type = F_LINK;
85 centry->info.slink = strdup(rlink(dp->d_name));
86 break;
87 case S_IFSOCK:
88 centry->info.type = F_SOCK;
89 break;
90 default:
91 (void)fprintf(stderr, "mtree: unknown file type %s.\n",
92 path + 2);
93 exit(1);
94 }
95 centry->info.st_uid = sbuf.st_uid;
96 centry->info.st_gid = sbuf.st_gid;
97 centry->info.st_size = sbuf.st_size;
98 centry->info.st_mode = sbuf.st_mode&07777;
99 centry->info.st_nlink = sbuf.st_nlink;
100 centry->info.st_uid = sbuf.st_uid;
101
102 if (!root) {
103 level = root = centry;
104 root->parent = root->child = NULL;
105 }
106 else if (parent) {
107 centry->parent = parent;
108 parent->child = centry;
109 level = centry;
110 parent = NULL;
111 }
112 else {
113 centry->parent = level->parent;
114 level = level->next = centry;
115 }
116 stats(&centry->info);
117 if (!S_ISDIR(sbuf.st_mode) || xflag && device != sbuf.st_dev)
118 continue;
119 if (chdir(dp->d_name)) {
120 (void)fprintf(stderr, "mtree: %s: %s\n", path + 2,
121 strerror(errno));
122 exit(1);
123 }
124 cwalk(level, tail + dp->d_namlen);
125 if (chdir("..")) {
126 (void)fprintf(stderr, "mtree: ..: %s\n",
127 strerror(errno));
128 exit(1);
129 }
130 }
131}
132
133#define LABEL { \
134 if (!label++) \
135 (void)printf("%s", level->nlen > 7 ? "\t" : "\t\t"); \
136 else \
137 (void)putchar(' '); \
138}
139
140extern mode_t dmode; /* default directory mode */
141extern mode_t fmode; /* default file mode */
142uid_t uid, gid; /* default owner, group */
aaece3b3 143u_int type;
097163c4
KB
144pwalk(level, tabs)
145 ENTRY *level;
146 int tabs;
147{
148 INFO *ip;
149 register int cnt;
150 int label;
151 char *ftype();
152
153 for (; level; level = level->next) {
154 for (cnt = tabs; cnt--; )
155 (void)putchar('\t');
156 (void)printf("%s", level->name);
157 label = 0;
aaece3b3 158 if ((ip = &level->info)->type != type) {
097163c4
KB
159 LABEL;
160 (void)printf("type=%s", ftype(ip->type));
161 }
162 if (ip->st_uid != uid) {
163 LABEL;
164 (void)printf("owner=%u", ip->st_uid);
165 }
166 if (ip->st_gid != gid) {
167 LABEL;
168 (void)printf("group=%u", ip->st_gid);
169 }
170 if (ip->type == F_DIR) {
171 if (ip->st_mode != dmode) {
172 LABEL;
173 (void)printf("mode=%o", ip->st_mode);
174 }
175 } else {
176 if (ip->st_mode != fmode) {
177 LABEL;
178 (void)printf("mode=%o", ip->st_mode);
179 }
180 if (ip->st_nlink != 1) {
181 LABEL;
182 (void)printf("nlink=%u", ip->st_nlink);
183 }
184 }
185 LABEL;
186 (void)printf("size=%ld", ip->st_size);
187 if (ip->slink)
188 (void)printf(" link=%s", ip->slink);
189 (void)putchar('\n');
190 if (level->child)
191 pwalk(level->child, tabs + 1);
192 if (ip->type == F_DIR) {
193 for (cnt = tabs; cnt--; )
194 (void)putchar('\t');
195 (void)printf("..\n");
196 }
197 }
198}
199
200ID *uhead;
201ID *ghead;
202u_long dmodes[0777 + 1];
203u_long fmodes[0777 + 1];
204
205stats(ip)
206 INFO *ip;
207{
208 register ID *p;
209
210 if (ip->type == F_DIR)
211 ++dmodes[ip->st_mode&0777];
212 else
213 ++fmodes[ip->st_mode&0777];
214 for (p = uhead;; p = p->next)
215 if (!p) {
216 p = (ID *)emalloc(sizeof(ID));
217 p->id = ip->st_uid;
218 p->next = uhead;
219 uhead = p;
220 break;
221 } else if (p->id == ip->st_uid) {
222 ++p->cnt;
223 break;
224 }
225 for (p = ghead;; p = p->next)
226 if (!p) {
227 p = (ID *)emalloc(sizeof(ID));
228 p->id = ip->st_gid;
229 p->next = ghead;
230 ghead = p;
231 break;
232 } else if (p->id == ip->st_gid) {
233 ++p->cnt;
234 break;
235 }
236}
237
238shostats()
239{
3243152b 240 extern int dflag;
097163c4
KB
241 register ID *p;
242 register mode_t cnt;
243 register u_long max;
244
245 for (max = 0, cnt = 0777; cnt; --cnt)
246 if (dmodes[cnt] > max) {
247 max = dmodes[cnt];
248 dmode = cnt;
249 }
250 (void)printf("/set dmode=%o\n", dmode);
251 for (max = 0, cnt = 0777; cnt; --cnt)
252 if (fmodes[cnt] > max) {
253 max = dmodes[cnt];
254 fmode = cnt;
255 }
256 (void)printf("/set fmode=%o\n", fmode);
257 for (max = 0, p = uhead; p; p = p->next)
258 if (p->cnt > max) {
259 max = p->cnt;
260 uid = p->id;
261 }
262 (void)printf("/set owner=%u\n", uid);
263 for (max = 0, p = ghead; p; p = p->next)
264 if (p->cnt > max) {
265 max = p->cnt;
266 gid = p->id;
267 }
268 (void)printf("/set group=%u\n", gid);
269 (void)printf("/set nlink=1\n");
aaece3b3
KB
270 if (dflag) {
271 type = F_DIR;
272 (void)printf("/set type=dir\n\n");
273 } else {
274 type = F_FILE;
275 (void)printf("/set type=file\n\n");
276 }
097163c4 277}