diff options
Diffstat (limited to 'cpio/mkbootfs.c')
-rw-r--r-- | cpio/mkbootfs.c | 73 |
1 files changed, 57 insertions, 16 deletions
diff --git a/cpio/mkbootfs.c b/cpio/mkbootfs.c index 9fe625278..f67233634 100644 --- a/cpio/mkbootfs.c +++ b/cpio/mkbootfs.c | |||
@@ -25,7 +25,7 @@ | |||
25 | void die(const char *why, ...) | 25 | void die(const char *why, ...) |
26 | { | 26 | { |
27 | va_list ap; | 27 | va_list ap; |
28 | 28 | ||
29 | va_start(ap, why); | 29 | va_start(ap, why); |
30 | fprintf(stderr,"error: "); | 30 | fprintf(stderr,"error: "); |
31 | vfprintf(stderr, why, ap); | 31 | vfprintf(stderr, why, ap); |
@@ -44,6 +44,11 @@ static void fix_stat(const char *path, struct stat *s) | |||
44 | 44 | ||
45 | static void _eject(struct stat *s, char *out, int olen, char *data, unsigned datasize) | 45 | static void _eject(struct stat *s, char *out, int olen, char *data, unsigned datasize) |
46 | { | 46 | { |
47 | // Nothing is special about this value, just picked something in the | ||
48 | // approximate range that was being used already, and avoiding small | ||
49 | // values which may be special. | ||
50 | static unsigned next_inode = 300000; | ||
51 | |||
47 | while(total_size & 3) { | 52 | while(total_size & 3) { |
48 | total_size++; | 53 | total_size++; |
49 | putchar(0); | 54 | putchar(0); |
@@ -55,12 +60,12 @@ static void _eject(struct stat *s, char *out, int olen, char *data, unsigned dat | |||
55 | printf("%06x%08x%08x%08x%08x%08x%08x" | 60 | printf("%06x%08x%08x%08x%08x%08x%08x" |
56 | "%08x%08x%08x%08x%08x%08x%08x%s%c", | 61 | "%08x%08x%08x%08x%08x%08x%08x%s%c", |
57 | 0x070701, | 62 | 0x070701, |
58 | (unsigned) s->st_ino, | 63 | next_inode++, // s.st_ino, |
59 | s->st_mode, | 64 | s->st_mode, |
60 | 0, // s.st_uid, | 65 | 0, // s.st_uid, |
61 | 0, // s.st_gid, | 66 | 0, // s.st_gid, |
62 | 1, // s.st_nlink, | 67 | 1, // s.st_nlink, |
63 | (unsigned) s->st_mtime, | 68 | 0, // s.st_mtime, |
64 | datasize, | 69 | datasize, |
65 | 0, // volmajor | 70 | 0, // volmajor |
66 | 0, // volminor | 71 | 0, // volminor |
@@ -75,7 +80,7 @@ static void _eject(struct stat *s, char *out, int olen, char *data, unsigned dat | |||
75 | total_size += 6 + 8*13 + olen + 1; | 80 | total_size += 6 + 8*13 + olen + 1; |
76 | 81 | ||
77 | if(strlen(out) != olen) die("ACK!"); | 82 | if(strlen(out) != olen) die("ACK!"); |
78 | 83 | ||
79 | while(total_size & 3) { | 84 | while(total_size & 3) { |
80 | total_size++; | 85 | total_size++; |
81 | putchar(0); | 86 | putchar(0); |
@@ -101,9 +106,13 @@ static void _eject_trailer() | |||
101 | 106 | ||
102 | static void _archive(char *in, char *out, int ilen, int olen); | 107 | static void _archive(char *in, char *out, int ilen, int olen); |
103 | 108 | ||
109 | static int compare(const void* a, const void* b) { | ||
110 | return strcmp(*(const char**)a, *(const char**)b); | ||
111 | } | ||
112 | |||
104 | static void _archive_dir(char *in, char *out, int ilen, int olen) | 113 | static void _archive_dir(char *in, char *out, int ilen, int olen) |
105 | { | 114 | { |
106 | int t; | 115 | int i, t; |
107 | DIR *d; | 116 | DIR *d; |
108 | struct dirent *de; | 117 | struct dirent *de; |
109 | 118 | ||
@@ -111,33 +120,65 @@ static void _archive_dir(char *in, char *out, int ilen, int olen) | |||
111 | fprintf(stderr,"_archive_dir('%s','%s',%d,%d)\n", | 120 | fprintf(stderr,"_archive_dir('%s','%s',%d,%d)\n", |
112 | in, out, ilen, olen); | 121 | in, out, ilen, olen); |
113 | } | 122 | } |
114 | 123 | ||
115 | d = opendir(in); | 124 | d = opendir(in); |
116 | if(d == 0) die("cannot open directory '%s'", in); | 125 | if(d == 0) die("cannot open directory '%s'", in); |
117 | 126 | ||
127 | int size = 32; | ||
128 | int entries = 0; | ||
129 | char** names = malloc(size * sizeof(char*)); | ||
130 | if (names == NULL) { | ||
131 | fprintf(stderr, "failed to allocate dir names array (size %d)\n", size); | ||
132 | exit(1); | ||
133 | } | ||
134 | |||
118 | while((de = readdir(d)) != 0){ | 135 | while((de = readdir(d)) != 0){ |
119 | /* xxx: feature? maybe some dotfiles are okay */ | 136 | /* xxx: feature? maybe some dotfiles are okay */ |
120 | if(de->d_name[0] == '.') continue; | 137 | if(de->d_name[0] == '.') continue; |
121 | 138 | ||
122 | /* xxx: hack. use a real exclude list */ | 139 | /* xxx: hack. use a real exclude list */ |
123 | if(!strcmp(de->d_name, "root")) continue; | 140 | if(!strcmp(de->d_name, "root")) continue; |
124 | 141 | ||
125 | t = strlen(de->d_name); | 142 | if (entries >= size) { |
143 | size *= 2; | ||
144 | names = realloc(names, size * sizeof(char*)); | ||
145 | if (names == NULL) { | ||
146 | fprintf(stderr, "failed to reallocate dir names array (size %d)\n", | ||
147 | size); | ||
148 | exit(1); | ||
149 | } | ||
150 | } | ||
151 | names[entries] = strdup(de->d_name); | ||
152 | if (names[entries] == NULL) { | ||
153 | fprintf(stderr, "failed to strdup name \"%s\"\n", | ||
154 | de->d_name); | ||
155 | exit(1); | ||
156 | } | ||
157 | ++entries; | ||
158 | } | ||
159 | |||
160 | qsort(names, entries, sizeof(char*), compare); | ||
161 | |||
162 | for (i = 0; i < entries; ++i) { | ||
163 | t = strlen(names[i]); | ||
126 | in[ilen] = '/'; | 164 | in[ilen] = '/'; |
127 | memcpy(in + ilen + 1, de->d_name, t + 1); | 165 | memcpy(in + ilen + 1, names[i], t + 1); |
128 | 166 | ||
129 | if(olen > 0) { | 167 | if(olen > 0) { |
130 | out[olen] = '/'; | 168 | out[olen] = '/'; |
131 | memcpy(out + olen + 1, de->d_name, t + 1); | 169 | memcpy(out + olen + 1, names[i], t + 1); |
132 | _archive(in, out, ilen + t + 1, olen + t + 1); | 170 | _archive(in, out, ilen + t + 1, olen + t + 1); |
133 | } else { | 171 | } else { |
134 | memcpy(out, de->d_name, t + 1); | 172 | memcpy(out, names[i], t + 1); |
135 | _archive(in, out, ilen + t + 1, t); | 173 | _archive(in, out, ilen + t + 1, t); |
136 | } | 174 | } |
137 | 175 | ||
138 | in[ilen] = 0; | 176 | in[ilen] = 0; |
139 | out[olen] = 0; | 177 | out[olen] = 0; |
178 | |||
179 | free(names[i]); | ||
140 | } | 180 | } |
181 | free(names); | ||
141 | } | 182 | } |
142 | 183 | ||
143 | static void _archive(char *in, char *out, int ilen, int olen) | 184 | static void _archive(char *in, char *out, int ilen, int olen) |
@@ -148,7 +189,7 @@ static void _archive(char *in, char *out, int ilen, int olen) | |||
148 | fprintf(stderr,"_archive('%s','%s',%d,%d)\n", | 189 | fprintf(stderr,"_archive('%s','%s',%d,%d)\n", |
149 | in, out, ilen, olen); | 190 | in, out, ilen, olen); |
150 | } | 191 | } |
151 | 192 | ||
152 | if(lstat(in, &s)) die("could not stat '%s'\n", in); | 193 | if(lstat(in, &s)) die("could not stat '%s'\n", in); |
153 | 194 | ||
154 | if(S_ISREG(s.st_mode)){ | 195 | if(S_ISREG(s.st_mode)){ |
@@ -166,7 +207,7 @@ static void _archive(char *in, char *out, int ilen, int olen) | |||
166 | } | 207 | } |
167 | 208 | ||
168 | _eject(&s, out, olen, tmp, s.st_size); | 209 | _eject(&s, out, olen, tmp, s.st_size); |
169 | 210 | ||
170 | free(tmp); | 211 | free(tmp); |
171 | close(fd); | 212 | close(fd); |
172 | } else if(S_ISDIR(s.st_mode)) { | 213 | } else if(S_ISDIR(s.st_mode)) { |
@@ -208,13 +249,13 @@ int main(int argc, char *argv[]) | |||
208 | } else { | 249 | } else { |
209 | x = ""; | 250 | x = ""; |
210 | } | 251 | } |
211 | 252 | ||
212 | archive(*argv, x); | 253 | archive(*argv, x); |
213 | 254 | ||
214 | argv++; | 255 | argv++; |
215 | } | 256 | } |
216 | 257 | ||
217 | _eject_trailer(); | 258 | _eject_trailer(); |
218 | 259 | ||
219 | return 0; | 260 | return 0; |
220 | } | 261 | } |