11556Srgrimes/*-
21556Srgrimes * Copyright (c) 1993
31556Srgrimes *	The Regents of the University of California.  All rights reserved.
41556Srgrimes *
51556Srgrimes * Redistribution and use in source and binary forms, with or without
61556Srgrimes * modification, are permitted provided that the following conditions
71556Srgrimes * are met:
81556Srgrimes * 1. Redistributions of source code must retain the above copyright
91556Srgrimes *    notice, this list of conditions and the following disclaimer.
101556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111556Srgrimes *    notice, this list of conditions and the following disclaimer in the
121556Srgrimes *    documentation and/or other materials provided with the distribution.
131556Srgrimes * 4. Neither the name of the University nor the names of its contributors
141556Srgrimes *    may be used to endorse or promote products derived from this software
151556Srgrimes *    without specific prior written permission.
161556Srgrimes *
171556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201556Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271556Srgrimes * SUCH DAMAGE.
281556Srgrimes */
291556Srgrimes
3090039Sobrien#if defined(LIBC_SCCS) && !defined(lint)
3127967Sstevestatic char sccsid[] = "@(#)stat_flags.c	8.1 (Berkeley) 5/31/93";
3290039Sobrien#endif /* LIBC_SCCS and not lint */
3390039Sobrien#include <sys/cdefs.h>
3490039Sobrien__FBSDID("$FreeBSD$");
351556Srgrimes
361556Srgrimes#include <sys/types.h>
371556Srgrimes#include <sys/stat.h>
381556Srgrimes
391556Srgrimes#include <stddef.h>
4061746Sjoe#include <stdlib.h>
411556Srgrimes#include <string.h>
42150065Sstefanf#include <unistd.h>
431556Srgrimes
44228972Sjilles#define longestflaglen	12
4554827Srobertostatic struct {
46228972Sjilles	char name[longestflaglen + 1];
47228972Sjilles	char invert;
4854827Sroberto	u_long flag;
49228972Sjilles} const mapping[] = {
5054827Sroberto	/* shorter names per flag first, all prefixed by "no" */
51228972Sjilles	{ "nosappnd",		0, SF_APPEND	},
52228972Sjilles	{ "nosappend",		0, SF_APPEND	},
53228972Sjilles	{ "noarch",		0, SF_ARCHIVED	},
54228972Sjilles	{ "noarchived",		0, SF_ARCHIVED	},
55228972Sjilles	{ "noschg",		0, SF_IMMUTABLE	},
56228972Sjilles	{ "noschange",		0, SF_IMMUTABLE	},
57228972Sjilles	{ "nosimmutable",	0, SF_IMMUTABLE	},
58228972Sjilles	{ "nosunlnk",		0, SF_NOUNLINK	},
59228972Sjilles	{ "nosunlink",		0, SF_NOUNLINK	},
6094831Sjoe#ifdef SF_SNAPSHOT
61228972Sjilles	{ "nosnapshot",		0, SF_SNAPSHOT	},
6294831Sjoe#endif
63228972Sjilles	{ "nouappnd",		0, UF_APPEND	},
64228972Sjilles	{ "nouappend",		0, UF_APPEND	},
65254627Sken	{ "nouarch", 		0, UF_ARCHIVE	},
66254627Sken	{ "nouarchive",		0, UF_ARCHIVE	},
67254627Sken	{ "nohidden",		0, UF_HIDDEN	},
68254627Sken	{ "nouhidden",		0, UF_HIDDEN	},
69228972Sjilles	{ "nouchg",		0, UF_IMMUTABLE	},
70228972Sjilles	{ "nouchange",		0, UF_IMMUTABLE	},
71228972Sjilles	{ "nouimmutable",	0, UF_IMMUTABLE	},
72228972Sjilles	{ "nodump",		1, UF_NODUMP	},
73254627Sken	{ "nouunlnk",		0, UF_NOUNLINK	},
74254627Sken	{ "nouunlink",		0, UF_NOUNLINK	},
75254627Sken	{ "nooffline",		0, UF_OFFLINE	},
76254627Sken	{ "nouoffline",		0, UF_OFFLINE	},
77228972Sjilles	{ "noopaque",		0, UF_OPAQUE	},
78254627Sken	{ "nordonly",		0, UF_READONLY	},
79254627Sken	{ "nourdonly",		0, UF_READONLY	},
80254627Sken	{ "noreadonly",		0, UF_READONLY	},
81254627Sken	{ "noureadonly",	0, UF_READONLY	},
82254627Sken	{ "noreparse",		0, UF_REPARSE	},
83254627Sken	{ "noureparse",		0, UF_REPARSE	},
84254627Sken	{ "nosparse",		0, UF_SPARSE	},
85254627Sken	{ "nousparse",		0, UF_SPARSE	},
86254627Sken	{ "nosystem",		0, UF_SYSTEM	},
87254627Sken	{ "nousystem",		0, UF_SYSTEM	}
8854827Sroberto};
8954827Sroberto#define nmappings	(sizeof(mapping) / sizeof(mapping[0]))
901556Srgrimes
911556Srgrimes/*
9261737Sjoe * fflagstostr --
9361737Sjoe *	Convert file flags to a comma-separated string.  If no flags
9461738Sjoe *	are set, return the empty string.
951556Srgrimes */
961556Srgrimeschar *
9761738Sjoefflagstostr(flags)
981556Srgrimes	u_long flags;
991556Srgrimes{
10061746Sjoe	char *string;
101229024Sdim	const char *sp;
102229024Sdim	char *dp;
10354827Sroberto	u_long setflags;
10454827Sroberto	int i;
1051556Srgrimes
10661746Sjoe	if ((string = (char *)malloc(nmappings * (longestflaglen + 1))) == NULL)
10761746Sjoe		return (NULL);
10861746Sjoe
10954827Sroberto	setflags = flags;
11054827Sroberto	dp = string;
11154827Sroberto	for (i = 0; i < nmappings; i++) {
11254827Sroberto		if (setflags & mapping[i].flag) {
11354827Sroberto			if (dp > string)
11454827Sroberto				*dp++ = ',';
11554827Sroberto			for (sp = mapping[i].invert ? mapping[i].name :
11654827Sroberto			    mapping[i].name + 2; *sp; *dp++ = *sp++) ;
11754827Sroberto			setflags &= ~mapping[i].flag;
11854827Sroberto		}
11954827Sroberto	}
12054948Sroberto	*dp = '\0';
12161738Sjoe	return (string);
1221556Srgrimes}
1231556Srgrimes
1241556Srgrimes/*
12561737Sjoe * strtofflags --
12661737Sjoe *	Take string of arguments and return file flags.  Return 0 on
1271556Srgrimes *	success, 1 on failure.  On failure, stringp is set to point
1281556Srgrimes *	to the offending token.
1291556Srgrimes */
1301556Srgrimesint
13161737Sjoestrtofflags(stringp, setp, clrp)
1321556Srgrimes	char **stringp;
1331556Srgrimes	u_long *setp, *clrp;
1341556Srgrimes{
1351556Srgrimes	char *string, *p;
13654827Sroberto	int i;
1371556Srgrimes
1381556Srgrimes	if (setp)
1391556Srgrimes		*setp = 0;
1401556Srgrimes	if (clrp)
1411556Srgrimes		*clrp = 0;
1421556Srgrimes	string = *stringp;
1431556Srgrimes	while ((p = strsep(&string, "\t ,")) != NULL) {
1441556Srgrimes		*stringp = p;
1451556Srgrimes		if (*p == '\0')
1461556Srgrimes			continue;
14754827Sroberto		for (i = 0; i < nmappings; i++) {
14854827Sroberto			if (strcmp(p, mapping[i].name + 2) == 0) {
14954827Sroberto				if (mapping[i].invert) {
15054827Sroberto					if (clrp)
15154827Sroberto						*clrp |= mapping[i].flag;
15254827Sroberto				} else {
15354827Sroberto					if (setp)
15454827Sroberto						*setp |= mapping[i].flag;
15554827Sroberto				}
15654827Sroberto				break;
15754827Sroberto			} else if (strcmp(p, mapping[i].name) == 0) {
15854827Sroberto				if (mapping[i].invert) {
15954827Sroberto					if (setp)
16054827Sroberto						*setp |= mapping[i].flag;
16154827Sroberto				} else {
16254827Sroberto					if (clrp)
16354827Sroberto						*clrp |= mapping[i].flag;
16454827Sroberto				}
16554827Sroberto				break;
16654827Sroberto			}
1671556Srgrimes		}
16854827Sroberto		if (i == nmappings)
16954827Sroberto			return 1;
1701556Srgrimes	}
17154827Sroberto	return 0;
1721556Srgrimes}
173