Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 60305abf authored by Vincent Donnefort's avatar Vincent Donnefort Committed by Gerrit Code Review
Browse files

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
parents 93e02c6d 99ab5210
Loading
Loading
Loading
Loading
+158 −21
Original line number Diff line number Diff line

#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);
}

int main(int argc, char *argv[])
static int append_devnodes_desc_dir(char* path, char* args)
{
    if (argc == 1) {
        fprintf(stderr,
                "usage: %s [-d TARGET_OUTPUT_PATH] [-f CANNED_CONFIGURATION_PATH] DIRECTORIES...\n",
                argv[0]);
        exit(1);
    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;
}

    argc--;
    argv++;
static int append_devnodes_desc_nod(char* path, char* args)
{
    int minor, major;
    struct stat s;
    char dev;

    if (argc > 1 && strcmp(argv[0], "-d") == 0) {
        target_out_path = argv[1];
        argc -= 2;
        argv += 2;
    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;
}

    if (argc > 1 && strcmp(argv[0], "-f") == 0) {
        read_canned_config(argv[1]);
        argc -= 2;
        argv += 2;
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(argc == 0) die("no directories to process?!");
        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[])
{
    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]);
        }
    }

    int num_dirs = argc - optind;
    argv += optind;

    if (num_dirs <= 0) {
        usage();
        die("no directories to process?!");
    }

    while(argc-- > 0){
    while(num_dirs-- > 0){
        char *x = strchr(*argv, '=');
        if(x != 0) {
            *x++ = 0;