1 /** \ingroup payload rpmio
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
14 #define xfree(_p) free((void *)_p)
16 #define CPIO_NEWC_MAGIC "070701"
17 #define CPIO_CRC_MAGIC "070702"
18 #define TRAILER "TRAILER!!!"
21 * Keeps track of set of all hard linked files in archive.
24 struct hardLink * next;
25 const char ** files; /* nlink of these, used by install */
26 int * fileMaps; /* used by build */
43 * Cpio archive header information.
44 * @todo Add support for tar (soon) and ar (eventually) archive formats.
46 struct cpioCrcPhysicalHeader {
60 char checksum[8]; /* ignored !! */
63 #define PHYS_HDR_SIZE 110 /*!< Don't depend on sizeof(struct) */
66 * File name and stat information.
69 /*@owned@*/ const char * path;
74 static void prtli(const char *msg, struct hardLink * li)
76 if (msg) fprintf(stderr, "%s", msg);
77 fprintf(stderr, " next %p files %p fileMaps %p dev %x ino %x nlink %d left %d createdPath %d size %d\n", li->next, li->files, li->fileMaps, (unsigned)li->dev, (unsigned)li->inode, li->nlink, li->linksLeft, li->createdPath, li->sb.st_size);
82 static inline off_t saferead(FD_t cfd, /*@out@*/void * vbuf, size_t amount)
83 /*@modifies cfd, *vbuf @*/
91 nb = Fread(buf, sizeof(buf[0]), amount, cfd);
104 static inline off_t ourread(FD_t cfd, /*@out@*/void * buf, size_t size)
105 /*@modifies cfd, *buf @*/
107 off_t i = saferead(cfd, buf, size);
109 fdSetCpioPos(cfd, fdGetCpioPos(cfd) + i);
114 static inline void padinfd(FD_t cfd, int modulo)
120 amount = (modulo - fdGetCpioPos(cfd) % modulo) % modulo;
121 (void)ourread(cfd, buf, amount);
125 static inline off_t safewrite(FD_t cfd, const void * vbuf, size_t amount)
129 const char * buf = vbuf;
134 nb = Fwrite(buf, sizeof(buf[0]), amount, cfd);
148 static inline int padoutfd(FD_t cfd, size_t * where, int modulo)
149 /*@modifies cfd, *where @*/
151 static int buf[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
154 amount = (modulo - *where % modulo) % modulo;
157 if (safewrite(cfd, buf, amount) != amount)
158 return CPIOERR_WRITE_FAILED;
163 static int strntoul(const char *str, /*@out@*/char **endptr, int base, int num)
164 /*@modifies *endptr @*/
169 buf = alloca(num + 1);
170 strncpy(buf, str, num);
173 ret = strtoul(buf, &end, base);
175 *endptr = ((char *)str) + (end - buf); /* XXX discards const */
177 *endptr = ((char *)str) + strlen(str);
179 return strtoul(buf, endptr, base);
182 #define GET_NUM_FIELD(phys, log) \
183 log = strntoul(phys, &end, 16, sizeof(phys)); \
184 if (*end) return CPIOERR_BAD_HEADER;
185 #define SET_NUM_FIELD(phys, val, space) \
186 sprintf(space, "%8.8lx", (unsigned long) (val)); \
187 memcpy(phys, space, 8);
190 static int getNextHeader(FD_t cfd, struct cpioHeader * hdr)
191 /*@modifies cfd, hdr->path, hdr->sb @*/
193 struct cpioCrcPhysicalHeader physHeader;
194 struct stat * st = &hdr->sb;
199 if (ourread(cfd, &physHeader, PHYS_HDR_SIZE) != PHYS_HDR_SIZE)
200 return CPIOERR_READ_FAILED;
202 if (strncmp(CPIO_CRC_MAGIC, physHeader.magic, sizeof(CPIO_CRC_MAGIC)-1) &&
203 strncmp(CPIO_NEWC_MAGIC, physHeader.magic, sizeof(CPIO_NEWC_MAGIC)-1))
204 return CPIOERR_BAD_MAGIC;
206 GET_NUM_FIELD(physHeader.inode, st->st_ino);
207 GET_NUM_FIELD(physHeader.mode, st->st_mode);
208 GET_NUM_FIELD(physHeader.uid, st->st_uid);
209 GET_NUM_FIELD(physHeader.gid, st->st_gid);
210 GET_NUM_FIELD(physHeader.nlink, st->st_nlink);
211 GET_NUM_FIELD(physHeader.mtime, st->st_mtime);
212 GET_NUM_FIELD(physHeader.filesize, st->st_size);
214 GET_NUM_FIELD(physHeader.devMajor, major);
215 GET_NUM_FIELD(physHeader.devMinor, minor);
216 st->st_dev = /*@-shiftsigned@*/ makedev(major, minor) /*@=shiftsigned@*/ ;
218 GET_NUM_FIELD(physHeader.rdevMajor, major);
219 GET_NUM_FIELD(physHeader.rdevMinor, minor);
220 st->st_rdev = /*@-shiftsigned@*/ makedev(major, minor) /*@=shiftsigned@*/ ;
222 GET_NUM_FIELD(physHeader.namesize, nameSize);
224 { char * t = xmalloc(nameSize + 1);
225 if (ourread(cfd, t, nameSize) != nameSize) {
228 return CPIOERR_BAD_HEADER;
233 /* this is unecessary hdr->path[nameSize] = '\0'; */
240 int cpioFileMapCmp(const void * a, const void * b)
242 const char * afn = ((const struct cpioFileMapping *)a)->archivePath;
243 const char * bfn = ((const struct cpioFileMapping *)b)->archivePath;
245 /* Match payloads with ./ prefixes as well. */
246 if (afn[0] == '.' && afn[1] == '/') afn += 2;
247 if (bfn[0] == '.' && bfn[1] == '/') bfn += 2;
249 return strcmp(afn, bfn);
252 /* This could trash files in the path! I'm not sure that's a good thing */
254 static int createDirectory(const char * path, mode_t perms)
255 /*@modifies fileSystem @*/
259 if (!lstat(path, &sb)) {
260 int dounlink = 0; /* XXX eliminate, dounlink==1 on all paths */
261 if (S_ISDIR(sb.st_mode)) {
263 } else if (S_ISLNK(sb.st_mode)) {
264 if (stat(path, &sb)) {
266 return CPIOERR_STAT_FAILED;
269 if (S_ISDIR(sb.st_mode))
277 if (dounlink && unlink(path)) {
278 return CPIOERR_UNLINK_FAILED;
282 if (mkdir(path, 000))
283 return CPIOERR_MKDIR_FAILED;
285 if (chmod(path, perms))
286 return CPIOERR_CHMOD_FAILED;
292 static int setInfo(struct cpioHeader * hdr)
293 /*@modifies fileSystem @*/
296 struct utimbuf stamp;
297 struct stat * st = &hdr->sb;
299 stamp.actime = st->st_mtime;
300 stamp.modtime = st->st_mtime;
302 if (!S_ISLNK(st->st_mode)) {
303 if (!getuid() && chown(hdr->path, st->st_uid, st->st_gid))
304 rc = CPIOERR_CHOWN_FAILED;
305 if (!rc && chmod(hdr->path, st->st_mode & 07777))
306 rc = CPIOERR_CHMOD_FAILED;
307 if (!rc && utime(hdr->path, &stamp))
308 rc = CPIOERR_UTIME_FAILED;
310 # if ! CHOWN_FOLLOWS_SYMLINK
311 if (!getuid() && !rc && lchown(hdr->path, st->st_uid, st->st_gid))
312 rc = CPIOERR_CHOWN_FAILED;
320 static int inline checkDirectory(const char * filename) /*@*/
322 /*@only@*/ static char * lastDir = NULL; /* XXX memory leak */
323 static int lastDirLength = 0;
324 static int lastDirAlloced = 0;
325 int length = strlen(filename);
330 buf = alloca(length + 1);
331 strcpy(buf, filename);
333 for (chptr = buf + length - 1; chptr > buf; chptr--) {
334 if (*chptr == '/') break;
337 if (chptr == buf) return 0; /* /filename - no directories */
339 *chptr = '\0'; /* buffer is now just directories */
341 length = strlen(buf);
342 if (lastDirLength == length && !strcmp(buf, lastDir)) return 0;
344 if (lastDirAlloced < (length + 1)) {
345 lastDirAlloced = length + 100;
346 lastDir = xrealloc(lastDir, lastDirAlloced); /* XXX memory leak */
349 strcpy(lastDir, buf);
350 lastDirLength = length;
352 for (chptr = buf + 1; *chptr; chptr++) {
355 rc = createDirectory(buf, 0755);
360 rc = createDirectory(buf, 0755);
366 static int expandRegular(FD_t cfd, const struct cpioHeader * hdr,
367 cpioCallback cb, void * cbData)
368 /*@modifies fileSystem, cfd @*/
373 const struct stat * st = &hdr->sb;
374 int left = st->st_size;
376 struct cpioCallbackInfo cbInfo = { NULL, 0, 0, 0 };
379 /* Rename the old file before attempting unlink to avoid EBUSY errors */
380 if (!lstat(hdr->path, &sb)) {
381 strcpy(buf, hdr->path);
382 strcat(buf, "-RPMDELETE");
383 if (rename(hdr->path, buf)) {
384 fprintf(stderr, _("can't rename %s to %s: %s\n"),
385 hdr->path, buf, strerror(errno));
386 return CPIOERR_UNLINK_FAILED;
390 fprintf(stderr, _("can't unlink %s: %s\n"),
391 buf, strerror(errno));
393 return CPIOERR_UNLINK_FAILED;
398 ofd = Fopen(hdr->path, "w.ufdio");
399 if (ofd == NULL || Ferror(ofd))
400 return CPIOERR_OPEN_FAILED;
402 cbInfo.file = hdr->path;
403 cbInfo.fileSize = st->st_size;
406 bytesRead = ourread(cfd, buf, left < sizeof(buf) ? left : sizeof(buf));
407 if (bytesRead <= 0) {
408 rc = CPIOERR_READ_FAILED;
412 if (Fwrite(buf, sizeof(buf[0]), bytesRead, ofd) != bytesRead) {
413 rc = CPIOERR_COPY_FAILED;
419 /* don't call this with fileSize == fileComplete */
420 if (!rc && cb && left) {
421 cbInfo.fileComplete = st->st_size - left;
422 cbInfo.bytesProcessed = fdGetCpioPos(cfd);
433 static int expandSymlink(FD_t cfd, const struct cpioHeader * hdr)
434 /*@modifies fileSystem, cfd @*/
436 char buf[2048], buf2[2048];
438 const struct stat * st = &hdr->sb;
441 if ((st->st_size + 1)> sizeof(buf))
442 return CPIOERR_HDR_SIZE;
444 if (ourread(cfd, buf, st->st_size) != st->st_size)
445 return CPIOERR_READ_FAILED;
447 buf[st->st_size] = '\0';
449 if (!lstat(hdr->path, &sb)) {
450 if (S_ISLNK(sb.st_mode)) {
451 len = readlink(hdr->path, buf2, sizeof(buf2) - 1);
454 if (!strcmp(buf, buf2)) return 0;
458 if (unlink(hdr->path))
459 return CPIOERR_UNLINK_FAILED;
462 if (symlink(buf, hdr->path) < 0)
463 return CPIOERR_SYMLINK_FAILED;
469 static int expandFifo( /*@unused@*/ FD_t cfd, const struct cpioHeader * hdr)
470 /*@modifies fileSystem @*/
474 if (!lstat(hdr->path, &sb)) {
475 if (S_ISFIFO(sb.st_mode)) return 0;
477 if (unlink(hdr->path))
478 return CPIOERR_UNLINK_FAILED;
481 if (mkfifo(hdr->path, 0))
482 return CPIOERR_MKFIFO_FAILED;
488 static int expandDevice( /*@unused@*/ FD_t cfd, const struct cpioHeader * hdr)
489 /*@modifies fileSystem @*/
491 const struct stat * st = &hdr->sb;
494 if (!lstat(hdr->path, &sb)) {
495 if ((S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode)) &&
496 (sb.st_rdev == st->st_rdev))
498 if (unlink(hdr->path))
499 return CPIOERR_UNLINK_FAILED;
502 if ( /*@-unrecog@*/ mknod(hdr->path, st->st_mode & (~0777), st->st_rdev) /*@=unrecog@*/ )
503 return CPIOERR_MKNOD_FAILED;
509 static /*@only@*/ struct hardLink * newHardLink(const struct stat * st,
510 enum hardLinkType hltype) /*@*/
512 struct hardLink * li = xmalloc(sizeof(*li));
515 li->nlink = st->st_nlink;
516 li->dev = st->st_dev;
517 li->inode = st->st_ino;
518 li->createdPath = -1;
521 case HARDLINK_INSTALL:
522 li->linksLeft = st->st_nlink;
523 li->fileMaps = xmalloc(sizeof(li->fileMaps[0]) * st->st_nlink);
529 li->files = xcalloc(st->st_nlink, sizeof(*li->files));
533 { struct stat * myst = (struct stat *) &li->sb;
534 *myst = *st; /* structure assignment */
541 static void freeHardLink( /*@only@*/ struct hardLink * li)
546 for (i = 0; i < li->nlink; i++) {
547 if (li->files[i] == NULL) continue;
548 /*@-unqualifiedtrans@*/ free((void *)li->files[i]) /*@=unqualifiedtrans@*/ ;
562 static int createLinks(struct hardLink * li, /*@out@*/ const char ** failedFile)
563 /*@modifies fileSystem, *failedFile, li->files, li->linksLeft @*/
568 for (i = 0; i < li->nlink; i++) {
569 if (i == li->createdPath) continue;
570 if (li->files[i] == NULL) continue;
572 if (!lstat(li->files[i], &sb)) {
573 if (unlink(li->files[i])) {
575 *failedFile = xstrdup(li->files[i]);
576 return CPIOERR_UNLINK_FAILED;
580 if (link(li->files[li->createdPath], li->files[i])) {
582 *failedFile = xstrdup(li->files[i]);
583 return CPIOERR_LINK_FAILED;
586 /*@-unqualifiedtrans@*/ free((void *)li->files[i]) /*@=unqualifiedtrans@*/ ;
595 static int eatBytes(FD_t cfd, int amount)
602 bite = (amount > sizeof(buf)) ? sizeof(buf) : amount;
603 if (ourread(cfd, buf, bite) != bite)
604 return CPIOERR_READ_FAILED;
611 int cpioInstallArchive(FD_t cfd, const struct cpioFileMapping * mappings,
612 int numMappings, cpioCallback cb, void * cbData,
613 const char ** failedFile)
615 struct cpioHeader ch, *hdr = &ch;
616 struct cpioFileMapping * map = NULL;
617 struct cpioFileMapping needle;
618 struct cpioCallbackInfo cbInfo = { NULL, 0, 0, 0 };
619 struct hardLink * links = NULL;
620 struct hardLink * li = NULL;
623 fdSetCpioPos(cfd, 0);
627 memset(hdr, 0, sizeof(*hdr));
636 if ((rc = getNextHeader(cfd, hdr))) {
637 #if 0 /* XXX this is the failure point for an unreadable rpm */
638 fprintf(stderr, _("getNextHeader: %s\n"), cpioStrerror(rc));
644 if (!strcmp(hdr->path, TRAILER))
648 needle.archivePath = hdr->path;
649 map = bsearch(&needle, mappings, numMappings, sizeof(needle),
653 if (mappings && !map) {
654 eatBytes(cfd, st->st_size);
657 if (map->mapFlags & CPIO_MAP_PATH) {
658 if (hdr->path) xfree(hdr->path);
659 hdr->path = xstrdup(map->fsPath);
662 if (map->mapFlags & CPIO_MAP_MODE)
663 st->st_mode = map->finalMode;
664 if (map->mapFlags & CPIO_MAP_UID)
665 st->st_uid = map->finalUid;
666 if (map->mapFlags & CPIO_MAP_GID)
667 st->st_gid = map->finalGid;
670 /* This won't get hard linked symlinks right, but I can't seem
671 to create those anyway */
673 if (S_ISREG(st->st_mode) && st->st_nlink > 1) {
674 for (li = links; li; li = li->next) {
675 if (li->inode == st->st_ino && li->dev == st->st_dev) break;
679 li = newHardLink(st, HARDLINK_BUILD);
684 li->files[li->linksLeft++] = xstrdup(hdr->path);
687 if ((st->st_nlink > 1) && S_ISREG(st->st_mode) && !st->st_size &&
688 li->createdPath == -1) {
689 /* defer file creation */
690 } else if ((st->st_nlink > 1) && S_ISREG(st->st_mode) &&
691 (li->createdPath != -1)) {
692 createLinks(li, failedFile);
694 /* this only happens for cpio archives which contain
695 hardlinks w/ the contents of each hardlink being
696 listed (intead of the data being given just once. This
697 shouldn't happen, but I've made it happen w/ buggy
698 code, so what the heck? GNU cpio handles this well fwiw */
699 if (st->st_size) eatBytes(cfd, st->st_size);
701 rc = checkDirectory(hdr->path);
704 if (S_ISREG(st->st_mode))
705 rc = expandRegular(cfd, hdr, cb, cbData);
706 else if (S_ISDIR(st->st_mode))
707 rc = createDirectory(hdr->path, 000);
708 else if (S_ISLNK(st->st_mode))
709 rc = expandSymlink(cfd, hdr);
710 else if (S_ISFIFO(st->st_mode))
711 rc = expandFifo(cfd, hdr);
712 else if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
713 rc = expandDevice(cfd, hdr);
714 else if (S_ISSOCK(st->st_mode)) {
715 /* this mimicks cpio but probably isnt' right */
716 rc = expandFifo(cfd, hdr);
718 rc = CPIOERR_UNKNOWN_FILETYPE;
725 if (S_ISREG(st->st_mode) && st->st_nlink > 1) {
726 li->createdPath = --li->linksLeft;
727 rc = createLinks(li, failedFile);
731 if (rc && failedFile && *failedFile == NULL) {
734 *failedFile = xstrdup(hdr->path);
744 cbInfo.file = hdr->path;
745 cbInfo.fileSize = st->st_size;
746 cbInfo.fileComplete = st->st_size;
747 cbInfo.bytesProcessed = fdGetCpioPos(cfd);
758 /* Create any remaining links (if no error), and clean up. */
759 while ((li = links) != NULL) {
763 if (rc == 0 && li->linksLeft) {
764 if (li->createdPath == -1)
765 rc = CPIOERR_MISSING_HARDLINK;
767 rc = createLinks(li, failedFile);
777 static int writeFile(FD_t cfd, const struct stat * st,
778 const struct cpioFileMapping * map, /*@out@*/ size_t * sizep,
780 /*@modifies cfd, *sizep @*/
782 struct cpioCrcPhysicalHeader hdr;
783 char buf[8192], symbuf[2048];
786 size_t st_size = st->st_size; /* XXX hard links need size preserved */
787 const char * archivePath;
788 mode_t st_mode = st->st_mode;
789 uid_t st_uid = st->st_uid;
790 gid_t st_gid = st->st_gid;
791 size_t size, amount = 0;
794 archivePath = (!(map->mapFlags & CPIO_MAP_PATH))
795 ? map->fsPath : map->archivePath;
797 if (map->mapFlags & CPIO_MAP_MODE)
798 st_mode = (st_mode & S_IFMT) | map->finalMode;
799 if (map->mapFlags & CPIO_MAP_UID)
800 st_uid = map->finalUid;
801 if (map->mapFlags & CPIO_MAP_GID)
802 st_gid = map->finalGid;
804 if (!writeData || S_ISDIR(st_mode)) {
806 } else if (S_ISLNK(st_mode)) {
807 /* While linux puts the size of a symlink in the st_size field,
808 I don't think that's a specified standard */
810 amount = Readlink(map->fsPath, symbuf, sizeof(symbuf));
812 return CPIOERR_READLINK_FAILED;
818 memcpy(hdr.magic, CPIO_NEWC_MAGIC, sizeof(hdr.magic));
819 SET_NUM_FIELD(hdr.inode, st->st_ino, buf);
820 SET_NUM_FIELD(hdr.mode, st_mode, buf);
821 SET_NUM_FIELD(hdr.uid, st_uid, buf);
822 SET_NUM_FIELD(hdr.gid, st_gid, buf);
823 SET_NUM_FIELD(hdr.nlink, st->st_nlink, buf);
824 SET_NUM_FIELD(hdr.mtime, st->st_mtime, buf);
825 SET_NUM_FIELD(hdr.filesize, st_size, buf);
827 num = major((unsigned)st->st_dev); SET_NUM_FIELD(hdr.devMajor, num, buf);
828 num = minor((unsigned)st->st_dev); SET_NUM_FIELD(hdr.devMinor, num, buf);
829 num = major((unsigned)st->st_rdev); SET_NUM_FIELD(hdr.rdevMajor, num, buf);
830 num = minor((unsigned)st->st_rdev); SET_NUM_FIELD(hdr.rdevMinor, num, buf);
832 num = strlen(archivePath) + 1; SET_NUM_FIELD(hdr.namesize, num, buf);
833 memcpy(hdr.checksum, "00000000", 8);
835 if ((rc = safewrite(cfd, &hdr, PHYS_HDR_SIZE)) != PHYS_HDR_SIZE)
837 if ((rc = safewrite(cfd, archivePath, num)) != num)
839 size = PHYS_HDR_SIZE + num;
840 if ((rc = padoutfd(cfd, &size, 4)))
843 if (writeData && S_ISREG(st_mode)) {
850 /* XXX unbuffered mmap generates *lots* of fdio debugging */
851 datafd = Fopen(map->fsPath, "r.ufdio");
852 if (datafd == NULL || Ferror(datafd))
853 return CPIOERR_OPEN_FAILED;
857 mapped = mmap(NULL, st_size, PROT_READ, MAP_SHARED, Fileno(datafd), 0);
858 if (mapped != (void *)-1) {
871 if (mapped != (void *)-1) {
876 amount = Fread(b, sizeof(buf[0]),
877 (st_size > sizeof(buf) ? sizeof(buf) : st_size),
880 int olderrno = errno;
883 return CPIOERR_READ_FAILED;
887 if ((rc = safewrite(cfd, b, amount)) != amount) {
888 int olderrno = errno;
898 if (mapped != (void *)-1) {
899 /*@-noeffect@*/ munmap(mapped, nmapped) /*@=noeffect@*/;
904 } else if (writeData && S_ISLNK(st_mode)) {
905 if ((rc = safewrite(cfd, symbuf, amount)) != amount)
910 /* this is a noop for most file types */
911 if ((rc = padoutfd(cfd, &size, 4)))
921 static int writeLinkedFile(FD_t cfd, const struct hardLink * hlink,
922 const struct cpioFileMapping * mappings,
923 cpioCallback cb, void * cbData,
924 /*@out@*/size_t * sizep,
925 /*@out@*/const char ** failedFile)
926 /*@modifies cfd, *sizep, *failedFile @*/
930 struct cpioCallbackInfo cbInfo = { NULL, 0, 0, 0 };
934 for (i = hlink->nlink - 1; i > hlink->linksLeft; i--) {
935 if ((rc = writeFile(cfd, &hlink->sb, mappings + hlink->fileMaps[i],
938 *failedFile = xstrdup(mappings[hlink->fileMaps[i]].fsPath);
945 cbInfo.file = mappings[i].archivePath;
950 if ((rc = writeFile(cfd, &hlink->sb,
951 mappings + hlink->fileMaps[hlink->linksLeft],
956 *failedFile = xstrdup(mappings[hlink->fileMaps[hlink->linksLeft]].fsPath);
965 cbInfo.file = mappings[i].archivePath;
972 int cpioBuildArchive(FD_t cfd, const struct cpioFileMapping * mappings,
973 int numMappings, cpioCallback cb, void * cbData,
974 unsigned int * archiveSize, const char ** failedFile)
976 size_t size, totalsize = 0;
979 struct cpioCallbackInfo cbInfo = { NULL, 0, 0, 0 };
980 struct cpioCrcPhysicalHeader hdr;
982 struct hardLink hlinkList = { NULL };
984 struct stat * st = (struct stat *) &hlinkList.sb;
985 struct hardLink * hlink;
987 hlinkList.next = NULL;
989 for (i = 0; i < numMappings; i++) {
990 const struct cpioFileMapping * map;
994 if (map->mapFlags & CPIO_FOLLOW_SYMLINKS)
995 rc = Stat(map->fsPath, st);
997 rc = Lstat(map->fsPath, st);
1001 *failedFile = xstrdup(map->fsPath);
1002 return CPIOERR_STAT_FAILED;
1005 if (!S_ISDIR(st->st_mode) && st->st_nlink > 1) {
1006 hlink = hlinkList.next;
1008 (hlink->dev != st->st_dev || hlink->inode != st->st_ino))
1009 hlink = hlink->next;
1010 if (hlink == NULL) {
1011 hlink = newHardLink(st, HARDLINK_INSTALL);
1012 hlink->next = hlinkList.next;
1013 hlinkList.next = hlink;
1016 hlink->fileMaps[--hlink->linksLeft] = i;
1018 if (hlink->linksLeft == 0) {
1019 struct hardLink * prev;
1020 if ((rc = writeLinkedFile(cfd, hlink, mappings, cb, cbData,
1021 &size, failedFile)))
1028 if (prev->next != hlink)
1030 prev->next = hlink->next;
1032 freeHardLink(hlink);
1035 } while ((prev = prev->next) != NULL);
1038 if ((rc = writeFile(cfd, st, map, &size, 1))) {
1040 *failedFile = xstrdup(mappings[i].fsPath);
1045 cbInfo.file = map->archivePath;
1046 cb(&cbInfo, cbData);
1054 while ((hlink = hlinkList.next) != NULL) {
1055 hlinkList.next = hlink->next;
1059 rc = writeLinkedFile(cfd, hlink, mappings, cb, cbData,
1063 freeHardLink(hlink);
1068 memset(&hdr, '0', PHYS_HDR_SIZE);
1069 memcpy(hdr.magic, CPIO_NEWC_MAGIC, sizeof(hdr.magic));
1070 memcpy(hdr.nlink, "00000001", 8);
1071 memcpy(hdr.namesize, "0000000b", 8);
1072 if ((rc = safewrite(cfd, &hdr, PHYS_HDR_SIZE)) != PHYS_HDR_SIZE)
1074 if ((rc = safewrite(cfd, "TRAILER!!!", 11)) != 11)
1076 totalsize += PHYS_HDR_SIZE + 11;
1078 /* GNU cpio pads to 512 bytes here, but we don't. I'm not sure if
1079 it matters or not */
1081 if ((rc = padoutfd(cfd, &totalsize, 4)))
1084 if (archiveSize) *archiveSize = totalsize;
1089 const char * cpioStrerror(int rc)
1091 static char msg[256];
1093 int l, myerrno = errno;
1095 strcpy(msg, "cpio: ");
1098 s = msg + strlen(msg);
1099 sprintf(s, _("(error 0x%x)"), (unsigned)rc);
1102 case CPIOERR_BAD_MAGIC: s = _("Bad magic"); break;
1103 case CPIOERR_BAD_HEADER: s = _("Bad/unreadable header");break;
1105 case CPIOERR_OPEN_FAILED: s = "open"; break;
1106 case CPIOERR_CHMOD_FAILED: s = "chmod"; break;
1107 case CPIOERR_CHOWN_FAILED: s = "chown"; break;
1108 case CPIOERR_WRITE_FAILED: s = "write"; break;
1109 case CPIOERR_UTIME_FAILED: s = "utime"; break;
1110 case CPIOERR_UNLINK_FAILED: s = "unlink"; break;
1111 case CPIOERR_SYMLINK_FAILED: s = "symlink"; break;
1112 case CPIOERR_STAT_FAILED: s = "stat"; break;
1113 case CPIOERR_MKDIR_FAILED: s = "mkdir"; break;
1114 case CPIOERR_MKNOD_FAILED: s = "mknod"; break;
1115 case CPIOERR_MKFIFO_FAILED: s = "mkfifo"; break;
1116 case CPIOERR_LINK_FAILED: s = "link"; break;
1117 case CPIOERR_READLINK_FAILED: s = "readlink"; break;
1118 case CPIOERR_READ_FAILED: s = "read"; break;
1119 case CPIOERR_COPY_FAILED: s = "copy"; break;
1121 case CPIOERR_HDR_SIZE: s = _("Header size too big"); break;
1122 case CPIOERR_UNKNOWN_FILETYPE: s = _("Unknown file type"); break;
1123 case CPIOERR_MISSING_HARDLINK: s = _("Missing hard link"); break;
1124 case CPIOERR_INTERNAL: s = _("Internal error"); break;
1127 l = sizeof(msg) - strlen(msg) - 1;
1129 if (l > 0) strncat(msg, s, l);
1132 if ((rc & CPIOERR_CHECK_ERRNO) && myerrno) {
1133 s = _(" failed - ");
1134 if (l > 0) strncat(msg, s, l);
1136 if (l > 0) strncat(msg, strerror(myerrno), l);