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