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:
Roy Marples 2007-09-19 16:27:37 +00:00
parent a74dd430d5
commit b6aa1c857c
8 changed files with 197 additions and 20 deletions

View File

@ -3,6 +3,11 @@
19 Sep 2007; Roy Marples <uberlord@gentoo.org>: 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 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 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 more than a holding place for our scripts now. It also has the added

View File

@ -56,7 +56,7 @@ LIBRCSO = librc.so.$(LIBRCSOVER)
LIBRCOBJS = librc.o librc-depend.o librc-daemon.o librc-misc.o librc-strlist.o LIBRCOBJS = librc.o librc-depend.o librc-daemon.o librc-misc.o librc-strlist.o
LDLIBS_LIBRC = -leinfo 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 \ rc-depend.o rc-plugin.o rc-status.o rc-update.o runscript.o \
start-stop-daemon.o rc.o start-stop-daemon.o rc.o
LDLIBS_RC = $(LDLIBS_LIBRC) -lrc LDLIBS_RC = $(LDLIBS_LIBRC) -lrc
@ -80,7 +80,7 @@ RCLINKS = einfon einfo ewarnn ewarn eerrorn eerror ebegin eend ewend \
mark_service_coldplugged \ mark_service_coldplugged \
get_options save_options rc-abort rc-depend \ get_options save_options rc-abort rc-depend \
is_runlevel_start is_runlevel_stop service_started_daemon \ is_runlevel_start is_runlevel_stop service_started_daemon \
fstabinfo mountinfo checkown fstabinfo mountinfo
BINLINKS = rc-status BINLINKS = rc-status
SBINLINKS = env-update rc-update runscript start-stop-daemon SBINLINKS = env-update rc-update runscript start-stop-daemon

View File

@ -7,12 +7,14 @@
* Released under the GPLv2 * Released under the GPLv2
*/ */
#define getoptstring_COMMON "Ch" #define getoptstring_COMMON "Chq"
#define longopts_COMMON \ #define longopts_COMMON \
{ "help", 0, NULL, 'h'}, \ { "help", 0, NULL, 'h'}, \
{ "nocolor", 0, NULL, 'C'}, { "nocolor", 0, NULL, 'C'}, \
{ "quiet", 0, NULL, 'q'},
#define case_RC_COMMON_GETOPT \ #define case_RC_COMMON_GETOPT \
case 'C': setenv ("RC_NOCOLOR", "yes", 1); break; \ case 'C': setenv ("RC_NOCOLOR", "yes", 1); break; \
case 'h': usage (EXIT_SUCCESS); \ case 'h': usage (EXIT_SUCCESS); \
case 'q': setenv ("RC_QUIET", "yes", 1); break; \
default: usage (EXIT_FAILURE); default: usage (EXIT_FAILURE);

View File

@ -7,6 +7,7 @@
* Released under the GPLv2 * Released under the GPLv2
*/ */
int checkown (int argc, char **argv);
int env_update (int argc, char **argv); int env_update (int argc, char **argv);
int fstabinfo (int argc, char **argv); int fstabinfo (int argc, char **argv);
int mountinfo (int argc, char **argv); int mountinfo (int argc, char **argv);

179
src/checkown.c Normal file
View 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);
}

View File

@ -259,7 +259,6 @@ static struct option longopts[] = {
{ "options", 0, NULL, 'i'}, { "options", 0, NULL, 'i'},
{ "fstype", 0, NULL, 's'}, { "fstype", 0, NULL, 's'},
{ "node", 0, NULL, 't'}, { "node", 0, NULL, 't'},
{ "quiet", 0, NULL, 'q'},
longopts_COMMON longopts_COMMON
{ NULL, 0, NULL, 0} { NULL, 0, NULL, 0}
}; };
@ -274,7 +273,6 @@ int mountinfo (int argc, char **argv)
char **nodes = NULL; char **nodes = NULL;
char *n; char *n;
int opt; int opt;
bool quiet = false;
int result; int result;
#define DO_REG(_var) \ #define DO_REG(_var) \
@ -321,9 +319,6 @@ int mountinfo (int argc, char **argv)
case 't': case 't':
args.mount_type = mount_from; args.mount_type = mount_from;
break; break;
case 'q':
quiet = true;
break;
case_RC_COMMON_GETOPT case_RC_COMMON_GETOPT
} }
@ -358,7 +353,7 @@ int mountinfo (int argc, char **argv)
continue; continue;
if (skip_point_regex && regexec (skip_point_regex, n, 0, NULL, 0) == 0) if (skip_point_regex && regexec (skip_point_regex, n, 0, NULL, 0) == 0)
continue; continue;
if (! quiet) if (! rc_is_env ("RC_QUIET", "yes"))
printf ("%s\n", n); printf ("%s\n", n);
result = EXIT_SUCCESS; result = EXIT_SUCCESS;
} }

View File

@ -759,6 +759,8 @@ int main (int argc, char **argv)
exit (runscript (argc, argv)); exit (runscript (argc, argv));
else if (strcmp (applet, "start-stop-daemon") == 0) else if (strcmp (applet, "start-stop-daemon") == 0)
exit (start_stop_daemon (argc, argv)); exit (start_stop_daemon (argc, argv));
else if (strcmp (applet, "checkown") == 0)
exit (checkown (argc, argv));
argc--; argc--;
argv++; argv++;

View File

@ -461,7 +461,7 @@ static void handle_signal (int sig)
#include "_usage.h" #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[] = { static struct option longopts[] = {
{ "stop", 0, NULL, 'K'}, { "stop", 0, NULL, 'K'},
{ "nicelevel", 1, NULL, 'N'}, { "nicelevel", 1, NULL, 'N'},
@ -476,7 +476,6 @@ static struct option longopts[] = {
{ "name", 1, NULL, 'n'}, { "name", 1, NULL, 'n'},
{ "oknodo", 0, NULL, 'o'}, { "oknodo", 0, NULL, 'o'},
{ "pidfile", 1, NULL, 'p'}, { "pidfile", 1, NULL, 'p'},
{ "quiet", 0, NULL, 'q'},
{ "signal", 1, NULL, 's'}, { "signal", 1, NULL, 's'},
{ "test", 0, NULL, 't'}, { "test", 0, NULL, 't'},
{ "user", 1, NULL, 'u'}, { "user", 1, NULL, 'u'},
@ -507,7 +506,7 @@ int start_stop_daemon (int argc, char **argv)
bool stop = false; bool stop = false;
bool oknodo = false; bool oknodo = false;
bool test = false; bool test = false;
bool quiet = false; bool quiet;
bool verbose = false; bool verbose = false;
char *exec = NULL; char *exec = NULL;
char *cmd = NULL; char *cmd = NULL;
@ -635,10 +634,6 @@ int start_stop_daemon (int argc, char **argv)
pidfile = optarg; pidfile = optarg;
break; break;
case 'q': /* --quiet */
quiet = true;
break;
case 's': /* --signal <signal> */ case 's': /* --signal <signal> */
sig = parse_signal (optarg); sig = parse_signal (optarg);
break; break;
@ -671,9 +666,7 @@ int start_stop_daemon (int argc, char **argv)
case_RC_COMMON_GETOPT case_RC_COMMON_GETOPT
} }
/* Respect RC as well as how we are called */ quiet = rc_is_env ("RC_QUIET", "yes");
if (rc_is_env ("RC_QUIET", "yes") && ! verbose)
quiet = true;
/* Allow start-stop-daemon --signal HUP --exec /usr/sbin/dnsmasq /* Allow start-stop-daemon --signal HUP --exec /usr/sbin/dnsmasq
* instead of forcing --stop --oknodo as well */ * instead of forcing --stop --oknodo as well */