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
18 /*@access rpmTransactionSet@*/
22 #define CPIO_NEWC_MAGIC "070701"
23 #define CPIO_CRC_MAGIC "070702"
24 #define TRAILER "TRAILER!!!"
26 #define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s))
28 static /*@null@*/ void * _free(/*@only@*/ /*@null@*/ const void * this) {
29 if (this) free((void *)this);
36 * Keeps track of the set of all hard links to a file in an archive.
39 /*@dependent@*/ struct hardLink * next;
40 /*@owned@*/ const char ** files; /* nlink of these, used by install */
41 /*@owned@*/ const char ** nsuffix;
42 /*@owned@*/ const void ** fileMaps;
43 /*@owned@*/ int * filex;
61 * Defines a single file to be included in a cpio payload.
63 struct cpioFileMapping {
64 /*@dependent@*/ const char * archivePath; /*!< Path to store in cpio archive. */
65 /*@dependent@*/ const char * dirName; /*!< Payload file directory. */
66 /*@dependent@*/ const char * baseName; /*!< Payload file base name. */
67 /*@dependent@*/ const char * md5sum; /*!< File MD5 sum (NULL disables). */
70 mode_t finalMode; /*!< Mode of payload file (from header). */
71 uid_t finalUid; /*!< Uid of payload file (from header). */
72 gid_t finalGid; /*!< Gid of payload file (from header). */
73 cpioMapFlags mapFlags;
79 /*@dependent@*/ rpmTransactionSet ts;
80 /*@dependent@*/ TFI_t fi;
83 struct cpioFileMapping map;
87 * File name and stat information.
90 /*@owned@*/ const char * path;
91 /*@owned@*/ const char * opath;
94 /*@owned@*/ char * rdbuf;
95 /*@dependent@*/ char * rdb;
100 /*@owned@*/ char * wrbuf;
101 /*@dependent@*/ char * wrb;
105 /*@owned@*/ void * mapi;
106 /*@dependent@*/ const void * map;
107 /*@owned@*/ struct hardLink * links;
108 /*@dependent@*/ struct hardLink * li;
109 unsigned int * archiveSize;
110 /*@dependent@*/ const char ** failedFile;
111 /*@owned@*/ short * dnlx;
112 /*@shared@*/ const char * subdir;
113 char subbuf[64]; /* XXX eliminate */
114 /*@shared@*/ const char * osuffix;
115 /*@shared@*/ const char * nsuffix;
116 /*@shared@*/ const char * suffix;
117 char sufbuf[64]; /* XXX eliminate */
118 /*@only@*/ char * ldn;
134 rpmTransactionSet fsmGetTs(FSM_t fsm) {
135 struct mapi * mapi = fsm->mapi;
136 return (mapi ? mapi->ts : NULL);
139 TFI_t fsmGetFi(FSM_t fsm) {
140 struct mapi * mapi = fsm->mapi;
141 return (mapi ? mapi->fi : NULL);
144 static int fsmSetIndex(FSM_t fsm, int isave) {
145 struct mapi * mapi = fsm->mapi;
154 int fsmGetIndex(FSM_t fsm) {
155 struct mapi * mapi = fsm->mapi;
156 return (mapi ? mapi->isave : -1);
161 static int fsmFlags(FSM_t fsm, cpioMapFlags mask) {
162 struct mapi * mapi = (struct mapi *) fsm->mapi;
165 const struct cpioFileMapping * map = fsm->map;
166 rc = (map->mapFlags & mask);
173 static int mapCommit(/*@null@*/ const void * this) {
174 const struct cpioFileMapping * map = this;
175 return (map ? map->commit : 0);
178 #define SUFFIX_RPMORIG ".rpmorig"
179 #define SUFFIX_RPMSAVE ".rpmsave"
180 #define SUFFIX_RPMNEW ".rpmnew"
184 static /*@only@*/ const char * mapArchivePath(/*@null@*/ const void * this) {
185 const struct cpioFileMapping * map = this;
186 return (map ? xstrdup(map->archivePath) : NULL);
191 static /*@only@*//*@null@*/ const char * mapFsPath(/*@null@*/ const void * this,
192 /*@null@*/ const struct stat * st,
193 /*@null@*/ const char * subdir,
194 /*@null@*/ const char * suffix)
196 const struct cpioFileMapping * map = this;
197 const char * s = NULL;
202 nb = strlen(map->dirName) +
203 (st && subdir && !S_ISDIR(st->st_mode) ? strlen(subdir) : 0) +
204 (st && suffix && !S_ISDIR(st->st_mode) ? strlen(suffix) : 0) +
205 strlen(map->baseName) + 1;
207 t = stpcpy(t, map->dirName);
208 if (st && subdir && !S_ISDIR(st->st_mode))
209 t = stpcpy(t, subdir);
210 t = stpcpy(t, map->baseName);
211 if (st && suffix && !S_ISDIR(st->st_mode))
212 t = stpcpy(t, suffix);
219 static mode_t mapFinalMode(/*@null@*/ const void * this) {
220 const struct cpioFileMapping * map = this;
221 return (map ? map->finalMode : 0);
226 static uid_t mapFinalUid(/*@null@*/ const void * this) {
227 const struct cpioFileMapping * map = this;
228 return (map ? map->finalUid : 0);
233 static gid_t mapFinalGid(/*@null@*/ const void * this) {
234 const struct cpioFileMapping * map = this;
235 return (map ? map->finalGid : 0);
240 static /*@observer@*/ const char * const mapMd5sum(/*@null@*/ const void * this)
242 const struct cpioFileMapping * map = this;
243 return (map ? map->md5sum : NULL);
248 static /*@only@*/ /*@null@*/ void * mapLink(const void * this) {
249 const struct cpioFileMapping * omap = this;
250 struct cpioFileMapping * nmap = NULL;
252 nmap = xcalloc(1, sizeof(*nmap));
253 *nmap = *omap; /* structure assignment */
260 static inline /*@null@*/ void * mapFree(/*@only@*//*@null@*/ const void * this) {
261 return _free((void *)this);
266 static /*@null@*/ void * mapFreeIterator(/*@only@*//*@null@*/const void * this) {
267 return _free((void *)this);
273 mapInitIterator(/*@kept@*/ const void * this, /*@kept@*/ const void * that)
276 rpmTransactionSet ts = (void *)this;
277 TFI_t fi = (void *)that;
281 mapi = xcalloc(1, sizeof(*mapi));
284 mapi->isave = mapi->i = 0;
286 if (ts && ts->notify) {
287 (void)ts->notify(fi->h, RPMCALLBACK_INST_START, 0, fi->archiveSize,
288 (fi->ap ? fi->ap->key : NULL), ts->notifyData);
296 static const void * mapNextIterator(void * this) {
297 struct mapi * mapi = this;
298 rpmTransactionSet ts = mapi->ts;
300 struct cpioFileMapping * map = &mapi->map;
304 if (!((i = mapi->i) < fi->fc))
307 } while (fi->actions && XFA_SKIPPING(fi->actions[i]));
311 /* src rpms have simple base name in payload. */
312 map->archivePath = (fi->apath ? fi->apath[i] + fi->striplen : fi->bnl[i]);
313 map->dirName = fi->dnl[fi->dil[i]];
314 map->baseName = fi->bnl[i];
315 map->md5sum = (fi->fmd5s ? fi->fmd5s[i] : NULL);
316 map->action = (fi->actions ? fi->actions[i] : FA_UNKNOWN);
318 #define _tsmask (RPMTRANS_FLAG_PKGCOMMIT | RPMTRANS_FLAG_COMMIT)
319 map->commit = (ts->transFlags & _tsmask) ? 0 : 1;
322 map->finalMode = fi->fmodes[i];
323 map->finalUid = (fi->fuids ? fi->fuids[i] : fi->uid); /* XXX chmod u-s */
324 map->finalGid = (fi->fgids ? fi->fgids[i] : fi->gid); /* XXX chmod g-s */
325 map->mapFlags = (fi->fmapflags ? fi->fmapflags[i] : fi->mapflags);
329 int pkgAction(const rpmTransactionSet ts, TFI_t fi, int i, fileStage a)
331 int nb = (!ts->chrootDone ? strlen(ts->rootDir) : 0);
332 char * opath = alloca(nb + fi->dnlmax + fi->bnlmax + 64);
333 char * o = (!ts->chrootDone ? stpcpy(opath, ts->rootDir) : opath);
334 char * npath = alloca(nb + fi->dnlmax + fi->bnlmax + 64);
335 char * n = (!ts->chrootDone ? stpcpy(npath, ts->rootDir) : npath);
339 switch (fi->actions[i]) {
343 if (fi->type == TR_REMOVED)
347 case FA_SKIPMULTILIB:
350 case FA_SKIPNETSHARED:
355 /*@notreached@*/ break;
358 rpmMessage(RPMMESS_DEBUG, _(" file: %s%s action: %s\n"),
359 fi->dnl[fi->dil[i]], fi->bnl[i],
360 fileActionString((fi->actions ? fi->actions[i] : FA_UNKNOWN)) );
362 switch (fi->actions[i]) {
364 case FA_SKIPMULTILIB:
368 case FA_SKIPNETSHARED:
372 /*@notreached@*/ break;
375 ext = (fi->type == TR_ADDED ? SUFFIX_RPMORIG : SUFFIX_RPMSAVE);
379 assert(fi->type == TR_REMOVED);
380 /* Append file name to (possible) root dir. */
381 (void) stpcpy( stpcpy(o, fi->dnl[fi->dil[i]]), fi->bnl[i]);
382 if (S_ISDIR(fi->fmodes[i])) {
386 case ENOENT: /* XXX rmdir("/") linux 2.2.x kernel hack */
389 if (fi->fflags[i] & RPMFILE_MISSINGOK)
392 rpmError(RPMERR_RMDIR,
393 _("%s: cannot remove %s - directory not empty\n"),
394 fiTypeString(fi), o);
397 rpmError(RPMERR_RMDIR,
398 _("%s rmdir of %s failed: %s\n"),
399 fiTypeString(fi), o, strerror(errno));
403 /*@notreached@*/ break;
407 if (errno == ENOENT && (fi->fflags[i] & RPMFILE_MISSINGOK))
409 rpmError(RPMERR_UNLINK, _("%s removal of %s failed: %s\n"),
410 fiTypeString(fi), o, strerror(errno));
414 if (ext == NULL) return 0;
416 /* Append file name to (possible) root dir. */
417 (void) stpcpy( stpcpy(o, fi->dnl[fi->dil[i]]), fi->bnl[i]);
419 /* XXX TR_REMOVED dinna do this. */
420 rc = access(opath, F_OK);
421 if (rc != 0) return 0;
423 (void) stpcpy( stpcpy(n, o), ext);
424 rpmMessage(RPMMESS_WARNING, _("%s: %s saved as %s\n"),
425 fiTypeString(fi), o, n);
427 rc = rename(opath, npath);
430 rpmError(RPMERR_RENAME, _("%s rename of %s to %s failed: %s\n"),
431 fiTypeString(fi), o, n, strerror(errno));
437 /*@dependent@*/ TFI_t fi;
438 /*@only@*/ /*@null@*/ char * active;
446 static /*@null@*/ void * dnlFreeIterator(/*@only@*/ /*@null@*/ const void * this)
449 struct dnli * dnli = (void *)this;
450 if (dnli->active) free(dnli->active);
455 static int dnlCount(void * this)
457 struct dnli * dnli = this;
458 return (dnli ? dnli->fi->dc : 0);
461 static int dnlIndex(void * this)
463 struct dnli * dnli = this;
464 return (dnli ? dnli->isave : -1);
469 static /*@only@*/ void * dnlInitIterator(/*@null@*/ const void * this,
472 const struct mapi * mapi = this;
480 dnli = xcalloc(1, sizeof(*dnli));
482 dnli->reverse = reverse;
483 dnli->i = (reverse ? fi->dc : 0);
486 dnli->active = xcalloc(fi->dc, sizeof(*dnli->active));
488 /* Identify parent directories not skipped. */
489 for (i = 0; i < fi->fc; i++)
490 if (!XFA_SKIPPING(fi->actions[i])) dnli->active[fi->dil[i]] = 1;
492 /* Exclude parent directories that are explicitly included. */
493 for (i = 0; i < fi->fc; i++) {
494 int dil, dnlen, bnlen;
495 if (!S_ISDIR(fi->fmodes[i]))
498 dnlen = strlen(fi->dnl[dil]);
499 bnlen = strlen(fi->bnl[i]);
500 for (j = 0; j < fi->dc; j++) {
503 if (!dnli->active[j] || j == dil) continue;
506 if (jlen != (dnlen+bnlen+1)) continue;
507 if (strncmp(dnl, fi->dnl[dil], dnlen)) continue;
508 if (strncmp(dnl+dnlen, fi->bnl[i], bnlen)) continue;
509 if (dnl[dnlen+bnlen] != '/' || dnl[dnlen+bnlen+1] != '\0')
515 /* Print only once per package. */
518 for (i = 0; i < fi->dc; i++) {
519 if (!dnli->active[i]) continue;
522 rpmMessage(RPMMESS_DEBUG,
523 _("========= Directories not explictly included in package:\n"));
525 rpmMessage(RPMMESS_DEBUG, _("%9d %s\n"), i, fi->dnl[i]);
528 rpmMessage(RPMMESS_DEBUG, "=========\n");
536 static const char * dnlNextIterator(void * this) {
537 struct dnli * dnli = this;
542 i = (!dnli->reverse ? dnli->i++ : --dnli->i);
543 } while (i >= 0 && i < dnli->fi->dc && !dnli->active[i]);
545 return (i >= 0 && i < dnli->fi->dc ? fi->dnl[i] : NULL);
550 static int cpioStrCmp(const void * a, const void * b) {
551 const char * afn = *(const char **)a;
552 const char * bfn = *(const char **)b;
554 /* Match rpm-4.0 payloads with ./ prefixes. */
555 if (afn[0] == '.' && afn[1] == '/') afn += 2;
556 if (bfn[0] == '.' && bfn[1] == '/') bfn += 2;
558 /* If either path is absolute, make it relative. */
559 if (afn[0] == '/') afn += 1;
560 if (bfn[0] == '/') bfn += 1;
562 return strcmp(afn, bfn);
567 static const void * mapFind(void * this, const char * fsmPath) {
568 struct mapi * mapi = this;
569 const TFI_t fi = mapi->fi;
572 p = bsearch(&fsmPath, fi->apath, fi->fc, sizeof(fsmPath), cpioStrCmp);
574 fprintf(stderr, "*** not mapped %s\n", fsmPath);
577 mapi->i = p - fi->apath;
578 return mapNextIterator(this);
582 * Create and initialize set of hard links.
583 * @param st link stat info
584 * @param hltype type of hard link set to create
585 * @return pointer to set of hard links
587 static /*@only@*/ struct hardLink * newHardLink(const struct stat * st,
588 enum hardLinkType hltype) /*@*/
590 struct hardLink * li = xcalloc(1, sizeof(*li));
593 li->nlink = st->st_nlink;
594 li->dev = st->st_dev;
595 li->inode = st->st_ino;
597 li->createdPath = -1;
599 li->filex = xcalloc(st->st_nlink, sizeof(li->filex[0]));
600 memset(li->filex, -1, (st->st_nlink * sizeof(li->filex[0])));
603 li->linksLeft = st->st_nlink;
604 li->fileMaps = xcalloc(st->st_nlink, sizeof(li->fileMaps[0]));
608 case HARDLINK_INSTALL:
611 li->nsuffix = xcalloc(st->st_nlink, sizeof(li->nsuffix[0]));
612 li->files = xcalloc(st->st_nlink, sizeof(*li->files));
616 { struct stat * myst = (struct stat *) &li->sb;
617 *myst = *st; /* structure assignment */
624 * Destroy set of hard links.
625 * @param li set of hard links
627 static /*@null@*/ void * freeHardLink(/*@only@*/ /*@null@*/ struct hardLink * li)
632 for (i = 0; i < li->nlink; i++) {
633 /*@-unqualifiedtrans@*/
634 li->files[i] = _free(li->files[i]);
635 /*@=unqualifiedtrans@*/
638 li->files = _free(li->files);
639 li->nsuffix = _free(li->nsuffix); /* XXX elements are shared */
640 li->fileMaps = _free(li->fileMaps);
641 li->filex = _free(li->filex);
647 FSM_t fsm = xcalloc(1, sizeof(*fsm));
651 FSM_t freeFSM(FSM_t fsm)
654 if (fsm->path) free((void *)fsm->path);
655 while ((fsm->li = fsm->links) != NULL) {
656 fsm->links = fsm->li->next;
657 fsm->li->next = NULL;
658 fsm->li = freeHardLink(fsm->li);
660 fsm->dnlx = _free(fsm->dnlx);
661 fsm->ldn = _free(fsm->ldn);
662 fsm->mapi = mapFreeIterator(fsm->mapi);
668 * Convert string to unsigned integer (with buffer size check).
669 * @param input string
670 * @retval address of 1st character not processed
671 * @param base numerical conversion base
672 * @param num max no. of bytes to read
673 * @return converted integer
675 static int strntoul(const char *str, /*@out@*/char **endptr, int base, int num)
676 /*@modifies *endptr @*/
681 buf = alloca(num + 1);
682 strncpy(buf, str, num);
685 ret = strtoul(buf, &end, base);
687 *endptr = ((char *)str) + (end - buf); /* XXX discards const */
689 *endptr = ((char *)str) + strlen(str);
695 * Cpio archive header information.
696 * @todo Add support for tar (soon) and ar (eventually) archive formats.
698 struct cpioCrcPhysicalHeader {
712 char checksum[8]; /* ignored !! */
715 #define PHYS_HDR_SIZE 110 /*!< Don't depend on sizeof(struct) */
717 #define GET_NUM_FIELD(phys, log) \
718 log = strntoul(phys, &end, 16, sizeof(phys)); \
719 if (*end) return CPIOERR_BAD_HEADER;
720 #define SET_NUM_FIELD(phys, val, space) \
721 sprintf(space, "%8.8lx", (unsigned long) (val)); \
722 memcpy(phys, space, 8);
726 * @retval fsm file path and stat info
727 * @return 0 on success
729 static int cpioHeaderWrite(FSM_t fsm, struct stat * st)
731 struct cpioCrcPhysicalHeader * hdr = (struct cpioCrcPhysicalHeader *)fsm->rdbuf;
737 memcpy(hdr->magic, CPIO_NEWC_MAGIC, sizeof(hdr->magic));
738 SET_NUM_FIELD(hdr->inode, st->st_ino, field);
739 SET_NUM_FIELD(hdr->mode, st->st_mode, field);
740 SET_NUM_FIELD(hdr->uid, st->st_uid, field);
741 SET_NUM_FIELD(hdr->gid, st->st_gid, field);
742 SET_NUM_FIELD(hdr->nlink, st->st_nlink, field);
743 SET_NUM_FIELD(hdr->mtime, st->st_mtime, field);
744 SET_NUM_FIELD(hdr->filesize, st->st_size, field);
746 dev = major((unsigned)st->st_dev); SET_NUM_FIELD(hdr->devMajor, dev, field);
747 dev = minor((unsigned)st->st_dev); SET_NUM_FIELD(hdr->devMinor, dev, field);
748 dev = major((unsigned)st->st_rdev); SET_NUM_FIELD(hdr->rdevMajor, dev, field);
749 dev = minor((unsigned)st->st_rdev); SET_NUM_FIELD(hdr->rdevMinor, dev, field);
751 len = strlen(fsm->path) + 1; SET_NUM_FIELD(hdr->namesize, len, field);
752 memcpy(hdr->checksum, "00000000", 8);
753 memcpy(fsm->rdbuf + PHYS_HDR_SIZE, fsm->path, len);
755 /* XXX DWRITE uses rdnb for I/O length. */
756 fsm->rdnb = PHYS_HDR_SIZE + len;
757 rc = fsmStage(fsm, FSM_DWRITE);
758 if (!rc && fsm->rdnb != fsm->wrnb)
759 rc = CPIOERR_WRITE_FAILED;
761 rc = fsmStage(fsm, FSM_PAD);
767 * @retval fsm file path and stat info
768 * @return 0 on success
770 static int cpioHeaderRead(FSM_t fsm, struct stat * st)
771 /*@modifies fsm->cfd, fsm->path, *st @*/
773 struct cpioCrcPhysicalHeader hdr;
779 fsm->wrlen = PHYS_HDR_SIZE;
780 rc = fsmStage(fsm, FSM_DREAD);
781 if (!rc && fsm->rdnb != fsm->wrlen)
782 rc = CPIOERR_READ_FAILED;
784 memcpy(&hdr, fsm->wrbuf, fsm->rdnb);
786 if (strncmp(CPIO_CRC_MAGIC, hdr.magic, sizeof(CPIO_CRC_MAGIC)-1) &&
787 strncmp(CPIO_NEWC_MAGIC, hdr.magic, sizeof(CPIO_NEWC_MAGIC)-1))
788 return CPIOERR_BAD_MAGIC;
790 GET_NUM_FIELD(hdr.inode, st->st_ino);
791 GET_NUM_FIELD(hdr.mode, st->st_mode);
792 GET_NUM_FIELD(hdr.uid, st->st_uid);
793 GET_NUM_FIELD(hdr.gid, st->st_gid);
794 GET_NUM_FIELD(hdr.nlink, st->st_nlink);
795 GET_NUM_FIELD(hdr.mtime, st->st_mtime);
796 GET_NUM_FIELD(hdr.filesize, st->st_size);
798 GET_NUM_FIELD(hdr.devMajor, major);
799 GET_NUM_FIELD(hdr.devMinor, minor);
800 st->st_dev = /*@-shiftsigned@*/ makedev(major, minor) /*@=shiftsigned@*/ ;
802 GET_NUM_FIELD(hdr.rdevMajor, major);
803 GET_NUM_FIELD(hdr.rdevMinor, minor);
804 st->st_rdev = /*@-shiftsigned@*/ makedev(major, minor) /*@=shiftsigned@*/ ;
806 GET_NUM_FIELD(hdr.namesize, nameSize);
807 if (nameSize >= fsm->wrsize)
808 return CPIOERR_BAD_HEADER;
810 { char * t = xmalloc(nameSize + 1);
811 fsm->wrlen = nameSize;
812 rc = fsmStage(fsm, FSM_DREAD);
813 if (!rc && fsm->rdnb != fsm->wrlen)
814 rc = CPIOERR_BAD_HEADER;
820 memcpy(t, fsm->wrbuf, fsm->rdnb);
829 * Create file from payload stream.
830 * @todo Legacy: support brokenEndian MD5 checks?
831 * @param fsm file path and stat info
832 * @return 0 on success
834 static int expandRegular(FSM_t fsm)
835 /*@modifies fileSystem, fsm->cfd @*/
837 const char * filemd5;
838 const struct stat * st = &fsm->sb;
839 int left = st->st_size;
842 /* XXX HACK_ALERT: something fubar with linked files. */
843 filemd5 = (st->st_nlink == 1 ? mapMd5sum(fsm->map) : NULL);
846 const char * opath = fsm->opath;
847 const char * path = fsm->path;
850 fsm->path = mapFsPath(fsm->map, st, NULL, NULL);
851 rc = fsmStage(fsm, FSM_VERIFY);
852 if (rc == 0 && fsm->osuffix) {
853 fsm->opath = fsm->path;
854 fsm->path = mapFsPath(fsm->map, st, NULL, fsm->osuffix);
855 rc = fsmStage(fsm, FSM_RENAME);
857 rpmMessage(RPMMESS_WARNING, _("%s saved as %s\n"), fsm->opath, fsm->path);
858 fsm->path = _free(fsm->path);
859 fsm->opath = _free(fsm->opath);
866 if (rc != CPIOERR_LSTAT_FAILED) return rc;
869 rc = fsmStage(fsm, FSM_WOPEN);
873 /* XXX This doesn't support brokenEndian checks. */
875 fdInitMD5(fsm->wfd, 0);
879 fsm->wrlen = (left > fsm->wrsize ? fsm->wrsize : left);
880 rc = fsmStage(fsm, FSM_DREAD);
884 rc = fsmStage(fsm, FSM_WRITE);
890 /* don't call this with fileSize == fileComplete */
892 (void) fsmStage(fsm, FSM_NOTIFY);
896 const char * md5sum = NULL;
899 fdFiniMD5(fsm->wfd, (void **)&md5sum, NULL, 1);
901 if (md5sum == NULL) {
902 rc = CPIOERR_MD5SUM_MISMATCH;
904 if (strcmp(md5sum, filemd5))
905 rc = CPIOERR_MD5SUM_MISMATCH;
906 md5sum = _free(md5sum);
911 (void) fsmStage(fsm, FSM_WCLOSE);
917 static int fsmMakeLinks(FSM_t fsm)
919 const char * path = fsm->path;
920 const char * opath = fsm->opath;
924 fsm->opath = fsm->li->files[fsm->li->createdPath];
925 for (i = 0; i < fsm->li->nlink; i++) {
926 if (fsm->li->filex[i] < 0) continue;
927 if (i == fsm->li->createdPath) continue;
928 if (fsm->li->files[i] == NULL) continue;
930 fsm->path = fsm->li->files[i];
931 rc = fsmStage(fsm, FSM_VERIFY);
933 if (rc != CPIOERR_LSTAT_FAILED) break;
935 /* XXX link(fsm->opath, fsm->path) */
936 rc = fsmStage(fsm, FSM_LINK);
940 /*@-unqualifiedtrans@*/
941 fsm->li->files[i] = _free(fsm->li->files[i]);
942 /*@=unqualifiedtrans@*/
944 fsm->li->linksLeft--;
947 if (rc && fsm->failedFile && *fsm->failedFile == NULL)
948 *fsm->failedFile = xstrdup(fsm->path);
958 static int fsmCommitLinks(FSM_t fsm)
960 const char * path = fsm->path;
961 const char * nsuffix = fsm->nsuffix;
962 struct stat * st = &fsm->sb;
963 struct mapi * mapi = fsm->mapi;
964 int mapiIndex = mapi->i;
968 for (fsm->li = fsm->links; fsm->li; fsm->li = fsm->li->next) {
969 if (fsm->li->inode == st->st_ino && fsm->li->dev == st->st_dev)
973 for (i = 0; i < fsm->li->nlink; i++) {
974 if (fsm->li->files[i] == NULL) continue;
975 mapi->i = fsm->li->filex[i];
976 fsm->path = xstrdup(fsm->li->files[i]);
977 rc = fsmStage(fsm, FSM_FINALIZE);
978 fsm->path = _free(fsm->path);
979 fsm->li->filex[i] = -1;
983 fsm->nsuffix = nsuffix;
988 int fsmStage(FSM_t fsm, fileStage stage)
991 fileStage prevStage = fsm->stage;
992 const char * const prev = fileStageString(prevStage);
994 static int modulo = 4;
995 const char * const cur = fileStageString(stage);
996 struct stat * st = &fsm->sb;
997 struct stat * ost = &fsm->osb;
998 int saveerrno = errno;
1003 if (stage & FSM_DEAD) {
1005 } else if (stage & FSM_INTERNAL) {
1006 if (_fsm_debug && !(stage & FSM_SYSCALL))
1007 rpmMessage(RPMMESS_DEBUG, " %8s %06o%3d (%4d,%4d)%10d %s %s\n",
1009 st->st_mode, st->st_nlink, st->st_uid, st->st_gid, st->st_size,
1010 (fsm->path ? fsm->path : ""),
1011 ((fsm->action != FA_UNKNOWN && fsm->action != FA_CREATE)
1012 ? fileActionString(fsm->action) : ""));
1015 if (_fsm_debug || !(stage & FSM_VERBOSE))
1016 rpmMessage(RPMMESS_DEBUG, "%-8s %06o%3d (%4d,%4d)%10d %s %s\n",
1018 st->st_mode, st->st_nlink, st->st_uid, st->st_gid, st->st_size,
1019 (fsm->path ? fsm->path + fsm->astriplen : ""),
1020 ((fsm->action != FA_UNKNOWN && fsm->action != FA_CREATE)
1021 ? fileActionString(fsm->action) : ""));
1035 fsm->dnlx = _free(fsm->dnlx);
1036 fsm->ldn = _free(fsm->ldn);
1037 fsm->ldnalloc = fsm->ldnlen = 0;
1038 fsm->rdsize = 8 * BUFSIZ;
1039 fsm->rdb = fsm->rdbuf = _free(fsm->rdbuf);
1040 fsm->rdb = fsm->rdbuf = xmalloc(fsm->rdsize);
1041 fsm->wrsize = 8 * BUFSIZ;
1042 fsm->wrb = fsm->wrbuf = _free(fsm->wrbuf);
1043 fsm->wrb = fsm->wrbuf = xmalloc(fsm->wrsize);
1044 fsm->mkdirsdone = 0;
1048 errno = 0; /* XXX get rid of EBADF */
1051 /* Detect and create directories not explicitly in package. */
1052 rc = fsmStage(fsm, FSM_MKDIRS);
1057 fsm->path = _free(fsm->path);
1059 fsm->diskchecked = fsm->exists = 0;
1061 fsm->suffix = (fsm->sufbuf[0] != '\0' ? fsm->sufbuf : NULL);
1062 fsm->action = FA_UNKNOWN;
1063 fsm->osuffix = NULL;
1064 fsm->nsuffix = NULL;
1066 if (fsm->goal == FSM_INSTALL) {
1067 /* Detect and create directories not explicitly in package. */
1068 if (!fsm->mkdirsdone) {
1069 rc = fsmStage(fsm, FSM_MKDIRS);
1070 fsm->mkdirsdone = 1;
1073 /* Read next header from payload. */
1074 rc = fsmStage(fsm, FSM_POS);
1076 rc = fsmStage(fsm, FSM_NEXT);
1079 /* Remap name/perms/uid/gid of archive file. */
1081 rc = fsmStage(fsm, FSM_MAP);
1083 /* Perform lstat/stat for disk file. */
1084 fsm->diskchecked = fsm->exists = 0;
1087 (!fsmFlags(fsm, CPIO_FOLLOW_SYMLINKS) ? FSM_LSTAT : FSM_STAT));
1088 if (rc == CPIOERR_LSTAT_FAILED && errno == ENOENT) {
1092 } else if (rc == 0) {
1095 fsm->diskchecked = 1;
1097 /* FSM_INIT -> {FSM_PRE,FSM_DESTROY} */
1103 { const char * path = fsm->path;
1104 mode_t st_mode = st->st_mode;
1105 void * dnli = dnlInitIterator(fsm->mapi, 0);
1106 char * dn = fsm->rdbuf;
1107 int dc = dnlCount(dnli);
1111 fsm->dnlx = (dc ? xcalloc(dc, sizeof(*fsm->dnlx)) : NULL);
1112 while ((fsm->path = dnlNextIterator(dnli)) != NULL) {
1113 int dnlen = strlen(fsm->path);
1116 dc = dnlIndex(dnli);
1117 fsm->dnlx[dc] = dnlen;
1120 if (dnlen <= fsm->ldnlen && !strcmp(fsm->path, fsm->ldn))
1123 /* Copy to avoid const on fsm->path. */
1124 (void) stpcpy(dn, fsm->path);
1127 /* Initial mode for created dirs is 0700 */
1128 st->st_mode &= ~07777; /* XXX abuse st->st_mode */
1129 st->st_mode |= 00700;
1131 /* Assume '/' directory, otherwise "mkdir -p" */
1132 for (i = 1, te = dn + 1; *te; te++, i++) {
1133 if (*te != '/') continue;
1137 /* Already validated? */
1138 if (i < fsm->ldnlen &&
1139 (fsm->ldn[i] == '/' || fsm->ldn[i] == '\0') &&
1140 !strncmp(fsm->path, fsm->ldn, i))
1143 /* Move pre-existing path marker forward. */
1144 fsm->dnlx[dc] = (te - dn);
1148 /* Validate next component of path. */
1149 rc = fsmStage(fsm, FSM_LSTAT);
1152 /* Directory already exists? */
1153 if (rc == 0 && S_ISDIR(ost->st_mode)) {
1154 /* Move pre-existing path marker forward. */
1155 fsm->dnlx[dc] = (te - dn);
1156 } else if (rc == CPIOERR_LSTAT_FAILED) {
1158 rc = fsmStage(fsm, FSM_MKDIR);
1165 /* Save last validated path. */
1166 if (fsm->ldnalloc < (dnlen + 1)) {
1167 fsm->ldnalloc = dnlen + 100;
1168 fsm->ldn = xrealloc(fsm->ldn, fsm->ldnalloc);
1170 strcpy(fsm->ldn, fsm->path);
1171 fsm->ldnlen = dnlen;
1173 dnli = dnlFreeIterator(dnli);
1175 st->st_mode = st_mode; /* XXX restore st->st_mode */
1180 const char * path = fsm->path;
1181 void * dnli = dnlInitIterator(fsm->mapi, 1);
1182 char * dn = fsm->rdbuf;
1183 int dc = dnlCount(dnli);
1186 while ((fsm->path = dnlNextIterator(dnli)) != NULL) {
1187 int dnlen = strlen(fsm->path);
1190 dc = dnlIndex(dnli);
1191 if (fsm->dnlx[dc] < 1 || fsm->dnlx[dc] >= dnlen)
1194 /* Copy to avoid const on fsm->path. */
1195 te = stpcpy(dn, fsm->path) - 1;
1198 /* Remove generated directories. */
1202 rc = fsmStage(fsm, FSM_RMDIR);
1207 } while ((te - dn) > fsm->dnlx[dc]);
1209 dnli = dnlFreeIterator(dnli);
1214 if (S_ISREG(st->st_mode) && st->st_nlink > 1) {
1215 for (fsm->li = fsm->links; fsm->li; fsm->li = fsm->li->next) {
1216 if (fsm->li->inode == st->st_ino && fsm->li->dev == st->st_dev)
1220 /* Save new hard link set. */
1221 if (fsm->li == NULL) {
1222 fsm->li = newHardLink(st, HARDLINK_INSTALL);
1223 fsm->li->next = fsm->links;
1224 fsm->links = fsm->li;
1227 fsm->li->filex[fsm->li->linksLeft] = fsmGetIndex(fsm);
1228 fsm->li->files[fsm->li->linksLeft] = xstrdup(fsm->path);
1229 /* XXX this is just an observer pointer. */
1230 fsm->li->nsuffix[fsm->li->linksLeft] = fsm->nsuffix;
1231 fprintf(stderr, "*** %p link[%d:%d] %d filex %d %s\n", fsm->li, fsm->li->linksLeft, st->st_nlink, (int)st->st_size, fsm->li->filex[fsm->li->linksLeft], fsm->li->files[fsm->li->linksLeft]);
1232 fsm->li->linksLeft++;
1234 if (!(st->st_size || fsm->li->linksLeft == st->st_nlink)) {
1237 TFI_t fi = fsmGetFi(fsm);
1240 /* Here come the bits, time to choose a non-skipped file name. */
1241 for (j = fsm->li->linksLeft - 1; j >= 0; j--) {
1242 i = fsm->li->filex[j];
1243 if (i < 0 || XFA_SKIPPING(fi->actions[i]))
1247 /* Are all links skipped or not encountered yet? */
1252 fsm->li->linkIndex = j;
1253 fsm->path = _free(fsm->path);
1254 fsm->path = xstrdup(fsm->li->files[j]);
1261 /* @todo This makes all dir paths, only needs doing once. */
1262 if (!fsm->mkdirsdone) {
1263 rc = fsmStage(fsm, FSM_MKDIRS);
1264 fsm->mkdirsdone = 1;
1267 fsm->postpone = XFA_SKIPPING(fsm->action);
1270 if (fsm->postpone) {
1271 if (fsm->goal == FSM_INSTALL) {
1272 (void) fsmStage(fsm, FSM_POS);
1273 (void) fsmStage(fsm, FSM_EAT);
1275 /* FSM_PRE -> FSM_INIT */
1277 if (fsm->goal == FSM_INSTALL)
1278 (void) fsmStage(fsm, FSM_POS);
1279 /* FSM_PRE -> FSM_PROCESS */
1284 if (S_ISREG(st->st_mode)) {
1285 /* XXX nlink > 1, insure that path/createdPath is non-skipped. */
1286 rc = expandRegular(fsm);
1287 } else if (S_ISDIR(st->st_mode)) {
1288 mode_t st_mode = st->st_mode;
1289 rc = fsmStage(fsm, FSM_VERIFY);
1290 if (rc == CPIOERR_LSTAT_FAILED) {
1291 st->st_mode &= ~07777; /* XXX abuse st->st_mode */
1292 st->st_mode |= 00700;
1293 rc = fsmStage(fsm, FSM_MKDIR);
1294 st->st_mode = st_mode; /* XXX restore st->st_mode */
1296 } else if (S_ISLNK(st->st_mode)) {
1297 const char * opath = fsm->opath;
1299 if ((st->st_size + 1) > fsm->rdsize) {
1300 rc = CPIOERR_HDR_SIZE;
1304 fsm->wrlen = st->st_size;
1305 rc = fsmStage(fsm, FSM_DREAD);
1306 if (!rc && fsm->rdnb != fsm->wrlen)
1307 rc = CPIOERR_READ_FAILED;
1310 fsm->wrbuf[st->st_size] = '\0';
1311 /* XXX symlink(fsm->opath, fsm->path) */
1312 fsm->opath = fsm->wrbuf; /* XXX abuse fsm->path */
1313 rc = fsmStage(fsm, FSM_VERIFY);
1314 if (rc == CPIOERR_LSTAT_FAILED)
1315 rc = fsmStage(fsm, FSM_SYMLINK);
1316 fsm->opath = opath; /* XXX restore fsm->path */
1317 } else if (S_ISFIFO(st->st_mode) || S_ISSOCK(st->st_mode)) {
1318 mode_t st_mode = st->st_mode;
1319 /* This mimics cpio S_ISSOCK() behavior but probably isnt' right */
1320 rc = fsmStage(fsm, FSM_VERIFY);
1321 if (rc == CPIOERR_LSTAT_FAILED) {
1322 st->st_mode = 0000; /* XXX abuse st->st_mode */
1323 rc = fsmStage(fsm, FSM_MKFIFO);
1324 st->st_mode = st_mode; /* XXX restore st->st_mode*/
1326 } else if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) {
1327 rc = fsmStage(fsm, FSM_VERIFY);
1328 if (rc == CPIOERR_LSTAT_FAILED)
1329 rc = fsmStage(fsm, FSM_MKNOD);
1331 rc = CPIOERR_UNKNOWN_FILETYPE;
1333 /* FSM_PROCESS -> FSM_POST */
1338 /* XXX nlink > 1, insure that path/createdPath is non-skipped. */
1339 if (S_ISREG(st->st_mode) && st->st_nlink > 1) {
1340 fsm->li->createdPath = fsm->li->linkIndex;
1341 rc = fsmStage(fsm, FSM_MKLINKS);
1343 /* FSM_POST -> {FSM_COMMIT,FSM_UNDO} */
1346 rc = fsmMakeLinks(fsm);
1348 case FSM_NOTIFY: /* XXX move from fsm to psm -> tsm */
1349 { rpmTransactionSet ts = fsmGetTs(fsm);
1350 TFI_t fi = fsmGetFi(fsm);
1351 if (ts && ts->notify && fi)
1352 (void)ts->notify(fi->h, RPMCALLBACK_INST_PROGRESS,
1353 fdGetCpioPos(fsm->cfd), fi->archiveSize,
1354 (fi->ap ? fi->ap->key : NULL), ts->notifyData);
1360 if (S_ISDIR(st->st_mode)) {
1361 (void) fsmStage(fsm, FSM_RMDIR);
1363 (void) fsmStage(fsm, FSM_UNLINK);
1365 #ifdef NOTYET /* XXX remove only dirs just created, not all. */
1367 (void) fsmStage(fsm, FSM_RMDIRS);
1370 if (fsm->failedFile && *fsm->failedFile == NULL)
1371 *fsm->failedFile = xstrdup(fsm->path);
1372 /* FSM_UNDO -> FSM_INIT */
1375 if (fsm->goal == FSM_INSTALL) {
1376 if (!fsm->postpone && mapCommit(fsm->map)) {
1377 if (S_ISREG(st->st_mode) && st->st_nlink > 1) {
1378 rc = fsmCommitLinks(fsm);
1380 rc = fsmStage(fsm, FSM_FINALIZE);
1384 fsm->path = _free(fsm->path);
1385 memset(st, 0, sizeof(*st));
1386 /* FSM_COMMIT -> FSM_INIT */
1389 if (!S_ISDIR(st->st_mode) && (fsm->subdir || fsm->suffix)) {
1390 fsm->opath = fsm->path;
1391 fsm->path = mapFsPath(fsm->map, st, NULL, fsm->nsuffix);
1392 rc = fsmStage(fsm, FSM_RENAME);
1393 if (!rc && fsm->nsuffix) {
1394 const char * opath = mapFsPath(fsm->map, st, NULL, NULL);
1395 rpmMessage(RPMMESS_WARNING, _("%s created as %s\n"), opath, fsm->path);
1396 opath = _free(opath);
1398 fsm->opath = _free(fsm->opath);
1400 if (S_ISLNK(st->st_mode)) {
1401 if (!rc && !getuid() &&
1402 !(fsm->diskchecked && st->st_mode == ost->st_mode))
1403 rc = fsmStage(fsm, FSM_LCHOWN);
1405 if (!rc && !getuid() &&
1406 !(fsm->diskchecked && st->st_uid == ost->st_uid
1407 && st->st_uid == ost->st_uid))
1408 rc = fsmStage(fsm, FSM_CHOWN);
1410 !(fsm->diskchecked &&
1411 (st->st_mode & 07777) == (ost->st_mode & 07777)))
1412 rc = fsmStage(fsm, FSM_CHMOD);
1414 rc = fsmStage(fsm, FSM_UTIME);
1416 /* Notify on success. */
1417 if (!rc) rc = fsmStage(fsm, FSM_NOTIFY);
1420 fsm->path = _free(fsm->path);
1421 /* Create any remaining links (if no error), and clean up. */
1422 while ((fsm->li = fsm->links) != NULL) {
1423 fsm->links = fsm->li->next;
1424 fsm->li->next = NULL;
1425 if (fsm->li->linksLeft) {
1426 for (i = 0 ; i < fsm->li->linksLeft; i++) {
1427 if (fsm->li->filex[i] < 0) continue;
1428 rc = CPIOERR_MISSING_HARDLINK;
1429 if (!(fsm->li->files && fsm->li->files[i])) continue;
1430 if (fsm->failedFile && *fsm->failedFile == NULL)
1431 *fsm->failedFile = xstrdup(fsm->li->files[i]);
1435 fsm->li = freeHardLink(fsm->li);
1437 fsm->ldn = _free(fsm->ldn);
1438 fsm->ldnalloc = fsm->ldnlen = 0;
1439 fsm->rdb = fsm->rdbuf = _free(fsm->rdbuf);
1440 fsm->wrb = fsm->wrbuf = _free(fsm->wrbuf);
1443 if (fsm->diskchecked && !fsm->exists) {
1444 rc = CPIOERR_LSTAT_FAILED;
1447 if (S_ISREG(st->st_mode)) {
1448 char * path = alloca(strlen(fsm->path) + sizeof("-RPMDELETE"));
1449 (void) stpcpy( stpcpy(path, fsm->path), "-RPMDELETE");
1451 * XXX HP-UX (and other os'es) don't permit unlink on busy
1454 fsm->opath = fsm->path;
1456 rc = fsmStage(fsm, FSM_RENAME);
1458 (void) fsmStage(fsm, FSM_UNLINK);
1460 rc = CPIOERR_UNLINK_FAILED;
1461 fsm->path = fsm->opath;
1463 return (rc ? rc : CPIOERR_LSTAT_FAILED);
1465 } else if (S_ISDIR(st->st_mode)) {
1466 if (S_ISDIR(ost->st_mode)) return 0;
1467 if (S_ISLNK(ost->st_mode)) {
1468 rc = fsmStage(fsm, FSM_STAT);
1469 if (rc == CPIOERR_STAT_FAILED && errno == ENOENT) rc = 0;
1472 if (S_ISDIR(ost->st_mode)) return 0;
1474 } else if (S_ISLNK(st->st_mode)) {
1475 if (S_ISLNK(ost->st_mode)) {
1476 /* XXX NUL terminated result in fsm->rdbuf, len in fsm->rdnb. */
1477 rc = fsmStage(fsm, FSM_READLINK);
1480 if (!strcmp(fsm->opath, fsm->rdbuf)) return 0;
1482 } else if (S_ISFIFO(st->st_mode)) {
1483 if (S_ISFIFO(ost->st_mode)) return 0;
1484 } else if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) {
1485 if ((S_ISCHR(ost->st_mode) || S_ISBLK(ost->st_mode)) &&
1486 (ost->st_rdev == st->st_rdev)) return 0;
1487 } else if (S_ISSOCK(st->st_mode)) {
1488 if (S_ISSOCK(ost->st_mode)) return 0;
1490 /* XXX shouldn't do this with commit/undo. */
1492 if (fsm->stage == FSM_PROCESS) rc = fsmStage(fsm, FSM_UNLINK);
1493 if (rc == 0) rc = CPIOERR_LSTAT_FAILED;
1494 return (rc ? rc : CPIOERR_LSTAT_FAILED); /* XXX HACK */
1498 rc = Unlink(fsm->path);
1499 if (_fsm_debug && (stage & FSM_SYSCALL))
1500 rpmMessage(RPMMESS_DEBUG, " %8s (%s) %s\n", cur,
1501 fsm->path, (rc < 0 ? strerror(errno) : ""));
1502 if (rc < 0) rc = CPIOERR_UNLINK_FAILED;
1505 rc = Rename(fsm->opath, fsm->path);
1506 if (_fsm_debug && (stage & FSM_SYSCALL))
1507 rpmMessage(RPMMESS_DEBUG, " %8s (%s, %s) %s\n", cur,
1508 fsm->opath, fsm->path, (rc < 0 ? strerror(errno) : ""));
1509 if (rc < 0) rc = CPIOERR_RENAME_FAILED;
1512 rc = Mkdir(fsm->path, (st->st_mode & 07777));
1513 if (_fsm_debug && (stage & FSM_SYSCALL))
1514 rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0%o) %s\n", cur,
1515 fsm->path, (st->st_mode & 07777),
1516 (rc < 0 ? strerror(errno) : ""));
1517 if (rc < 0) rc = CPIOERR_MKDIR_FAILED;
1520 rc = Rmdir(fsm->path);
1521 if (_fsm_debug && (stage & FSM_SYSCALL))
1522 rpmMessage(RPMMESS_DEBUG, " %8s (%s) %s\n", cur,
1523 fsm->path, (rc < 0 ? strerror(errno) : ""));
1524 if (rc < 0) rc = CPIOERR_RMDIR_FAILED;
1527 rc = chown(fsm->path, st->st_uid, st->st_gid);
1528 if (_fsm_debug && (stage & FSM_SYSCALL))
1529 rpmMessage(RPMMESS_DEBUG, " %8s (%s, %d, %d) %s\n", cur,
1530 fsm->path, st->st_uid, st->st_gid,
1531 (rc < 0 ? strerror(errno) : ""));
1532 if (rc < 0) rc = CPIOERR_CHOWN_FAILED;
1535 #if ! CHOWN_FOLLOWS_SYMLINK
1536 rc = lchown(fsm->path, st->st_uid, st->st_gid);
1537 if (_fsm_debug && (stage & FSM_SYSCALL))
1538 rpmMessage(RPMMESS_DEBUG, " %8s (%s, %d, %d) %s\n", cur,
1539 fsm->path, st->st_uid, st->st_gid,
1540 (rc < 0 ? strerror(errno) : ""));
1541 if (rc < 0) rc = CPIOERR_CHOWN_FAILED;
1545 rc = chmod(fsm->path, (st->st_mode & 07777));
1546 if (_fsm_debug && (stage & FSM_SYSCALL))
1547 rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0%o) %s\n", cur,
1548 fsm->path, (st->st_mode & 07777),
1549 (rc < 0 ? strerror(errno) : ""));
1550 if (rc < 0) rc = CPIOERR_CHMOD_FAILED;
1553 { struct utimbuf stamp;
1554 stamp.actime = st->st_mtime;
1555 stamp.modtime = st->st_mtime;
1556 rc = utime(fsm->path, &stamp);
1557 if (_fsm_debug && (stage & FSM_SYSCALL))
1558 rpmMessage(RPMMESS_DEBUG, " %8s (%s, %x) %s\n", cur,
1559 fsm->path, (unsigned)st->st_mtime,
1560 (rc < 0 ? strerror(errno) : ""));
1561 if (rc < 0) rc = CPIOERR_UTIME_FAILED;
1565 rc = symlink(fsm->opath, fsm->path);
1566 if (_fsm_debug && (stage & FSM_SYSCALL))
1567 rpmMessage(RPMMESS_DEBUG, " %8s (%s, %s) %s\n", cur,
1568 fsm->opath, fsm->path, (rc < 0 ? strerror(errno) : ""));
1569 if (rc < 0) rc = CPIOERR_SYMLINK_FAILED;
1572 rc = Link(fsm->opath, fsm->path);
1573 if (_fsm_debug && (stage & FSM_SYSCALL))
1574 rpmMessage(RPMMESS_DEBUG, " %8s (%s, %s) %s\n", cur,
1575 fsm->opath, fsm->path, (rc < 0 ? strerror(errno) : ""));
1576 if (rc < 0) rc = CPIOERR_LINK_FAILED;
1579 rc = mkfifo(fsm->path, (st->st_mode & 07777));
1580 if (_fsm_debug && (stage & FSM_SYSCALL))
1581 rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0%o) %s\n", cur,
1582 fsm->path, (st->st_mode & 07777),
1583 (rc < 0 ? strerror(errno) : ""));
1584 if (rc < 0) rc = CPIOERR_MKFIFO_FAILED;
1588 rc = mknod(fsm->path, (st->st_mode & ~07777), st->st_rdev);
1589 if (_fsm_debug && (stage & FSM_SYSCALL))
1590 rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0%o, 0x%x) %s\n", cur,
1591 fsm->path, (st->st_mode & ~07777), (unsigned)st->st_rdev,
1592 (rc < 0 ? strerror(errno) : ""));
1593 if (rc < 0) rc = CPIOERR_MKNOD_FAILED;
1597 rc = Lstat(fsm->path, ost);
1598 if (_fsm_debug && (stage & FSM_SYSCALL) && errno != ENOENT)
1599 rpmMessage(RPMMESS_DEBUG, " %8s (%s, ost) %s\n", cur,
1600 fsm->path, (rc < 0 ? strerror(errno) : ""));
1601 if (rc < 0) rc = CPIOERR_LSTAT_FAILED;
1604 rc = Stat(fsm->path, ost);
1605 if (_fsm_debug && (stage & FSM_SYSCALL) && errno != ENOENT)
1606 rpmMessage(RPMMESS_DEBUG, " %8s (%s, ost) %s\n", cur,
1607 fsm->path, (rc < 0 ? strerror(errno) : ""));
1608 if (rc < 0) rc = CPIOERR_STAT_FAILED;
1611 /* XXX NUL terminated result in fsm->rdbuf, len in fsm->rdnb. */
1612 rc = Readlink(fsm->path, fsm->rdbuf, fsm->rdsize - 1);
1613 if (_fsm_debug && (stage & FSM_SYSCALL))
1614 rpmMessage(RPMMESS_DEBUG, " %8s (%s, rdbuf, %d) %s\n", cur,
1615 fsm->path, fsm->rdlen, (rc < 0 ? strerror(errno) : ""));
1616 if (rc < 0) rc = CPIOERR_READLINK_FAILED;
1619 fsm->rdbuf[fsm->rdnb] = '\0';
1627 rc = fsmStage(fsm, FSM_HREAD);
1629 if (!strcmp(fsm->path, TRAILER)) { /* Detect end-of-payload. */
1630 fsm->path = _free(fsm->path);
1631 rc = CPIOERR_HDR_TRAILER;
1635 for (left = st->st_size; left > 0; left -= fsm->rdnb) {
1636 fsm->wrlen = (left > fsm->wrsize ? fsm->wrsize : left);
1637 rc = fsmStage(fsm, FSM_DREAD);
1642 left = (modulo - (fdGetCpioPos(fsm->cfd) % modulo)) % modulo;
1645 (void) fsmStage(fsm, FSM_DREAD);
1649 left = (modulo - (fdGetCpioPos(fsm->cfd) % modulo)) % modulo;
1651 memset(fsm->rdbuf, 0, left);
1652 /* XXX DWRITE uses rdnb for I/O length. */
1654 (void) fsmStage(fsm, FSM_DWRITE);
1658 rc = cpioHeaderRead(fsm, st); /* Read next payload header. */
1661 rc = cpioHeaderWrite(fsm, st); /* Write next payload header. */
1664 fsm->rdnb = Fread(fsm->wrbuf, sizeof(*fsm->wrbuf), fsm->wrlen, fsm->cfd);
1665 if (_fsm_debug && (stage & FSM_SYSCALL))
1666 rpmMessage(RPMMESS_DEBUG, " %8s (%s, %d, cfd)\trdnb %d\n",
1667 cur, (fsm->wrbuf == fsm->wrb ? "wrbuf" : "mmap"),
1668 fsm->wrlen, fsm->rdnb);
1669 if (fsm->rdnb != fsm->wrlen) fprintf(stderr, "*** short read, had %d, got %d\n", fsm->rdnb, fsm->wrlen);
1671 if (Ferror(fsm->rfd))
1672 rc = CPIOERR_READ_FAILED;
1675 fdSetCpioPos(fsm->cfd, fdGetCpioPos(fsm->cfd) + fsm->rdnb);
1678 fsm->wrnb = Fwrite(fsm->rdbuf, sizeof(*fsm->rdbuf), fsm->rdnb, fsm->cfd);
1679 if (_fsm_debug && (stage & FSM_SYSCALL))
1680 rpmMessage(RPMMESS_DEBUG, " %8s (%s, %d, cfd)\twrnb %d\n",
1681 cur, (fsm->rdbuf == fsm->rdb ? "rdbuf" : "mmap"),
1682 fsm->rdnb, fsm->wrnb);
1683 if (fsm->rdnb != fsm->wrnb) fprintf(stderr, "*** short write, had %d, got %d\n", fsm->rdnb, fsm->wrnb);
1685 if (Ferror(fsm->wfd))
1686 rc = CPIOERR_WRITE_FAILED;
1689 fdSetCpioPos(fsm->cfd, fdGetCpioPos(fsm->cfd) + fsm->wrnb);
1693 fsm->rfd = Fopen(fsm->path, "r.ufdio");
1694 if (fsm->rfd == NULL || Ferror(fsm->rfd)) {
1695 if (fsm->rfd) (void) fsmStage(fsm, FSM_RCLOSE);
1697 rc = CPIOERR_OPEN_FAILED;
1700 if (_fsm_debug && (stage & FSM_SYSCALL))
1701 rpmMessage(RPMMESS_DEBUG, " %8s (%s, \"r\") rfd %p rdbuf %p\n", cur,
1702 fsm->path, fsm->rfd, fsm->rdbuf);
1705 fsm->rdnb = Fread(fsm->rdbuf, sizeof(*fsm->rdbuf), fsm->rdlen, fsm->rfd);
1706 if (_fsm_debug && (stage & FSM_SYSCALL))
1707 rpmMessage(RPMMESS_DEBUG, " %8s (rdbuf, %d, rfd)\trdnb %d\n",
1708 cur, fsm->rdlen, fsm->rdnb);
1709 if (fsm->rdnb != fsm->rdlen) fprintf(stderr, "*** short read, had %d, got %d\n", fsm->rdnb, fsm->rdlen);
1711 if (Ferror(fsm->rfd))
1712 rc = CPIOERR_READ_FAILED;
1716 if (_fsm_debug && (stage & FSM_SYSCALL))
1717 rpmMessage(RPMMESS_DEBUG, " %8s (%p)\n", cur, fsm->rfd);
1719 (void) Fclose(fsm->rfd);
1725 fsm->wfd = Fopen(fsm->path, "w.ufdio");
1726 if (fsm->wfd == NULL || Ferror(fsm->wfd)) {
1727 if (fsm->wfd) (void) fsmStage(fsm, FSM_WCLOSE);
1729 rc = CPIOERR_OPEN_FAILED;
1731 if (_fsm_debug && (stage & FSM_SYSCALL))
1732 rpmMessage(RPMMESS_DEBUG, " %8s (%s, \"w\") wfd %p wrbuf %p\n", cur,
1733 fsm->path, fsm->wfd, fsm->wrbuf);
1736 fsm->wrnb = Fwrite(fsm->wrbuf, sizeof(*fsm->wrbuf), fsm->rdnb, fsm->wfd);
1737 if (_fsm_debug && (stage & FSM_SYSCALL))
1738 rpmMessage(RPMMESS_DEBUG, " %8s (wrbuf, %d, wfd)\twrnb %d\n",
1739 cur, fsm->rdnb, fsm->wrnb);
1740 if (fsm->rdnb != fsm->wrnb) fprintf(stderr, "*** short write: had %d, got %d\n", fsm->rdnb, fsm->wrnb);
1742 if (Ferror(fsm->wfd))
1743 rc = CPIOERR_WRITE_FAILED;
1747 if (_fsm_debug && (stage & FSM_SYSCALL))
1748 rpmMessage(RPMMESS_DEBUG, " %8s (%p)\n", cur, fsm->wfd);
1750 (void) Fclose(fsm->wfd);
1760 if (!(stage & FSM_INTERNAL)) {
1761 fsm->rc = (rc == CPIOERR_HDR_TRAILER ? 0 : rc);
1766 int fsmSetup(FSM_t fsm, fileStage goal,
1767 const rpmTransactionSet ts, const TFI_t fi, FD_t cfd,
1768 unsigned int * archiveSize, const char ** failedFile)
1770 int rc = fsmStage(fsm, FSM_CREATE);
1772 rpmSetVerbosity(RPMMESS_DEBUG);
1776 fsm->cfd = fdLink(cfd, "persist (fsm)");
1777 fdSetCpioPos(fsm->cfd, 0);
1779 fsm->mapi = mapInitIterator(ts, fi);
1780 fsm->archiveSize = archiveSize;
1781 fsm->failedFile = failedFile;
1782 if (fsm->failedFile)
1783 *fsm->failedFile = NULL;
1785 memset(fsm->sufbuf, 0, sizeof(fsm->sufbuf));
1786 if (fsm->goal != FSM_BUILD) {
1788 sprintf(fsm->sufbuf, ";%08x", ts->id);
1793 int fsmTeardown(FSM_t fsm) {
1795 fsm->mapi = mapFreeIterator(fsm->mapi);
1797 fsm->cfd = fdFree(fsm->cfd, "persist (fsm)");
1800 fsm->failedFile = NULL;
1804 int fsmMap(FSM_t fsm)
1806 struct stat * st = &fsm->sb;
1807 TFI_t fi = fsmGetFi(fsm);
1808 int i = fsmGetIndex(fsm);
1811 fsm->action = FA_UNKNOWN;
1812 fsm->osuffix = NULL;
1813 fsm->nsuffix = NULL;
1814 fsm->astriplen = (fi ? fi->astriplen : 0);
1816 if (fsm->goal == FSM_INSTALL) {
1817 if (fsm->mapi == NULL)
1819 fsm->map = mapFind(fsm->mapi, fsm->path);
1821 fsm->map = mapNextIterator(fsm->mapi);
1824 if (fsm->goal == FSM_BUILD) {
1825 if (fsm->map == NULL) {
1826 rc = CPIOERR_HDR_TRAILER;
1829 fsm->path = mapFsPath(fsm->map, NULL, NULL, NULL);
1833 if (fsm->map && fi && i >= 0 && i < fi->fc) {
1834 fsm->action = fi->actions[i];
1835 switch (fsm->action) {
1837 fprintf(stderr, "*** %s:%s %s\n", fiTypeString(fi), fileActionString(fsm->action), fsm->path);
1839 case FA_SKIPMULTILIB: /* XXX RPMFILE_STATE_MULTILIB? */
1840 fprintf(stderr, "*** %s:%s %s\n", fiTypeString(fi), fileActionString(fsm->action), fsm->path);
1843 fprintf(stderr, "*** %s:%s %s\n", fiTypeString(fi), fileActionString(fsm->action), fsm->path);
1847 assert(fi->type == TR_ADDED);
1851 fprintf(stderr, "*** %s:%s %s\n", fiTypeString(fi), fileActionString(fsm->action), fsm->path);
1852 if (fi->type == TR_ADDED)
1853 fi->fstates[i] = RPMFILE_STATE_NOTINSTALLED;
1856 case FA_SKIPNETSHARED:
1857 fprintf(stderr, "*** %s:%s %s\n", fiTypeString(fi), fileActionString(fsm->action), fsm->path);
1858 if (fi->type == TR_ADDED)
1859 fi->fstates[i] = RPMFILE_STATE_NETSHARED;
1863 fprintf(stderr, "*** %s:%s %s\n", fiTypeString(fi), fileActionString(fsm->action), fsm->path);
1866 fsm->osuffix = SUFFIX_RPMORIG;
1869 fsm->osuffix = SUFFIX_RPMSAVE;
1875 fprintf(stderr, "*** %s:%s %s\n", fiTypeString(fi), fileActionString(fsm->action), fsm->path);
1876 assert(fi->type == TR_ADDED);
1877 fsm->nsuffix = SUFFIX_RPMNEW;
1881 fprintf(stderr, "*** %s:%s %s\n", fiTypeString(fi), fileActionString(fsm->action), fsm->path);
1882 assert(fi->type == TR_ADDED);
1883 fsm->osuffix = SUFFIX_RPMSAVE;
1886 fprintf(stderr, "*** %s:%s %s\n", fiTypeString(fi), fileActionString(fsm->action), fsm->path);
1887 assert(fi->type == TR_REMOVED);
1890 fprintf(stderr, "*** %s:%s %s\n", fiTypeString(fi), fileActionString(fsm->action), fsm->path);
1894 if (fsmFlags(fsm, CPIO_MAP_PATH) || fsm->nsuffix) {
1895 fsm->path = _free(fsm->path);
1896 fsm->path = mapFsPath(fsm->map, st, fsm->subdir,
1897 (fsm->suffix ? fsm->suffix : fsm->nsuffix));
1900 if (fsmFlags(fsm, CPIO_MAP_MODE))
1901 st->st_mode = (st->st_mode & S_IFMT) | mapFinalMode(fsm->map);
1902 if (fsmFlags(fsm, CPIO_MAP_UID))
1903 st->st_uid = mapFinalUid(fsm->map);
1904 if (fsmFlags(fsm, CPIO_MAP_GID))
1905 st->st_gid = mapFinalGid(fsm->map);
1910 /** @todo Verify payload MD5 sum. */
1911 int cpioInstallArchive(FSM_t fsm)
1916 char * md5sum = NULL;
1923 /* Clean fsm, free'ing memory. Read next archive header. */
1924 rc = fsmStage(fsm, FSM_INIT);
1926 /* Exit on end-of-payload. */
1927 if (rc == CPIOERR_HDR_TRAILER) {
1932 /* Abort on error. */
1935 /* Create any directories in path. */
1936 rc = fsmStage(fsm, FSM_PRE);
1938 /* Extract file from archive. */
1939 if (!rc) rc = fsmStage(fsm, FSM_PROCESS);
1941 /* If successfully extracted, set final file info. */
1942 if (!rc) rc = fsmStage(fsm, FSM_POST);
1944 /* Notify on success. */
1945 if (!rc) (void) fsmStage(fsm, FSM_NOTIFY);
1947 (void) fsmStage(fsm, (rc ? FSM_UNDO : FSM_COMMIT));
1951 rc = fsmStage(fsm, FSM_DESTROY);
1954 fdFiniMD5(fsm->cfd, (void **)&md5sum, NULL, 1);
1965 * Write next item to payload stream.
1966 * @retval sizep address of no. bytes written
1967 * @param writeData should data be written?
1968 * @return 0 on success
1970 static int writeFile(FSM_t fsm, int writeData)
1971 /*@modifies fsm->cfd @*/
1973 const char * path = fsm->path;
1974 const char * opath = fsm->opath;
1975 const rpmTransactionSet ts = fsmGetTs(fsm);
1976 TFI_t fi = fsmGetFi(fsm);
1977 struct stat * st = &fsm->sb;
1978 size_t pos = fdGetCpioPos(fsm->cfd);
1982 fsm->path = mapFsPath(fsm->map, NULL, NULL, NULL);
1984 if (fsmFlags(fsm, CPIO_MAP_MODE))
1985 st->st_mode = (st->st_mode & S_IFMT) | mapFinalMode(fsm->map);
1986 if (fsmFlags(fsm, CPIO_MAP_UID))
1987 st->st_uid = mapFinalUid(fsm->map);
1988 if (fsmFlags(fsm, CPIO_MAP_GID))
1989 st->st_gid = mapFinalGid(fsm->map);
1991 if (!writeData || S_ISDIR(st->st_mode)) {
1993 } else if (S_ISLNK(st->st_mode)) {
1995 * While linux puts the size of a symlink in the st_size field,
1996 * I don't think that's a specified standard.
1998 /* XXX NUL terminated result in fsm->rdbuf, len in fsm->rdnb. */
1999 rc = fsmStage(fsm, FSM_READLINK);
2002 st->st_size = fsm->rdnb;
2005 { const char * fsmPath = fsm->path;
2006 if (fsmFlags(fsm, CPIO_MAP_PATH))
2007 fsm->path = mapArchivePath(fsm->map);
2008 rc = fsmStage(fsm, FSM_HWRITE);
2009 fsm->path = fsmPath;
2014 if (writeData && S_ISREG(st->st_mode)) {
2016 char * rdbuf = NULL;
2021 rc = fsmStage(fsm, FSM_ROPEN);
2025 /* XXX unbuffered mmap generates *lots* of fdio debugging */
2028 mapped = mmap(NULL, st->st_size, PROT_READ, MAP_SHARED, Fileno(fsm->rfd), 0);
2029 if (mapped != (void *)-1) {
2031 fsm->rdbuf = (char *) mapped;
2032 fsm->rdlen = nmapped = st->st_size;
2040 if (mapped != (void *)-1) {
2041 fsm->rdnb = nmapped;
2045 fsm->rdlen = (left > fsm->rdsize ? fsm->rdsize : left),
2046 rc = fsmStage(fsm, FSM_READ);
2050 /* XXX DWRITE uses rdnb for I/O length. */
2051 rc = fsmStage(fsm, FSM_DWRITE);
2058 if (mapped != (void *)-1) {
2059 /*@-noeffect@*/ munmap(mapped, nmapped) /*@=noeffect@*/;
2064 } else if (writeData && S_ISLNK(st->st_mode)) {
2065 /* XXX DWRITE uses rdnb for I/O length. */
2066 rc = fsmStage(fsm, FSM_DWRITE);
2071 rc = fsmStage(fsm, FSM_PAD);
2074 if (ts && fi && ts->notify) {
2075 size_t size = (fdGetCpioPos(fsm->cfd) - pos);
2076 (void)ts->notify(fi->h, RPMCALLBACK_INST_PROGRESS, size, size,
2077 (fi->ap ? fi->ap->key : NULL), ts->notifyData);
2084 (void) fsmStage(fsm, FSM_RCLOSE);
2085 fsm->opath = _free(fsm->opath);
2087 fsm->path = _free(fsm->path);
2093 * Write set of linked files to payload stream.
2094 * @param hlink set of linked files
2095 * @return 0 on success
2097 static int writeLinkedFile(FSM_t fsm, const struct hardLink * hlink)
2098 /*@modifies fsm->cfd, *fsm->failedFile @*/
2103 for (i = hlink->nlink - 1; i > hlink->linksLeft; i--) {
2104 (void) fsmSetIndex(fsm, hlink->filex[i]);
2105 fsm->map = hlink->fileMaps[i];
2106 fsm->sb = hlink->sb; /* structure assignment */
2107 if ((rc = writeFile(fsm, 0)) != 0)
2109 fsm->map = mapFree(fsm->map);
2112 i = hlink->linksLeft;
2113 (void) fsmSetIndex(fsm, hlink->filex[i]);
2114 fsm->map = hlink->fileMaps[i];
2115 fsm->sb = hlink->sb; /* structure assignment */
2116 if ((rc = writeFile(fsm, 1)))
2122 if (rc && fsm->failedFile && *fsm->failedFile == NULL)
2123 *fsm->failedFile = mapFsPath(fsm->map, NULL, NULL, NULL);
2124 fsm->map = mapFree(fsm->map);
2128 int cpioBuildArchive(FSM_t fsm)
2130 /*@-fullinitblock@*/
2131 struct hardLink hlinkList = { NULL };
2132 /*@=fullinitblock@*/
2133 struct stat * st = &fsm->sb;
2134 struct stat * ost = &fsm->osb;
2135 struct hardLink * hlink;
2136 size_t pos = fdGetCpioPos(fsm->cfd);
2139 hlinkList.next = NULL;
2143 rc = fsmStage(fsm, FSM_INIT);
2145 if (rc == CPIOERR_HDR_TRAILER) {
2152 (!fsmFlags(fsm, CPIO_FOLLOW_SYMLINKS) ? FSM_LSTAT : FSM_STAT));
2156 if (!S_ISDIR(ost->st_mode) && ost->st_nlink > 1) {
2157 hlink = hlinkList.next;
2159 (hlink->dev != ost->st_dev || hlink->inode != ost->st_ino))
2160 hlink = hlink->next;
2161 if (hlink == NULL) {
2162 hlink = newHardLink(ost, HARDLINK_BUILD);
2163 hlink->next = hlinkList.next;
2164 hlinkList.next = hlink;
2168 hlink->filex[hlink->linksLeft] = fsmGetIndex(fsm);
2169 hlink->fileMaps[hlink->linksLeft] = mapLink(fsm->map);
2171 if (hlink->linksLeft == 0) {
2172 struct hardLink * prev;
2173 rc = writeLinkedFile(fsm, hlink);
2176 fsm->path = _free(fsm->path);
2182 if (prev->next != hlink)
2184 prev->next = hlink->next;
2186 hlink = freeHardLink(hlink);
2188 } while ((prev = prev->next) != NULL);
2191 *st = *ost; /* structure assignment */
2192 rc = writeFile(fsm, 1);
2196 rc = fsmStage(fsm, FSM_COMMIT);
2200 while ((hlink = hlinkList.next) != NULL) {
2201 hlinkList.next = hlink->next;
2204 rc = writeLinkedFile(fsm, hlink);
2205 hlink = freeHardLink(hlink);
2209 { struct cpioCrcPhysicalHeader * hdr = (struct cpioCrcPhysicalHeader *)fsm->rdbuf;
2210 memset(hdr, '0', PHYS_HDR_SIZE);
2211 memcpy(hdr->magic, CPIO_NEWC_MAGIC, sizeof(hdr->magic));
2212 memcpy(hdr->nlink, "00000001", 8);
2213 memcpy(hdr->namesize, "0000000b", 8);
2214 memcpy(fsm->rdbuf + PHYS_HDR_SIZE, "TRAILER!!!", sizeof("TRAILER!!!"));
2216 /* XXX DWRITE uses rdnb for I/O length. */
2217 fsm->rdnb = PHYS_HDR_SIZE + sizeof("TRAILER!!!");
2218 rc = fsmStage(fsm, FSM_DWRITE);
2223 * GNU cpio pads to 512 bytes here, but we don't. This may matter for
2224 * for tape device access and/or concateneated cpio archives.
2226 rc = fsmStage(fsm, FSM_PAD);
2228 if (!rc && fsm->archiveSize)
2229 *fsm->archiveSize = (fdGetCpioPos(fsm->cfd) - pos);
2232 if (rc && fsm->path && fsm->failedFile && *fsm->failedFile == NULL)
2233 *fsm->failedFile = xstrdup(fsm->path);
2234 fsm->path = _free(fsm->path);
2238 const char *const cpioStrerror(int rc)
2240 static char msg[256];
2242 int l, myerrno = errno;
2244 strcpy(msg, "cpio: ");
2247 s = msg + strlen(msg);
2248 sprintf(s, _("(error 0x%x)"), (unsigned)rc);
2251 case CPIOERR_BAD_MAGIC: s = _("Bad magic"); break;
2252 case CPIOERR_BAD_HEADER: s = _("Bad/unreadable header");break;
2254 case CPIOERR_OPEN_FAILED: s = "open"; break;
2255 case CPIOERR_CHMOD_FAILED: s = "chmod"; break;
2256 case CPIOERR_CHOWN_FAILED: s = "chown"; break;
2257 case CPIOERR_WRITE_FAILED: s = "write"; break;
2258 case CPIOERR_UTIME_FAILED: s = "utime"; break;
2259 case CPIOERR_UNLINK_FAILED: s = "unlink"; break;
2260 case CPIOERR_RENAME_FAILED: s = "rename"; break;
2261 case CPIOERR_SYMLINK_FAILED: s = "symlink"; break;
2262 case CPIOERR_STAT_FAILED: s = "stat"; break;
2263 case CPIOERR_LSTAT_FAILED: s = "lstat"; break;
2264 case CPIOERR_MKDIR_FAILED: s = "mkdir"; break;
2265 case CPIOERR_RMDIR_FAILED: s = "rmdir"; break;
2266 case CPIOERR_MKNOD_FAILED: s = "mknod"; break;
2267 case CPIOERR_MKFIFO_FAILED: s = "mkfifo"; break;
2268 case CPIOERR_LINK_FAILED: s = "link"; break;
2269 case CPIOERR_READLINK_FAILED: s = "readlink"; break;
2270 case CPIOERR_READ_FAILED: s = "read"; break;
2271 case CPIOERR_COPY_FAILED: s = "copy"; break;
2273 case CPIOERR_HDR_SIZE: s = _("Header size too big"); break;
2274 case CPIOERR_UNKNOWN_FILETYPE: s = _("Unknown file type"); break;
2275 case CPIOERR_MISSING_HARDLINK: s = _("Missing hard link"); break;
2276 case CPIOERR_MD5SUM_MISMATCH: s = _("MD5 sum mismatch"); break;
2277 case CPIOERR_INTERNAL: s = _("Internal error"); break;
2280 l = sizeof(msg) - strlen(msg) - 1;
2282 if (l > 0) strncat(msg, s, l);
2285 if ((rc & CPIOERR_CHECK_ERRNO) && myerrno) {
2286 s = _(" failed - ");
2287 if (l > 0) strncat(msg, s, l);
2289 if (l > 0) strncat(msg, strerror(myerrno), l);