Merge changes Ieb75b1d1,Id1c83c8b,I8cb3de94
* changes: mkbootfs: Add support for a dev node list file mkbootfs: Add support for dev nodes mkbootfs: Use getopt_long
This commit is contained in:
commit
60305abf38
1 changed files with 160 additions and 23 deletions
|
|
@ -1,4 +1,7 @@
|
|||
|
||||
#include <error.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
|
@ -7,11 +10,14 @@
|
|||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysmacros.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <linux/kdev_t.h>
|
||||
|
||||
#include <private/android_filesystem_config.h>
|
||||
#include <private/fs_config.h>
|
||||
|
||||
|
|
@ -21,7 +27,6 @@
|
|||
** an explanation of this file format
|
||||
** - dotfiles are ignored
|
||||
** - directories named 'root' are ignored
|
||||
** - device notes, pipes, etc are not supported (error)
|
||||
*/
|
||||
|
||||
static void die(const char* why, ...) {
|
||||
|
|
@ -86,6 +91,10 @@ static void fix_stat(const char *path, struct stat *s)
|
|||
fs_config(path, is_dir, target_out_path, &s->st_uid, &s->st_gid, &st_mode, &capabilities);
|
||||
s->st_mode = (typeof(s->st_mode)) st_mode;
|
||||
}
|
||||
|
||||
if (S_ISREG(s->st_mode) || S_ISDIR(s->st_mode) || S_ISLNK(s->st_mode)) {
|
||||
s->st_rdev = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void _eject(struct stat *s, char *out, int olen, char *data, unsigned datasize)
|
||||
|
|
@ -115,8 +124,8 @@ static void _eject(struct stat *s, char *out, int olen, char *data, unsigned dat
|
|||
datasize,
|
||||
0, // volmajor
|
||||
0, // volminor
|
||||
0, // devmajor
|
||||
0, // devminor,
|
||||
major(s->st_rdev),
|
||||
minor(s->st_rdev),
|
||||
olen + 1,
|
||||
0,
|
||||
out,
|
||||
|
|
@ -267,6 +276,9 @@ static void _archive(char *in, char *out, int ilen, int olen)
|
|||
size = readlink(in, buf, 1024);
|
||||
if(size < 0) die("cannot read symlink '%s'", in);
|
||||
_eject(&s, out, olen, buf, size);
|
||||
} else if(S_ISBLK(s.st_mode) || S_ISCHR(s.st_mode) ||
|
||||
S_ISFIFO(s.st_mode) || S_ISSOCK(s.st_mode)) {
|
||||
_eject(&s, out, olen, NULL, 0);
|
||||
} else {
|
||||
die("Unknown '%s' (mode %d)?\n", in, s.st_mode);
|
||||
}
|
||||
|
|
@ -327,34 +339,159 @@ static void read_canned_config(char* filename)
|
|||
fclose(f);
|
||||
}
|
||||
|
||||
static void devnodes_desc_error(const char* filename, unsigned long line_num,
|
||||
const char* msg)
|
||||
{
|
||||
error(EXIT_FAILURE, 0, "failed to read nodes desc file '%s' line %lu: %s",
|
||||
filename, line_num, msg);
|
||||
}
|
||||
|
||||
static int append_devnodes_desc_dir(char* path, char* args)
|
||||
{
|
||||
struct stat s;
|
||||
|
||||
if (sscanf(args, "%o %d %d", &s.st_mode, &s.st_uid, &s.st_gid) != 3) return -1;
|
||||
|
||||
s.st_mode |= S_IFDIR;
|
||||
|
||||
_eject(&s, path, strlen(path), NULL, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int append_devnodes_desc_nod(char* path, char* args)
|
||||
{
|
||||
int minor, major;
|
||||
struct stat s;
|
||||
char dev;
|
||||
|
||||
if (sscanf(args, "%o %d %d %c %d %d", &s.st_mode, &s.st_uid, &s.st_gid,
|
||||
&dev, &major, &minor) != 6) return -1;
|
||||
|
||||
s.st_rdev = MKDEV(major, minor);
|
||||
switch (dev) {
|
||||
case 'b':
|
||||
s.st_mode |= S_IFBLK;
|
||||
break;
|
||||
case 'c':
|
||||
s.st_mode |= S_IFCHR;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
_eject(&s, path, strlen(path), NULL, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void append_devnodes_desc(const char* filename)
|
||||
{
|
||||
FILE* f = fopen(filename, "re");
|
||||
if (!f) error(EXIT_FAILURE, errno,
|
||||
"failed to open nodes description file '%s'", filename);
|
||||
|
||||
char *line, *args, *type, *path;
|
||||
unsigned long line_num = 0;
|
||||
size_t allocated_len;
|
||||
|
||||
while (getline(&line, &allocated_len, f) != -1) {
|
||||
char* type;
|
||||
|
||||
line_num++;
|
||||
|
||||
if (*line == '#') continue;
|
||||
|
||||
if (!(type = strtok(line, " \t"))) {
|
||||
devnodes_desc_error(filename, line_num, "a type is missing");
|
||||
}
|
||||
|
||||
if (*type == '\n') continue;
|
||||
|
||||
if (!(path = strtok(NULL, " \t"))) {
|
||||
devnodes_desc_error(filename, line_num, "a path is missing");
|
||||
}
|
||||
|
||||
if (!(args = strtok(NULL, "\n"))) {
|
||||
devnodes_desc_error(filename, line_num, "args are missing");
|
||||
}
|
||||
|
||||
if (!strcmp(type, "dir")) {
|
||||
if (append_devnodes_desc_dir(path, args)) {
|
||||
devnodes_desc_error(filename, line_num, "bad arguments for dir");
|
||||
}
|
||||
} else if (!strcmp(type, "nod")) {
|
||||
if (append_devnodes_desc_nod(path, args)) {
|
||||
devnodes_desc_error(filename, line_num, "bad arguments for nod");
|
||||
}
|
||||
} else {
|
||||
devnodes_desc_error(filename, line_num, "type unknown");
|
||||
}
|
||||
}
|
||||
|
||||
free(line);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
static const struct option long_options[] = {
|
||||
{ "dirname", required_argument, NULL, 'd' },
|
||||
{ "file", required_argument, NULL, 'f' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "nodes", required_argument, NULL, 'n' },
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: mkbootfs [-n FILE] [-d DIR|-F FILE] DIR...\n"
|
||||
"\n"
|
||||
"\t-d, --dirname=DIR: fs-config directory\n"
|
||||
"\t-f, --file=FILE: Canned configuration file\n"
|
||||
"\t-h, --help: Print this help\n"
|
||||
"\t-n, --nodes=FILE: Dev nodes description file\n"
|
||||
"\nDev nodes description:\n"
|
||||
"\t[dir|nod] [perms] [uid] [gid] [c|b] [minor] [major]\n"
|
||||
"\tExample:\n"
|
||||
"\t\t# My device nodes\n"
|
||||
"\t\tdir dev 0755 0 0\n"
|
||||
"\t\tnod dev/null 0600 0 0 c 1 5\n"
|
||||
);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc == 1) {
|
||||
fprintf(stderr,
|
||||
"usage: %s [-d TARGET_OUTPUT_PATH] [-f CANNED_CONFIGURATION_PATH] DIRECTORIES...\n",
|
||||
argv[0]);
|
||||
exit(1);
|
||||
int opt, unused;
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "hd:f:n:", long_options, &unused)) != -1) {
|
||||
switch (opt) {
|
||||
case 'd':
|
||||
target_out_path = argv[optind - 1];
|
||||
break;
|
||||
case 'f':
|
||||
read_canned_config(argv[optind - 1]);
|
||||
break;
|
||||
case 'h':
|
||||
usage();
|
||||
return 0;
|
||||
case 'n':
|
||||
append_devnodes_desc(argv[optind - 1]);
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
die("Unknown option %s", argv[optind - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
int num_dirs = argc - optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc > 1 && strcmp(argv[0], "-d") == 0) {
|
||||
target_out_path = argv[1];
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
if (num_dirs <= 0) {
|
||||
usage();
|
||||
die("no directories to process?!");
|
||||
}
|
||||
|
||||
if (argc > 1 && strcmp(argv[0], "-f") == 0) {
|
||||
read_canned_config(argv[1]);
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
}
|
||||
|
||||
if(argc == 0) die("no directories to process?!");
|
||||
|
||||
while(argc-- > 0){
|
||||
while(num_dirs-- > 0){
|
||||
char *x = strchr(*argv, '=');
|
||||
if(x != 0) {
|
||||
*x++ = 0;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue