annotate toys/posix/cpio.c @ 1331:11fe363078b8 draft

cpio: archive more files While writing tests for cpio, I found that cpio tries to open empty files if they're regular files, and fails to archive them if unreadable. This can be easily avoided, and is not the usual behavior.
author Isaac Dunham <ibid.ag@gmail.com>
date Sun, 01 Jun 2014 13:50:39 -0500
parents c214de62b18b
children 2148d1502264
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1087
b73a61542297 I've finally gotten 'cpio' into a shape where it could be useable.
Isaac Dunham <ibid.ag@gmail.com>
parents:
diff changeset
1 /* cpio.c - a basic cpio
b73a61542297 I've finally gotten 'cpio' into a shape where it could be useable.
Isaac Dunham <ibid.ag@gmail.com>
parents:
diff changeset
2 *
b73a61542297 I've finally gotten 'cpio' into a shape where it could be useable.
Isaac Dunham <ibid.ag@gmail.com>
parents:
diff changeset
3 * Written 2013 AD by Isaac Dunham; this code is placed under the
b73a61542297 I've finally gotten 'cpio' into a shape where it could be useable.
Isaac Dunham <ibid.ag@gmail.com>
parents:
diff changeset
4 * same license as toybox or as CC0, at your option.
1121
977f0a4dc562 Support -F, and ignore -u since that's what we do anyway.
Isaac Dunham <ibid.ag@gmail.com>
parents: 1098
diff changeset
5 *
977f0a4dc562 Support -F, and ignore -u since that's what we do anyway.
Isaac Dunham <ibid.ag@gmail.com>
parents: 1098
diff changeset
6 * http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/cpio.html
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
7 * and http://pubs.opengroup.org/onlinepubs/7908799/xcu/cpio.html
1121
977f0a4dc562 Support -F, and ignore -u since that's what we do anyway.
Isaac Dunham <ibid.ag@gmail.com>
parents: 1098
diff changeset
8 *
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
9 * Yes, that's SUSv2, the newer standards removed it around the time RPM
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
10 * and initramfs started heavily using this archive format.
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
11 *
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
12 * Modern cpio expanded header to 110 bytes (first field 6 bytes, rest are 8).
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
13 * In order: magic ino mode uid gid nlink mtime filesize devmajor devminor
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
14 * rdevmajor rdevminor namesize check
1121
977f0a4dc562 Support -F, and ignore -u since that's what we do anyway.
Isaac Dunham <ibid.ag@gmail.com>
parents: 1098
diff changeset
15
1230
c78ffc6c330a More cpio bugfixes from Isaac Dunham.
Rob Landley <rob@landley.net>
parents: 1229
diff changeset
16 USE_CPIO(NEWTOY(cpio, "duH:i|t|F:v(verbose)o|[!io][!ot]", TOYFLAG_BIN))
1087
b73a61542297 I've finally gotten 'cpio' into a shape where it could be useable.
Isaac Dunham <ibid.ag@gmail.com>
parents:
diff changeset
17
b73a61542297 I've finally gotten 'cpio' into a shape where it could be useable.
Isaac Dunham <ibid.ag@gmail.com>
parents:
diff changeset
18 config CPIO
b73a61542297 I've finally gotten 'cpio' into a shape where it could be useable.
Isaac Dunham <ibid.ag@gmail.com>
parents:
diff changeset
19 bool "cpio"
1229
34d4ee60e78f Promote cpio out of pending.
Rob Landley <rob@landley.net>
parents: 1228
diff changeset
20 default y
1087
b73a61542297 I've finally gotten 'cpio' into a shape where it could be useable.
Isaac Dunham <ibid.ag@gmail.com>
parents:
diff changeset
21 help
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
22 usage: cpio -{o|t|i} [-v] [--verbose] [-F FILE] [ignored: -du -H newc]
1221
8451065c5a19 Cleanup cpio: fiddle with help text, make option parsing require/exclude -iot combinations, move loopfiles_stdin() down after write_cpio_member() so we can hardwire it instead of using a function pointer that only ever has one value.
Rob Landley <rob@landley.net>
parents: 1220
diff changeset
23
8451065c5a19 Cleanup cpio: fiddle with help text, make option parsing require/exclude -iot combinations, move loopfiles_stdin() down after write_cpio_member() so we can hardwire it instead of using a function pointer that only ever has one value.
Rob Landley <rob@landley.net>
parents: 1220
diff changeset
24 copy files into and out of a "newc" format cpio archive
1087
b73a61542297 I've finally gotten 'cpio' into a shape where it could be useable.
Isaac Dunham <ibid.ag@gmail.com>
parents:
diff changeset
25
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
26 -F FILE use archive FILE instead of stdin/stdout
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
27 -i extract from archive into file system (stdin=archive)
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
28 -o create archive (stdin=list of files, stdout=archive)
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
29 -t test files (list only, stdin=archive, stdout=list of files)
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
30 -v verbose (list files during create/extract)
1087
b73a61542297 I've finally gotten 'cpio' into a shape where it could be useable.
Isaac Dunham <ibid.ag@gmail.com>
parents:
diff changeset
31 */
1135
581c35250cff Minor drive-by cleanups to cpio. Whitespace, curly brackets, replace %4 with &3, turn a switch/case into if/else.
Rob Landley <rob@landley.net>
parents: 1121
diff changeset
32
1087
b73a61542297 I've finally gotten 'cpio' into a shape where it could be useable.
Isaac Dunham <ibid.ag@gmail.com>
parents:
diff changeset
33 #define FOR_cpio
b73a61542297 I've finally gotten 'cpio' into a shape where it could be useable.
Isaac Dunham <ibid.ag@gmail.com>
parents:
diff changeset
34 #include "toys.h"
b73a61542297 I've finally gotten 'cpio' into a shape where it could be useable.
Isaac Dunham <ibid.ag@gmail.com>
parents:
diff changeset
35
b73a61542297 I've finally gotten 'cpio' into a shape where it could be useable.
Isaac Dunham <ibid.ag@gmail.com>
parents:
diff changeset
36 GLOBALS(
1135
581c35250cff Minor drive-by cleanups to cpio. Whitespace, curly brackets, replace %4 with &3, turn a switch/case into if/else.
Rob Landley <rob@landley.net>
parents: 1121
diff changeset
37 char *archive;
581c35250cff Minor drive-by cleanups to cpio. Whitespace, curly brackets, replace %4 with &3, turn a switch/case into if/else.
Rob Landley <rob@landley.net>
parents: 1121
diff changeset
38 char *fmt;
1087
b73a61542297 I've finally gotten 'cpio' into a shape where it could be useable.
Isaac Dunham <ibid.ag@gmail.com>
parents:
diff changeset
39 )
b73a61542297 I've finally gotten 'cpio' into a shape where it could be useable.
Isaac Dunham <ibid.ag@gmail.com>
parents:
diff changeset
40
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
41 // Read strings, tail padded to 4 byte alignment. Argument "align" is amount
1271
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
42 // by which start of string isn't aligned (usually 0, but header is 110 bytes
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
43 // which is 2 bytes off because the first field wasn't expanded from 6 to 8).
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
44 static char *strpad(int fd, unsigned len, unsigned align)
1087
b73a61542297 I've finally gotten 'cpio' into a shape where it could be useable.
Isaac Dunham <ibid.ag@gmail.com>
parents:
diff changeset
45 {
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
46 char *str;
1087
b73a61542297 I've finally gotten 'cpio' into a shape where it could be useable.
Isaac Dunham <ibid.ag@gmail.com>
parents:
diff changeset
47
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
48 align = (align + len) & 3;
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
49 if (align) len += (4-align);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
50 xreadall(fd, str = xmalloc(len+1), len);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
51 str[len]=0; // redundant, in case archive is bad
1221
8451065c5a19 Cleanup cpio: fiddle with help text, make option parsing require/exclude -iot combinations, move loopfiles_stdin() down after write_cpio_member() so we can hardwire it instead of using a function pointer that only ever has one value.
Rob Landley <rob@landley.net>
parents: 1220
diff changeset
52
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
53 return str;
1221
8451065c5a19 Cleanup cpio: fiddle with help text, make option parsing require/exclude -iot combinations, move loopfiles_stdin() down after write_cpio_member() so we can hardwire it instead of using a function pointer that only ever has one value.
Rob Landley <rob@landley.net>
parents: 1220
diff changeset
54 }
8451065c5a19 Cleanup cpio: fiddle with help text, make option parsing require/exclude -iot combinations, move loopfiles_stdin() down after write_cpio_member() so we can hardwire it instead of using a function pointer that only ever has one value.
Rob Landley <rob@landley.net>
parents: 1220
diff changeset
55
1087
b73a61542297 I've finally gotten 'cpio' into a shape where it could be useable.
Isaac Dunham <ibid.ag@gmail.com>
parents:
diff changeset
56 //convert hex to uint; mostly to allow using bits of non-terminated strings
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
57 unsigned x8u(char *hex)
1087
b73a61542297 I've finally gotten 'cpio' into a shape where it could be useable.
Isaac Dunham <ibid.ag@gmail.com>
parents:
diff changeset
58 {
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
59 unsigned val, inpos = 8, outpos;
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
60 char pattern[6];
1087
b73a61542297 I've finally gotten 'cpio' into a shape where it could be useable.
Isaac Dunham <ibid.ag@gmail.com>
parents:
diff changeset
61
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
62 while (*hex == '0') {
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
63 hex++;
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
64 if (!--inpos) return 0;
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
65 }
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
66 // Because scanf gratuitously treats %*X differently than printf does.
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
67 sprintf(pattern, "%%%dX%%n", inpos);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
68 sscanf(hex, pattern, &val, &outpos);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
69 if (inpos != outpos) error_exit("bad header");
1220
10d4dd6621cb Patch from Isaac Dunham to add cpio -d, with a few tweaks by me.
Rob Landley <rob@landley.net>
parents: 1135
diff changeset
70
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
71 return val;
1087
b73a61542297 I've finally gotten 'cpio' into a shape where it could be useable.
Isaac Dunham <ibid.ag@gmail.com>
parents:
diff changeset
72 }
b73a61542297 I've finally gotten 'cpio' into a shape where it could be useable.
Isaac Dunham <ibid.ag@gmail.com>
parents:
diff changeset
73
b73a61542297 I've finally gotten 'cpio' into a shape where it could be useable.
Isaac Dunham <ibid.ag@gmail.com>
parents:
diff changeset
74 void cpio_main(void)
b73a61542297 I've finally gotten 'cpio' into a shape where it could be useable.
Isaac Dunham <ibid.ag@gmail.com>
parents:
diff changeset
75 {
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
76 int afd;
1223
a7d5b93111a5 Next round of cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1222
diff changeset
77
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
78 // Subtle bit: FLAG_o is 1 so we can just use it to select stdin/stdout.
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
79
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
80 afd = toys.optflags & FLAG_o;
1121
977f0a4dc562 Support -F, and ignore -u since that's what we do anyway.
Isaac Dunham <ibid.ag@gmail.com>
parents: 1098
diff changeset
81 if (TT.archive) {
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
82 int perm = (toys.optflags & FLAG_o) ? O_CREAT|O_WRONLY|O_TRUNC : O_RDONLY;
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
83
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
84 afd = xcreate(TT.archive, perm, 0644);
1121
977f0a4dc562 Support -F, and ignore -u since that's what we do anyway.
Isaac Dunham <ibid.ag@gmail.com>
parents: 1098
diff changeset
85 }
977f0a4dc562 Support -F, and ignore -u since that's what we do anyway.
Isaac Dunham <ibid.ag@gmail.com>
parents: 1098
diff changeset
86
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
87 // read cpio archive
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
88
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
89 if (toys.optflags & (FLAG_i|FLAG_t)) for (;;) {
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
90 char *name, *tofree, *data;
1271
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
91 unsigned size, mode, uid, gid, timestamp;
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
92 int test = toys.optflags & FLAG_t, err = 0;
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
93
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
94 // Read header and name.
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
95 xreadall(afd, toybuf, 110);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
96 tofree = name = strpad(afd, x8u(toybuf+94), 110);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
97 if (!strcmp("TRAILER!!!", name)) break;
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
98
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
99 // If you want to extract absolute paths, "cd /" and run cpio.
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
100 while (*name == '/') name++;
1271
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
101 // TODO: remove .. entries
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
102
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
103 size = x8u(toybuf+54);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
104 mode = x8u(toybuf+14);
1271
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
105 uid = x8u(toybuf+30);
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
106 gid = x8u(toybuf+38);
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
107 timestamp = x8u(toybuf+46); // unsigned 32 bit, so year 2100 problem
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
108
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
109 if (toys.optflags & (FLAG_t|FLAG_v)) puts(name);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
110
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
111 if (!test && strrchr(name, '/') && mkpathat(AT_FDCWD, name, 0, 2)) {
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
112 perror_msg("mkpath '%s'", name);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
113 test++;
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
114 }
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
115
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
116 // Consume entire record even if it couldn't create file, so we're
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
117 // properly aligned with next file.
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
118
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
119 if (S_ISDIR(mode)) {
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
120 if (!test) err = mkdir(name, mode);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
121 } else if (S_ISLNK(mode)) {
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
122 data = strpad(afd, size, 0);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
123 if (!test) err = symlink(data, name);
1271
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
124 // Can't get a filehandle to a symlink, so do special chown
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
125 if (!err && !getpid()) err = lchown(name, uid, gid);
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
126 } else if (S_ISREG(mode)) {
1271
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
127 int fd = test ? 0 : open(name, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW, mode);
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
128
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
129 // If write fails, we still need to read/discard data to continue with
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
130 // archive. Since doing so overwrites errno, report error now
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
131 if (fd < 0) {
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
132 perror_msg("create %s", name);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
133 test++;
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
134 }
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
135
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
136 data = toybuf;
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
137 while (size) {
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
138 if (size < sizeof(toybuf)) data = strpad(afd, size, 0);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
139 else xreadall(afd, toybuf, sizeof(toybuf));
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
140 if (!test) xwrite(fd, data, data == toybuf ? sizeof(toybuf) : size);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
141 if (data != toybuf) {
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
142 free(data);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
143 break;
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
144 }
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
145 size -= sizeof(toybuf);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
146 }
1271
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
147
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
148 if (!test) {
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
149 // set owner, restore dropped suid bit
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
150 if (!getpid()) {
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
151 err = fchown(fd, uid, gid);
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
152 if (!err) err = fchmod(fd, mode);
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
153 }
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
154 close(fd);
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
155 }
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
156 } else if (!test)
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
157 err = mknod(name, mode, makedev(x8u(toybuf+62), x8u(toybuf+70)));
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
158
1271
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
159 // Set ownership and timestamp.
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
160 if (!test && !err) {
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
161 // Creading dir/dev doesn't give us a filehandle, we have to refer to it
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
162 // by name to chown/utime, but how do we know it's the same item?
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
163 // Check that we at least have the right type of entity open, and do
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
164 // NOT restore dropped suid bit in this case.
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
165 if (!S_ISREG(mode) && !S_ISLNK(mode) && !getpid()) {
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
166 int fd = open(name, O_WRONLY|O_NOFOLLOW);
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
167 struct stat st;
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
168
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
169 if (fd != -1 && !fstat(fd, &st) && (st.st_mode&S_IFMT) == mode)
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
170 err = fchown(fd, uid, gid);
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
171 else err = 1;
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
172
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
173 close(fd);
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
174 }
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
175
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
176 // set timestamp
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
177 if (!err) {
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
178 struct timespec times[2];
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
179
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
180 memset(times, 0, sizeof(struct timespec)*2);
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
181 times[0].tv_sec = times[1].tv_sec = timestamp;
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
182 err = utimensat(AT_FDCWD, name, times, AT_SYMLINK_NOFOLLOW);
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
183 }
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
184 }
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
185
c214de62b18b Teach cpio to set uid/gid and timestamp. (Timestamp has year 2100 problem.)
Rob Landley <rob@landley.net>
parents: 1231
diff changeset
186 if (err) perror_msg("'%s'", name);
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
187 free(tofree);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
188
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
189 // Output cpio archive
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
190
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
191 } else {
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
192 char *name = 0;
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
193 size_t size = 0;
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
194
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
195 for (;;) {
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
196 struct stat st;
1230
c78ffc6c330a More cpio bugfixes from Isaac Dunham.
Rob Landley <rob@landley.net>
parents: 1229
diff changeset
197 unsigned nlen, error = 0, zero = 0;
1228
2366f9d73745 Several cpio bugfixes spotted by Isaac Dunham.
Rob Landley <rob@landley.net>
parents: 1227
diff changeset
198 int len, fd = -1;
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
199 ssize_t llen;
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
200
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
201 len = getline(&name, &size, stdin);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
202 if (len<1) break;
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
203 if (name[len-1] == '\n') name[--len] = 0;
1230
c78ffc6c330a More cpio bugfixes from Isaac Dunham.
Rob Landley <rob@landley.net>
parents: 1229
diff changeset
204 nlen = len+1;
1331
11fe363078b8 cpio: archive more files
Isaac Dunham <ibid.ag@gmail.com>
parents: 1271
diff changeset
205 if (lstat(name, &st) || (S_ISREG(st.st_mode)
11fe363078b8 cpio: archive more files
Isaac Dunham <ibid.ag@gmail.com>
parents: 1271
diff changeset
206 && st.st_size && (fd = open(name, O_RDONLY))<0))
1228
2366f9d73745 Several cpio bugfixes spotted by Isaac Dunham.
Rob Landley <rob@landley.net>
parents: 1227
diff changeset
207 {
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
208 perror_msg("%s", name);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
209 continue;
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
210 }
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
211
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
212 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) st.st_size = 0;
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
213 if (st.st_size >> 32) perror_msg("skipping >2G file '%s'", name);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
214 else {
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
215 llen = sprintf(toybuf,
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
216 "070701%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X",
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
217 (int)st.st_ino, st.st_mode, st.st_uid, st.st_gid, (int)st.st_nlink,
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
218 (int)st.st_mtime, (int)st.st_size, major(st.st_dev),
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
219 minor(st.st_dev), major(st.st_rdev), minor(st.st_rdev), nlen, 0);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
220 xwrite(afd, toybuf, llen);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
221 xwrite(afd, name, nlen);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
222
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
223 // NUL Pad header up to 4 multiple bytes.
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
224 llen = (llen + nlen) & 3;
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
225 if (llen) xwrite(afd, &zero, 4-llen);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
226
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
227 // Write out body for symlink or regular file
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
228 llen = st.st_size;
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
229 if (S_ISLNK(st.st_mode)) {
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
230 if (readlink(name, toybuf, sizeof(toybuf)-1) == llen)
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
231 xwrite(afd, toybuf, llen);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
232 else perror_msg("readlink '%s'", name);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
233 } else while (llen) {
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
234 nlen = llen > sizeof(toybuf) ? sizeof(toybuf) : llen;
1228
2366f9d73745 Several cpio bugfixes spotted by Isaac Dunham.
Rob Landley <rob@landley.net>
parents: 1227
diff changeset
235 llen -= nlen;
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
236 // If read fails, write anyway (already wrote size in header)
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
237 if (nlen != readall(fd, toybuf, nlen))
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
238 if (!error++) perror_msg("bad read from file '%s'", name);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
239 xwrite(afd, toybuf, nlen);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
240 }
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
241 llen = st.st_size & 3;
1228
2366f9d73745 Several cpio bugfixes spotted by Isaac Dunham.
Rob Landley <rob@landley.net>
parents: 1227
diff changeset
242 if (llen) write(afd, &zero, 4-llen);
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
243 }
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
244 close(fd);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
245 }
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
246 free(name);
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
247
1230
c78ffc6c330a More cpio bugfixes from Isaac Dunham.
Rob Landley <rob@landley.net>
parents: 1229
diff changeset
248 memset(toybuf, 0, sizeof(toybuf));
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
249 xwrite(afd, toybuf,
1230
c78ffc6c330a More cpio bugfixes from Isaac Dunham.
Rob Landley <rob@landley.net>
parents: 1229
diff changeset
250 sprintf(toybuf, "070701%040X%056X%08XTRAILER!!!", 1, 0x0b, 0)+4);
1227
903acf85bd1d Most of the remaining cpio cleanup.
Rob Landley <rob@landley.net>
parents: 1223
diff changeset
251 }
1087
b73a61542297 I've finally gotten 'cpio' into a shape where it could be useable.
Isaac Dunham <ibid.ag@gmail.com>
parents:
diff changeset
252 }