Skip to content

Commit 1400227

Browse files
ddissnathanchance
authored andcommitted
gen_init_cpio: write to fd instead of stdout stream
In preparation for more efficient archiving using copy_file_range(), switch from writing archive data to stdout to using STDOUT_FILENO and I/O via write(), dprintf(), etc. Basic I/O error handling is added to cover cases such as ENOSPC. Partial writes are treated as errors. Signed-off-by: David Disseldorp <ddiss@suse.de> Reviewed-by: Nicolas Schier <nsc@kernel.org> Link: https://lore.kernel.org/r/20250819032607.28727-2-ddiss@suse.de Signed-off-by: Nathan Chancellor <nathan@kernel.org>
1 parent 75a6b45 commit 1400227

1 file changed

Lines changed: 81 additions & 58 deletions

File tree

usr/gen_init_cpio.c

Lines changed: 81 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -23,64 +23,71 @@
2323
#define xstr(s) #s
2424
#define str(s) xstr(s)
2525
#define MIN(a, b) ((a) < (b) ? (a) : (b))
26+
#define CPIO_HDR_LEN 110
27+
#define padlen(_off, _align) (((_align) - ((_off) & ((_align) - 1))) % (_align))
2628

29+
static char padding[512];
2730
static unsigned int offset;
2831
static unsigned int ino = 721;
2932
static time_t default_mtime;
3033
static bool do_file_mtime;
3134
static bool do_csum = false;
35+
static int outfd = STDOUT_FILENO;
3236

3337
struct file_handler {
3438
const char *type;
3539
int (*handler)(const char *line);
3640
};
3741

38-
static void push_string(const char *name)
42+
static int push_string(const char *name)
3943
{
4044
unsigned int name_len = strlen(name) + 1;
45+
ssize_t len;
46+
47+
len = write(outfd, name, name_len);
48+
if (len != name_len)
49+
return -1;
4150

42-
fputs(name, stdout);
43-
putchar(0);
4451
offset += name_len;
52+
return 0;
4553
}
4654

47-
static void push_pad (void)
55+
static int push_pad(size_t padlen)
4856
{
49-
while (offset & 3) {
50-
putchar(0);
51-
offset++;
52-
}
57+
ssize_t len = 0;
58+
59+
if (!padlen)
60+
return 0;
61+
62+
if (padlen < sizeof(padding))
63+
len = write(outfd, padding, padlen);
64+
if (len != padlen)
65+
return -1;
66+
67+
offset += padlen;
68+
return 0;
5369
}
5470

55-
static void push_rest(const char *name)
71+
static int push_rest(const char *name)
5672
{
5773
unsigned int name_len = strlen(name) + 1;
58-
unsigned int tmp_ofs;
74+
ssize_t len;
5975

60-
fputs(name, stdout);
61-
putchar(0);
62-
offset += name_len;
76+
len = write(outfd, name, name_len);
77+
if (len != name_len)
78+
return -1;
6379

64-
tmp_ofs = name_len + 110;
65-
while (tmp_ofs & 3) {
66-
putchar(0);
67-
offset++;
68-
tmp_ofs++;
69-
}
70-
}
80+
offset += name_len;
7181

72-
static void push_hdr(const char *s)
73-
{
74-
fputs(s, stdout);
75-
offset += 110;
82+
return push_pad(padlen(name_len + CPIO_HDR_LEN, 4));
7683
}
7784

78-
static void cpio_trailer(void)
85+
static int cpio_trailer(void)
7986
{
80-
char s[256];
8187
const char name[] = "TRAILER!!!";
88+
int len;
8289

83-
sprintf(s, "%s%08X%08X%08lX%08lX%08X%08lX"
90+
len = dprintf(outfd, "%s%08X%08X%08lX%08lX%08X%08lX"
8491
"%08X%08X%08X%08X%08X%08X%08X",
8592
do_csum ? "070702" : "070701", /* magic */
8693
0, /* ino */
@@ -96,23 +103,24 @@ static void cpio_trailer(void)
96103
0, /* rminor */
97104
(unsigned)strlen(name)+1, /* namesize */
98105
0); /* chksum */
99-
push_hdr(s);
100-
push_rest(name);
106+
offset += len;
101107

102-
while (offset % 512) {
103-
putchar(0);
104-
offset++;
105-
}
108+
if (len != CPIO_HDR_LEN ||
109+
push_rest(name) < 0 ||
110+
push_pad(padlen(offset, 512)) < 0)
111+
return -1;
112+
113+
return 0;
106114
}
107115

108116
static int cpio_mkslink(const char *name, const char *target,
109117
unsigned int mode, uid_t uid, gid_t gid)
110118
{
111-
char s[256];
119+
int len;
112120

113121
if (name[0] == '/')
114122
name++;
115-
sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
123+
len = dprintf(outfd, "%s%08X%08X%08lX%08lX%08X%08lX"
116124
"%08X%08X%08X%08X%08X%08X%08X",
117125
do_csum ? "070702" : "070701", /* magic */
118126
ino++, /* ino */
@@ -128,12 +136,17 @@ static int cpio_mkslink(const char *name, const char *target,
128136
0, /* rminor */
129137
(unsigned)strlen(name) + 1,/* namesize */
130138
0); /* chksum */
131-
push_hdr(s);
132-
push_string(name);
133-
push_pad();
134-
push_string(target);
135-
push_pad();
139+
offset += len;
140+
141+
if (len != CPIO_HDR_LEN ||
142+
push_string(name) < 0 ||
143+
push_pad(padlen(offset, 4)) < 0 ||
144+
push_string(target) < 0 ||
145+
push_pad(padlen(offset, 4)) < 0)
146+
return -1;
147+
136148
return 0;
149+
137150
}
138151

139152
static int cpio_mkslink_line(const char *line)
@@ -157,11 +170,11 @@ static int cpio_mkslink_line(const char *line)
157170
static int cpio_mkgeneric(const char *name, unsigned int mode,
158171
uid_t uid, gid_t gid)
159172
{
160-
char s[256];
173+
int len;
161174

162175
if (name[0] == '/')
163176
name++;
164-
sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
177+
len = dprintf(outfd, "%s%08X%08X%08lX%08lX%08X%08lX"
165178
"%08X%08X%08X%08X%08X%08X%08X",
166179
do_csum ? "070702" : "070701", /* magic */
167180
ino++, /* ino */
@@ -177,8 +190,12 @@ static int cpio_mkgeneric(const char *name, unsigned int mode,
177190
0, /* rminor */
178191
(unsigned)strlen(name) + 1,/* namesize */
179192
0); /* chksum */
180-
push_hdr(s);
181-
push_rest(name);
193+
offset += len;
194+
195+
if (len != CPIO_HDR_LEN ||
196+
push_rest(name) < 0)
197+
return -1;
198+
182199
return 0;
183200
}
184201

@@ -246,7 +263,7 @@ static int cpio_mknod(const char *name, unsigned int mode,
246263
uid_t uid, gid_t gid, char dev_type,
247264
unsigned int maj, unsigned int min)
248265
{
249-
char s[256];
266+
int len;
250267

251268
if (dev_type == 'b')
252269
mode |= S_IFBLK;
@@ -255,7 +272,7 @@ static int cpio_mknod(const char *name, unsigned int mode,
255272

256273
if (name[0] == '/')
257274
name++;
258-
sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
275+
len = dprintf(outfd, "%s%08X%08X%08lX%08lX%08X%08lX"
259276
"%08X%08X%08X%08X%08X%08X%08X",
260277
do_csum ? "070702" : "070701", /* magic */
261278
ino++, /* ino */
@@ -271,8 +288,12 @@ static int cpio_mknod(const char *name, unsigned int mode,
271288
min, /* rminor */
272289
(unsigned)strlen(name) + 1,/* namesize */
273290
0); /* chksum */
274-
push_hdr(s);
275-
push_rest(name);
291+
offset += len;
292+
293+
if (len != CPIO_HDR_LEN ||
294+
push_rest(name) < 0)
295+
return -1;
296+
276297
return 0;
277298
}
278299

@@ -324,11 +345,9 @@ static int cpio_mkfile(const char *name, const char *location,
324345
unsigned int mode, uid_t uid, gid_t gid,
325346
unsigned int nlinks)
326347
{
327-
char s[256];
328348
struct stat buf;
329349
unsigned long size;
330-
int file;
331-
int retval;
350+
int file, retval, len;
332351
int rc = -1;
333352
time_t mtime;
334353
int namesize;
@@ -386,7 +405,7 @@ static int cpio_mkfile(const char *name, const char *location,
386405
if (name[0] == '/')
387406
name++;
388407
namesize = strlen(name) + 1;
389-
sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
408+
len = dprintf(outfd, "%s%08X%08X%08lX%08lX%08X%08lX"
390409
"%08lX%08X%08X%08X%08X%08X%08X",
391410
do_csum ? "070702" : "070701", /* magic */
392411
ino, /* ino */
@@ -402,9 +421,12 @@ static int cpio_mkfile(const char *name, const char *location,
402421
0, /* rminor */
403422
namesize, /* namesize */
404423
size ? csum : 0); /* chksum */
405-
push_hdr(s);
406-
push_string(name);
407-
push_pad();
424+
offset += len;
425+
426+
if (len != CPIO_HDR_LEN ||
427+
push_string(name) < 0 ||
428+
push_pad(padlen(offset, 4)) < 0)
429+
goto error;
408430

409431
while (size) {
410432
unsigned char filebuf[65536];
@@ -417,14 +439,15 @@ static int cpio_mkfile(const char *name, const char *location,
417439
goto error;
418440
}
419441

420-
if (fwrite(filebuf, this_read, 1, stdout) != 1) {
442+
if (write(outfd, filebuf, this_read) != this_read) {
421443
fprintf(stderr, "writing filebuf failed\n");
422444
goto error;
423445
}
424446
offset += this_read;
425447
size -= this_read;
426448
}
427-
push_pad();
449+
if (push_pad(padlen(offset, 4)) < 0)
450+
goto error;
428451

429452
name += namesize;
430453
}
@@ -691,7 +714,7 @@ int main (int argc, char *argv[])
691714
}
692715
}
693716
if (ec == 0)
694-
cpio_trailer();
717+
ec = cpio_trailer();
695718

696719
exit(ec);
697720
}

0 commit comments

Comments
 (0)