BSD 4_4 release
[unix-history] / usr / src / usr.sbin / mtree / create.c
CommitLineData
256cb8b6 1/*-
ad787160
C
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
097163c4 4 *
ad787160
C
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
097163c4
KB
32 */
33
34#ifndef lint
ad787160 35static char sccsid[] = "@(#)create.c 8.1 (Berkeley) 6/6/93";
097163c4
KB
36#endif /* not lint */
37
cbe4b98c 38#include <sys/param.h>
097163c4 39#include <sys/stat.h>
256cb8b6 40#include <time.h>
275bb093 41#include <fcntl.h>
256cb8b6 42#include <fts.h>
097163c4 43#include <dirent.h>
275bb093
KB
44#include <grp.h>
45#include <pwd.h>
256cb8b6 46#include <errno.h>
275bb093 47#include <unistd.h>
097163c4 48#include <stdio.h>
097163c4 49#include "mtree.h"
275bb093 50#include "extern.h"
097163c4 51
275bb093
KB
52#define INDENTNAMELEN 15
53#define MAXLINELEN 80
cbe4b98c 54
275bb093
KB
55extern int crc_total, ftsoptions;
56extern int dflag, sflag;
57extern u_short keys;
58extern char fullpath[MAXPATHLEN];
256cb8b6 59
275bb093
KB
60static gid_t gid;
61static uid_t uid;
62static mode_t mode;
63
64static int dsort __P((const FTSENT **, const FTSENT **));
65static void output __P((int *, const char *, ...));
66static int statd __P((FTS *, FTSENT *, uid_t *, gid_t *, mode_t *));
67static void statf __P((FTSENT *));
68
69void
256cb8b6 70cwalk()
cbe4b98c 71{
256cb8b6
KB
72 register FTS *t;
73 register FTSENT *p;
256cb8b6 74 time_t clock;
275bb093
KB
75 char *argv[2], host[MAXHOSTNAMELEN];
76
cbe4b98c 77 (void)time(&clock);
275bb093
KB
78 (void)gethostname(host, sizeof(host));
79 (void)printf(
80 "#\t user: %s\n#\tmachine: %s\n#\t tree: %s\n#\t date: %s",
81 getlogin(), host, fullpath, ctime(&clock));
cbe4b98c 82
037978a6 83 argv[0] = ".";
275bb093
KB
84 argv[1] = NULL;
85 if ((t = fts_open(argv, ftsoptions, dsort)) == NULL)
86 err("fts_open: %s", strerror(errno));
87 while (p = fts_read(t))
256cb8b6
KB
88 switch(p->fts_info) {
89 case FTS_D:
275bb093
KB
90 (void)printf("\n# %s\n", p->fts_path);
91 statd(t, p, &uid, &gid, &mode);
92 statf(p);
256cb8b6 93 break;
256cb8b6 94 case FTS_DP:
275bb093
KB
95 if (p->fts_level > 0)
96 (void)printf("# %s\n..\n\n", p->fts_path);
97 break;
fc48cb7f 98 case FTS_DNR:
256cb8b6 99 case FTS_ERR:
fc48cb7f 100 case FTS_NS:
275bb093
KB
101 (void)fprintf(stderr,
102 "mtree: %s: %s\n", p->fts_path, strerror(errno));
103 break;
097163c4 104 default:
275bb093
KB
105 if (!dflag)
106 statf(p);
107 break;
108
097163c4 109 }
275bb093
KB
110 (void)fts_close(t);
111 if (sflag && keys & F_CKSUM)
112 (void)fprintf(stderr,
113 "mtree: %s checksum: %lu\n", fullpath, crc_total);
114}
097163c4 115
275bb093
KB
116static void
117statf(p)
118 FTSENT *p;
119{
120 struct group *gr;
121 struct passwd *pw;
122 u_long len, val;
123 int fd, indent;
cbe4b98c 124
12a5bdae 125 if (S_ISDIR(p->fts_statp->st_mode))
275bb093
KB
126 indent = printf("%s", p->fts_name);
127 else
128 indent = printf(" %s", p->fts_name);
129
130 if (indent > INDENTNAMELEN)
131 indent = MAXLINELEN;
132 else
133 indent += printf("%*s", INDENTNAMELEN - indent, "");
134
12a5bdae
KB
135 if (!S_ISREG(p->fts_statp->st_mode))
136 output(&indent, "type=%s", inotype(p->fts_statp->st_mode));
137 if (keys & (F_UID | F_UNAME) && p->fts_statp->st_uid != uid)
138 if (keys & F_UNAME && (pw = getpwuid(p->fts_statp->st_uid)))
275bb093
KB
139 output(&indent, "uname=%s", pw->pw_name);
140 else /* if (keys & F_UID) */
12a5bdae
KB
141 output(&indent, "uid=%u", p->fts_statp->st_uid);
142 if (keys & (F_GID | F_GNAME) && p->fts_statp->st_gid != gid)
143 if (keys & F_GNAME && (gr = getgrgid(p->fts_statp->st_gid)))
8b29e2f1 144 output(&indent, "gname=%s", gr->gr_name);
275bb093 145 else /* if (keys & F_GID) */
12a5bdae
KB
146 output(&indent, "gid=%u", p->fts_statp->st_gid);
147 if (keys & F_MODE && (p->fts_statp->st_mode & MBITS) != mode)
148 output(&indent, "mode=%#o", p->fts_statp->st_mode & MBITS);
149 if (keys & F_NLINK && p->fts_statp->st_nlink != 1)
150 output(&indent, "nlink=%u", p->fts_statp->st_nlink);
275bb093 151 if (keys & F_SIZE)
12f048c6 152 output(&indent, "size=%qd", p->fts_statp->st_size);
275bb093 153 if (keys & F_TIME)
c2bd878c
KB
154 output(&indent, "time=%ld.%ld",
155 p->fts_statp->st_mtimespec.ts_sec,
156 p->fts_statp->st_mtimespec.ts_nsec);
12a5bdae 157 if (keys & F_CKSUM && S_ISREG(p->fts_statp->st_mode)) {
275bb093
KB
158 if ((fd = open(p->fts_accpath, O_RDONLY, 0)) < 0 ||
159 crc(fd, &val, &len))
160 err("%s: %s", p->fts_accpath, strerror(errno));
161 (void)close(fd);
162 output(&indent, "cksum=%lu", val);
097163c4 163 }
275bb093
KB
164 if (keys & F_SLINK &&
165 (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE))
166 output(&indent, "link=%s", rlink(p->fts_accpath));
167 (void)putchar('\n');
097163c4
KB
168}
169
256cb8b6
KB
170#define MAXGID 5000
171#define MAXUID 5000
6e4c29b1 172#define MAXMODE MBITS + 1
097163c4 173
275bb093
KB
174static int
175statd(t, parent, puid, pgid, pmode)
256cb8b6
KB
176 FTS *t;
177 FTSENT *parent;
178 uid_t *puid;
179 gid_t *pgid;
180 mode_t *pmode;
097163c4 181{
256cb8b6 182 register FTSENT *p;
275bb093
KB
183 register gid_t sgid;
184 register uid_t suid;
185 register mode_t smode;
186 struct group *gr;
187 struct passwd *pw;
256cb8b6
KB
188 gid_t savegid;
189 uid_t saveuid;
190 mode_t savemode;
191 u_short maxgid, maxuid, maxmode, g[MAXGID], u[MAXUID], m[MAXMODE];
192
81e3630c 193 if ((p = fts_children(t, 0)) == NULL) {
275bb093
KB
194 if (errno)
195 err("%s: %s", RP(parent), strerror(errno));
196 return (1);
256cb8b6
KB
197 }
198
199 bzero(g, sizeof(g));
200 bzero(u, sizeof(u));
201 bzero(m, sizeof(m));
202
256cb8b6
KB
203 maxuid = maxgid = maxmode = 0;
204 for (; p; p = p->fts_link) {
12a5bdae 205 smode = p->fts_statp->st_mode & MBITS;
275bb093
KB
206 if (smode < MAXMODE && ++m[smode] > maxmode) {
207 savemode = smode;
208 maxmode = m[smode];
256cb8b6 209 }
12a5bdae 210 sgid = p->fts_statp->st_gid;
275bb093
KB
211 if (sgid < MAXGID && ++g[sgid] > maxgid) {
212 savegid = sgid;
213 maxgid = g[sgid];
256cb8b6 214 }
12a5bdae 215 suid = p->fts_statp->st_uid;
275bb093
KB
216 if (suid < MAXUID && ++u[suid] > maxuid) {
217 saveuid = suid;
218 maxuid = u[suid];
256cb8b6 219 }
256cb8b6 220 }
275bb093
KB
221 (void)printf("/set type=file");
222 if (keys & F_GID)
223 (void)printf(" gid=%u", savegid);
224 if (keys & F_GNAME)
225 if ((gr = getgrgid(savegid)) != NULL)
226 (void)printf(" gname=%s", gr->gr_name);
227 else
228 (void)printf(" gid=%u", savegid);
229 if (keys & F_UNAME)
230 if ((pw = getpwuid(saveuid)) != NULL)
231 (void)printf(" uname=%s", pw->pw_name);
232 else
233 (void)printf(" uid=%u", saveuid);
234 if (keys & F_UID)
235 (void)printf(" uid=%u", saveuid);
236 if (keys & F_MODE)
237 (void)printf(" mode=%#o", savemode);
238 if (keys & F_NLINK)
239 (void)printf(" nlink=1");
240 (void)printf("\n");
256cb8b6
KB
241 *puid = saveuid;
242 *pgid = savegid;
243 *pmode = savemode;
275bb093 244 return (0);
097163c4
KB
245}
246
275bb093
KB
247static int
248dsort(a, b)
249 const FTSENT **a, **b;
097163c4 250{
12a5bdae
KB
251 if (S_ISDIR((*a)->fts_statp->st_mode)) {
252 if (!S_ISDIR((*b)->fts_statp->st_mode))
275bb093 253 return (1);
12a5bdae 254 } else if (S_ISDIR((*b)->fts_statp->st_mode))
275bb093
KB
255 return (-1);
256 return (strcmp((*a)->fts_name, (*b)->fts_name));
257}
097163c4 258
275bb093
KB
259#if __STDC__
260#include <stdarg.h>
261#else
262#include <varargs.h>
263#endif
256cb8b6 264
275bb093
KB
265void
266#if __STDC__
267output(int *offset, const char *fmt, ...)
268#else
269output(offset, fmt, va_alist)
270 int *offset;
271 char *fmt;
272 va_dcl
273#endif
274{
275 va_list ap;
275bb093
KB
276 char buf[1024];
277#if __STDC__
278 va_start(ap, fmt);
279#else
280 va_start(ap);
281#endif
2dbdf5a9 282 (void)vsnprintf(buf, sizeof(buf), fmt, ap);
275bb093
KB
283 va_end(ap);
284
2dbdf5a9 285 if (*offset + strlen(buf) > MAXLINELEN - 3) {
275bb093
KB
286 (void)printf(" \\\n%*s", INDENTNAMELEN, "");
287 *offset = INDENTNAMELEN;
288 }
289 *offset += printf(" %s", buf) + 1;
097163c4 290}