2 * Copyright (c) 2003-2007 Tim Kientzle
3 * Copyright (c) 2006 Rudolf Marek SYSGO s.r.o.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include "archive_platform.h"
28 __FBSDID("$FreeBSD: src/lib/libarchive/archive_write_set_format_cpio_newc.c,v 1.4 2008/03/15 11:04:45 kientzle Exp $");
42 #include "archive_entry.h"
43 #include "archive_private.h"
44 #include "archive_write_private.h"
46 static ssize_t
archive_write_newc_data(struct archive_write
*,
47 const void *buff
, size_t s
);
48 static int archive_write_newc_finish(struct archive_write
*);
49 static int archive_write_newc_destroy(struct archive_write
*);
50 static int archive_write_newc_finish_entry(struct archive_write
*);
51 static int archive_write_newc_header(struct archive_write
*,
52 struct archive_entry
*);
53 static int format_hex(int64_t, void *, int);
54 static int64_t format_hex_recursive(int64_t, char *, int);
57 uint64_t entry_bytes_remaining
;
61 struct cpio_header_newc
{
79 * Set output format to 'cpio' format.
82 archive_write_set_format_cpio_newc(struct archive
*_a
)
84 struct archive_write
*a
= (struct archive_write
*)_a
;
87 /* If someone else was already registered, unregister them. */
88 if (a
->format_destroy
!= NULL
)
89 (a
->format_destroy
)(a
);
91 cpio
= (struct cpio
*)malloc(sizeof(*cpio
));
93 archive_set_error(&a
->archive
, ENOMEM
, "Can't allocate cpio data");
94 return (ARCHIVE_FATAL
);
96 memset(cpio
, 0, sizeof(*cpio
));
97 a
->format_data
= cpio
;
99 a
->pad_uncompressed
= 1;
100 a
->format_name
= "cpio";
101 a
->format_write_header
= archive_write_newc_header
;
102 a
->format_write_data
= archive_write_newc_data
;
103 a
->format_finish_entry
= archive_write_newc_finish_entry
;
104 a
->format_finish
= archive_write_newc_finish
;
105 a
->format_destroy
= archive_write_newc_destroy
;
106 a
->archive
.archive_format
= ARCHIVE_FORMAT_CPIO_SVR4_NOCRC
;
107 a
->archive
.archive_format_name
= "SVR4 cpio nocrc";
112 archive_write_newc_header(struct archive_write
*a
, struct archive_entry
*entry
)
115 const char *p
, *path
;
117 struct cpio_header_newc h
;
120 cpio
= (struct cpio
*)a
->format_data
;
123 path
= archive_entry_pathname(entry
);
124 pathlength
= strlen(path
) + 1; /* Include trailing null. */
126 memset(&h
, 0, sizeof(h
));
127 format_hex(0x070701, &h
.c_magic
, sizeof(h
.c_magic
));
128 format_hex(archive_entry_devmajor(entry
), &h
.c_devmajor
, sizeof(h
.c_devmajor
));
129 format_hex(archive_entry_devminor(entry
), &h
.c_devminor
, sizeof(h
.c_devminor
));
130 if (archive_entry_ino(entry
) > 0xffffffff) {
131 archive_set_error(&a
->archive
, ERANGE
, "large inode number truncated");
135 format_hex(archive_entry_ino(entry
) & 0xffffffff, &h
.c_ino
, sizeof(h
.c_ino
));
136 format_hex(archive_entry_mode(entry
), &h
.c_mode
, sizeof(h
.c_mode
));
137 format_hex(archive_entry_uid(entry
), &h
.c_uid
, sizeof(h
.c_uid
));
138 format_hex(archive_entry_gid(entry
), &h
.c_gid
, sizeof(h
.c_gid
));
139 format_hex(archive_entry_nlink(entry
), &h
.c_nlink
, sizeof(h
.c_nlink
));
140 if (archive_entry_filetype(entry
) == AE_IFBLK
141 || archive_entry_filetype(entry
) == AE_IFCHR
) {
142 format_hex(archive_entry_rdevmajor(entry
), &h
.c_rdevmajor
, sizeof(h
.c_rdevmajor
));
143 format_hex(archive_entry_rdevminor(entry
), &h
.c_rdevminor
, sizeof(h
.c_rdevminor
));
145 format_hex(0, &h
.c_rdevmajor
, sizeof(h
.c_rdevmajor
));
146 format_hex(0, &h
.c_rdevminor
, sizeof(h
.c_rdevminor
));
148 format_hex(archive_entry_mtime(entry
), &h
.c_mtime
, sizeof(h
.c_mtime
));
149 format_hex(pathlength
, &h
.c_namesize
, sizeof(h
.c_namesize
));
150 format_hex(0, &h
.c_checksum
, sizeof(h
.c_checksum
));
152 /* Non-regular files don't store bodies. */
153 if (archive_entry_filetype(entry
) != AE_IFREG
)
154 archive_entry_set_size(entry
, 0);
156 /* Symlinks get the link written as the body of the entry. */
157 p
= archive_entry_symlink(entry
);
158 if (p
!= NULL
&& *p
!= '\0')
159 format_hex(strlen(p
), &h
.c_filesize
, sizeof(h
.c_filesize
));
161 format_hex(archive_entry_size(entry
),
162 &h
.c_filesize
, sizeof(h
.c_filesize
));
164 ret
= (a
->compressor
.write
)(a
, &h
, sizeof(h
));
165 if (ret
!= ARCHIVE_OK
)
166 return (ARCHIVE_FATAL
);
168 /* Pad pathname to even length. */
169 ret
= (a
->compressor
.write
)(a
, path
, pathlength
);
170 if (ret
!= ARCHIVE_OK
)
171 return (ARCHIVE_FATAL
);
172 pad
= 0x3 & - (pathlength
+ sizeof(struct cpio_header_newc
));
174 ret
= (a
->compressor
.write
)(a
, "\0\0\0", pad
);
175 if (ret
!= ARCHIVE_OK
)
176 return (ARCHIVE_FATAL
);
178 cpio
->entry_bytes_remaining
= archive_entry_size(entry
);
179 cpio
->padding
= 3 & (-cpio
->entry_bytes_remaining
);
181 /* Write the symlink now. */
182 if (p
!= NULL
&& *p
!= '\0') {
183 ret
= (a
->compressor
.write
)(a
, p
, strlen(p
));
184 if (ret
!= ARCHIVE_OK
)
185 return (ARCHIVE_FATAL
);
186 pad
= 0x3 & -strlen(p
);
187 ret
= (a
->compressor
.write
)(a
, "\0\0\0", pad
);
194 archive_write_newc_data(struct archive_write
*a
, const void *buff
, size_t s
)
199 cpio
= (struct cpio
*)a
->format_data
;
200 if (s
> cpio
->entry_bytes_remaining
)
201 s
= cpio
->entry_bytes_remaining
;
203 ret
= (a
->compressor
.write
)(a
, buff
, s
);
204 cpio
->entry_bytes_remaining
-= s
;
212 * Format a number into the specified field.
215 format_hex(int64_t v
, void *p
, int digits
)
220 max
= (((int64_t)1) << (digits
* 4)) - 1;
221 if (v
>= 0 && v
<= max
) {
222 format_hex_recursive(v
, (char *)p
, digits
);
225 format_hex_recursive(max
, (char *)p
, digits
);
232 format_hex_recursive(int64_t v
, char *p
, int s
)
236 v
= format_hex_recursive(v
, p
+1, s
-1);
237 *p
= "0123456789abcdef"[v
& 0xf];
242 archive_write_newc_finish(struct archive_write
*a
)
246 struct archive_entry
*trailer
;
248 cpio
= (struct cpio
*)a
->format_data
;
249 trailer
= archive_entry_new();
250 archive_entry_set_nlink(trailer
, 1);
251 archive_entry_set_pathname(trailer
, "TRAILER!!!");
252 er
= archive_write_newc_header(a
, trailer
);
253 archive_entry_free(trailer
);
258 archive_write_newc_destroy(struct archive_write
*a
)
262 cpio
= (struct cpio
*)a
->format_data
;
264 a
->format_data
= NULL
;
269 archive_write_newc_finish_entry(struct archive_write
*a
)
274 cpio
= (struct cpio
*)a
->format_data
;
276 while (cpio
->entry_bytes_remaining
> 0) {
277 to_write
= cpio
->entry_bytes_remaining
< a
->null_length
?
278 cpio
->entry_bytes_remaining
: a
->null_length
;
279 ret
= (a
->compressor
.write
)(a
, a
->nulls
, to_write
);
280 if (ret
!= ARCHIVE_OK
)
282 cpio
->entry_bytes_remaining
-= to_write
;
284 ret
= (a
->compressor
.write
)(a
, a
->nulls
, cpio
->padding
);