summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/makedevs
diff options
context:
space:
mode:
authorChen Qi <Qi.Chen@windriver.com>2013-08-13 14:11:49 +0800
committerRichard Purdie <richard.purdie@linuxfoundation.org>2013-08-16 11:14:33 +0100
commit36d622b4c6e2ff1e976b713c6841383f4188f851 (patch)
treedcc8ed0dbaaa4362702beb5c6e7afe2a73d61dae /meta/recipes-devtools/makedevs
parentca367d02fde01bebc37666a05341a91d6b1366cc (diff)
downloadpoky-36d622b4c6e2ff1e976b713c6841383f4188f851.tar.gz
makedevs: support using user/group names in device table files
Compared to hard coding the numeric group and user ids in the device table files, the way of using user/group names is preferred. This patch adds the ability to makedevs to correctly deal with device table files with user/group names in them. To maintain backward compatibility, the way of using uid/gid is still supported. [YOCTO #1159] (From OE-Core rev: 1fcf718e3a1e50446ab61972069566e5016bc625) Signed-off-by: Chen Qi <Qi.Chen@windriver.com> Signed-off-by: Saul Wold <sgw@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/recipes-devtools/makedevs')
-rw-r--r--meta/recipes-devtools/makedevs/makedevs-1.0.0/makedevs.c207
1 files changed, 178 insertions, 29 deletions
diff --git a/meta/recipes-devtools/makedevs/makedevs-1.0.0/makedevs.c b/meta/recipes-devtools/makedevs/makedevs-1.0.0/makedevs.c
index 6c1f2fb461..cc3707b2c8 100644
--- a/meta/recipes-devtools/makedevs/makedevs-1.0.0/makedevs.c
+++ b/meta/recipes-devtools/makedevs/makedevs-1.0.0/makedevs.c
@@ -16,6 +16,11 @@
16 16
17#define MINORBITS 8 17#define MINORBITS 8
18#define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi)) 18#define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi))
19#define MAX_ID_LEN 40
20#define MAX_NAME_LEN 40
21#ifndef PATH_MAX
22#define PATH_MAX 4096
23#endif
19 24
20/* These are all stolen from busybox's libbb to make 25/* These are all stolen from busybox's libbb to make
21 * error handling simpler (and since I maintain busybox, 26 * error handling simpler (and since I maintain busybox,
@@ -27,6 +32,15 @@ static const char *const memory_exhausted = "memory exhausted";
27static char default_rootdir[]="."; 32static char default_rootdir[]=".";
28static char *rootdir = default_rootdir; 33static char *rootdir = default_rootdir;
29 34
35struct name_id {
36 char name[MAX_NAME_LEN+1];
37 unsigned long id;
38 struct name_id *next;
39};
40
41static struct name_id *usr_list = NULL;
42static struct name_id *grp_list = NULL;
43
30static void verror_msg(const char *s, va_list p) 44static void verror_msg(const char *s, va_list p)
31{ 45{
32 fflush(stdout); 46 fflush(stdout);
@@ -57,17 +71,6 @@ static void vperror_msg(const char *s, va_list p)
57 fprintf(stderr, "%s%s\n", s, strerror(err)); 71 fprintf(stderr, "%s%s\n", s, strerror(err));
58} 72}
59 73
60#if 0
61static void perror_msg(const char *s, ...)
62{
63 va_list p;
64
65 va_start(p, s);
66 vperror_msg(s, p);
67 va_end(p);
68}
69#endif
70
71static void perror_msg_and_die(const char *s, ...) 74static void perror_msg_and_die(const char *s, ...)
72{ 75{
73 va_list p; 76 va_list p;
@@ -102,6 +105,124 @@ static char *xstrdup(const char *s)
102 return t; 105 return t;
103} 106}
104 107
108static struct name_id* alloc_node(void)
109{
110 struct name_id *node;
111 node = (struct name_id*)malloc(sizeof(struct name_id));
112 if (node == NULL) {
113 error_msg_and_die(memory_exhausted);
114 }
115 memset((void *)node->name, 0, MAX_NAME_LEN+1);
116 node->id = 0xffffffff;
117 node->next = NULL;
118 return node;
119}
120
121static struct name_id* parse_line(char *line)
122{
123 char *p;
124 int i;
125 char id_buf[MAX_ID_LEN+1];
126 struct name_id *node;
127 node = alloc_node();
128 p = line;
129 i = 0;
130 // Get name field
131 while (*p != ':') {
132 if (i > MAX_NAME_LEN)
133 error_msg_and_die("Name field too long");
134 node->name[i++] = *p++;
135 }
136 node->name[i] = '\0';
137 p++;
138 // Skip the second field
139 while (*p != ':')
140 p++;
141 p++;
142 // Get id field
143 i = 0;
144 while (*p != ':') {
145 if (i > MAX_ID_LEN)
146 error_msg_and_die("ID filed too long");
147 id_buf[i++] = *p++;
148 }
149 id_buf[i] = '\0';
150 node->id = atol(id_buf);
151 return node;
152}
153
154static void get_list_from_file(FILE *file, struct name_id **plist)
155{
156 char *line;
157 int len = 0;
158 size_t length = 256;
159 struct name_id *node, *cur;
160
161 if((line = (char *)malloc(length)) == NULL) {
162 error_msg_and_die(memory_exhausted);
163 }
164
165 while ((len = getline(&line, &length, file)) != -1) {
166 node = parse_line(line);
167 if (*plist == NULL) {
168 *plist = node;
169 cur = *plist;
170 } else {
171 cur->next = node;
172 cur = cur->next;
173 }
174 }
175
176 if (line)
177 free(line);
178}
179
180static unsigned long convert2guid(char *id_buf, struct name_id *search_list)
181{
182 char *p;
183 int isnum;
184 struct name_id *node;
185 p = id_buf;
186 isnum = 1;
187 while (*p != '\0') {
188 if (!isdigit(*p)) {
189 isnum = 0;
190 break;
191 }
192 p++;
193 }
194 if (isnum) {
195 // Check for bad user/group name
196 node = search_list;
197 while (node != NULL) {
198 if (!strncmp(node->name, id_buf, strlen(id_buf))) {
199 fprintf(stderr, "WARNING: Bad user/group name %s detected\n", id_buf);
200 break;
201 }
202 node = node->next;
203 }
204 return (unsigned long)atol(id_buf);
205 } else {
206 node = search_list;
207 while (node != NULL) {
208 if (!strncmp(node->name, id_buf, strlen(id_buf)))
209 return node->id;
210 node = node->next;
211 }
212 error_msg_and_die("No entry for %s in search list", id_buf);
213 }
214}
215
216static void free_list(struct name_id *list)
217{
218 struct name_id *cur;
219 cur = list;
220 while (cur != NULL) {
221 list = cur;
222 cur = cur->next;
223 free(list);
224 }
225}
105 226
106static void add_new_directory(char *name, char *path, 227static void add_new_directory(char *name, char *path,
107 unsigned long uid, unsigned long gid, unsigned long mode) 228 unsigned long uid, unsigned long gid, unsigned long mode)
@@ -162,8 +283,9 @@ static void add_new_fifo(char *name, char *path, unsigned long uid,
162 283
163 284
164/* device table entries take the form of: 285/* device table entries take the form of:
165 <path> <type> <mode> <uid> <gid> <major> <minor> <start> <inc> <count> 286 <path> <type> <mode> <usr> <grp> <major> <minor> <start> <inc> <count>
166 /dev/mem c 640 0 0 1 1 0 0 - 287 /dev/mem c 640 0 0 1 1 0 0 -
288 /dev/zero c 644 root root 1 5 - - -
167 289
168 type can be one of: 290 type can be one of:
169 f A regular file 291 f A regular file
@@ -181,18 +303,23 @@ static void add_new_fifo(char *name, char *path, unsigned long uid,
181static int interpret_table_entry(char *line) 303static int interpret_table_entry(char *line)
182{ 304{
183 char *name; 305 char *name;
306 char usr_buf[MAX_ID_LEN];
307 char grp_buf[MAX_ID_LEN];
184 char path[4096], type; 308 char path[4096], type;
185 unsigned long mode = 0755, uid = 0, gid = 0, major = 0, minor = 0; 309 unsigned long mode = 0755, uid = 0, gid = 0, major = 0, minor = 0;
186 unsigned long start = 0, increment = 1, count = 0; 310 unsigned long start = 0, increment = 1, count = 0;
187 311
188 if (0 > sscanf(line, "%40s %c %lo %lu %lu %lu %lu %lu %lu %lu", path, 312 if (0 > sscanf(line, "%40s %c %lo %40s %40s %lu %lu %lu %lu %lu", path,
189 &type, &mode, &uid, &gid, &major, &minor, &start, 313 &type, &mode, usr_buf, grp_buf, &major, &minor, &start,
190 &increment, &count)) 314 &increment, &count))
191 { 315 {
192 return 1; 316 return 1;
193 } 317 }
194 318
195 if (!strcmp(path, "/")) { 319 uid = convert2guid(usr_buf, usr_list);
320 gid = convert2guid(grp_buf, grp_list);
321
322 if (strncmp(path, "/", 1)) {
196 error_msg_and_die("Device table entries require absolute paths"); 323 error_msg_and_die("Device table entries require absolute paths");
197 } 324 }
198 name = xstrdup(path + 1); 325 name = xstrdup(path + 1);
@@ -231,7 +358,6 @@ static int interpret_table_entry(char *line)
231 /* FIXME: MKDEV uses illicit insider knowledge of kernel 358 /* FIXME: MKDEV uses illicit insider knowledge of kernel
232 * major/minor representation... */ 359 * major/minor representation... */
233 dev_t rdev = MKDEV(major, minor); 360 dev_t rdev = MKDEV(major, minor);
234
235 add_new_device(name, path, uid, gid, mode, rdev); 361 add_new_device(name, path, uid, gid, mode, rdev);
236 } 362 }
237 break; 363 break;
@@ -249,17 +375,15 @@ static void parse_device_table(FILE * file)
249 size_t length = 256; 375 size_t length = 256;
250 int len = 0; 376 int len = 0;
251 377
378 if((line = (char *)malloc(length)) == NULL) {
379 error_msg_and_die(memory_exhausted);
380 }
252 /* Looks ok so far. The general plan now is to read in one 381 /* Looks ok so far. The general plan now is to read in one
253 * line at a time, check for leading comment delimiters ('#'), 382 * line at a time, check for leading comment delimiters ('#'),
254 * then try and parse the line as a device table. If we fail 383 * then try and parse the line as a device table. If we fail
255 * to parse things, try and help the poor fool to fix their 384 * to parse things, try and help the poor fool to fix their
256 * device table with a useful error msg... */ 385 * device table with a useful error msg... */
257 386
258 if((line = (char *)malloc(length)) == NULL) {
259 fclose(file);
260 return;
261 }
262
263 while ((len = getline(&line, &length, file)) != -1) { 387 while ((len = getline(&line, &length, file)) != -1) {
264 /* First trim off any whitespace */ 388 /* First trim off any whitespace */
265 389
@@ -273,20 +397,20 @@ static void parse_device_table(FILE * file)
273 /* If this is NOT a comment line, try to interpret it */ 397 /* If this is NOT a comment line, try to interpret it */
274 if (*line != '#') interpret_table_entry(line); 398 if (*line != '#') interpret_table_entry(line);
275 } 399 }
276 if (line) free(line);
277 400
278 fclose(file); 401 if (line)
402 free(line);
279} 403}
280 404
281static int go(char *dname, FILE * devtable) 405static int parse_devtable(FILE * devtable)
282{ 406{
283 struct stat sb; 407 struct stat sb;
284 408
285 if (lstat(dname, &sb)) { 409 if (lstat(rootdir, &sb)) {
286 perror_msg_and_die("%s", dname); 410 perror_msg_and_die("%s", rootdir);
287 } 411 }
288 if (chdir(dname)) 412 if (chdir(rootdir))
289 perror_msg_and_die("%s", dname); 413 perror_msg_and_die("%s", rootdir);
290 414
291 if (devtable) 415 if (devtable)
292 parse_device_table(devtable); 416 parse_device_table(devtable);
@@ -322,6 +446,10 @@ int main(int argc, char **argv)
322 int c, opt; 446 int c, opt;
323 extern char *optarg; 447 extern char *optarg;
324 struct stat statbuf; 448 struct stat statbuf;
449 char passwd_path[PATH_MAX];
450 char group_path[PATH_MAX];
451 FILE *passwd_file = NULL;
452 FILE *group_file = NULL;
325 FILE *devtable = NULL; 453 FILE *devtable = NULL;
326 454
327 umask (0); 455 umask (0);
@@ -354,6 +482,27 @@ int main(int argc, char **argv)
354 } 482 }
355 } 483 }
356 484
357 go(rootdir, devtable); 485 // Get name-id mapping
486 sprintf(passwd_path, "%s/etc/passwd", rootdir);
487 sprintf(group_path, "%s/etc/group", rootdir);
488 if ((passwd_file = fopen(passwd_path, "r")) != NULL) {
489 get_list_from_file(passwd_file, &usr_list);
490 fclose(passwd_file);
491 }
492 if ((group_file = fopen(group_path, "r")) != NULL) {
493 get_list_from_file(group_file, &grp_list);
494 fclose(group_file);
495 }
496
497 // Parse devtable
498 if(devtable) {
499 parse_devtable(devtable);
500 fclose(devtable);
501 }
502
503 // Free list
504 free_list(usr_list);
505 free_list(grp_list);
506
358 return 0; 507 return 0;
359} 508}