diff options
author | Panu Matilainen <pmatilai@redhat.com> | 2012-02-10 10:40:45 +0200 |
---|---|---|
committer | Panu Matilainen <pmatilai@redhat.com> | 2012-02-10 10:40:45 +0200 |
commit | 7a9a5505667c681044bacb21c9b84ac66c062fe7 (patch) | |
tree | 336d8d147fbcbfce79ace0b16f3a58f10b18ae0d | |
parent | da0091cfc754d84cd0f7f2d2711ebb7c073f892b (diff) | |
download | librpm-tizen-7a9a5505667c681044bacb21c9b84ac66c062fe7.tar.gz librpm-tizen-7a9a5505667c681044bacb21c9b84ac66c062fe7.tar.bz2 librpm-tizen-7a9a5505667c681044bacb21c9b84ac66c062fe7.zip |
Remap inode numbers to fit into 32bit integer space on build (RhBug:714678)
- 64bit inode numbers lose their uniquity when brutally truncated
to 32bit integers as we've done so far. This can and will cause rpm
(and cpio) to mix up arbitrary file entries as hardlinks and vice versa.
- As the only interesting aspect of inode numbers is whether they're
equal to something else or not, we dont have to carry the "physical"
on-disk value to preserve semantics. So we can just remap the
inode numbers to something that fits our 32bit integer tags
without causing compatibility complexies with older rpms and
cpio (and since we can't handle more than INT32_MAX files in a package
anyway, breaking compatibility for this would be just braindead dumb).
An extremely simple way to achieve this is to use our
build-time file list index as the basis of stored inode number.
- In theory this breaks inode-device pairing, but as the buildroot
cannot span across filesystems in any remotely normal conditions,
just add a sanity check to catch the dirty tricksters...
- Based on a patch by Zdenek Pavlas, just further simplified and
buildroot fs boundary sanity check added.
-rw-r--r-- | build/files.c | 27 | ||||
-rw-r--r-- | lib/fsm.c | 2 |
2 files changed, 26 insertions, 3 deletions
diff --git a/build/files.c b/build/files.c index 64344f7d5..5d7829bb1 100644 --- a/build/files.c +++ b/build/files.c @@ -986,10 +986,11 @@ static int checkHardLinks(FileList fl) return 0; } -static int seenHardLink(FileList fl, FileListRec flp) +static int seenHardLink(FileList fl, FileListRec flp, rpm_ino_t *fileid) { for (FileListRec ilp = fl->fileList; ilp < flp; ilp++) { if (isHardLink(flp, ilp)) { + *fileid = ilp - fl->fileList; return 1; } } @@ -1017,6 +1018,7 @@ static void genCpioListAndHeader(FileList fl, int i; uint32_t defaultalgo = PGPHASHALGO_MD5, digestalgo; rpm_loff_t totalFileSize = 0; + dev_t brdev = 0; /* * See if non-md5 file digest algorithm is requested. If not @@ -1045,6 +1047,8 @@ static void genCpioListAndHeader(FileList fl, } for (i = 0, flp = fl->fileList; i < fl->fileListRecsUsed; i++, flp++) { + rpm_ino_t fileid = flp - fl->fileList; + /* Merge duplicate entries. */ while (i < (fl->fileListRecsUsed - 1) && rstreq(flp->cpioPath, flp[1].cpioPath)) { @@ -1099,6 +1103,17 @@ static void genCpioListAndHeader(FileList fl, /* Skip files that were marked with %exclude. */ if (flp->flags & RPMFILE_EXCLUDE) continue; + if (brdev == 0 && flp->fl_dev != 0) + brdev = flp->fl_dev; + /* + * We could handle this quite easily but it can't happen without + * some very dirty tricks, so just error out for now... + */ + if (brdev && flp->fl_dev && brdev != flp->fl_dev) { + rpmlog(RPMLOG_ERR, _("buildroot spans across filesystems\n")); + fl->processingFailed = 1; + } + /* Omit '/' and/or URL prefix, leave room for "./" prefix */ apathlen += (strlen(flp->cpioPath) - skipLen + (_addDotSlash ? 3 : 1)); @@ -1130,7 +1145,7 @@ static void genCpioListAndHeader(FileList fl, } /* Excludes and dupes have been filtered out by now. */ if (S_ISREG(flp->fl_mode)) { - if (flp->fl_nlink == 1 || !seenHardLink(fl, flp)) { + if (flp->fl_nlink == 1 || !seenHardLink(fl, flp, &fileid)) { totalFileSize += flp->fl_size; } } @@ -1156,7 +1171,13 @@ static void genCpioListAndHeader(FileList fl, headerPutUint32(h, RPMTAG_FILEDEVICES, &rdev, 1); } - { rpm_ino_t rino = (rpm_ino_t) flp->fl_ino; + /* + * To allow rpmbuild to work on filesystems with 64bit inodes numbers, + * remap them into 32bit integers based on filelist index, just + * preserving semantics for determining hardlinks. + * Start at 1 as inode zero as that could be considered as an error. + */ + { rpm_ino_t rino = fileid + 1; headerPutUint32(h, RPMTAG_FILEINODES, &rino, 1); } @@ -716,6 +716,7 @@ static int fsmMapAttrs(FSM_t fsm) /* this check is pretty moot, rpmfi accessors check array bounds etc */ if (fi && i >= 0 && i < rpmfiFC(fi)) { + ino_t finalInode = rpmfiFInodeIndex(fi, i); mode_t finalMode = rpmfiFModeIndex(fi, i); dev_t finalRdev = rpmfiFRdevIndex(fi, i); time_t finalMtime = rpmfiFMtimeIndex(fi, i); @@ -745,6 +746,7 @@ static int fsmMapAttrs(FSM_t fsm) if ((S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) && st->st_nlink == 0) st->st_nlink = 1; + st->st_ino = finalInode; st->st_rdev = finalRdev; st->st_mtime = finalMtime; } |