Add support for -R for file relabel operations.
Add 'setfsmac' link, which permits labels to be provided in a label specification file, making it easier to provide initial file system labeling specifications. This is used by the new mac_lomac to provide initial system labeling and policy, and by sebsd, the port of SELinux FLASK/TE to FreeBSD. Approved by: re (jhb) Obtained from: TrustedBSD Project Sponsored by: DARPA, Network Associates Laboratories
This commit is contained in:
parent
5b8429c7b3
commit
a8896b02e0
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=107489
@ -4,6 +4,10 @@ PROG= setfmac
|
||||
MAN= setfmac.8
|
||||
SRCS= setfmac.c
|
||||
|
||||
LINKS+= ${BINDIR}/setfmac ${BINDIR}/setfsmac
|
||||
|
||||
MLINKS+= setfmac.8 setfsmac.8
|
||||
|
||||
WARNS?= 2
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
@ -15,9 +15,6 @@
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. The names of the authors may not be used to endorse or promote
|
||||
.\" products derived from this software without specific prior written
|
||||
.\" permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@ -35,18 +32,86 @@
|
||||
.Dd June 27, 2002
|
||||
.Dt SETFMAC 8
|
||||
.Sh NAME
|
||||
.Nm setfmac
|
||||
.Nm setfmac ,
|
||||
.Nm setfsmac
|
||||
.Nd set MAC label for a file system object
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Nm setfmac
|
||||
.Op Fl hR
|
||||
.Ar label
|
||||
.Ar
|
||||
.Op Ar file ...
|
||||
.Nm setfsmac
|
||||
.Op Fl ehvx
|
||||
.Op Fl f Ar specfile
|
||||
.Op Fl s Ar specfile
|
||||
.Ar path
|
||||
.Op Ar file ...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility associates the specified MAC label to the specified files.
|
||||
.Nm setfmac
|
||||
utility assigns the specified MAC label to the specified files.
|
||||
The following options are available:
|
||||
.Bl -tag -width indent
|
||||
.It Fl R
|
||||
Set the labels on the file hierarchies rooted in the files instead of
|
||||
just the files themselves.
|
||||
.It Fl h
|
||||
If the file is a symbolic link, change the label of the link rather
|
||||
than the file that the link points to.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Nm setfsmac
|
||||
utility accepts a list of specification files as input and sets the MAC
|
||||
labels on the specified file system hierarchies.
|
||||
Path names specified will be visited in order as given on the command line,
|
||||
and each tree will be traversed in pre-order.
|
||||
(Generally, it will not be very useful to use relative, instead of absolute,
|
||||
paths.)
|
||||
The labels that match a file will be combined and set in a single
|
||||
transaction.
|
||||
.Pp
|
||||
The following options are available:
|
||||
.Bl -tag -width indent
|
||||
.It Fl e
|
||||
Treat any filesystems encountered which do not support MAC labelling as
|
||||
errors, instead of warning and skipping past them.
|
||||
.It Fl f Ar specfile
|
||||
Add the specifications in
|
||||
.Ar specfile
|
||||
as a set of which at most one will be applied to each file traversed per
|
||||
.Fl f Ar specfile
|
||||
given.
|
||||
.It Fl h
|
||||
If the file is a symbolic link, change the label of the link rather
|
||||
than the file that the link points to.
|
||||
.It Fl s Ar specfile
|
||||
Add the specification in
|
||||
.Ar specfile ,
|
||||
but assume that the specification format is that used in the port
|
||||
of SELinux to FreeBSD as SEBSD.
|
||||
At most one of the specifications will be applied to each file traversed per
|
||||
.Fl f Ar specfile
|
||||
given.
|
||||
The prefix
|
||||
.Dq sebsd/
|
||||
will automatically be prepended to the labels in this file, and labels
|
||||
matching
|
||||
.Dq <<none>>
|
||||
will be explicitly not relabeled.
|
||||
This permits SEBSD to re-use existing SELinux policy specification files
|
||||
unmodified.
|
||||
.It Fl v
|
||||
Increase the degree of verbosity.
|
||||
When given, information detailing the labelling operation is printed while
|
||||
in progress.
|
||||
.It Fl x
|
||||
Do not cross recurse into new filesystems when traversing them.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr mac 3 ,
|
||||
.Xr mac_set_file 3 ,
|
||||
.Xr mac_set_link 3 ,
|
||||
.Xr re_format 7 ,
|
||||
.Xr getfmac 8 ,
|
||||
.Xr mac 9
|
||||
|
@ -15,9 +15,6 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the authors may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@ -33,71 +30,466 @@
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/mac.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/mac.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <paths.h>
|
||||
#include <errno.h>
|
||||
#include <fts.h>
|
||||
#include <libgen.h>
|
||||
#include <regex.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sysexits.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define MAXELEMENTS 32
|
||||
struct label_spec {
|
||||
struct label_spec_entry {
|
||||
regex_t regex; /* compiled regular expression to match */
|
||||
char *regexstr; /* uncompiled regular expression */
|
||||
mode_t mode; /* mode to possibly match */
|
||||
char *modestr; /* print-worthy ",-?" mode string */
|
||||
char *mactext; /* MAC label to apply */
|
||||
int flags; /* miscellaneous flags */
|
||||
#define F_DONTLABEL 0x01
|
||||
#define F_ALWAYSMATCH 0x02
|
||||
} *entries, /* entries[0..nentries] */
|
||||
*match; /* cached decision for MAC label to apply */
|
||||
size_t nentries; /* size of entries list */
|
||||
STAILQ_ENTRY(label_spec) link;
|
||||
};
|
||||
|
||||
struct label_specs {
|
||||
STAILQ_HEAD(label_specs_head, label_spec) head;
|
||||
};
|
||||
|
||||
void usage(int) __dead2;
|
||||
struct label_specs *new_specs(void);
|
||||
void add_specs(struct label_specs *, const char *, int);
|
||||
void add_setfmac_specs(struct label_specs *, char *);
|
||||
void add_spec_line(const char *, int, struct label_spec_entry *, char *);
|
||||
int apply_specs(struct label_specs *, FTSENT *, int, int);
|
||||
int specs_empty(struct label_specs *);
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
FTSENT *ftsent;
|
||||
FTS *fts;
|
||||
struct label_specs *specs;
|
||||
int eflag = 0, xflag = 0, vflag = 0, Rflag = 0, hflag;
|
||||
int ch, is_setfmac;
|
||||
char *bn;
|
||||
|
||||
bn = basename(argv[0]);
|
||||
if (bn == NULL)
|
||||
err(1, "basename");
|
||||
is_setfmac = strcmp(bn, "setfmac") == 0;
|
||||
hflag = is_setfmac ? FTS_LOGICAL : FTS_PHYSICAL;
|
||||
specs = new_specs();
|
||||
while ((ch = getopt(argc, argv, is_setfmac ? "Rh" : "ef:s:vx")) != -1) {
|
||||
switch (ch) {
|
||||
case 'R':
|
||||
Rflag = 1;
|
||||
break;
|
||||
case 'e':
|
||||
eflag = 1;
|
||||
break;
|
||||
case 'f':
|
||||
add_specs(specs, optarg, 0);
|
||||
break;
|
||||
case 'h':
|
||||
hflag = FTS_PHYSICAL;
|
||||
break;
|
||||
case 's':
|
||||
add_specs(specs, optarg, 1);
|
||||
break;
|
||||
case 'v':
|
||||
vflag++;
|
||||
break;
|
||||
case 'x':
|
||||
xflag = FTS_XDEV;
|
||||
break;
|
||||
default:
|
||||
usage(is_setfmac);
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (is_setfmac) {
|
||||
if (argc <= 1)
|
||||
usage(is_setfmac);
|
||||
add_setfmac_specs(specs, *argv);
|
||||
argc--;
|
||||
argv++;
|
||||
} else {
|
||||
if (argc == 0 || specs_empty(specs))
|
||||
usage(is_setfmac);
|
||||
}
|
||||
fts = fts_open(argv, hflag | xflag, NULL);
|
||||
if (fts == NULL)
|
||||
err(1, "cannot traverse filesystem%s", argc ? "s" : "");
|
||||
while ((ftsent = fts_read(fts)) != NULL) {
|
||||
switch (ftsent->fts_info) {
|
||||
case FTS_DP: /* skip post-order */
|
||||
break;
|
||||
case FTS_D: /* do pre-order */
|
||||
case FTS_DC: /* do cyclic? */
|
||||
/* don't ever recurse directories as setfmac(8) */
|
||||
if (is_setfmac && !Rflag)
|
||||
fts_set(fts, ftsent, FTS_SKIP);
|
||||
case FTS_DEFAULT: /* do default */
|
||||
case FTS_F: /* do regular */
|
||||
case FTS_SL: /* do symlink */
|
||||
case FTS_W: /* do whiteout */
|
||||
if (apply_specs(specs, ftsent, hflag, vflag)) {
|
||||
if (eflag) {
|
||||
errx(1, "labeling not supported in "
|
||||
"%.*s", ftsent->fts_pathlen,
|
||||
ftsent->fts_path);
|
||||
}
|
||||
warnx("labeling not supported in %.*s",
|
||||
ftsent->fts_pathlen, ftsent->fts_path);
|
||||
fts_set(fts, ftsent, FTS_SKIP);
|
||||
}
|
||||
break;
|
||||
case FTS_DNR: /* die on all errors */
|
||||
case FTS_ERR:
|
||||
case FTS_NS:
|
||||
err(1, "traversing %.*s", ftsent->fts_pathlen,
|
||||
ftsent->fts_path);
|
||||
default:
|
||||
errx(1, "CANNOT HAPPEN (%d) traversing %.*s",
|
||||
ftsent->fts_info, ftsent->fts_pathlen,
|
||||
ftsent->fts_path);
|
||||
}
|
||||
}
|
||||
fts_close(fts);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
usage(void)
|
||||
usage(int is_setfmac)
|
||||
{
|
||||
|
||||
fprintf(stderr, "setfmac [-h] [label] [file1] [file2 ...]\n");
|
||||
exit (EX_USAGE);
|
||||
if (is_setfmac)
|
||||
fprintf(stderr, "usage: setfmac [-Rh] label path [...]\n");
|
||||
else
|
||||
fprintf(stderr, "usage: setfsmac [-evx] [-f specfile [...]] [-s specfile [...]] path [...]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
chomp_line(char **line, size_t *linesize)
|
||||
{
|
||||
char ch;
|
||||
mac_t label;
|
||||
int hflag;
|
||||
int error, i;
|
||||
char *s;
|
||||
int freeme = 0;
|
||||
|
||||
for (s = *line; s - *line < *linesize; s++) {
|
||||
if (!isspace(*s))
|
||||
break;
|
||||
}
|
||||
if (*s == '#') {
|
||||
**line = '\0';
|
||||
*linesize = 0;
|
||||
return (freeme);
|
||||
}
|
||||
memmove(*line, s, *linesize - (s - *line));
|
||||
*linesize -= s - *line;
|
||||
for (s = &(*line)[*linesize - 1]; s >= *line; s--) {
|
||||
if (!isspace(*s))
|
||||
break;
|
||||
}
|
||||
if (s != &(*line)[*linesize - 1]) {
|
||||
*linesize = s - *line + 1;
|
||||
} else {
|
||||
s = malloc(*linesize + 1);
|
||||
if (s == NULL)
|
||||
err(1, "malloc");
|
||||
strncpy(s, *line, *linesize);
|
||||
*line = s;
|
||||
freeme = 1;
|
||||
}
|
||||
(*line)[*linesize] = '\0';
|
||||
return (freeme);
|
||||
}
|
||||
|
||||
hflag = 0;
|
||||
while ((ch = getopt(argc, argv, "h")) != -1) {
|
||||
switch (ch) {
|
||||
case 'h':
|
||||
hflag = 1;
|
||||
void
|
||||
add_specs(struct label_specs *specs, const char *file, int is_sebsd)
|
||||
{
|
||||
struct label_spec *spec;
|
||||
FILE *fp;
|
||||
char *line;
|
||||
size_t nlines = 0, linesize;
|
||||
int freeline;
|
||||
|
||||
spec = malloc(sizeof(*spec));
|
||||
if (spec == NULL)
|
||||
err(1, "malloc");
|
||||
fp = fopen(file, "r");
|
||||
if (fp == NULL)
|
||||
err(1, "opening %s", file);
|
||||
while ((line = fgetln(fp, &linesize)) != NULL) {
|
||||
freeline = chomp_line(&line, &linesize);
|
||||
if (linesize > 0) /* only allocate space for non-comments */
|
||||
nlines++;
|
||||
if (freeline)
|
||||
free(line);
|
||||
}
|
||||
if (ferror(fp))
|
||||
err(1, "fgetln on %s", file);
|
||||
rewind(fp);
|
||||
spec->entries = calloc(nlines, sizeof(*spec->entries));
|
||||
if (spec->entries == NULL)
|
||||
err(1, "malloc");
|
||||
spec->nentries = nlines;
|
||||
while (nlines > 0) {
|
||||
line = fgetln(fp, &linesize);
|
||||
if (line == NULL) {
|
||||
if (feof(fp))
|
||||
errx(1, "%s ended prematurely", file);
|
||||
else
|
||||
err(1, "failure reading %s", file);
|
||||
}
|
||||
freeline = chomp_line(&line, &linesize);
|
||||
if (linesize == 0) {
|
||||
if (freeline)
|
||||
free(line);
|
||||
continue;
|
||||
}
|
||||
add_spec_line(file, is_sebsd, &spec->entries[--nlines], line);
|
||||
if (freeline)
|
||||
free(line);
|
||||
}
|
||||
fclose(fp);
|
||||
warnx("%s: read %u specifications", file, spec->nentries);
|
||||
STAILQ_INSERT_TAIL(&specs->head, spec, link);
|
||||
}
|
||||
|
||||
void
|
||||
add_setfmac_specs(struct label_specs *specs, char *label)
|
||||
{
|
||||
struct label_spec *spec;
|
||||
|
||||
spec = malloc(sizeof(*spec));
|
||||
if (spec == NULL)
|
||||
err(1, "malloc");
|
||||
spec->nentries = 1;
|
||||
spec->entries = calloc(spec->nentries, sizeof(*spec->entries));
|
||||
if (spec->entries == NULL)
|
||||
err(1, "malloc");
|
||||
/* The _only_ thing specified here is the mactext! */
|
||||
spec->entries->mactext = label;
|
||||
spec->entries->flags |= F_ALWAYSMATCH;
|
||||
STAILQ_INSERT_TAIL(&specs->head, spec, link);
|
||||
}
|
||||
|
||||
void
|
||||
add_spec_line(const char *file, int is_sebsd, struct label_spec_entry *entry,
|
||||
char *line)
|
||||
{
|
||||
char *regexstr, *modestr, *macstr, *regerrorstr;
|
||||
size_t size;
|
||||
int error;
|
||||
|
||||
regexstr = strtok(line, " \t");
|
||||
if (regexstr == NULL)
|
||||
errx(1, "%s: need regular expression", file);
|
||||
modestr = strtok(NULL, " \t");
|
||||
if (modestr == NULL)
|
||||
errx(1, "%s: need a label", file);
|
||||
macstr = strtok(NULL, " \t");
|
||||
if (macstr == NULL) { /* the mode is just optional */
|
||||
macstr = modestr;
|
||||
modestr = NULL;
|
||||
}
|
||||
if (strtok(NULL, " \t") != NULL)
|
||||
errx(1, "%s: extraneous fields at end of line", file);
|
||||
/* assume we need to anchor this regex */
|
||||
if (asprintf(®exstr, "^%s$", regexstr) == -1)
|
||||
err(1, "%s: processing regular expression", file);
|
||||
entry->regexstr = regexstr;
|
||||
error = regcomp(&entry->regex, regexstr, REG_EXTENDED | REG_NOSUB);
|
||||
if (error) {
|
||||
size = regerror(error, &entry->regex, NULL, 0);
|
||||
regerrorstr = malloc(size);
|
||||
if (regerrorstr == NULL)
|
||||
err(1, "malloc");
|
||||
(void)regerror(error, &entry->regex, regerrorstr, size);
|
||||
errx(1, "%s: %s: %s", file, entry->regexstr, regerrorstr);
|
||||
}
|
||||
if (!is_sebsd) {
|
||||
entry->mactext = strdup(macstr);
|
||||
if (entry->mactext == NULL)
|
||||
err(1, "strdup");
|
||||
} else {
|
||||
if (asprintf(&entry->mactext, "sebsd/%s", macstr) == -1)
|
||||
err(1, "asprintf");
|
||||
if (strcmp(macstr, "<<none>>") == 0)
|
||||
entry->flags |= F_DONTLABEL;
|
||||
}
|
||||
if (modestr != NULL) {
|
||||
if (strlen(modestr) != 2 || modestr[0] != '-')
|
||||
errx(1, "%s: invalid mode string: %s", file, modestr);
|
||||
switch (modestr[1]) {
|
||||
case 'b':
|
||||
entry->mode = S_IFBLK;
|
||||
entry->modestr = ",-b";
|
||||
break;
|
||||
case 'c':
|
||||
entry->mode = S_IFCHR;
|
||||
entry->modestr = ",-c";
|
||||
break;
|
||||
case 'd':
|
||||
entry->mode = S_IFDIR;
|
||||
entry->modestr = ",-d";
|
||||
break;
|
||||
case 'p':
|
||||
entry->mode = S_IFIFO;
|
||||
entry->modestr = ",-p";
|
||||
break;
|
||||
case 'l':
|
||||
entry->mode = S_IFLNK;
|
||||
entry->modestr = ",-l";
|
||||
break;
|
||||
case 's':
|
||||
entry->mode = S_IFSOCK;
|
||||
entry->modestr = ",-s";
|
||||
break;
|
||||
case '-':
|
||||
entry->mode = S_IFREG;
|
||||
entry->modestr = ",--";
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
errx(1, "%s: invalid mode string: %s", file, modestr);
|
||||
}
|
||||
} else {
|
||||
entry->modestr = "";
|
||||
}
|
||||
|
||||
argv += optind;
|
||||
argc -= optind;
|
||||
|
||||
if (argc < 2)
|
||||
usage();
|
||||
|
||||
error = mac_from_text(&label, argv[0]);
|
||||
if (error != 0) {
|
||||
perror("mac_from_text");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (hflag)
|
||||
error = mac_set_link(argv[i], label);
|
||||
else
|
||||
error = mac_set_file(argv[i], label);
|
||||
if (error != 0) {
|
||||
perror(argv[i]);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mac_free(label);
|
||||
|
||||
exit(EX_OK);
|
||||
}
|
||||
|
||||
int
|
||||
specs_empty(struct label_specs *specs)
|
||||
{
|
||||
|
||||
return (STAILQ_EMPTY(&specs->head));
|
||||
}
|
||||
|
||||
int
|
||||
apply_specs(struct label_specs *specs, FTSENT *ftsent, int hflag, int vflag)
|
||||
{
|
||||
regmatch_t pmatch;
|
||||
struct label_spec *ls;
|
||||
struct label_spec_entry *ent;
|
||||
char *regerrorstr, *macstr;
|
||||
size_t size;
|
||||
mac_t mac;
|
||||
int error, matchedby;
|
||||
|
||||
/*
|
||||
* Work through file context sources in order of specification
|
||||
* on the command line, and through their entries in reverse
|
||||
* order to find the "last" (hopefully "best") match.
|
||||
*/
|
||||
matchedby = 0;
|
||||
STAILQ_FOREACH(ls, &specs->head, link) {
|
||||
for (ls->match = NULL, ent = ls->entries;
|
||||
ent < &ls->entries[ls->nentries]; ent++) {
|
||||
if (ent->flags & F_ALWAYSMATCH)
|
||||
goto matched;
|
||||
if (ent->mode != 0 &&
|
||||
(ftsent->fts_statp->st_mode & S_IFMT) != ent->mode)
|
||||
continue;
|
||||
pmatch.rm_so = 0;
|
||||
pmatch.rm_eo = ftsent->fts_pathlen;
|
||||
error = regexec(&ent->regex, ftsent->fts_path, 1,
|
||||
&pmatch, REG_STARTEND);
|
||||
switch (error) {
|
||||
case REG_NOMATCH:
|
||||
continue;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
size = regerror(error, &ent->regex, NULL, 0);
|
||||
regerrorstr = malloc(size);
|
||||
if (regerrorstr == NULL)
|
||||
err(1, "malloc");
|
||||
(void)regerror(error, &ent->regex, regerrorstr,
|
||||
size);
|
||||
errx(1, "%s: %s", ent->regexstr, regerrorstr);
|
||||
}
|
||||
matched:
|
||||
ls->match = ent;
|
||||
if (vflag) {
|
||||
if (matchedby == 0) {
|
||||
printf("%.*s matched by ",
|
||||
ftsent->fts_pathlen,
|
||||
ftsent->fts_path);
|
||||
matchedby = 1;
|
||||
}
|
||||
printf("%s(%s%s,%s)", matchedby == 2 ? "," : "",
|
||||
ent->regexstr, ent->modestr, ent->mactext);
|
||||
if (matchedby == 1)
|
||||
matchedby = 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (vflag && matchedby)
|
||||
printf("\n");
|
||||
size = 0;
|
||||
STAILQ_FOREACH(ls, &specs->head, link) {
|
||||
/* cached match decision */
|
||||
if (ls->match && (ls->match->flags & F_DONTLABEL) == 0)
|
||||
/* add length of "x\0"/"y," */
|
||||
size += strlen(ls->match->mactext) + 1;
|
||||
}
|
||||
if (size == 0)
|
||||
return (0);
|
||||
macstr = malloc(size);
|
||||
if (macstr == NULL)
|
||||
err(1, "malloc");
|
||||
*macstr = '\0';
|
||||
STAILQ_FOREACH(ls, &specs->head, link) {
|
||||
/* cached match decision */
|
||||
if (ls->match && (ls->match->flags & F_DONTLABEL) == 0) {
|
||||
if (*macstr != '\0')
|
||||
strcat(macstr, ",");
|
||||
strcat(macstr, ls->match->mactext);
|
||||
}
|
||||
}
|
||||
if (mac_from_text(&mac, macstr))
|
||||
err(1, "mac_from_text(%s)", macstr);
|
||||
if ((hflag == FTS_PHYSICAL ? mac_set_link(ftsent->fts_accpath, mac) :
|
||||
mac_set_file(ftsent->fts_accpath, mac)) != 0) {
|
||||
if (errno == EOPNOTSUPP) {
|
||||
mac_free(mac);
|
||||
free(macstr);
|
||||
return (1);
|
||||
}
|
||||
err(1, "mac_set_link(%.*s, %s)", ftsent->fts_pathlen,
|
||||
ftsent->fts_path, macstr);
|
||||
}
|
||||
mac_free(mac);
|
||||
free(macstr);
|
||||
return (0);
|
||||
}
|
||||
|
||||
struct label_specs *
|
||||
new_specs(void)
|
||||
{
|
||||
struct label_specs *specs;
|
||||
|
||||
specs = malloc(sizeof(*specs));
|
||||
if (specs == NULL)
|
||||
err(1, "malloc");
|
||||
STAILQ_INIT(&specs->head);
|
||||
return (specs);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user