1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h>
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h>
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
6f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker#include <ctype.h>
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/types.h>
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/stat.h>
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <dirent.h>
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdarg.h>
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <fcntl.h>
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <private/android_filesystem_config.h>
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* NOTES
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** - see buffer-format.txt from the linux kernel docs for
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**   an explanation of this file format
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** - dotfiles are ignored
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** - directories named 'root' are ignored
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** - device notes, pipes, etc are not supported (error)
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project*/
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid die(const char *why, ...)
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_list ap;
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_start(ap, why);
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr,"error: ");
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    vfprintf(stderr, why, ap);
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr,"\n");
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_end(ap);
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    exit(1);
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
38f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongkerstruct fs_config_entry {
39f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker    char* name;
40f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker    int uid, gid, mode;
41f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker};
42f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker
43f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongkerstatic struct fs_config_entry* canned_config = NULL;
44f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker
45f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker/* Each line in the canned file should be a path plus three ints (uid,
46f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker * gid, mode). */
47a865f6d85a52d0a77d1aef8d5fb5bece08e3b246Doug Zongker#ifdef PATH_MAX
48f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker#define CANNED_LINE_LENGTH  (PATH_MAX+100)
49a865f6d85a52d0a77d1aef8d5fb5bece08e3b246Doug Zongker#else
50a865f6d85a52d0a77d1aef8d5fb5bece08e3b246Doug Zongker#define CANNED_LINE_LENGTH  (1024)
51a865f6d85a52d0a77d1aef8d5fb5bece08e3b246Doug Zongker#endif
52f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int verbose = 0;
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int total_size = 0;
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fix_stat(const char *path, struct stat *s)
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
58e9e74f3c881bd73bd86be4db8b12200a61f143e1Nick Kralevich    uint64_t capabilities;
59f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker    if (canned_config) {
60f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker        // Use the list of file uid/gid/modes loaded from the file
61f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker        // given with -f.
62f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker
63f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker        struct fs_config_entry* empty_path_config = NULL;
64f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker        struct fs_config_entry* p;
65f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker        for (p = canned_config; p->name; ++p) {
66f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker            if (!p->name[0]) {
67f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker                empty_path_config = p;
68f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker            }
69f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker            if (strcmp(p->name, path) == 0) {
70f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker                s->st_uid = p->uid;
71f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker                s->st_gid = p->gid;
72f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker                s->st_mode = p->mode | (s->st_mode & ~07777);
73f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker                return;
74f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker            }
75f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker        }
76f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker        s->st_uid = empty_path_config->uid;
77f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker        s->st_gid = empty_path_config->gid;
78f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker        s->st_mode = empty_path_config->mode | (s->st_mode & ~07777);
79f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker    } else {
80f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker        // Use the compiled-in fs_config() function.
81f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker
82e9e74f3c881bd73bd86be4db8b12200a61f143e1Nick Kralevich        fs_config(path, S_ISDIR(s->st_mode), &s->st_uid, &s->st_gid, &s->st_mode, &capabilities);
83f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker    }
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void _eject(struct stat *s, char *out, int olen, char *data, unsigned datasize)
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // Nothing is special about this value, just picked something in the
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // approximate range that was being used already, and avoiding small
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // values which may be special.
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    static unsigned next_inode = 300000;
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while(total_size & 3) {
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        total_size++;
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        putchar(0);
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fix_stat(out, s);
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project//    fprintf(stderr, "_eject %s: mode=0%o\n", out, s->st_mode);
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    printf("%06x%08x%08x%08x%08x%08x%08x"
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           "%08x%08x%08x%08x%08x%08x%08x%s%c",
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           0x070701,
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           next_inode++,  //  s.st_ino,
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           s->st_mode,
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           0, // s.st_uid,
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           0, // s.st_gid,
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           1, // s.st_nlink,
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           0, // s.st_mtime,
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           datasize,
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           0, // volmajor
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           0, // volminor
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           0, // devmajor
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           0, // devminor,
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           olen + 1,
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           0,
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           out,
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           0
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           );
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    total_size += 6 + 8*13 + olen + 1;
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
123f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker    if(strlen(out) != (unsigned int)olen) die("ACK!");
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while(total_size & 3) {
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        total_size++;
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        putchar(0);
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(datasize) {
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fwrite(data, datasize, 1, stdout);
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        total_size += datasize;
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void _eject_trailer()
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct stat s;
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(&s, 0, sizeof(s));
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    _eject(&s, "TRAILER!!!", 10, 0, 0);
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while(total_size & 0xff) {
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        total_size++;
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        putchar(0);
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void _archive(char *in, char *out, int ilen, int olen);
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int compare(const void* a, const void* b) {
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project  return strcmp(*(const char**)a, *(const char**)b);
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void _archive_dir(char *in, char *out, int ilen, int olen)
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int i, t;
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    DIR *d;
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct dirent *de;
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(verbose) {
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,"_archive_dir('%s','%s',%d,%d)\n",
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                in, out, ilen, olen);
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    d = opendir(in);
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(d == 0) die("cannot open directory '%s'", in);
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int size = 32;
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int entries = 0;
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char** names = malloc(size * sizeof(char*));
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (names == NULL) {
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      fprintf(stderr, "failed to allocate dir names array (size %d)\n", size);
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      exit(1);
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while((de = readdir(d)) != 0){
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* xxx: feature? maybe some dotfiles are okay */
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(de->d_name[0] == '.') continue;
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* xxx: hack. use a real exclude list */
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(!strcmp(de->d_name, "root")) continue;
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (entries >= size) {
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project          size *= 2;
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project          names = realloc(names, size * sizeof(char*));
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project          if (names == NULL) {
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fprintf(stderr, "failed to reallocate dir names array (size %d)\n",
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    size);
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            exit(1);
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project          }
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        names[entries] = strdup(de->d_name);
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (names[entries] == NULL) {
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project          fprintf(stderr, "failed to strdup name \"%s\"\n",
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                  de->d_name);
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project          exit(1);
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ++entries;
199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    qsort(names, entries, sizeof(char*), compare);
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (i = 0; i < entries; ++i) {
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        t = strlen(names[i]);
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        in[ilen] = '/';
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        memcpy(in + ilen + 1, names[i], t + 1);
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(olen > 0) {
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            out[olen] = '/';
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            memcpy(out + olen + 1, names[i], t + 1);
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            _archive(in, out, ilen + t + 1, olen + t + 1);
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            memcpy(out, names[i], t + 1);
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            _archive(in, out, ilen + t + 1, t);
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        in[ilen] = 0;
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        out[olen] = 0;
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        free(names[i]);
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    free(names);
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void _archive(char *in, char *out, int ilen, int olen)
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct stat s;
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(verbose) {
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,"_archive('%s','%s',%d,%d)\n",
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                in, out, ilen, olen);
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(lstat(in, &s)) die("could not stat '%s'\n", in);
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(S_ISREG(s.st_mode)){
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char *tmp;
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int fd;
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fd = open(in, O_RDONLY);
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(fd < 0) die("cannot open '%s' for read", in);
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        tmp = (char*) malloc(s.st_size);
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(tmp == 0) die("cannot allocate %d bytes", s.st_size);
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(read(fd, tmp, s.st_size) != s.st_size) {
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            die("cannot read %d bytes", s.st_size);
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        _eject(&s, out, olen, tmp, s.st_size);
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        free(tmp);
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        close(fd);
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if(S_ISDIR(s.st_mode)) {
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        _eject(&s, out, olen, 0, 0);
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        _archive_dir(in, out, ilen, olen);
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if(S_ISLNK(s.st_mode)) {
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char buf[1024];
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int size;
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        size = readlink(in, buf, 1024);
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(size < 0) die("cannot read symlink '%s'", in);
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        _eject(&s, out, olen, buf, size);
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        die("Unknown '%s' (mode %d)?\n", in, s.st_mode);
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid archive(const char *start, const char *prefix)
269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char in[8192];
271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char out[8192];
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    strcpy(in, start);
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    strcpy(out, prefix);
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    _archive_dir(in, out, strlen(in), strlen(out));
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
279f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongkerstatic void read_canned_config(char* filename)
280f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker{
281f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker    int allocated = 8;
282f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker    int used = 0;
283f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker
284f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker    canned_config =
285f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker        (struct fs_config_entry*)malloc(allocated * sizeof(struct fs_config_entry));
286f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker
287f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker    char line[CANNED_LINE_LENGTH];
288f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker    FILE* f = fopen(filename, "r");
289f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker    if (f == NULL) die("failed to open canned file");
290f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker
291f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker    while (fgets(line, CANNED_LINE_LENGTH, f) != NULL) {
292f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker        if (!line[0]) break;
293f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker        if (used >= allocated) {
294f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker            allocated *= 2;
295f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker            canned_config = (struct fs_config_entry*)realloc(
296f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker                canned_config, allocated * sizeof(struct fs_config_entry));
297f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker        }
298f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker
299f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker        struct fs_config_entry* cc = canned_config + used;
300f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker
301f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker        if (isspace(line[0])) {
302f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker            cc->name = strdup("");
303f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker            cc->uid = atoi(strtok(line, " \n"));
304f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker        } else {
305f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker            cc->name = strdup(strtok(line, " \n"));
306f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker            cc->uid = atoi(strtok(NULL, " \n"));
307f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker        }
308f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker        cc->gid = atoi(strtok(NULL, " \n"));
309f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker        cc->mode = strtol(strtok(NULL, " \n"), NULL, 8);
310f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker        ++used;
311f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker    }
312f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker    if (used >= allocated) {
313f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker        ++allocated;
314f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker        canned_config = (struct fs_config_entry*)realloc(
315f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker            canned_config, allocated * sizeof(struct fs_config_entry));
316f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker    }
317f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker    canned_config[used].name = NULL;
318f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker
319f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker    fclose(f);
320f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker}
321f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker
322f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker
323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint main(int argc, char *argv[])
324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    argc--;
326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    argv++;
327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
328f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker    if (argc > 1 && strcmp(argv[0], "-f") == 0) {
329f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker        read_canned_config(argv[1]);
330f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker        argc -= 2;
331f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker        argv += 2;
332f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker    }
333f2c3a8331ca9ec61aba82c4af6c8c7aa75d56f14Doug Zongker
334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(argc == 0) die("no directories to process?!");
335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while(argc-- > 0){
337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char *x = strchr(*argv, '=');
338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(x != 0) {
339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            *x++ = 0;
340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            x = "";
342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        archive(*argv, x);
345dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        argv++;
347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    _eject_trailer();
350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
353