Implement the "flavor" output discussed in tech-userlevel@, by Brooks Davis

This commit is contained in:
christos 2012-12-20 16:43:16 +00:00
parent fa9acd1bd7
commit 3afc22d858
5 changed files with 185 additions and 53 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: create.c,v 1.67 2012/12/15 01:24:40 christos Exp $ */
/* $NetBSD: create.c,v 1.68 2012/12/20 16:43:16 christos Exp $ */
/*-
* Copyright (c) 1989, 1993
@ -38,7 +38,7 @@
#if 0
static char sccsid[] = "@(#)create.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: create.c,v 1.67 2012/12/15 01:24:40 christos Exp $");
__RCSID("$NetBSD: create.c,v 1.68 2012/12/20 16:43:16 christos Exp $");
#endif
#endif /* not lint */
@ -136,18 +136,22 @@ cwalk(void)
}
switch(p->fts_info) {
case FTS_D:
printf("\n");
if (!bflag)
printf("\n");
if (!nflag)
printf("# %s\n", p->fts_path);
statd(t, p, &uid, &gid, &mode, &flags);
statf(indent, p);
break;
case FTS_DP:
if (p->fts_level > 0) {
if (p->fts_level > 0)
if (!nflag)
printf("%*s# %s\n", indent, "",
p->fts_path);
printf("%*s..\n\n", indent, "");
if (p->fts_level > 0 || flavor == F_FREEBSD9) {
printf("%*s..\n", indent, "");
if (!bflag)
printf("\n");
}
break;
case FTS_DNR:
@ -186,7 +190,7 @@ statf(int indent, FTSENT *p)
else
offset += printf("%*s", (INDENTNAMELEN + indent) - offset, "");
if (!S_ISREG(p->fts_statp->st_mode))
if (!S_ISREG(p->fts_statp->st_mode) && (flavor == F_NETBSD6 || !dflag))
output(indent, &offset, "type=%s",
inotype(p->fts_statp->st_mode));
if (keys & (F_UID | F_UNAME) && p->fts_statp->st_uid != uid) {
@ -212,7 +216,8 @@ statf(int indent, FTSENT *p)
(long long)p->fts_statp->st_rdev);
if (keys & F_NLINK && p->fts_statp->st_nlink != 1)
output(indent, &offset, "nlink=%u", p->fts_statp->st_nlink);
if (keys & F_SIZE && S_ISREG(p->fts_statp->st_mode))
if (keys & F_SIZE &&
(flavor != F_NETBSD6 || S_ISREG(p->fts_statp->st_mode)))
output(indent, &offset, "size=%lld",
(long long)p->fts_statp->st_size);
if (keys & F_TIME)
@ -349,29 +354,32 @@ statd(FTS *t, FTSENT *parent, uid_t *puid, gid_t *pgid, mode_t *pmode,
maxuid = maxgid = maxmode = maxflags = 0;
for (; p; p = p->fts_link) {
smode = p->fts_statp->st_mode & MBITS;
if (smode < MTREE_MAXMODE && ++m[smode] > maxmode) {
savemode = smode;
maxmode = m[smode];
}
sgid = p->fts_statp->st_gid;
if (sgid < MTREE_MAXGID && ++g[sgid] > maxgid) {
savegid = sgid;
maxgid = g[sgid];
}
suid = p->fts_statp->st_uid;
if (suid < MTREE_MAXUID && ++u[suid] > maxuid) {
saveuid = suid;
maxuid = u[suid];
}
if (flavor == F_NETBSD6 || !dflag ||
(dflag && S_ISDIR(p->fts_statp->st_mode))) {
smode = p->fts_statp->st_mode & MBITS;
if (smode < MTREE_MAXMODE && ++m[smode] > maxmode) {
savemode = smode;
maxmode = m[smode];
}
sgid = p->fts_statp->st_gid;
if (sgid < MTREE_MAXGID && ++g[sgid] > maxgid) {
savegid = sgid;
maxgid = g[sgid];
}
suid = p->fts_statp->st_uid;
if (suid < MTREE_MAXUID && ++u[suid] > maxuid) {
saveuid = suid;
maxuid = u[suid];
}
#if HAVE_STRUCT_STAT_ST_FLAGS
sflags = FLAGS2INDEX(p->fts_statp->st_flags);
if (sflags < MTREE_MAXFLAGS && ++f[sflags] > maxflags) {
saveflags = p->fts_statp->st_flags;
maxflags = f[sflags];
}
sflags = FLAGS2INDEX(p->fts_statp->st_flags);
if (sflags < MTREE_MAXFLAGS && ++f[sflags] > maxflags) {
saveflags = p->fts_statp->st_flags;
maxflags = f[sflags];
}
#endif
}
}
/*
* If the /set record is the same as the last one we do not need to
@ -384,7 +392,10 @@ statd(FTS *t, FTSENT *parent, uid_t *puid, gid_t *pgid, mode_t *pmode,
((keys & F_FLAGS) && (*pflags != saveflags)) ||
first) {
first = 0;
printf("/set type=file");
if (flavor != F_NETBSD6 && dflag)
printf("/set type=dir");
else
printf("/set type=file");
if (keys & (F_UID | F_UNAME)) {
if (keys & F_UNAME &&
(name = user_from_uid(saveuid, 1)) != NULL)

View File

@ -1,4 +1,4 @@
/* $NetBSD: extern.h,v 1.36 2012/10/05 01:26:56 christos Exp $ */
/* $NetBSD: extern.h,v 1.37 2012/12/20 16:43:16 christos Exp $ */
/*-
* Copyright (c) 1991, 1993
@ -52,6 +52,12 @@
#define MAXHOSTNAMELEN 256
#endif
enum flavor {
F_MTREE,
F_FREEBSD9,
F_NETBSD6
};
void addtag(slist_t *, char *);
int check_excludes(const char *, const char *);
int compare(NODE *, FTSENT *);
@ -69,10 +75,11 @@ void read_excludes_file(const char *);
const char *rlink(const char *);
int verify(FILE *);
extern int dflag, eflag, iflag, jflag, lflag, mflag,
extern int bflag, dflag, eflag, iflag, jflag, lflag, mflag,
nflag, qflag, rflag, sflag, tflag, uflag;
extern int mtree_Mflag, mtree_Sflag, mtree_Wflag;
extern size_t mtree_lineno;
extern enum flavor flavor;
extern u_int32_t crc_total;
extern int ftsoptions, keys;
extern char fullpath[];

View File

@ -1,4 +1,4 @@
.\" $NetBSD: mtree.8,v 1.64 2012/12/12 15:52:10 christos Exp $
.\" $NetBSD: mtree.8,v 1.65 2012/12/20 16:43:16 christos Exp $
.\"
.\" Copyright (c) 1989, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@ -56,7 +56,7 @@
.\"
.\" @(#)mtree.8 8.2 (Berkeley) 12/11/93
.\"
.Dd October 4, 2012
.Dd December 20, 2012
.Dt MTREE 8
.Os
.Sh NAME
@ -64,9 +64,10 @@
.Nd map a directory hierarchy
.Sh SYNOPSIS
.Nm
.Op Fl CcDdejLlMnPqrStUuWx
.Op Fl bCcDdejLlMnPqrStUuWx
.Op Fl i | Fl m
.Op Fl E Ar tags
.Op Fl F Ar flavor
.Op Fl f Ar spec
.Op Fl I Ar tags
.Op Fl K Ar keywords
@ -92,6 +93,8 @@ missing from either the file hierarchy or the specification.
.Pp
The options are as follows:
.Bl -tag -width Xxxexcludexfilexx
.It Fl b
Suppress blank lines before entering and after exiting directories.
.It Fl C
Convert a specification into
a format that's easier to parse with various tools.
@ -140,6 +143,29 @@ and
.It Fl e
Don't complain about files that are in the file hierarchy, but not in the
specification.
.It Fl F Ar flavor
Set the compatibilty flavor of the
.Nm
utility.
The
.Ar flavor
can be one of
.Sy mtree ,
.Sy freebsd9 ,
or
.Sy netbsd6 .
The default is
.Sy mtree .
The
.Sy freebsd9
and
.Sy netbsd6
flavors attempt to preserve output compatiblity and command line optio
backward compatibility with
.Fx 9
and
.Nx 6
respectively.
.It Fl f Ar spec
Read the specification from
.Ar file ,
@ -681,6 +707,35 @@ option can be used in combination with
or
.Fl u
to create directory hierarchies for, for example, distributions.
.Sh COMPATIBILITY
The compatibility shims provided by the
.Fl F
option are incomplete by design.
Known limitations are described below.
.Pp
The
.Sy freebsd9
flavor retains the default handling of lookup failures for the
.Sy uname
and
.Sy group
keywords by replacing them with appropriate
.Sy uid
and
.Sy gid
keywords rather than failing and reporting an error.
The related
.Fl w
flag is a no-op rather than causing a warning to be printed and no
keyword to be emitted.
The latter behavior is not emulated as it is potentially dangerous in
the face of /set statements.
.Pp
The
.Sy netbsd6
flavor does not replicate the historical bug that reported time as
seconds.nanoseconds without zero padding nanosecond values less than
100000000.
.Sh SEE ALSO
.Xr chflags 1 ,
.Xr chgrp 1 ,

View File

@ -1,4 +1,4 @@
/* $NetBSD: mtree.c,v 1.43 2012/12/12 15:51:41 christos Exp $ */
/* $NetBSD: mtree.c,v 1.44 2012/12/20 16:43:16 christos Exp $ */
/*-
* Copyright (c) 1989, 1990, 1993
@ -43,7 +43,7 @@ __COPYRIGHT("@(#) Copyright (c) 1989, 1990, 1993\
#if 0
static char sccsid[] = "@(#)mtree.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: mtree.c,v 1.43 2012/12/12 15:51:41 christos Exp $");
__RCSID("$NetBSD: mtree.c,v 1.44 2012/12/20 16:43:16 christos Exp $");
#endif
#endif /* not lint */
@ -59,9 +59,19 @@ __RCSID("$NetBSD: mtree.c,v 1.43 2012/12/12 15:51:41 christos Exp $");
#include "extern.h"
int ftsoptions = FTS_PHYSICAL;
int cflag, Cflag, dflag, Dflag, eflag, iflag, jflag, lflag, mflag,
nflag, qflag, rflag, sflag, tflag, uflag, Uflag;
int bflag, cflag, Cflag, dflag, Dflag, eflag, iflag, jflag, lflag, mflag,
nflag, qflag, rflag, sflag, tflag, uflag, Uflag, wflag;
char fullpath[MAXPATHLEN];
enum flavor flavor = F_MTREE;
static struct {
enum flavor flavor;
const char name[9];
} flavors[] = {
{F_MTREE, "mtree"},
{F_FREEBSD9, "freebsd9"},
{F_NETBSD6, "netbsd6"},
};
__dead static void usage(void);
@ -69,6 +79,7 @@ int
main(int argc, char **argv)
{
int ch, status;
uint i;
char *dir, *p;
FILE *spec1, *spec2;
@ -80,9 +91,12 @@ main(int argc, char **argv)
spec2 = NULL;
while ((ch = getopt(argc, argv,
"cCdDeE:f:I:ijk:K:lLmMnN:p:PqrR:s:StuUWxX:"))
"bcCdDeE:f:F:I:ijk:K:lLmMnN:p:PqrR:s:StuUwWxX:"))
!= -1) {
switch((char)ch) {
case 'b':
bflag = 1;
break;
case 'c':
cflag = 1;
break;
@ -115,6 +129,15 @@ main(int argc, char **argv)
} else
usage();
break;
case 'F':
for (i = 0; i < __arraycount(flavors); i++)
if (strcmp(optarg, flavors[i].name) == 0) {
flavor = flavors[i].flavor;
break;
}
if (i == __arraycount(flavors))
usage();
break;
case 'i':
iflag = 1;
break;
@ -193,6 +216,9 @@ main(int argc, char **argv)
case 'U':
Uflag = uflag = 1;
break;
case 'w':
wflag = 1;
break;
case 'W':
mtree_Wflag = 1;
break;
@ -213,6 +239,36 @@ main(int argc, char **argv)
if (argc)
usage();
switch (flavor) {
case F_FREEBSD9:
if (cflag && iflag) {
warnx("-c and -i passed, replacing -i with -j for "
"FreeBSD compatibility");
iflag = 0;
jflag = 1;
}
if (dflag && !bflag) {
warnx("Adding -b to -d for FreeBSD compatibility");
bflag = 1;
}
if (uflag && !iflag) {
warnx("Adding -i to -%c for FreeBSD compatibility",
Uflag ? 'U' : 'u');
iflag = 1;
}
if (uflag && !tflag) {
warnx("Adding -t to -%c for FreeBSD compatibility",
Uflag ? 'U' : 'u');
tflag = 1;
}
if (wflag)
warnx("The -w flag is a no-op");
break;
default:
if (wflag)
usage();
}
if (spec2 && (cflag || Cflag || Dflag))
mtree_err("Double -f, -c, -C and -D flags are mutually "
"exclusive");
@ -255,12 +311,18 @@ main(int argc, char **argv)
static void
usage(void)
{
uint i;
fprintf(stderr,
"usage: %s [-CcDdejLlMnPqrStUuWx] [-i|-m] [-E tags]\n"
"usage: %s [-bCcDdejLlMnPqrStUuWx] [-i|-m] [-E tags]\n"
"\t\t[-f spec] [-f spec]\n"
"\t\t[-I tags] [-K keywords] [-k keywords] [-N dbdir] [-p path]\n"
"\t\t[-R keywords] [-s seed] [-X exclude-file]\n",
"\t\t[-R keywords] [-s seed] [-X exclude-file]\n"
"\t\t[-F flavor]\n",
getprogname());
fprintf(stderr, "\nflavors:");
for (i = 0; i < __arraycount(flavors); i++)
fprintf(stderr, " %s", flavors[i].name);
fprintf(stderr, "\n");
exit(1);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: spec.c,v 1.84 2012/10/07 18:40:49 christos Exp $ */
/* $NetBSD: spec.c,v 1.85 2012/12/20 16:43:16 christos Exp $ */
/*-
* Copyright (c) 1989, 1993
@ -67,7 +67,7 @@
#if 0
static char sccsid[] = "@(#)spec.c 8.2 (Berkeley) 4/28/95";
#else
__RCSID("$NetBSD: spec.c,v 1.84 2012/10/07 18:40:49 christos Exp $");
__RCSID("$NetBSD: spec.c,v 1.85 2012/12/20 16:43:16 christos Exp $");
#endif
#endif /* not lint */
@ -415,19 +415,16 @@ dump_nodes(const char *dir, NODE *root, int pathlast)
char *
vispath(const char *path)
{
const char extra[] = { ' ', '\t', '\n', '\\', '#',
#ifdef notyet
/*
* We don't encode the globbing characters yet, because they
* get encoded as \c and strunvis fails to decode them
*/
'*', '?', '[',
#endif
'\0' };
static const char extra[] = { ' ', '\t', '\n', '\\', '#', '\0' };
static const char extra_glob[] = { ' ', '\t', '\n', '\\', '#', '*',
'?', '[', '\0' };
static char pathbuf[4*MAXPATHLEN + 1];
strsvis(pathbuf, path, VIS_CSTYLE, extra);
return(pathbuf);
if (flavor == F_NETBSD6)
strsvis(pathbuf, path, VIS_CSTYLE, extra);
else
strsvis(pathbuf, path, VIS_OCTAL, extra_glob);
return pathbuf;
}