symbolic chmod, thanks pancake
This commit is contained in:
		
							
								
								
									
										1
									
								
								LICENSE
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								LICENSE
									
									
									
									
									
								
							@@ -5,6 +5,7 @@ MIT/X Consortium License
 | 
				
			|||||||
© 2011 stateless <stateless@archlinux.us>
 | 
					© 2011 stateless <stateless@archlinux.us>
 | 
				
			||||||
© 2011 Rob Pilling <robpilling@gmail.com>
 | 
					© 2011 Rob Pilling <robpilling@gmail.com>
 | 
				
			||||||
© 2011 Hiltjo Posthuma <hiltjo@codemadness.org>
 | 
					© 2011 Hiltjo Posthuma <hiltjo@codemadness.org>
 | 
				
			||||||
 | 
					© 2011 pancake <pancake@youterm.com>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Permission is hereby granted, free of charge, to any person obtaining a
 | 
					Permission is hereby granted, free of charge, to any person obtaining a
 | 
				
			||||||
copy of this software and associated documentation files (the "Software"),
 | 
					copy of this software and associated documentation files (the "Software"),
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										63
									
								
								chmod.1
									
									
									
									
									
								
							
							
						
						
									
										63
									
								
								chmod.1
									
									
									
									
									
								
							@@ -4,18 +4,65 @@ chmod \- change file mode
 | 
				
			|||||||
.SH SYNOPSIS
 | 
					.SH SYNOPSIS
 | 
				
			||||||
.B chmod
 | 
					.B chmod
 | 
				
			||||||
.RB [ \-Rr ]
 | 
					.RB [ \-Rr ]
 | 
				
			||||||
.RI mode
 | 
					.I octal
 | 
				
			||||||
 | 
					.RI [ file ...]
 | 
				
			||||||
 | 
					.P
 | 
				
			||||||
 | 
					.B chmod
 | 
				
			||||||
 | 
					.RB [ \-Rr ]
 | 
				
			||||||
 | 
					.RB [ ugoa ][ +-= ][ rwxs ]
 | 
				
			||||||
.RI [ file ...]
 | 
					.RI [ file ...]
 | 
				
			||||||
.SH DESCRIPTION
 | 
					.SH DESCRIPTION
 | 
				
			||||||
.B chmod
 | 
					.B chmod
 | 
				
			||||||
changes the file mode for the given files.  The
 | 
					changes the file mode for the given files.
 | 
				
			||||||
.I mode
 | 
					 | 
				
			||||||
is a four digit octal number derived from its comprising bits.
 | 
					 | 
				
			||||||
.P
 | 
					.P
 | 
				
			||||||
The first digit defines the setuid (4) and setgid (2) attributes.  The second
 | 
					If the mode is an
 | 
				
			||||||
digit defines the owner's permissions: read (4), write (2), and execute (1); the
 | 
					.I octal
 | 
				
			||||||
third defines permissions for others in the file's group; and the fourth for all
 | 
					number, the modes are set according to that number's comprising bits. The first
 | 
				
			||||||
other users. Leading zeroes may be omitted.
 | 
					digit defines the setuid (4) and setgid (2) attributes.  The second digit
 | 
				
			||||||
 | 
					defines the owner's permissions: read (4), write (2), and execute (1); the third
 | 
				
			||||||
 | 
					defines permissions for others in the file's group; and the fourth for all other
 | 
				
			||||||
 | 
					users. Leading zeroes may be omitted.
 | 
				
			||||||
 | 
					.P
 | 
				
			||||||
 | 
					Alternatively the mode may be symbolic. The symbol meanings are:
 | 
				
			||||||
 | 
					.TP
 | 
				
			||||||
 | 
					.B u
 | 
				
			||||||
 | 
					modifies owner permissions.
 | 
				
			||||||
 | 
					.PD 0
 | 
				
			||||||
 | 
					.TP
 | 
				
			||||||
 | 
					.B g
 | 
				
			||||||
 | 
					modifies group permissions.
 | 
				
			||||||
 | 
					.TP
 | 
				
			||||||
 | 
					.B o
 | 
				
			||||||
 | 
					modifies other user permissions.
 | 
				
			||||||
 | 
					.TP
 | 
				
			||||||
 | 
					.B a
 | 
				
			||||||
 | 
					modifies all user permissions.
 | 
				
			||||||
 | 
					.PD
 | 
				
			||||||
 | 
					.TP
 | 
				
			||||||
 | 
					.B +
 | 
				
			||||||
 | 
					adds the given permissions to the mode.
 | 
				
			||||||
 | 
					.PD 0
 | 
				
			||||||
 | 
					.TP
 | 
				
			||||||
 | 
					.B -
 | 
				
			||||||
 | 
					removes the given permissions from the mode.
 | 
				
			||||||
 | 
					.TP
 | 
				
			||||||
 | 
					.B =
 | 
				
			||||||
 | 
					sets the mode to the given permissions.
 | 
				
			||||||
 | 
					.PD
 | 
				
			||||||
 | 
					.TP
 | 
				
			||||||
 | 
					.B r
 | 
				
			||||||
 | 
					read permissions.
 | 
				
			||||||
 | 
					.PD 0
 | 
				
			||||||
 | 
					.TP
 | 
				
			||||||
 | 
					.B w
 | 
				
			||||||
 | 
					write permissions.
 | 
				
			||||||
 | 
					.TP
 | 
				
			||||||
 | 
					.B x
 | 
				
			||||||
 | 
					execute permissions.
 | 
				
			||||||
 | 
					.TP
 | 
				
			||||||
 | 
					.B s
 | 
				
			||||||
 | 
					setuid and setgid attributes.
 | 
				
			||||||
 | 
					.PD
 | 
				
			||||||
.SH OPTIONS
 | 
					.SH OPTIONS
 | 
				
			||||||
.TP
 | 
					.TP
 | 
				
			||||||
.B \-R, \-r
 | 
					.B \-R, \-r
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										98
									
								
								chmod.c
									
									
									
									
									
								
							
							
						
						
									
										98
									
								
								chmod.c
									
									
									
									
									
								
							@@ -7,15 +7,16 @@
 | 
				
			|||||||
#include "util.h"
 | 
					#include "util.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void chmodr(const char *);
 | 
					static void chmodr(const char *);
 | 
				
			||||||
 | 
					static void parsemode(const char *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool rflag = false;
 | 
					static bool rflag = false;
 | 
				
			||||||
 | 
					static char oper = '=';
 | 
				
			||||||
static mode_t mode = 0;
 | 
					static mode_t mode = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
main(int argc, char *argv[])
 | 
					main(int argc, char *argv[])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char c;
 | 
						char c;
 | 
				
			||||||
	int octal;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while((c = getopt(argc, argv, "Rr")) != -1)
 | 
						while((c = getopt(argc, argv, "Rr")) != -1)
 | 
				
			||||||
		switch(c) {
 | 
							switch(c) {
 | 
				
			||||||
@@ -28,9 +29,45 @@ main(int argc, char *argv[])
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	if(optind == argc)
 | 
						if(optind == argc)
 | 
				
			||||||
		eprintf("usage: %s [-Rr] mode [file...]\n", argv[0]);
 | 
							eprintf("usage: %s [-Rr] mode [file...]\n", argv[0]);
 | 
				
			||||||
	octal = estrtol(argv[optind++], 8);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* posix doesn't specify modal bits */
 | 
						parsemode(argv[optind++]);
 | 
				
			||||||
 | 
						for(; optind < argc; optind++)
 | 
				
			||||||
 | 
							chmodr(argv[optind]);
 | 
				
			||||||
 | 
						return EXIT_SUCCESS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					chmodr(const char *path)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct stat st;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(stat(path, &st) == -1)
 | 
				
			||||||
 | 
							eprintf("stat %s:", path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch(oper) {
 | 
				
			||||||
 | 
						case '+':
 | 
				
			||||||
 | 
							st.st_mode |= mode;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case '-':
 | 
				
			||||||
 | 
							st.st_mode &= ~mode;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if(chmod(path, st.st_mode) == -1)
 | 
				
			||||||
 | 
							eprintf("chmod %s:", path);
 | 
				
			||||||
 | 
						if(rflag)
 | 
				
			||||||
 | 
							recurse(path, chmodr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					parsemode(const char *str)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						char *end;
 | 
				
			||||||
 | 
						const char *p;
 | 
				
			||||||
 | 
						int octal;
 | 
				
			||||||
 | 
						mode_t mask = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						octal = strtol(str, &end, 8);
 | 
				
			||||||
 | 
						if(*end == '\0') {
 | 
				
			||||||
		if(octal & 04000) mode |= S_ISUID;
 | 
							if(octal & 04000) mode |= S_ISUID;
 | 
				
			||||||
		if(octal & 02000) mode |= S_ISGID;
 | 
							if(octal & 02000) mode |= S_ISGID;
 | 
				
			||||||
		if(octal & 00400) mode |= S_IRUSR;
 | 
							if(octal & 00400) mode |= S_IRUSR;
 | 
				
			||||||
@@ -42,17 +79,46 @@ main(int argc, char *argv[])
 | 
				
			|||||||
		if(octal & 00004) mode |= S_IROTH;
 | 
							if(octal & 00004) mode |= S_IROTH;
 | 
				
			||||||
		if(octal & 00002) mode |= S_IWOTH;
 | 
							if(octal & 00002) mode |= S_IWOTH;
 | 
				
			||||||
		if(octal & 00001) mode |= S_IXOTH;
 | 
							if(octal & 00001) mode |= S_IXOTH;
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
	for(; optind < argc; optind++)
 | 
						}
 | 
				
			||||||
		chmodr(argv[optind]);
 | 
						for(p = str; *p; p++)
 | 
				
			||||||
	return EXIT_SUCCESS;
 | 
							switch(*p) {
 | 
				
			||||||
}
 | 
							/* masks */
 | 
				
			||||||
 | 
							case 'u':
 | 
				
			||||||
void
 | 
								mask |= S_IRWXU;
 | 
				
			||||||
chmodr(const char *path)
 | 
								break;
 | 
				
			||||||
{
 | 
							case 'g':
 | 
				
			||||||
	if(chmod(path, mode) == -1)
 | 
								mask |= S_IRWXG;
 | 
				
			||||||
		eprintf("chmod %s:", path);
 | 
								break;
 | 
				
			||||||
	if(rflag)
 | 
							case 'o':
 | 
				
			||||||
		recurse(path, chmodr);
 | 
								mask |= S_IRWXO;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 'a':
 | 
				
			||||||
 | 
								mask |= S_IRWXU|S_IRWXG|S_IRWXO;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							/* opers */
 | 
				
			||||||
 | 
							case '+':
 | 
				
			||||||
 | 
							case '-':
 | 
				
			||||||
 | 
							case '=':
 | 
				
			||||||
 | 
								oper = *p;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							/* modes */
 | 
				
			||||||
 | 
							case 'r':
 | 
				
			||||||
 | 
								mode |= S_IRUSR|S_IRGRP|S_IROTH;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 'w':
 | 
				
			||||||
 | 
								mode |= S_IWUSR|S_IWGRP|S_IWOTH;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 'x':
 | 
				
			||||||
 | 
								mode |= S_IXUSR|S_IXGRP|S_IXOTH;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 's':
 | 
				
			||||||
 | 
								mode |= S_ISUID|S_ISGID;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							/* error */
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								eprintf("%s: invalid mode\n", str);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						if(mask)
 | 
				
			||||||
 | 
							mode &= mask;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user