|
1 | | -/* dracut-install.c -- install files and executables |
| 1 | +/* skipcpio.c |
2 | 2 |
|
3 | 3 | Copyright (C) 2012 Harald Hoyer |
4 | 4 | Copyright (C) 2012 Red Hat, Inc. All rights reserved. |
|
28 | 28 | #include <string.h> |
29 | 29 |
|
30 | 30 | #define CPIO_MAGIC "070701" |
| 31 | + |
31 | 32 | #define CPIO_END "TRAILER!!!" |
32 | 33 | #define CPIO_ENDLEN (sizeof(CPIO_END) - 1) |
33 | 34 |
|
34 | 35 | #define CPIO_ALIGNMENT 4 |
35 | 36 |
|
| 37 | +#define ALIGN_UP(n, a) (((n) + (a) - 1) & (~((a) - 1))) |
| 38 | + |
| 39 | +#define pr_err(fmt, ...) \ |
| 40 | + fprintf(stderr, "ERROR: %s:%d:%s(): " fmt, __FILE__, __LINE__, \ |
| 41 | + __func__, ##__VA_ARGS__) |
| 42 | + |
36 | 43 | struct cpio_header { |
37 | 44 | char c_magic[6]; |
38 | 45 | char c_ino[8]; |
@@ -62,110 +69,135 @@ union buf_union { |
62 | 69 |
|
63 | 70 | static union buf_union buf; |
64 | 71 |
|
65 | | -#define ALIGN_UP(n, a) (((n) + (a) - 1) & (~((a) - 1))) |
66 | | - |
67 | 72 | int main(int argc, char **argv) |
68 | 73 | { |
69 | | - FILE *f; |
70 | 74 | size_t s; |
| 75 | + long pos = 0; |
| 76 | + FILE *f = NULL; |
| 77 | + char *fname = NULL; |
| 78 | + int ret = EXIT_FAILURE; |
| 79 | + unsigned long filesize; |
| 80 | + unsigned long filename_length; |
71 | 81 |
|
72 | 82 | if (argc != 2) { |
73 | 83 | fprintf(stderr, "Usage: %s <file>\n", argv[0]); |
74 | | - exit(1); |
| 84 | + goto end; |
75 | 85 | } |
76 | 86 |
|
77 | | - f = fopen(argv[1], "r"); |
78 | | - |
| 87 | + fname = argv[1]; |
| 88 | + f = fopen(fname, "r"); |
79 | 89 | if (f == NULL) { |
80 | | - fprintf(stderr, "Cannot open file '%s'\n", argv[1]); |
81 | | - exit(1); |
| 90 | + pr_err("Cannot open file '%s'\n", fname); |
| 91 | + goto end; |
82 | 92 | } |
83 | 93 |
|
84 | | - s = fread(&buf.cpio, sizeof(buf.cpio), 1, f); |
85 | | - if (s <= 0) { |
86 | | - fprintf(stderr, "Read error from file '%s'\n", argv[1]); |
87 | | - fclose(f); |
88 | | - exit(1); |
| 94 | + if ((fread(&buf.cpio, sizeof(buf.cpio), 1, f) != 1) || |
| 95 | + ferror(f)) { |
| 96 | + pr_err("Read error from file '%s'\n", fname); |
| 97 | + goto end; |
89 | 98 | } |
90 | | - fseek(f, 0, SEEK_SET); |
91 | | - |
92 | | - /* check, if this is a cpio archive */ |
93 | | - if (memcmp(buf.cpio.h.c_magic, CPIO_MAGIC, 6) == 0) { |
94 | 99 |
|
95 | | - long pos = 0; |
| 100 | + if (fseek(f, 0, SEEK_SET)) { |
| 101 | + pr_err("fseek error on file '%s'\n", fname); |
| 102 | + goto end; |
| 103 | + } |
96 | 104 |
|
97 | | - unsigned long filesize; |
98 | | - unsigned long filename_length; |
| 105 | + /* check, if this is a cpio archive */ |
| 106 | + if (memcmp(buf.cpio.h.c_magic, CPIO_MAGIC, 6)) { |
| 107 | + goto cat_rest; |
| 108 | + } |
99 | 109 |
|
100 | | - do { |
101 | | - // zero string, spilling into next unused field, to use strtol |
102 | | - buf.cpio.h.c_chksum[0] = 0; |
103 | | - filename_length = strtoul(buf.cpio.h.c_namesize, NULL, 16); |
104 | | - pos = ALIGN_UP(pos + sizeof(struct cpio_header) + filename_length, CPIO_ALIGNMENT); |
105 | | - |
106 | | - // zero string, spilling into next unused field, to use strtol |
107 | | - buf.cpio.h.c_dev_maj[0] = 0; |
108 | | - filesize = strtoul(buf.cpio.h.c_filesize, NULL, 16); |
109 | | - pos = ALIGN_UP(pos + filesize, CPIO_ALIGNMENT); |
110 | | - |
111 | | - if (filename_length == (CPIO_ENDLEN + 1) |
112 | | - && strncmp(buf.cpio.filename, CPIO_END, CPIO_ENDLEN) == 0) { |
113 | | - fseek(f, pos, SEEK_SET); |
114 | | - break; |
| 110 | + do { |
| 111 | + // zero string, spilling into next unused field, to use strtol |
| 112 | + buf.cpio.h.c_chksum[0] = 0; |
| 113 | + filename_length = strtoul(buf.cpio.h.c_namesize, NULL, 16); |
| 114 | + pos = ALIGN_UP(pos + sizeof(struct cpio_header) + filename_length, CPIO_ALIGNMENT); |
| 115 | + |
| 116 | + // zero string, spilling into next unused field, to use strtol |
| 117 | + buf.cpio.h.c_dev_maj[0] = 0; |
| 118 | + filesize = strtoul(buf.cpio.h.c_filesize, NULL, 16); |
| 119 | + pos = ALIGN_UP(pos + filesize, CPIO_ALIGNMENT); |
| 120 | + |
| 121 | + if (filename_length == (CPIO_ENDLEN + 1) |
| 122 | + && strncmp(buf.cpio.filename, CPIO_END, CPIO_ENDLEN) == 0) { |
| 123 | + if (fseek(f, pos, SEEK_SET)) { |
| 124 | + pr_err("fseek\n"); |
| 125 | + goto end; |
115 | 126 | } |
| 127 | + break; |
| 128 | + } |
116 | 129 |
|
117 | | - if (fseek(f, pos, SEEK_SET) != 0) { |
118 | | - perror("fseek"); |
119 | | - exit(1); |
120 | | - } |
| 130 | + if (fseek(f, pos, SEEK_SET)) { |
| 131 | + pr_err("fseek\n"); |
| 132 | + goto end; |
| 133 | + } |
121 | 134 |
|
122 | | - if (fread(&buf.cpio, sizeof(buf.cpio), 1, f) != 1) { |
123 | | - perror("fread"); |
124 | | - exit(1); |
125 | | - } |
| 135 | + if ((fread(&buf.cpio, sizeof(buf.cpio), 1, f) != 1) || |
| 136 | + ferror(f)) { |
| 137 | + pr_err("fread\n"); |
| 138 | + goto end; |
| 139 | + } |
126 | 140 |
|
127 | | - if (memcmp(buf.cpio.h.c_magic, CPIO_MAGIC, 6) != 0) { |
128 | | - fprintf(stderr, "Corrupt CPIO archive!\n"); |
129 | | - exit(1); |
130 | | - } |
131 | | - } while (!feof(f)); |
| 141 | + if (memcmp(buf.cpio.h.c_magic, CPIO_MAGIC, 6)) { |
| 142 | + pr_err("Corrupt CPIO archive!\n"); |
| 143 | + goto end; |
| 144 | + } |
| 145 | + } while (!feof(f)); |
132 | 146 |
|
133 | | - if (feof(f)) { |
134 | | - /* CPIO_END not found, just cat the whole file */ |
135 | | - fseek(f, 0, SEEK_SET); |
136 | | - } else { |
137 | | - /* skip zeros */ |
138 | | - do { |
139 | | - size_t i; |
| 147 | + if (feof(f)) { |
| 148 | + /* CPIO_END not found, just cat the whole file */ |
| 149 | + if (fseek(f, 0, SEEK_SET)) { |
| 150 | + pr_err("fseek\n"); |
| 151 | + goto end; |
| 152 | + } |
| 153 | + } else { |
| 154 | + /* skip zeros */ |
| 155 | + do { |
| 156 | + size_t i; |
140 | 157 |
|
141 | | - s = fread(buf.copy_buffer, 1, sizeof(buf.copy_buffer) - 1, f); |
142 | | - if (s <= 0) |
143 | | - break; |
| 158 | + s = fread(buf.copy_buffer, 1, sizeof(buf.copy_buffer) - 1, f); |
| 159 | + if (ferror(f)) { |
| 160 | + pr_err("fread\n"); |
| 161 | + goto end; |
| 162 | + } |
144 | 163 |
|
145 | | - for (i = 0; (i < s) && (buf.copy_buffer[i] == 0); i++) ; |
| 164 | + for (i = 0; (i < s) && (buf.copy_buffer[i] == 0); i++) ; |
146 | 165 |
|
147 | | - if (buf.copy_buffer[i] != 0) { |
148 | | - pos += i; |
| 166 | + if (buf.copy_buffer[i]) { |
| 167 | + pos += i; |
149 | 168 |
|
150 | | - fseek(f, pos, SEEK_SET); |
151 | | - break; |
| 169 | + if (fseek(f, pos, SEEK_SET)) { |
| 170 | + pr_err("fseek\n"); |
| 171 | + goto end; |
152 | 172 | } |
| 173 | + break; |
| 174 | + } |
153 | 175 |
|
154 | | - pos += s; |
155 | | - } while (!feof(f)); |
156 | | - } |
| 176 | + pos += s; |
| 177 | + } while (!feof(f)); |
157 | 178 | } |
| 179 | + |
| 180 | +cat_rest: |
158 | 181 | /* cat out the rest */ |
159 | 182 | while (!feof(f)) { |
160 | 183 | s = fread(buf.copy_buffer, 1, sizeof(buf.copy_buffer), f); |
161 | | - if (s <= 0) |
162 | | - break; |
| 184 | + if (ferror(f)) { |
| 185 | + pr_err("fread\n"); |
| 186 | + goto end; |
| 187 | + } |
163 | 188 |
|
164 | | - s = fwrite(buf.copy_buffer, 1, s, stdout); |
165 | | - if (s <= 0) |
166 | | - break; |
| 189 | + if (fwrite(buf.copy_buffer, 1, s, stdout) != s) { |
| 190 | + pr_err("fwrite\n"); |
| 191 | + goto end; |
| 192 | + } |
| 193 | + } |
| 194 | + |
| 195 | + ret = EXIT_SUCCESS; |
| 196 | + |
| 197 | +end: |
| 198 | + if (f) { |
| 199 | + fclose(f); |
167 | 200 | } |
168 | | - fclose(f); |
169 | 201 |
|
170 | | - return EXIT_SUCCESS; |
| 202 | + return ret; |
171 | 203 | } |
0 commit comments