xref: /netbsd-src/lib/libutil/stat_flags.c (revision 388550b026d49b7f7b7480b1113bf82bb8d6a480)
1*388550b0Srillig /*	$NetBSD: stat_flags.c,v 1.3 2022/04/19 20:32:17 rillig Exp $	*/
233d6b113Schristos 
333d6b113Schristos /*-
433d6b113Schristos  * Copyright (c) 1993
533d6b113Schristos  *	The Regents of the University of California.  All rights reserved.
633d6b113Schristos  *
733d6b113Schristos  * Redistribution and use in source and binary forms, with or without
833d6b113Schristos  * modification, are permitted provided that the following conditions
933d6b113Schristos  * are met:
1033d6b113Schristos  * 1. Redistributions of source code must retain the above copyright
1133d6b113Schristos  *    notice, this list of conditions and the following disclaimer.
1233d6b113Schristos  * 2. Redistributions in binary form must reproduce the above copyright
1333d6b113Schristos  *    notice, this list of conditions and the following disclaimer in the
1433d6b113Schristos  *    documentation and/or other materials provided with the distribution.
1533d6b113Schristos  * 3. Neither the name of the University nor the names of its contributors
1633d6b113Schristos  *    may be used to endorse or promote products derived from this software
1733d6b113Schristos  *    without specific prior written permission.
1833d6b113Schristos  *
1933d6b113Schristos  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2033d6b113Schristos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2133d6b113Schristos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2233d6b113Schristos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2333d6b113Schristos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2433d6b113Schristos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2533d6b113Schristos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2633d6b113Schristos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2733d6b113Schristos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2833d6b113Schristos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2933d6b113Schristos  * SUCH DAMAGE.
3033d6b113Schristos  */
3133d6b113Schristos 
3233d6b113Schristos #if HAVE_NBTOOL_CONFIG_H
3333d6b113Schristos #include "nbtool_config.h"
3433d6b113Schristos #else
3533d6b113Schristos #define HAVE_STRUCT_STAT_ST_FLAGS 1
3633d6b113Schristos #endif
3733d6b113Schristos 
3833d6b113Schristos #include <sys/cdefs.h>
3933d6b113Schristos #if !defined(lint)
4033d6b113Schristos #if 0
4133d6b113Schristos static char sccsid[] = "@(#)stat_flags.c	8.2 (Berkeley) 7/28/94";
4233d6b113Schristos #else
43*388550b0Srillig __RCSID("$NetBSD: stat_flags.c,v 1.3 2022/04/19 20:32:17 rillig Exp $");
4433d6b113Schristos #endif
4533d6b113Schristos #endif /* not lint */
4633d6b113Schristos 
4733d6b113Schristos #include <sys/types.h>
4833d6b113Schristos #include <sys/stat.h>
4933d6b113Schristos #include <fts.h>
5033d6b113Schristos #include <stddef.h>
5133d6b113Schristos #include <string.h>
5233d6b113Schristos #include <stdlib.h>
5333d6b113Schristos 
5433d6b113Schristos #include "util.h"
5533d6b113Schristos 
5633d6b113Schristos #define	SAPPEND(s) do {							\
5733d6b113Schristos 	if (prefix != NULL)						\
5833d6b113Schristos 		(void)strlcat(string, prefix, sizeof(string));		\
5933d6b113Schristos 	(void)strlcat(string, s, sizeof(string));			\
6033d6b113Schristos 	prefix = ",";							\
61*388550b0Srillig } while (0)
6233d6b113Schristos 
6333d6b113Schristos /*
6433d6b113Schristos  * flags_to_string --
6533d6b113Schristos  *	Convert stat flags to a comma-separated string.  If no flags
6633d6b113Schristos  *	are set, return the default string.
6733d6b113Schristos  */
6833d6b113Schristos char *
flags_to_string(u_long flags,const char * def)6933d6b113Schristos flags_to_string(u_long flags, const char *def)
7033d6b113Schristos {
7113b35046Scbiere 	char string[128];
7233d6b113Schristos 	const char *prefix;
7333d6b113Schristos 
7433d6b113Schristos 	string[0] = '\0';
7533d6b113Schristos 	prefix = NULL;
7633d6b113Schristos #if HAVE_STRUCT_STAT_ST_FLAGS
7733d6b113Schristos 	if (flags & UF_APPEND)
7833d6b113Schristos 		SAPPEND("uappnd");
7933d6b113Schristos 	if (flags & UF_IMMUTABLE)
8033d6b113Schristos 		SAPPEND("uchg");
8133d6b113Schristos 	if (flags & UF_NODUMP)
8233d6b113Schristos 		SAPPEND("nodump");
8333d6b113Schristos 	if (flags & UF_OPAQUE)
8433d6b113Schristos 		SAPPEND("opaque");
8533d6b113Schristos 	if (flags & SF_APPEND)
8633d6b113Schristos 		SAPPEND("sappnd");
8733d6b113Schristos 	if (flags & SF_ARCHIVED)
8833d6b113Schristos 		SAPPEND("arch");
8933d6b113Schristos 	if (flags & SF_IMMUTABLE)
9033d6b113Schristos 		SAPPEND("schg");
9133d6b113Schristos #ifdef SF_SNAPSHOT
9233d6b113Schristos 	if (flags & SF_SNAPSHOT)
9333d6b113Schristos 		SAPPEND("snap");
9433d6b113Schristos #endif
9533d6b113Schristos #endif
9633d6b113Schristos 	if (prefix != NULL)
9713b35046Scbiere 		return strdup(string);
9833d6b113Schristos 	return strdup(def);
9933d6b113Schristos }
10033d6b113Schristos 
10133d6b113Schristos #define	TEST(a, b, f) {							\
10233d6b113Schristos 	if (!strcmp(a, b)) {						\
10333d6b113Schristos 		if (clear) {						\
10433d6b113Schristos 			if (clrp)					\
10533d6b113Schristos 				*clrp |= (f);				\
10633d6b113Schristos 			if (setp)					\
10733d6b113Schristos 				*setp &= ~(f);				\
10833d6b113Schristos 		} else {						\
10933d6b113Schristos 			if (setp)					\
11033d6b113Schristos 				*setp |= (f);				\
11133d6b113Schristos 			if (clrp)					\
11233d6b113Schristos 				*clrp &= ~(f);				\
11333d6b113Schristos 		}							\
11433d6b113Schristos 		break;							\
11533d6b113Schristos 	}								\
11633d6b113Schristos }
11733d6b113Schristos 
11833d6b113Schristos /*
11933d6b113Schristos  * string_to_flags --
12033d6b113Schristos  *	Take string of arguments and return stat flags.  Return 0 on
12133d6b113Schristos  *	success, 1 on failure.  On failure, stringp is set to point
12233d6b113Schristos  *	to the offending token.
12333d6b113Schristos  */
12433d6b113Schristos int
string_to_flags(char ** stringp,u_long * setp,u_long * clrp)12533d6b113Schristos string_to_flags(char **stringp, u_long *setp, u_long *clrp)
12633d6b113Schristos {
12733d6b113Schristos 	int clear;
12833d6b113Schristos 	char *string, *p;
12933d6b113Schristos 
13033d6b113Schristos 	if (setp)
13133d6b113Schristos 		*setp = 0;
13233d6b113Schristos 	if (clrp)
13333d6b113Schristos 		*clrp = 0;
13433d6b113Schristos 
13533d6b113Schristos #if HAVE_STRUCT_STAT_ST_FLAGS
13633d6b113Schristos 	string = *stringp;
13733d6b113Schristos 	while ((p = strsep(&string, "\t ,")) != NULL) {
13833d6b113Schristos 		clear = 0;
13933d6b113Schristos 		*stringp = p;
14033d6b113Schristos 		if (*p == '\0')
14133d6b113Schristos 			continue;
14233d6b113Schristos 		if (p[0] == 'n' && p[1] == 'o') {
14333d6b113Schristos 			clear = 1;
14433d6b113Schristos 			p += 2;
14533d6b113Schristos 		}
14633d6b113Schristos 		switch (p[0]) {
14733d6b113Schristos 		case 'a':
14833d6b113Schristos 			TEST(p, "arch", SF_ARCHIVED);
14933d6b113Schristos 			TEST(p, "archived", SF_ARCHIVED);
15033d6b113Schristos 			return (1);
15133d6b113Schristos 		case 'd':
15233d6b113Schristos 			clear = !clear;
15333d6b113Schristos 			TEST(p, "dump", UF_NODUMP);
15433d6b113Schristos 			return (1);
15533d6b113Schristos 		case 'n':
15633d6b113Schristos 				/*
15733d6b113Schristos 				 * Support `nonodump'. Note that
15833d6b113Schristos 				 * the state of clear is not changed.
15933d6b113Schristos 				 */
16033d6b113Schristos 			TEST(p, "nodump", UF_NODUMP);
16133d6b113Schristos 			return (1);
16233d6b113Schristos 		case 'o':
16333d6b113Schristos 			TEST(p, "opaque", UF_OPAQUE);
16433d6b113Schristos 			return (1);
16533d6b113Schristos 		case 's':
16633d6b113Schristos 			TEST(p, "sappnd", SF_APPEND);
16733d6b113Schristos 			TEST(p, "sappend", SF_APPEND);
16833d6b113Schristos 			TEST(p, "schg", SF_IMMUTABLE);
16933d6b113Schristos 			TEST(p, "schange", SF_IMMUTABLE);
17033d6b113Schristos 			TEST(p, "simmutable", SF_IMMUTABLE);
17133d6b113Schristos 			return (1);
17233d6b113Schristos 		case 'u':
17333d6b113Schristos 			TEST(p, "uappnd", UF_APPEND);
17433d6b113Schristos 			TEST(p, "uappend", UF_APPEND);
17533d6b113Schristos 			TEST(p, "uchg", UF_IMMUTABLE);
17633d6b113Schristos 			TEST(p, "uchange", UF_IMMUTABLE);
17733d6b113Schristos 			TEST(p, "uimmutable", UF_IMMUTABLE);
17833d6b113Schristos 			return (1);
17933d6b113Schristos 		default:
18033d6b113Schristos 			return (1);
18133d6b113Schristos 		}
18233d6b113Schristos 	}
18333d6b113Schristos #endif
18433d6b113Schristos 
18533d6b113Schristos 	return (0);
18633d6b113Schristos }
187