/[baselayout]/trunk/src/checkown.c
Gentoo

Contents of /trunk/src/checkown.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2899 - (show annotations) (download) (as text)
Wed Sep 19 17:08:25 2007 UTC (7 years, 3 months ago) by uberlord
File MIME type: text/x-csrc
File size: 3827 byte(s)
Allow checkown to create files too.
1 /*
2 checkown.c
3 Checks for the existance of a file or directory and creates it
4 if necessary. It can also correct its ownership.
5
6 Copyright 2007 Gentoo Foundation
7 */
8
9 #define APPLET "checkown"
10
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <errno.h>
14 #include <fcntl.h>
15 #include <getopt.h>
16 #include <grp.h>
17 #include <pwd.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <unistd.h>
22
23 #include "builtins.h"
24 #include "einfo.h"
25
26 static char *applet = NULL;
27
28 static int do_check (char *path, uid_t uid, gid_t gid, mode_t mode, bool file)
29 {
30 struct stat dirstat;
31
32 memset (&dirstat, 0, sizeof (dirstat));
33
34 if (stat (path, &dirstat)) {
35 if (file) {
36 int fd;
37 einfo ("%s: creating file", path);
38 if ((fd = open (path, O_CREAT)) == -1) {
39 eerror ("%s: open: %s", applet, strerror (errno));
40 return (-1);
41 }
42 close (fd);
43 } else {
44 einfo ("%s: creating directory", path);
45 if (! mode)
46 mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH;
47 if (mkdir (path, mode)) {
48 eerror ("%s: mkdir: %s", applet, strerror (errno));
49 return (-1);
50 }
51 mode = 0;
52 }
53 }
54
55 if (mode && (dirstat.st_mode & 0777) != mode) {
56 einfo ("%s: correcting mode", applet);
57 if (chmod (path, mode)) {
58 eerror ("%s: chmod: %s", applet, strerror (errno));
59 return (-1);
60 }
61 }
62
63 if (dirstat.st_uid != uid || dirstat.st_gid != gid) {
64 if (dirstat.st_dev || dirstat.st_ino)
65 einfo ("%s: correcting owner", path);
66 if (chown (path, uid, gid)) {
67 eerror ("%s: chown: %s", applet, strerror (errno));
68 return (-1);
69 }
70 }
71
72 return (0);
73 }
74
75 /* Based on busybox */
76 static int parse_mode (mode_t *mode, char *text)
77 {
78 /* Check for a numeric mode */
79 if ((*mode - '0') < 8) {
80 char *p;
81 unsigned long l = strtoul (text, &p, 8);
82 if (*p || l > 07777U) {
83 errno = EINVAL;
84 return (-1);
85 }
86 *mode = l;
87 return (0);
88 }
89
90 /* We currently don't check g+w type stuff */
91 errno = EINVAL;
92 return (-1);
93 }
94
95 static struct passwd *get_user (char **name)
96 {
97 struct passwd *pw;
98 char *p = *name;
99 char *token;
100 int tid;
101
102 token = strsep (&p, ":");
103 if (sscanf (token, "%d", &tid) != 1)
104 pw = getpwnam (token);
105 else
106 pw = getpwuid (tid);
107
108 if (pw)
109 *name = p;
110
111 return (pw);
112 }
113
114 static struct group *get_group (const char *name)
115 {
116 int tid;
117
118 if (sscanf (name, "%d", &tid) != 1)
119 return (getgrnam (name));
120 else
121 return (getgrgid (tid));
122 }
123
124 #include "_usage.h"
125 #define getoptstring "fm:g:u:" getoptstring_COMMON
126 static struct option longopts[] = {
127 { "directory", 0, NULL, 'd'},
128 { "file", 0, NULL, 'f'},
129 { "mode", 1, NULL, 'm'},
130 { "user", 1, NULL, 'u'},
131 { "group", 1, NULL, 'g'},
132 longopts_COMMON
133 { NULL, 0, NULL, 0}
134 };
135 #include "_usage.c"
136
137 int checkown (int argc, char **argv)
138 {
139 int opt;
140 uid_t uid = geteuid();
141 gid_t gid = getgid();
142 mode_t mode = 0;
143 struct passwd *pw = NULL;
144 struct group *gr = NULL;
145 bool file = 0;
146
147 char *p;
148 int retval = EXIT_SUCCESS;
149
150 applet = argv[0];
151
152 while ((opt = getopt_long (argc, argv, getoptstring,
153 longopts, (int *) 0)) != -1)
154 {
155 switch (opt) {
156 case 'd':
157 file = 0;
158 break;
159 case 'f':
160 file = 1;
161 break;
162 case 'm':
163 if (parse_mode (&mode, optarg))
164 eerrorx ("%s: invalid mode `%s'", applet, optarg);
165 break;
166 case 'u':
167 p = optarg;
168 if (! (pw = get_user (&p)))
169 eerrorx ("%s: user `%s' not found", applet, optarg);
170 if (p && *p)
171 optarg = p;
172 else
173 break;
174 case 'g':
175 if (! (gr = get_group (optarg)))
176 eerrorx ("%s: group `%s' not found", applet, optarg);
177 break;
178
179 case_RC_COMMON_GETOPT
180 }
181 }
182
183 if (pw) {
184 uid = pw->pw_uid;
185 gid = pw->pw_gid;
186 }
187 if (gr)
188 gid = gr->gr_gid;
189
190 while (optind < argc) {
191 if (do_check (argv[optind], uid, gid, mode, file))
192 retval = EXIT_FAILURE;
193 optind++;
194 }
195
196 exit (retval);
197 }

  ViewVC Help
Powered by ViewVC 1.1.20