Added the checkown applet based on the work by Renato Caldas, #192682
checkdir ensures that the specified files (or directories) are owned by the current user/group or as specified on the command line. You can optionally check permissions too.
This commit is contained in:
		| @@ -3,6 +3,11 @@ | ||||
|  | ||||
|   19 Sep 2007; Roy Marples <uberlord@gentoo.org>: | ||||
|  | ||||
|     Added the checkown applet based on the work by Renato Caldas, #192682 | ||||
|     checkdir ensures that the specified files (or directories) are owned | ||||
|     by the current user/group or as specified on the command line. You can | ||||
|     optionally check permissions too. | ||||
|  | ||||
|     Change from /lib/rcscripts to /lib/rc and adjust our files so changing | ||||
|     our libdir is much easier in future. This move makes sense it's so much | ||||
|     more than a holding place for our scripts now. It also has the added | ||||
|   | ||||
| @@ -56,7 +56,7 @@ LIBRCSO = librc.so.$(LIBRCSOVER) | ||||
| LIBRCOBJS = librc.o librc-depend.o librc-daemon.o librc-misc.o librc-strlist.o | ||||
| LDLIBS_LIBRC = -leinfo | ||||
|  | ||||
| RCOBJS = env-update.o fstabinfo.o mountinfo.o \ | ||||
| RCOBJS = checkown.o env-update.o fstabinfo.o mountinfo.o \ | ||||
| 		 rc-depend.o rc-plugin.o rc-status.o rc-update.o runscript.o \ | ||||
| 		 start-stop-daemon.o rc.o | ||||
| LDLIBS_RC = $(LDLIBS_LIBRC) -lrc | ||||
| @@ -80,7 +80,7 @@ RCLINKS = einfon einfo ewarnn ewarn eerrorn eerror ebegin eend ewend \ | ||||
| 	      mark_service_coldplugged \ | ||||
| 	      get_options save_options rc-abort rc-depend \ | ||||
| 	      is_runlevel_start is_runlevel_stop service_started_daemon \ | ||||
| 		  fstabinfo mountinfo | ||||
| 		  checkown fstabinfo mountinfo | ||||
| BINLINKS = rc-status | ||||
| SBINLINKS = env-update rc-update runscript start-stop-daemon | ||||
|  | ||||
|   | ||||
| @@ -7,12 +7,14 @@ | ||||
|  * Released under the GPLv2 | ||||
|  */ | ||||
|  | ||||
| #define getoptstring_COMMON "Ch" | ||||
| #define getoptstring_COMMON "Chq" | ||||
| #define longopts_COMMON \ | ||||
| 	{ "help",           0, NULL, 'h'}, \ | ||||
| 	{ "nocolor",        0, NULL, 'C'}, | ||||
| 	{ "nocolor",        0, NULL, 'C'}, \ | ||||
| 	{ "quiet",			0, NULL, 'q'}, | ||||
|  | ||||
| #define case_RC_COMMON_GETOPT \ | ||||
| 	case 'C': setenv ("RC_NOCOLOR", "yes", 1); break; \ | ||||
| 	case 'h': usage (EXIT_SUCCESS); \ | ||||
| 	case 'q': setenv ("RC_QUIET", "yes", 1); break; \ | ||||
| 	default:  usage (EXIT_FAILURE); | ||||
|   | ||||
| @@ -7,6 +7,7 @@ | ||||
|  * Released under the GPLv2 | ||||
|  */ | ||||
|  | ||||
| int checkown (int argc, char **argv); | ||||
| int env_update (int argc, char **argv); | ||||
| int fstabinfo (int argc, char **argv); | ||||
| int mountinfo (int argc, char **argv); | ||||
|   | ||||
							
								
								
									
										179
									
								
								src/checkown.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								src/checkown.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,179 @@ | ||||
| /* | ||||
|    checkown.c | ||||
|    Checks for the existance of a directory and creates it | ||||
|    if necessary. It can also correct its ownership. | ||||
|  | ||||
|    Copyright 2007 Gentoo Foundation | ||||
|    */ | ||||
|  | ||||
| #define APPLET "checkown" | ||||
|  | ||||
| #include <sys/types.h> | ||||
| #include <sys/stat.h> | ||||
| #include <errno.h> | ||||
| #include <getopt.h> | ||||
| #include <grp.h> | ||||
| #include <pwd.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| #include "builtins.h" | ||||
| #include "einfo.h" | ||||
|  | ||||
| static char *applet = NULL; | ||||
|  | ||||
| static int do_check (char *path, uid_t uid, gid_t gid, mode_t mode) | ||||
| { | ||||
| 	struct stat dirstat; | ||||
|  | ||||
| 	memset (&dirstat, 0, sizeof (dirstat)); | ||||
|  | ||||
| 	if (stat (path, &dirstat)) { | ||||
| 		einfo ("%s: creating directory", path); | ||||
| 		if (! mode) | ||||
| 			mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH; | ||||
| 		if (mkdir (path, mode)) { | ||||
| 			eerror ("%s: mkdir: %s", applet, strerror (errno)); | ||||
| 			return (-1); | ||||
| 		} | ||||
| 	} else if (mode && (dirstat.st_mode & 0777) != mode) { | ||||
| 		einfo ("%s: correcting mode", applet); | ||||
| 		if (chmod (path, mode)) { | ||||
| 			eerror ("%s: chmod: %s", applet, strerror (errno)); | ||||
| 			return (-1); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (dirstat.st_uid != uid || dirstat.st_gid != gid) { | ||||
| 		if (dirstat.st_dev || dirstat.st_ino) | ||||
| 			einfo ("%s: correcting owner", path); | ||||
| 		if (chown (path, uid, gid)) { | ||||
| 			eerror ("%s: chown: %s", applet, strerror (errno)); | ||||
| 			return (-1); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return (0); | ||||
| } | ||||
|  | ||||
| /* Based on busybox */ | ||||
| static int parse_mode (mode_t *mode, char *text) | ||||
| { | ||||
| 	/* Check for a numeric mode */ | ||||
| 	if ((*mode - '0') < 8) { | ||||
| 		char *p; | ||||
| 		unsigned long l = strtoul (text, &p, 8); | ||||
| 		if (*p || l > 07777U) { | ||||
| 			errno = EINVAL; | ||||
| 			return (-1); | ||||
| 		} | ||||
| 		*mode = l; | ||||
| 		return (0); | ||||
| 	} | ||||
|  | ||||
| 	/* We currently don't check g+w type stuff */ | ||||
| 	errno = EINVAL; | ||||
| 	return (-1); | ||||
| } | ||||
|  | ||||
| static struct passwd *get_user (char **name) | ||||
| { | ||||
| 	struct passwd *pw; | ||||
| 	char *p = *name; | ||||
| 	char *token; | ||||
| 	int tid; | ||||
|  | ||||
| 	token = strsep (&p, ":"); | ||||
| 	if (sscanf (token, "%d", &tid) != 1) | ||||
| 		pw = getpwnam (token); | ||||
| 	else | ||||
| 		pw = getpwuid (tid); | ||||
|  | ||||
| 	if (! pw) | ||||
| 		eerrorx ("%s: user `%s' not found", applet, token); | ||||
|  | ||||
| 	*name = p; | ||||
| 	return (pw); | ||||
| } | ||||
|  | ||||
| static struct group *get_group (const char *name) | ||||
| { | ||||
| 	struct group *gr; | ||||
| 	int tid; | ||||
|  | ||||
| 	if (sscanf (name, "%d", &tid) != 1) | ||||
| 		gr = getgrnam (name); | ||||
| 	else | ||||
| 		gr = getgrgid (tid); | ||||
|  | ||||
| 	if (! gr) | ||||
| 		eerrorx ("%s: group `%s' not found", applet, name); | ||||
|  | ||||
| 	return (gr); | ||||
| } | ||||
|  | ||||
| #include "_usage.h" | ||||
| #define getoptstring "m:g:u:" getoptstring_COMMON | ||||
| static struct option longopts[] = { | ||||
| 	{ "mode",			1, NULL, 'm'}, | ||||
| 	{ "user",           1, NULL, 'u'}, | ||||
| 	{ "group",          1, NULL, 'g'}, | ||||
| 	longopts_COMMON | ||||
| 	{ NULL,             0, NULL, 0} | ||||
| }; | ||||
| #include "_usage.c" | ||||
|  | ||||
| int checkown (int argc, char **argv) | ||||
| { | ||||
| 	int opt; | ||||
| 	uid_t uid = geteuid(); | ||||
| 	gid_t gid = getgid(); | ||||
| 	mode_t mode = 0; | ||||
|  | ||||
| 	struct passwd *pw = NULL; | ||||
| 	struct group *gr = NULL; | ||||
| 	char *p; | ||||
| 	int retval = EXIT_SUCCESS; | ||||
|  | ||||
| 	applet = argv[0]; | ||||
|  | ||||
| 	while ((opt = getopt_long (argc, argv, getoptstring, | ||||
| 							   longopts, (int *) 0)) != -1) | ||||
| 	{ | ||||
| 		switch (opt) { | ||||
| 			case 'm': | ||||
| 				if (parse_mode (&mode, optarg)) | ||||
| 					eerrorx ("%s: invalid mode `%s'", applet, optarg); | ||||
| 				break; | ||||
| 			case 'u': | ||||
| 				p = optarg; | ||||
| 				pw = get_user (&p); | ||||
| 				if (p && *p) | ||||
| 					optarg = p; | ||||
| 				else | ||||
| 					break; | ||||
| 			case 'g': | ||||
| 				gr = get_group (optarg); | ||||
| 				break; | ||||
|  | ||||
| 				case_RC_COMMON_GETOPT | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (pw) { | ||||
| 		uid = pw->pw_uid; | ||||
| 		gid = pw->pw_gid; | ||||
| 	} | ||||
| 	if (gr) | ||||
| 		gid = gr->gr_gid; | ||||
|  | ||||
| 	while (optind < argc) { | ||||
| 		if (do_check (argv[optind], uid, gid, mode)) | ||||
| 			retval = EXIT_FAILURE; | ||||
| 		optind++; | ||||
| 	} | ||||
|  | ||||
| 	exit (retval); | ||||
| } | ||||
| @@ -259,7 +259,6 @@ static struct option longopts[] = { | ||||
| 	{ "options",             0, NULL, 'i'}, | ||||
| 	{ "fstype",              0, NULL, 's'}, | ||||
| 	{ "node",                0, NULL, 't'}, | ||||
| 	{ "quiet",               0, NULL, 'q'}, | ||||
| 	longopts_COMMON | ||||
| 	{ NULL,             0, NULL, 0} | ||||
| }; | ||||
| @@ -274,7 +273,6 @@ int mountinfo (int argc, char **argv) | ||||
| 	char **nodes = NULL; | ||||
| 	char *n; | ||||
| 	int opt; | ||||
| 	bool quiet = false; | ||||
| 	int result; | ||||
|  | ||||
| #define DO_REG(_var) \ | ||||
| @@ -321,9 +319,6 @@ int mountinfo (int argc, char **argv) | ||||
| 			case 't': | ||||
| 				args.mount_type = mount_from; | ||||
| 				break; | ||||
| 			case 'q': | ||||
| 				quiet = true; | ||||
| 				break; | ||||
|  | ||||
| 				case_RC_COMMON_GETOPT | ||||
| 		} | ||||
| @@ -358,7 +353,7 @@ int mountinfo (int argc, char **argv) | ||||
| 			continue; | ||||
| 		if (skip_point_regex && regexec (skip_point_regex, n, 0, NULL, 0) == 0) | ||||
| 			continue; | ||||
| 		if (! quiet) | ||||
| 		if (! rc_is_env ("RC_QUIET", "yes")) | ||||
| 			printf ("%s\n", n); | ||||
| 		result = EXIT_SUCCESS; | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										2
									
								
								src/rc.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								src/rc.c
									
									
									
									
									
								
							| @@ -759,6 +759,8 @@ int main (int argc, char **argv) | ||||
| 		exit (runscript (argc, argv)); | ||||
| 	else if (strcmp (applet, "start-stop-daemon") == 0) | ||||
| 		exit (start_stop_daemon (argc, argv)); | ||||
| 	else if (strcmp (applet, "checkown") == 0) | ||||
| 		exit (checkown (argc, argv)); | ||||
|  | ||||
| 	argc--; | ||||
| 	argv++; | ||||
|   | ||||
| @@ -461,7 +461,7 @@ static void handle_signal (int sig) | ||||
|  | ||||
|  | ||||
| #include "_usage.h" | ||||
| #define getoptstring "KN:R:Sbc:d:g:mn:op:qs:tu:r:vx:1:2:" getoptstring_COMMON | ||||
| #define getoptstring "KN:R:Sbc:d:g:mn:op:s:tu:r:vx:1:2:" getoptstring_COMMON | ||||
| static struct option longopts[] = { | ||||
| 	{ "stop",         0, NULL, 'K'}, | ||||
| 	{ "nicelevel",    1, NULL, 'N'}, | ||||
| @@ -476,7 +476,6 @@ static struct option longopts[] = { | ||||
| 	{ "name",         1, NULL, 'n'}, | ||||
| 	{ "oknodo",       0, NULL, 'o'}, | ||||
| 	{ "pidfile",      1, NULL, 'p'}, | ||||
| 	{ "quiet",        0, NULL, 'q'}, | ||||
| 	{ "signal",       1, NULL, 's'}, | ||||
| 	{ "test",         0, NULL, 't'}, | ||||
| 	{ "user",         1, NULL, 'u'}, | ||||
| @@ -507,7 +506,7 @@ int start_stop_daemon (int argc, char **argv) | ||||
| 	bool stop = false; | ||||
| 	bool oknodo = false; | ||||
| 	bool test = false; | ||||
| 	bool quiet = false; | ||||
| 	bool quiet; | ||||
| 	bool verbose = false; | ||||
| 	char *exec = NULL; | ||||
| 	char *cmd = NULL; | ||||
| @@ -635,10 +634,6 @@ int start_stop_daemon (int argc, char **argv) | ||||
| 				pidfile = optarg; | ||||
| 				break; | ||||
|  | ||||
| 			case 'q':  /* --quiet */ | ||||
| 				quiet = true; | ||||
| 				break; | ||||
|  | ||||
| 			case 's':  /* --signal <signal> */ | ||||
| 				sig = parse_signal (optarg); | ||||
| 				break; | ||||
| @@ -671,9 +666,7 @@ int start_stop_daemon (int argc, char **argv) | ||||
| 				case_RC_COMMON_GETOPT | ||||
| 		} | ||||
|  | ||||
| 	/* Respect RC as well as how we are called */ | ||||
| 	if (rc_is_env ("RC_QUIET", "yes") && ! verbose) | ||||
| 		quiet = true; | ||||
| 	quiet = rc_is_env ("RC_QUIET", "yes"); | ||||
|  | ||||
| 	/* Allow start-stop-daemon --signal HUP --exec /usr/sbin/dnsmasq | ||||
| 	 * instead of forcing --stop --oknodo as well */ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user