diff options
| author | Chen Qi <Qi.Chen@windriver.com> | 2013-08-13 14:11:49 +0800 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2013-08-16 11:14:33 +0100 |
| commit | 36d622b4c6e2ff1e976b713c6841383f4188f851 (patch) | |
| tree | dcc8ed0dbaaa4362702beb5c6e7afe2a73d61dae /meta | |
| parent | ca367d02fde01bebc37666a05341a91d6b1366cc (diff) | |
| download | poky-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')
| -rw-r--r-- | meta/recipes-devtools/makedevs/makedevs-1.0.0/makedevs.c | 207 |
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"; | |||
| 27 | static char default_rootdir[]="."; | 32 | static char default_rootdir[]="."; |
| 28 | static char *rootdir = default_rootdir; | 33 | static char *rootdir = default_rootdir; |
| 29 | 34 | ||
| 35 | struct name_id { | ||
| 36 | char name[MAX_NAME_LEN+1]; | ||
| 37 | unsigned long id; | ||
| 38 | struct name_id *next; | ||
| 39 | }; | ||
| 40 | |||
| 41 | static struct name_id *usr_list = NULL; | ||
| 42 | static struct name_id *grp_list = NULL; | ||
| 43 | |||
| 30 | static void verror_msg(const char *s, va_list p) | 44 | static 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 | ||
| 61 | static 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 | |||
| 71 | static void perror_msg_and_die(const char *s, ...) | 74 | static 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 | ||
| 108 | static 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 | |||
| 121 | static 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 | |||
| 154 | static 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 | |||
| 180 | static 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 | |||
| 216 | static 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 | ||
| 106 | static void add_new_directory(char *name, char *path, | 227 | static 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, | |||
| 181 | static int interpret_table_entry(char *line) | 303 | static 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 | ||
| 281 | static int go(char *dname, FILE * devtable) | 405 | static 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 | } |
