OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [usr/] [gen_init_cpio.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
#include <stdio.h>
2
#include <stdlib.h>
3
#include <sys/types.h>
4
#include <sys/stat.h>
5
#include <string.h>
6
#include <unistd.h>
7
#include <time.h>
8
#include <fcntl.h>
9
#include <errno.h>
10
#include <ctype.h>
11
#include <limits.h>
12
 
13
/*
14
 * Original work by Jeff Garzik
15
 *
16
 * External file lists, symlink, pipe and fifo support by Thayne Harbaugh
17
 * Hard link support by Luciano Rocha
18
 */
19
 
20
#define xstr(s) #s
21
#define str(s) xstr(s)
22
 
23
static unsigned int offset;
24
static unsigned int ino = 721;
25
 
26
struct file_handler {
27
        const char *type;
28
        int (*handler)(const char *line);
29
};
30
 
31
static void push_string(const char *name)
32
{
33
        unsigned int name_len = strlen(name) + 1;
34
 
35
        fputs(name, stdout);
36
        putchar(0);
37
        offset += name_len;
38
}
39
 
40
static void push_pad (void)
41
{
42
        while (offset & 3) {
43
                putchar(0);
44
                offset++;
45
        }
46
}
47
 
48
static void push_rest(const char *name)
49
{
50
        unsigned int name_len = strlen(name) + 1;
51
        unsigned int tmp_ofs;
52
 
53
        fputs(name, stdout);
54
        putchar(0);
55
        offset += name_len;
56
 
57
        tmp_ofs = name_len + 110;
58
        while (tmp_ofs & 3) {
59
                putchar(0);
60
                offset++;
61
                tmp_ofs++;
62
        }
63
}
64
 
65
static void push_hdr(const char *s)
66
{
67
        fputs(s, stdout);
68
        offset += 110;
69
}
70
 
71
static void cpio_trailer(void)
72
{
73
        char s[256];
74
        const char name[] = "TRAILER!!!";
75
 
76
        sprintf(s, "%s%08X%08X%08lX%08lX%08X%08lX"
77
               "%08X%08X%08X%08X%08X%08X%08X",
78
                "070701",               /* magic */
79
                0,                       /* ino */
80
                0,                       /* mode */
81
                (long) 0,                /* uid */
82
                (long) 0,                /* gid */
83
                1,                      /* nlink */
84
                (long) 0,                /* mtime */
85
                0,                       /* filesize */
86
                0,                       /* major */
87
                0,                       /* minor */
88
                0,                       /* rmajor */
89
                0,                       /* rminor */
90
                (unsigned)strlen(name)+1, /* namesize */
91
                0);                      /* chksum */
92
        push_hdr(s);
93
        push_rest(name);
94
 
95
        while (offset % 512) {
96
                putchar(0);
97
                offset++;
98
        }
99
}
100
 
101
static int cpio_mkslink(const char *name, const char *target,
102
                         unsigned int mode, uid_t uid, gid_t gid)
103
{
104
        char s[256];
105
        time_t mtime = time(NULL);
106
 
107
        sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
108
               "%08X%08X%08X%08X%08X%08X%08X",
109
                "070701",               /* magic */
110
                ino++,                  /* ino */
111
                S_IFLNK | mode,         /* mode */
112
                (long) uid,             /* uid */
113
                (long) gid,             /* gid */
114
                1,                      /* nlink */
115
                (long) mtime,           /* mtime */
116
                (unsigned)strlen(target)+1, /* filesize */
117
                3,                      /* major */
118
                1,                      /* minor */
119
                0,                       /* rmajor */
120
                0,                       /* rminor */
121
                (unsigned)strlen(name) + 1,/* namesize */
122
                0);                      /* chksum */
123
        push_hdr(s);
124
        push_string(name);
125
        push_pad();
126
        push_string(target);
127
        push_pad();
128
        return 0;
129
}
130
 
131
static int cpio_mkslink_line(const char *line)
132
{
133
        char name[PATH_MAX + 1];
134
        char target[PATH_MAX + 1];
135
        unsigned int mode;
136
        int uid;
137
        int gid;
138
        int rc = -1;
139
 
140
        if (5 != sscanf(line, "%" str(PATH_MAX) "s %" str(PATH_MAX) "s %o %d %d", name, target, &mode, &uid, &gid)) {
141
                fprintf(stderr, "Unrecognized dir format '%s'", line);
142
                goto fail;
143
        }
144
        rc = cpio_mkslink(name, target, mode, uid, gid);
145
 fail:
146
        return rc;
147
}
148
 
149
static int cpio_mkgeneric(const char *name, unsigned int mode,
150
                       uid_t uid, gid_t gid)
151
{
152
        char s[256];
153
        time_t mtime = time(NULL);
154
 
155
        sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
156
               "%08X%08X%08X%08X%08X%08X%08X",
157
                "070701",               /* magic */
158
                ino++,                  /* ino */
159
                mode,                   /* mode */
160
                (long) uid,             /* uid */
161
                (long) gid,             /* gid */
162
                2,                      /* nlink */
163
                (long) mtime,           /* mtime */
164
                0,                       /* filesize */
165
                3,                      /* major */
166
                1,                      /* minor */
167
                0,                       /* rmajor */
168
                0,                       /* rminor */
169
                (unsigned)strlen(name) + 1,/* namesize */
170
                0);                      /* chksum */
171
        push_hdr(s);
172
        push_rest(name);
173
        return 0;
174
}
175
 
176
enum generic_types {
177
        GT_DIR,
178
        GT_PIPE,
179
        GT_SOCK
180
};
181
 
182
struct generic_type {
183
        const char *type;
184
        mode_t mode;
185
};
186
 
187
static struct generic_type generic_type_table[] = {
188
        [GT_DIR] = {
189
                .type = "dir",
190
                .mode = S_IFDIR
191
        },
192
        [GT_PIPE] = {
193
                .type = "pipe",
194
                .mode = S_IFIFO
195
        },
196
        [GT_SOCK] = {
197
                .type = "sock",
198
                .mode = S_IFSOCK
199
        }
200
};
201
 
202
static int cpio_mkgeneric_line(const char *line, enum generic_types gt)
203
{
204
        char name[PATH_MAX + 1];
205
        unsigned int mode;
206
        int uid;
207
        int gid;
208
        int rc = -1;
209
 
210
        if (4 != sscanf(line, "%" str(PATH_MAX) "s %o %d %d", name, &mode, &uid, &gid)) {
211
                fprintf(stderr, "Unrecognized %s format '%s'",
212
                        line, generic_type_table[gt].type);
213
                goto fail;
214
        }
215
        mode |= generic_type_table[gt].mode;
216
        rc = cpio_mkgeneric(name, mode, uid, gid);
217
 fail:
218
        return rc;
219
}
220
 
221
static int cpio_mkdir_line(const char *line)
222
{
223
        return cpio_mkgeneric_line(line, GT_DIR);
224
}
225
 
226
static int cpio_mkpipe_line(const char *line)
227
{
228
        return cpio_mkgeneric_line(line, GT_PIPE);
229
}
230
 
231
static int cpio_mksock_line(const char *line)
232
{
233
        return cpio_mkgeneric_line(line, GT_SOCK);
234
}
235
 
236
static int cpio_mknod(const char *name, unsigned int mode,
237
                       uid_t uid, gid_t gid, char dev_type,
238
                       unsigned int maj, unsigned int min)
239
{
240
        char s[256];
241
        time_t mtime = time(NULL);
242
 
243
        if (dev_type == 'b')
244
                mode |= S_IFBLK;
245
        else
246
                mode |= S_IFCHR;
247
 
248
        sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
249
               "%08X%08X%08X%08X%08X%08X%08X",
250
                "070701",               /* magic */
251
                ino++,                  /* ino */
252
                mode,                   /* mode */
253
                (long) uid,             /* uid */
254
                (long) gid,             /* gid */
255
                1,                      /* nlink */
256
                (long) mtime,           /* mtime */
257
                0,                       /* filesize */
258
                3,                      /* major */
259
                1,                      /* minor */
260
                maj,                    /* rmajor */
261
                min,                    /* rminor */
262
                (unsigned)strlen(name) + 1,/* namesize */
263
                0);                      /* chksum */
264
        push_hdr(s);
265
        push_rest(name);
266
        return 0;
267
}
268
 
269
static int cpio_mknod_line(const char *line)
270
{
271
        char name[PATH_MAX + 1];
272
        unsigned int mode;
273
        int uid;
274
        int gid;
275
        char dev_type;
276
        unsigned int maj;
277
        unsigned int min;
278
        int rc = -1;
279
 
280
        if (7 != sscanf(line, "%" str(PATH_MAX) "s %o %d %d %c %u %u",
281
                         name, &mode, &uid, &gid, &dev_type, &maj, &min)) {
282
                fprintf(stderr, "Unrecognized nod format '%s'", line);
283
                goto fail;
284
        }
285
        rc = cpio_mknod(name, mode, uid, gid, dev_type, maj, min);
286
 fail:
287
        return rc;
288
}
289
 
290
static int cpio_mkfile(const char *name, const char *location,
291
                        unsigned int mode, uid_t uid, gid_t gid,
292
                        unsigned int nlinks)
293
{
294
        char s[256];
295
        char *filebuf = NULL;
296
        struct stat buf;
297
        long size;
298
        int file = -1;
299
        int retval;
300
        int rc = -1;
301
        int namesize;
302
        int i;
303
 
304
        mode |= S_IFREG;
305
 
306
        retval = stat (location, &buf);
307
        if (retval) {
308
                fprintf (stderr, "File %s could not be located\n", location);
309
                goto error;
310
        }
311
 
312
        file = open (location, O_RDONLY);
313
        if (file < 0) {
314
                fprintf (stderr, "File %s could not be opened for reading\n", location);
315
                goto error;
316
        }
317
 
318
        filebuf = malloc(buf.st_size);
319
        if (!filebuf) {
320
                fprintf (stderr, "out of memory\n");
321
                goto error;
322
        }
323
 
324
        retval = read (file, filebuf, buf.st_size);
325
        if (retval < 0) {
326
                fprintf (stderr, "Can not read %s file\n", location);
327
                goto error;
328
        }
329
 
330
        size = 0;
331
        for (i = 1; i <= nlinks; i++) {
332
                /* data goes on last link */
333
                if (i == nlinks) size = buf.st_size;
334
 
335
                namesize = strlen(name) + 1;
336
                sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
337
                       "%08lX%08X%08X%08X%08X%08X%08X",
338
                        "070701",               /* magic */
339
                        ino,                    /* ino */
340
                        mode,                   /* mode */
341
                        (long) uid,             /* uid */
342
                        (long) gid,             /* gid */
343
                        nlinks,                 /* nlink */
344
                        (long) buf.st_mtime,    /* mtime */
345
                        size,                   /* filesize */
346
                        3,                      /* major */
347
                        1,                      /* minor */
348
                        0,                       /* rmajor */
349
                        0,                       /* rminor */
350
                        namesize,               /* namesize */
351
                        0);                      /* chksum */
352
                push_hdr(s);
353
                push_string(name);
354
                push_pad();
355
 
356
                if (size) {
357
                        fwrite(filebuf, size, 1, stdout);
358
                        offset += size;
359
                        push_pad();
360
                }
361
 
362
                name += namesize;
363
        }
364
        ino++;
365
        rc = 0;
366
 
367
error:
368
        if (filebuf) free(filebuf);
369
        if (file >= 0) close(file);
370
        return rc;
371
}
372
 
373
static int cpio_mkfile_line(const char *line)
374
{
375
        char name[PATH_MAX + 1];
376
        char *dname = NULL; /* malloc'ed buffer for hard links */
377
        char location[PATH_MAX + 1];
378
        unsigned int mode;
379
        int uid;
380
        int gid;
381
        int nlinks = 1;
382
        int end = 0, dname_len = 0;
383
        int rc = -1;
384
 
385
        if (5 > sscanf(line, "%" str(PATH_MAX) "s %" str(PATH_MAX)
386
                                "s %o %d %d %n",
387
                                name, location, &mode, &uid, &gid, &end)) {
388
                fprintf(stderr, "Unrecognized file format '%s'", line);
389
                goto fail;
390
        }
391
        if (end && isgraph(line[end])) {
392
                int len;
393
                int nend;
394
 
395
                dname = malloc(strlen(line));
396
                if (!dname) {
397
                        fprintf (stderr, "out of memory (%d)\n", dname_len);
398
                        goto fail;
399
                }
400
 
401
                dname_len = strlen(name) + 1;
402
                memcpy(dname, name, dname_len);
403
 
404
                do {
405
                        nend = 0;
406
                        if (sscanf(line + end, "%" str(PATH_MAX) "s %n",
407
                                        name, &nend) < 1)
408
                                break;
409
                        len = strlen(name) + 1;
410
                        memcpy(dname + dname_len, name, len);
411
                        dname_len += len;
412
                        nlinks++;
413
                        end += nend;
414
                } while (isgraph(line[end]));
415
        } else {
416
                dname = name;
417
        }
418
        rc = cpio_mkfile(dname, location, mode, uid, gid, nlinks);
419
 fail:
420
        if (dname_len) free(dname);
421
        return rc;
422
}
423
 
424
void usage(const char *prog)
425
{
426
        fprintf(stderr, "Usage:\n"
427
                "\t%s <cpio_list>\n"
428
                "\n"
429
                "<cpio_list> is a file containing newline separated entries that\n"
430
                "describe the files to be included in the initramfs archive:\n"
431
                "\n"
432
                "# a comment\n"
433
                "file <name> <location> <mode> <uid> <gid> [<hard links>]\n"
434
                "dir <name> <mode> <uid> <gid>\n"
435
                "nod <name> <mode> <uid> <gid> <dev_type> <maj> <min>\n"
436
                "slink <name> <target> <mode> <uid> <gid>\n"
437
                "pipe <name> <mode> <uid> <gid>\n"
438
                "sock <name> <mode> <uid> <gid>\n"
439
                "\n"
440
                "<name>       name of the file/dir/nod/etc in the archive\n"
441
                "<location>   location of the file in the current filesystem\n"
442
                "<target>     link target\n"
443
                "<mode>       mode/permissions of the file\n"
444
                "<uid>        user id (0=root)\n"
445
                "<gid>        group id (0=root)\n"
446
                "<dev_type>   device type (b=block, c=character)\n"
447
                "<maj>        major number of nod\n"
448
                "<min>        minor number of nod\n"
449
                "<hard links> space separated list of other links to file\n"
450
                "\n"
451
                "example:\n"
452
                "# A simple initramfs\n"
453
                "dir /dev 0755 0 0\n"
454
                "nod /dev/console 0600 0 0 c 5 1\n"
455
                "dir /root 0700 0 0\n"
456
                "dir /sbin 0755 0 0\n"
457
                "file /sbin/kinit /usr/src/klibc/kinit/kinit 0755 0 0\n",
458
                prog);
459
}
460
 
461
struct file_handler file_handler_table[] = {
462
        {
463
                .type    = "file",
464
                .handler = cpio_mkfile_line,
465
        }, {
466
                .type    = "nod",
467
                .handler = cpio_mknod_line,
468
        }, {
469
                .type    = "dir",
470
                .handler = cpio_mkdir_line,
471
        }, {
472
                .type    = "slink",
473
                .handler = cpio_mkslink_line,
474
        }, {
475
                .type    = "pipe",
476
                .handler = cpio_mkpipe_line,
477
        }, {
478
                .type    = "sock",
479
                .handler = cpio_mksock_line,
480
        }, {
481
                .type    = NULL,
482
                .handler = NULL,
483
        }
484
};
485
 
486
#define LINE_SIZE (2 * PATH_MAX + 50)
487
 
488
int main (int argc, char *argv[])
489
{
490
        FILE *cpio_list;
491
        char line[LINE_SIZE];
492
        char *args, *type;
493
        int ec = 0;
494
        int line_nr = 0;
495
 
496
        if (2 != argc) {
497
                usage(argv[0]);
498
                exit(1);
499
        }
500
 
501
        if (!strcmp(argv[1], "-"))
502
                cpio_list = stdin;
503
        else if (! (cpio_list = fopen(argv[1], "r"))) {
504
                fprintf(stderr, "ERROR: unable to open '%s': %s\n\n",
505
                        argv[1], strerror(errno));
506
                usage(argv[0]);
507
                exit(1);
508
        }
509
 
510
        while (fgets(line, LINE_SIZE, cpio_list)) {
511
                int type_idx;
512
                size_t slen = strlen(line);
513
 
514
                line_nr++;
515
 
516
                if ('#' == *line) {
517
                        /* comment - skip to next line */
518
                        continue;
519
                }
520
 
521
                if (! (type = strtok(line, " \t"))) {
522
                        fprintf(stderr,
523
                                "ERROR: incorrect format, could not locate file type line %d: '%s'\n",
524
                                line_nr, line);
525
                        ec = -1;
526
                        break;
527
                }
528
 
529
                if ('\n' == *type) {
530
                        /* a blank line */
531
                        continue;
532
                }
533
 
534
                if (slen == strlen(type)) {
535
                        /* must be an empty line */
536
                        continue;
537
                }
538
 
539
                if (! (args = strtok(NULL, "\n"))) {
540
                        fprintf(stderr,
541
                                "ERROR: incorrect format, newline required line %d: '%s'\n",
542
                                line_nr, line);
543
                        ec = -1;
544
                }
545
 
546
                for (type_idx = 0; file_handler_table[type_idx].type; type_idx++) {
547
                        int rc;
548
                        if (! strcmp(line, file_handler_table[type_idx].type)) {
549
                                if ((rc = file_handler_table[type_idx].handler(args))) {
550
                                        ec = rc;
551
                                        fprintf(stderr, " line %d\n", line_nr);
552
                                }
553
                                break;
554
                        }
555
                }
556
 
557
                if (NULL == file_handler_table[type_idx].type) {
558
                        fprintf(stderr, "unknown file type line %d: '%s'\n",
559
                                line_nr, line);
560
                }
561
        }
562
        if (ec == 0)
563
                cpio_trailer();
564
 
565
        exit(ec);
566
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.