Create first hard link file and keep open, write it at end upstream commit e276991614fd127f21aba94946f81f22cb7e6b73 upstream commit 0afe0c3c6cba64d8b7adcdec6ed70f8d32961b58 upstream commit ef3ff412c33a71be6b3543a50c244377dff3d9e7 --- ./lib/fsm.c.orig 2017-10-05 10:04:56.977602149 +0000 +++ ./lib/fsm.c 2017-12-05 12:05:19.529973029 +0000 @@ -218,56 +218,76 @@ static int linkSane(FD_t wfd, const char sb.st_dev == lsb.st_dev && sb.st_ino == lsb.st_ino); } -/** \ingroup payload - * Create file from payload stream. - * @return 0 on success - */ -static int expandRegular(rpmfi fi, const char *dest, rpmpsm psm, int exclusive, int nodigest, int nocontent) +static void wfd_close(FD_t *wfdp) { - FD_t wfd = NULL; - int rc = 0; + if (wfdp && *wfdp) { + int myerrno = errno; + static int oneshot = 0; + static int flush_io = 0; + if (!oneshot) { + flush_io = rpmExpandNumeric("%{?_flush_io}"); + oneshot = 1; + } + if (flush_io) { + int fdno = Fileno(*wfdp); + fsync(fdno); + } + Fclose(*wfdp); + *wfdp = NULL; + errno = myerrno; + } +} +static int wfd_open(FD_t *wfdp, const char *dest, int exclusive) +{ + int rc = 0; /* Create the file with 0200 permissions (write by owner). */ { mode_t old_umask = umask(0577); - wfd = Fopen(dest, exclusive ? "wx.ufdio" : "a.ufdio"); + *wfdp = Fopen(dest, exclusive ? "wx.ufdio" : "a.ufdio"); umask(old_umask); /* If reopening, make sure the file is what we expect */ - if (!exclusive && wfd != NULL && !linkSane(wfd, dest)) { + if (!exclusive && *wfdp != NULL && !linkSane(*wfdp, dest)) { rc = RPMERR_OPEN_FAILED; goto exit; } } - if (Ferror(wfd)) { + if (Ferror(*wfdp)) { rc = RPMERR_OPEN_FAILED; goto exit; } + return 0; + +exit: + wfd_close(wfdp); + return rc; +} + +/** \ingroup payload + * Create file from payload stream. + * @return 0 on success + */ +static int expandRegular(rpmfi fi, const char *dest, rpmpsm psm, int exclusive, int nodigest, int nocontent) +{ + FD_t wfd = NULL; + int rc; + + rc = wfd_open(&wfd, dest, exclusive); + if (rc != 0) + goto exit; + if (!nocontent) rc = rpmfiArchiveReadToFilePsm(fi, wfd, nodigest, psm); + wfd_close(&wfd); exit: - if (wfd) { - int myerrno = errno; - static int oneshot = 0; - static int flush_io = 0; - if (!oneshot) { - flush_io = rpmExpandNumeric("%{?_flush_io}"); - oneshot = 1; - } - if (flush_io) { - int fdno = Fileno(wfd); - fsync(fdno); - } - Fclose(wfd); - errno = myerrno; - } return rc; } static int fsmMkfile(rpmfi fi, const char *dest, rpmfiles files, rpmpsm psm, int nodigest, int *setmeta, - int * firsthardlink) + int * firsthardlink, FD_t *firstlinkfile) { int rc = 0; int numHardlinks = rpmfiFNlink(fi); @@ -276,7 +296,7 @@ static int fsmMkfile(rpmfi fi, const cha /* Create first hardlinked file empty */ if (*firsthardlink < 0) { *firsthardlink = rpmfiFX(fi); - rc = expandRegular(fi, dest, psm, 1, nodigest, 1); + rc = wfd_open(firstlinkfile, dest, 1); } else { /* Create hard links for others */ char *fn = rpmfilesFN(files, *firsthardlink); @@ -294,7 +314,8 @@ static int fsmMkfile(rpmfi fi, const cha rc = expandRegular(fi, dest, psm, 1, nodigest, 0); } else if (rpmfiArchiveHasContent(fi)) { if (!rc) - rc = expandRegular(fi, dest, psm, 0, nodigest, 0); + rc = rpmfiArchiveReadToFilePsm(fi, *firstlinkfile, nodigest, psm); + wfd_close(firstlinkfile); *firsthardlink = -1; } else { *setmeta = 0; @@ -861,6 +882,7 @@ int rpmPackageFilesInstall(rpmts ts, rpm int nodigest = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOFILEDIGEST) ? 1 : 0; int nofcaps = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOCAPS) ? 1 : 0; int firsthardlink = -1; + FD_t firstlinkfile = NULL; int skip; rpmFileAction action; char *tid = NULL; @@ -932,7 +954,7 @@ int rpmPackageFilesInstall(rpmts ts, rpm if (S_ISREG(sb.st_mode)) { if (rc == RPMERR_ENOENT) { rc = fsmMkfile(fi, fpath, files, psm, nodigest, - &setmeta, &firsthardlink); + &setmeta, &firsthardlink, &firstlinkfile); } } else if (S_ISDIR(sb.st_mode)) { if (rc == RPMERR_ENOENT) { @@ -970,7 +992,8 @@ int rpmPackageFilesInstall(rpmts ts, rpm /* we skip the hard linked file containing the content */ /* write the content to the first used instead */ char *fn = rpmfilesFN(files, firsthardlink); - rc = expandRegular(fi, fn, psm, 0, nodigest, 0); + rc = rpmfiArchiveReadToFilePsm(fi, firstlinkfile, nodigest, psm); + wfd_close(&firstlinkfile); firsthardlink = -1; free(fn); }