3 * Handle cpio payloads within rpm packages.
5 * \warning FIXME: We don't translate between cpio and system mode bits! These
6 * should both be the same, but really odd things are going to happen if
13 #include <sys/mkdev.h>
14 #elif MAJOR_IN_SYSMACROS
15 #include <sys/sysmacros.h>
17 #include <sys/types.h> /* already included from system.h */
22 #include <rpm/rpmio.h>
23 #include <rpm/rpmlog.h>
24 #include <rpm/rpmstring.h>
38 rpmcpio_t rpmcpioOpen(FD_t fd, char mode)
40 if ((mode & O_ACCMODE) != O_RDONLY &&
41 (mode & O_ACCMODE) != O_WRONLY)
44 rpmcpio_t cpio = xcalloc(1, sizeof(*cpio));
45 cpio->fd = fdLink(fd);
51 off_t rpmcpioTell(rpmcpio_t cpio)
58 * Convert string to unsigned integer (with buffer size check).
59 * @param str input string
60 * @retval endptr address of 1st character not processed
61 * @param base numerical conversion base
62 * @param num max no. of bytes to read
63 * @return converted integer
65 static unsigned long strntoul(const char *str,char **endptr, int base, size_t num)
67 char buf[num+1], * end;
70 strncpy(buf, str, num);
73 ret = strtoul(buf, &end, base);
75 *endptr = ((char *)str) + (end - buf); /* XXX discards const */
77 *endptr = ((char *)str) + strlen(buf);
83 static int rpmcpioWritePad(rpmcpio_t cpio, ssize_t modulo)
87 memset(buf, 0, modulo);
88 left = (modulo - ((cpio->offset) % modulo)) % modulo;
91 writen = Fwrite(&buf, left, 1, cpio->fd);
93 return CPIOERR_WRITE_FAILED;
95 cpio->offset += writen;
99 static int rpmcpioReadPad(rpmcpio_t cpio)
104 left = (modulo - (cpio->offset % modulo)) % modulo;
107 read = Fread(&buf, left, 1, cpio->fd);
108 cpio->offset += read;
110 return CPIOERR_READ_FAILED;
115 #define GET_NUM_FIELD(phys, log) \
117 log = strntoul(phys, &end, 16, sizeof(phys)); \
119 if ( (end - phys) != sizeof(phys) ) return CPIOERR_BAD_HEADER;
120 #define SET_NUM_FIELD(phys, val, space) \
121 sprintf(space, "%8.8lx", (unsigned long) (val)); \
123 memcpy(phys, space, 8) \
125 static int rpmcpioTrailerWrite(rpmcpio_t cpio)
127 struct cpioCrcPhysicalHeader hdr;
131 if (cpio->fileend != cpio->offset) {
132 return CPIOERR_WRITE_FAILED;
135 rc = rpmcpioWritePad(cpio, 4);
139 memset(&hdr, '0', PHYS_HDR_SIZE);
140 memcpy(&hdr.magic, CPIO_NEWC_MAGIC, sizeof(hdr.magic));
141 memcpy(&hdr.nlink, "00000001", 8);
142 memcpy(&hdr.namesize, "0000000b", 8);
143 writen = Fwrite(&hdr, PHYS_HDR_SIZE, 1, cpio->fd);
144 cpio->offset += writen;
145 if (writen != PHYS_HDR_SIZE) {
146 return CPIOERR_WRITE_FAILED;
148 writen = Fwrite(&CPIO_TRAILER, sizeof(CPIO_TRAILER), 1, cpio->fd);
149 cpio->offset += writen;
150 if (writen != sizeof(CPIO_TRAILER)) {
151 return CPIOERR_WRITE_FAILED;
155 * XXX GNU cpio pads to 512 bytes. This may matter for
156 * tape device(s) and/or concatenated cpio archives.
159 rc = rpmcpioWritePad(cpio, 4);
164 int rpmcpioHeaderWrite(rpmcpio_t cpio, char * path, struct stat * st)
166 struct cpioCrcPhysicalHeader hdr_s;
167 struct cpioCrcPhysicalHeader * hdr = &hdr_s;
173 if ((cpio->mode & O_ACCMODE) != O_WRONLY) {
174 return CPIOERR_WRITE_FAILED;
177 if (cpio->fileend != cpio->offset) {
178 return CPIOERR_WRITE_FAILED;
181 if (st->st_size >= CPIO_FILESIZE_MAX) {
182 return CPIOERR_FILE_SIZE;
185 rc = rpmcpioWritePad(cpio, 4);
190 memcpy(hdr->magic, CPIO_NEWC_MAGIC, sizeof(hdr->magic));
191 SET_NUM_FIELD(hdr->inode, st->st_ino, field);
192 SET_NUM_FIELD(hdr->mode, st->st_mode, field);
193 SET_NUM_FIELD(hdr->uid, st->st_uid, field);
194 SET_NUM_FIELD(hdr->gid, st->st_gid, field);
195 SET_NUM_FIELD(hdr->nlink, st->st_nlink, field);
196 SET_NUM_FIELD(hdr->mtime, st->st_mtime, field);
197 SET_NUM_FIELD(hdr->filesize, st->st_size, field);
199 dev = major(st->st_dev); SET_NUM_FIELD(hdr->devMajor, dev, field);
200 dev = minor(st->st_dev); SET_NUM_FIELD(hdr->devMinor, dev, field);
201 dev = major(st->st_rdev); SET_NUM_FIELD(hdr->rdevMajor, dev, field);
202 dev = minor(st->st_rdev); SET_NUM_FIELD(hdr->rdevMinor, dev, field);
204 len = strlen(path) + 1;
205 SET_NUM_FIELD(hdr->namesize, len, field);
207 memcpy(hdr->checksum, "00000000", 8);
209 writen = Fwrite(hdr, PHYS_HDR_SIZE, 1, cpio->fd);
210 cpio->offset += writen;
211 if (writen != PHYS_HDR_SIZE) {
212 return CPIOERR_WRITE_FAILED;
215 writen = Fwrite(path, len, 1, cpio->fd);
216 cpio->offset += writen;
218 return CPIOERR_WRITE_FAILED;
221 rc = rpmcpioWritePad(cpio, 4);
223 cpio->fileend = cpio->offset + st->st_size;
228 ssize_t rpmcpioWrite(rpmcpio_t cpio, void * buf, size_t size)
232 if ((cpio->mode & O_ACCMODE) != O_WRONLY) {
233 return CPIOERR_WRITE_FAILED;
236 // Do not write beyond file length
237 left = cpio->fileend - cpio->offset;
238 size = size > left ? left : size;
239 writen = Fwrite(buf, size, 1, cpio->fd);
240 cpio->offset += writen;
245 int rpmcpioHeaderRead(rpmcpio_t cpio, char ** path, struct stat * st)
247 struct cpioCrcPhysicalHeader hdr;
250 unsigned int major, minor;
254 if ((cpio->mode & O_ACCMODE) != O_RDONLY) {
255 return CPIOERR_READ_FAILED;
258 /* Move to next file */
259 if (cpio->fileend != cpio->offset) {
260 /* XXX try using Fseek() - which is currently broken */
262 while (cpio->fileend != cpio->offset) {
263 read = cpio->fileend - cpio->offset > 8*BUFSIZ ? 8*BUFSIZ : cpio->fileend - cpio->offset;
264 if (rpmcpioRead(cpio, &buf, read) != read) {
265 return CPIOERR_READ_FAILED;
270 rc = rpmcpioReadPad(cpio);
273 read = Fread(&hdr, PHYS_HDR_SIZE, 1, cpio->fd);
274 cpio->offset += read;
275 if (read != PHYS_HDR_SIZE)
276 return CPIOERR_READ_FAILED;
278 if (strncmp(CPIO_CRC_MAGIC, hdr.magic, sizeof(CPIO_CRC_MAGIC)-1) &&
279 strncmp(CPIO_NEWC_MAGIC, hdr.magic, sizeof(CPIO_NEWC_MAGIC)-1)) {
280 return CPIOERR_BAD_MAGIC;
282 GET_NUM_FIELD(hdr.inode, st->st_ino);
283 GET_NUM_FIELD(hdr.mode, st->st_mode);
284 GET_NUM_FIELD(hdr.uid, st->st_uid);
285 GET_NUM_FIELD(hdr.gid, st->st_gid);
286 GET_NUM_FIELD(hdr.nlink, st->st_nlink);
287 GET_NUM_FIELD(hdr.mtime, st->st_mtime);
288 GET_NUM_FIELD(hdr.filesize, st->st_size);
290 GET_NUM_FIELD(hdr.devMajor, major);
291 GET_NUM_FIELD(hdr.devMinor, minor);
292 st->st_dev = makedev(major, minor);
294 GET_NUM_FIELD(hdr.rdevMajor, major);
295 GET_NUM_FIELD(hdr.rdevMinor, minor);
296 st->st_rdev = makedev(major, minor);
298 GET_NUM_FIELD(hdr.namesize, nameSize);
300 *path = xmalloc(nameSize + 1);
301 read = Fread(*path, nameSize, 1, cpio->fd);
302 (*path)[nameSize] = '\0';
303 cpio->offset += read;
304 if (read != nameSize ) {
305 return CPIOERR_BAD_HEADER;
308 rc = rpmcpioReadPad(cpio);
309 cpio->fileend = cpio->offset + st->st_size;
311 if (!rc && rstreq(*path, CPIO_TRAILER))
312 rc = CPIOERR_HDR_TRAILER;
317 ssize_t rpmcpioRead(rpmcpio_t cpio, void * buf, size_t size)
321 if ((cpio->mode & O_ACCMODE) != O_RDONLY) {
322 return CPIOERR_READ_FAILED;
325 left = cpio->fileend - cpio->offset;
326 size = size > left ? left : size;
327 read = Fread(buf, size, 1, cpio->fd);
328 cpio->offset += read;
332 int rpmcpioClose(rpmcpio_t cpio)
335 if ((cpio->mode & O_ACCMODE) == O_WRONLY) {
336 rc = rpmcpioTrailerWrite(cpio);
343 rpmcpio_t rpmcpioFree(rpmcpio_t cpio)
347 (void) rpmcpioClose(cpio);
353 const char * rpmcpioStrerror(int rc)
355 static char msg[256];
360 strcpy(msg, "cpio: ");
363 char *t = msg + strlen(msg);
364 sprintf(t, _("(error 0x%x)"), (unsigned)rc);
368 case CPIOERR_BAD_MAGIC: s = _("Bad magic"); break;
369 case CPIOERR_BAD_HEADER: s = _("Bad/unreadable header");break;
371 case CPIOERR_OPEN_FAILED: s = "open"; break;
372 case CPIOERR_CHMOD_FAILED: s = "chmod"; break;
373 case CPIOERR_CHOWN_FAILED: s = "chown"; break;
374 case CPIOERR_WRITE_FAILED: s = "write"; break;
375 case CPIOERR_UTIME_FAILED: s = "utime"; break;
376 case CPIOERR_UNLINK_FAILED: s = "unlink"; break;
377 case CPIOERR_RENAME_FAILED: s = "rename"; break;
378 case CPIOERR_SYMLINK_FAILED: s = "symlink"; break;
379 case CPIOERR_STAT_FAILED: s = "stat"; break;
380 case CPIOERR_LSTAT_FAILED: s = "lstat"; break;
381 case CPIOERR_MKDIR_FAILED: s = "mkdir"; break;
382 case CPIOERR_RMDIR_FAILED: s = "rmdir"; break;
383 case CPIOERR_MKNOD_FAILED: s = "mknod"; break;
384 case CPIOERR_MKFIFO_FAILED: s = "mkfifo"; break;
385 case CPIOERR_LINK_FAILED: s = "link"; break;
386 case CPIOERR_READLINK_FAILED: s = "readlink"; break;
387 case CPIOERR_READ_FAILED: s = "read"; break;
388 case CPIOERR_COPY_FAILED: s = "copy"; break;
389 case CPIOERR_LSETFCON_FAILED: s = "lsetfilecon"; break;
390 case CPIOERR_SETCAP_FAILED: s = "cap_set_file"; break;
392 case CPIOERR_HDR_SIZE: s = _("Header size too big"); break;
393 case CPIOERR_FILE_SIZE: s = _("File too large for archive"); break;
394 case CPIOERR_UNKNOWN_FILETYPE: s = _("Unknown file type"); break;
395 case CPIOERR_MISSING_HARDLINK: s = _("Missing hard link(s)"); break;
396 case CPIOERR_DIGEST_MISMATCH: s = _("Digest mismatch"); break;
397 case CPIOERR_INTERNAL: s = _("Internal error"); break;
398 case CPIOERR_UNMAPPED_FILE: s = _("Archive file not in header"); break;
399 case CPIOERR_ENOENT: s = strerror(ENOENT); break;
400 case CPIOERR_ENOTEMPTY: s = strerror(ENOTEMPTY); break;
403 l = sizeof(msg) - strlen(msg) - 1;
405 if (l > 0) strncat(msg, s, l);
408 if ((rc & CPIOERR_CHECK_ERRNO) && myerrno) {
410 if (l > 0) strncat(msg, s, l);
412 if (l > 0) strncat(msg, strerror(myerrno), l);