Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 21 May 1997 11:41:58 +0200 (MET DST)
From:      Martin Birgmeier <mbirg@austria.ds.philips.com>
To:        FreeBSD-gnats-submit@FreeBSD.ORG
Subject:   bin/3648: find(1) extension for file flags
Message-ID:  <199705210941.LAA25804@ida.interface-business.de>
Resent-Message-ID: <199705210950.CAA01094@hub.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         3648
>Category:       bin
>Synopsis:       find(1) extension for file flags
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Wed May 21 02:50:01 PDT 1997
>Last-Modified:
>Originator:     Martin Birgmeier
>Organization:
Philips Speech Processing, Austria
>Release:        FreeBSD 2.2-STABLE i386
>Environment:


>Description:

I wanted find(1) to be able to check file flags... While working on this,
I found a bug in bin/ls/stat_flags.c, and largely rewrote the latter for
easier maintenance. Below you find both patches. Please forward them to
the NetBSD and OpenBSD groups as well.

Thanks for the system & best regards,

Martin

P.S. I'd also like to have HP-UX's -newer[acm][acm]{0,1} functions
to find(1), as well as my own invention (or someone else's?)
-date[acm]{0,1} [+-]{0,1}<free-form-date-time>. Once I find
some spare time again, I'll do that - unless you are faster :-). This
would be made easier by incorporating the various getdate.y(3) into the
C (or other?) library.

>How-To-Repeat:


>Fix:
	

==================== cut here ====================
*** /usr/src/bin/ls/stat_flags.c	Sat Sep 24 04:55:57 1994
--- /users/martin/find/stat_flags.c	Thu May  8 11:13:20 1997
***************
*** 43,54 ****
  #include <stddef.h>
  #include <string.h>
  
! #define	SAPPEND(s) {							\
! 	if (prefix != NULL)						\
! 		(void)strcat(string, prefix);				\
! 	(void)strcat(string, s);					\
! 	prefix = ",";							\
! }
  
  /*
   * flags_to_string --
--- 43,69 ----
  #include <stddef.h>
  #include <string.h>
  
! static struct {
! 	char *name;
! 	u_long flag;
! 	int invert;
! } mapping[] = {
! 	/* canonical names per flag first, all prefixed by "no" */
! 	{ "nosappend",		SF_APPEND,	0 },
! 	{ "nosappnd",		SF_APPEND,	0 },
! 	{ "noarchived",		SF_ARCHIVED,	0 },
! 	{ "noarch",		SF_ARCHIVED,	0 },
! 	{ "nosimmutable",	SF_IMMUTABLE,	0 },
! 	{ "noschange",		SF_IMMUTABLE,	0 },
! 	{ "noschg",		SF_IMMUTABLE,	0 },
! 	{ "nouappend",		UF_APPEND,	0 },
! 	{ "nouappnd",		UF_APPEND,	0 },
! 	{ "nouimmutable",	UF_IMMUTABLE,	0 },
! 	{ "nouchange",		UF_IMMUTABLE,	0 },
! 	{ "nouchg",		UF_IMMUTABLE,	0 },
! 	{ "nodump",		UF_NODUMP,	1 }
! };
! #define nmappings	(sizeof(mapping) / sizeof(mapping[0]))
  
  /*
   * flags_to_string --
***************
*** 61,94 ****
  	char *def;
  {
  	static char string[128];
! 	char *prefix;
! 
! 	string[0] = '\0';
! 	prefix = NULL;
! 	if (flags & UF_APPEND)
! 		SAPPEND("uappnd");
! 	if (flags & UF_IMMUTABLE)
! 		SAPPEND("uchg");
! 	if (flags & UF_NODUMP)
! 		SAPPEND("nodump");
! 	if (flags & SF_APPEND)
! 		SAPPEND("sappnd");
! 	if (flags & SF_ARCHIVED)
! 		SAPPEND("arch");
! 	if (flags & SF_IMMUTABLE)
! 		SAPPEND("schg");
! 	return (prefix == NULL && def != NULL ? def : string);
! }
  
! #define	TEST(a, b, f) {							\
! 	if (!memcmp(a, b, sizeof(b))) {					\
! 		if (clear) {						\
! 			if (clrp)					\
! 				*clrp |= (f);				\
! 		} else if (setp)					\
! 			*setp |= (f);					\
! 		break;							\
! 	}								\
  }
  
  /*
--- 76,98 ----
  	char *def;
  {
  	static char string[128];
! 	char *sp, *dp;
! 	u_long setflags;
! 	int i;
  
! 	setflags = flags;
! 	dp = string;
! 	for (i = 0; i < nmappings; i++) {
! 		if (setflags & mapping[i].flag) {
! 			if (dp > string)
! 				*dp++ = ',';
! 			for (sp = mapping[i].invert ? mapping[i].name :
! 			    mapping[i].name + 2; *sp; *dp++ = *sp++) ;
! 			setflags &= ~mapping[i].flag;
! 		}
! 	}
! 	*dp++ = '\0';
! 	return (dp == string && def != NULL ? def : string);
  }
  
  /*
***************
*** 102,111 ****
  	char **stringp;
  	u_long *setp, *clrp;
  {
- 	int clear;
  	char *string, *p;
  
- 	clear = 0;
  	if (setp)
  		*setp = 0;
  	if (clrp)
--- 106,114 ----
  	char **stringp;
  	u_long *setp, *clrp;
  {
  	char *string, *p;
+ 	int i;
  
  	if (setp)
  		*setp = 0;
  	if (clrp)
***************
*** 115,150 ****
  		*stringp = p;
  		if (*p == '\0')
  			continue;
! 		if (p[0] == 'n' && p[1] == 'o') {
! 			clear = 1;
! 			p += 2;
! 		}
! 		switch (p[0]) {
! 		case 'a':
! 			TEST(p, "arch", SF_ARCHIVED);
! 			TEST(p, "archived", SF_ARCHIVED);
! 			return (1);
! 		case 'd':
! 			clear = !clear;
! 			TEST(p, "dump", UF_NODUMP);
! 			return (1);
! 		case 's':
! 			TEST(p, "sappnd", SF_APPEND);
! 			TEST(p, "sappend", SF_APPEND);
! 			TEST(p, "schg", SF_IMMUTABLE);
! 			TEST(p, "schange", SF_IMMUTABLE);
! 			TEST(p, "simmutable", SF_IMMUTABLE);
! 			return (1);
! 		case 'u':
! 			TEST(p, "uappnd", UF_APPEND);
! 			TEST(p, "uappend", UF_APPEND);
! 			TEST(p, "uchg", UF_IMMUTABLE);
! 			TEST(p, "uchange", UF_IMMUTABLE);
! 			TEST(p, "uimmutable", UF_IMMUTABLE);
! 			/* FALLTHROUGH */
! 		default:
! 			return (1);
  		}
  	}
! 	return (0);
  }
--- 118,146 ----
  		*stringp = p;
  		if (*p == '\0')
  			continue;
! 		for (i = 0; i < nmappings; i++) {
! 			if (strcmp(p, mapping[i].name + 2) == 0) {
! 				if (mapping[i].invert) {
! 					if (clrp)
! 						*clrp |= mapping[i].flag;
! 				} else {
! 					if (setp)
! 						*setp |= mapping[i].flag;
! 				}
! 				break;
! 			} else if (strcmp(p, mapping[i].name) == 0) {
! 				if (mapping[i].invert) {
! 					if (setp)
! 						*setp |= mapping[i].flag;
! 				} else {
! 					if (clrp)
! 						*clrp |= mapping[i].flag;
! 				}
! 				break;
! 			}
  		}
+ 		if (i == nmappings)
+ 			return 1;
  	}
! 	return 0;
  }
==================== cut here ====================
==================== cut here ====================
diff -c /usr/src/usr.bin/find/Makefile /users/martin/find/Makefile
*** /usr/src/usr.bin/find/Makefile	Fri May 27 14:31:10 1994
--- /users/martin/find/Makefile	Wed May  7 21:33:15 1997
***************
*** 1,6 ****
  #	@(#)Makefile	8.1 (Berkeley) 6/6/93
  
  PROG=	find
! SRCS=	find.c function.c ls.c main.c misc.c operator.c option.c
  
  .include <bsd.prog.mk>
--- 1,7 ----
  #	@(#)Makefile	8.1 (Berkeley) 6/6/93
  
  PROG=	find
! SRCS=	find.c function.c ls.c main.c misc.c operator.c option.c stat_flags.c
! .PATH:	/usr/src/bin/ls
  
  .include <bsd.prog.mk>
diff -c /usr/src/usr.bin/find/extern.h /users/martin/find/extern.h
*** /usr/src/usr.bin/find/extern.h	Fri Oct  4 14:54:04 1996
--- /users/martin/find/extern.h	Wed May  7 21:37:51 1997
***************
*** 52,57 ****
--- 52,58 ----
  PLAN	*c_delete __P((void));
  PLAN	*c_depth __P((void));
  PLAN	*c_exec __P((char ***, int));
+ PLAN	*c_flags __P((char *));
  PLAN	*c_follow __P((void));
  PLAN	*c_fstype __P((char *));
  PLAN	*c_group __P((char *));
diff -c /usr/src/usr.bin/find/find.1 /users/martin/find/find.1
*** /usr/src/usr.bin/find/find.1	Wed May  7 19:36:47 1997
--- /users/martin/find/find.1	Thu May  8 11:18:21 1997
***************
*** 270,275 ****
--- 270,288 ----
  If the mode is not preceded by a dash, this primary evaluates to true if
  the bits in the mode exactly match the file's mode bits.
  Note, the first character of a symbolic mode may not be a dash (``\-'').
+ .It Ic -flags Op Fl Ns Ar flags
+ This primary evaluates to true if exactly those flags of the file are
+ set which are also set using the specified
+ .Ar flags
+ (if these are not preceded by a dash (``\-''),
+ or if they match the specified flags (if these are preceded by a dash).
+ The
+ .Ar flags
+ are specified using symbolic names (see
+ .Xr chflags 1  ).
+ Note that this is different from
+ .Ic -perm  ,
+ which only allows you to specify flags which are set.
  .It Ic -print
  This primary always evaluates to true.
  It prints the pathname of the current file to standard output.
***************
*** 399,404 ****
--- 412,418 ----
  that are newer than ``ttt''.
  .El
  .Sh SEE ALSO
+ .Xr chflags 1 ,
  .Xr chmod 1 ,
  .Xr locate 1 ,
  .Xr stat 2 ,
diff -c /usr/src/usr.bin/find/find.h /users/martin/find/find.h
*** /usr/src/usr.bin/find/find.h	Fri Oct  4 14:54:05 1996
--- /users/martin/find/find.h	Wed May  7 21:36:00 1997
***************
*** 39,45 ****
  /* node type */
  enum ntype {
  	N_AND = 1, 				/* must start > 0 */
! 	N_ATIME, N_CLOSEPAREN, N_CTIME, N_DEPTH, N_EXEC, N_EXPR, N_FOLLOW,
  	N_FSTYPE, N_GROUP, N_INUM, N_LINKS, N_LS, N_MTIME, N_NAME, N_NEWER,
  	N_NOGROUP, N_NOT, N_NOUSER, N_OK, N_OPENPAREN, N_OR, N_PATH,
  	N_PERM, N_PRINT, N_PRUNE, N_SIZE, N_TYPE, N_USER, N_XDEV,
--- 39,46 ----
  /* node type */
  enum ntype {
  	N_AND = 1, 				/* must start > 0 */
! 	N_ATIME, N_CLOSEPAREN, N_CTIME, N_DEPTH, N_EXEC, N_EXPR, N_FLAGS,
! 	N_FOLLOW,
  	N_FSTYPE, N_GROUP, N_INUM, N_LINKS, N_LS, N_MTIME, N_NAME, N_NEWER,
  	N_NOGROUP, N_NOT, N_NOUSER, N_OK, N_OPENPAREN, N_OR, N_PATH,
  	N_PERM, N_PRINT, N_PRUNE, N_SIZE, N_TYPE, N_USER, N_XDEV,
***************
*** 64,69 ****
--- 65,74 ----
  		gid_t _g_data;			/* gid */
  		ino_t _i_data;			/* inode */
  		mode_t _m_data;			/* mode mask */
+ 		struct {
+ 			u_long _f_flags;
+ 			u_long _f_mask;
+ 		} fl;
  		nlink_t _l_data;		/* link count */
  		off_t _o_data;			/* file size */
  		time_t _t_data;			/* time value */
***************
*** 81,88 ****
  } PLAN;
  #define	a_data	p_un._a_data
  #define	c_data	p_un._c_data
! #define	i_data	p_un._i_data
  #define	g_data	p_un._g_data
  #define	l_data	p_un._l_data
  #define	m_data	p_un._m_data
  #define	mt_data	p_un._mt_data
--- 86,95 ----
  } PLAN;
  #define	a_data	p_un._a_data
  #define	c_data	p_un._c_data
! #define fl_flags	p_un.fl._f_flags
! #define fl_mask		p_un.fl._f_mask
  #define	g_data	p_un._g_data
+ #define	i_data	p_un._i_data
  #define	l_data	p_un._l_data
  #define	m_data	p_un._m_data
  #define	mt_data	p_un._mt_data
diff -c /usr/src/usr.bin/find/function.c /users/martin/find/function.c
*** /usr/src/usr.bin/find/function.c	Sun Feb 16 09:41:05 1997
--- /users/martin/find/function.c	Thu May  8 11:26:34 1997
***************
*** 57,62 ****
--- 57,64 ----
  
  #include "find.h"
  
+ int string_to_flags __P((char **, u_long *, u_long *));
+ 
  #define	COMPARE(a, b) {							\
  	switch (plan->flags) {						\
  	case F_EQUAL:							\
***************
*** 763,772 ****
  	}
  
  	if ((set = setmode(perm)) == NULL)
! 		err(1, "-perm: %s: illegal mode string", perm);
  
  	new->m_data = getmode(set, 0);
  	return (new);
  }
  
  /*
--- 765,820 ----
  	}
  
  	if ((set = setmode(perm)) == NULL)
! 		errx(1, "-perm: %s: illegal mode string", perm);
  
  	new->m_data = getmode(set, 0);
  	return (new);
+ }
+ 
+ int
+ f_flags(plan, entry)
+ 	PLAN *plan;
+ 	FTSENT *entry;
+ {
+ 	u_long flags;
+ 
+ 	flags = entry->fts_statp->st_flags &
+ 	    (UF_NODUMP | UF_IMMUTABLE | UF_APPEND | UF_OPAQUE |
+ 	     SF_ARCHIVED | SF_IMMUTABLE | SF_APPEND);
+ 	if (plan->flags == F_ATLEAST)
+ 		/* note that plan->fl_flags always is a subset of
+ 		   plan->fl_mask */
+ 		return (flags & plan->fl_mask) == plan->fl_flags;
+ 	else
+ 		return flags == plan->fl_flags;
+ 	/* NOTREACHED */
+ }
+ 
+ PLAN *
+ c_flags(flags_str)
+ 	char *flags_str;
+ {
+ 	PLAN *new;
+ 	u_long flags, notflags;
+ 
+ 	ftsoptions &= ~FTS_NOSTAT;
+ 
+ 	new = palloc(N_FLAGS, f_flags);
+ 
+ 	if (*flags_str == '-') {
+ 		new->flags = F_ATLEAST;
+ 		flags_str++;
+ 	}
+ 	if (string_to_flags(&flags_str, &flags, &notflags) == 1)
+ 		errx(1, "-flags: %s: illegal flags string", flags_str);
+ 
+ 	new->fl_flags = flags;
+ 	new->fl_mask = flags | notflags;
+ #if 0
+ 	printf("flags = %08x, mask = %08x (%08x, %08x)\n",
+ 	    new->fl_flags, new->fl_mask, flags, notflags);
+ #endif
+ 	return new;
  }
  
  /*
diff -c /usr/src/usr.bin/find/option.c /users/martin/find/option.c
*** /usr/src/usr.bin/find/option.c	Fri Oct  4 14:54:07 1996
--- /users/martin/find/option.c	Wed May  7 20:50:35 1997
***************
*** 63,68 ****
--- 63,69 ----
  	{ "-delete",	N_DELETE,	c_delete,	O_ZERO },
  	{ "-depth",	N_DEPTH,	c_depth,	O_ZERO },
  	{ "-exec",	N_EXEC,		c_exec,		O_ARGVP },
+ 	{ "-flags",	N_FLAGS,	c_flags,	O_ARGV },
  	{ "-follow",	N_FOLLOW,	c_follow,	O_ZERO },
  	{ "-fstype",	N_FSTYPE,	c_fstype,	O_ARGV },
  	{ "-group",	N_GROUP,	c_group,	O_ARGV },
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199705210941.LAA25804>