bin/xbps-create: construct proplist objects in ftw.
This is the first commit in a series to make xbps-create build reproducable packages. xbps-create uses nftw(3) to walk through all files. As nftw doesn't sort files it may happen that the resulting packages will have different checksums due to differentiating orders of files on different filesystems. To solve this issue xbps-create uses xbps_directory_t, which is always sorted, instead of a simple linked list.
This commit is contained in:
parent
35ad10ccbd
commit
5c18a43c1c
@ -66,7 +66,7 @@ static TAILQ_HEAD(xentry_head, xentry) xentry_list =
|
|||||||
TAILQ_HEAD_INITIALIZER(xentry_list);
|
TAILQ_HEAD_INITIALIZER(xentry_list);
|
||||||
|
|
||||||
static uint64_t instsize;
|
static uint64_t instsize;
|
||||||
static xbps_dictionary_t pkg_propsd, pkg_filesd;
|
static xbps_dictionary_t pkg_propsd, pkg_filesd, all_filesd;
|
||||||
static const char *destdir;
|
static const char *destdir;
|
||||||
|
|
||||||
static void __attribute__((noreturn))
|
static void __attribute__((noreturn))
|
||||||
@ -303,6 +303,7 @@ static int
|
|||||||
ftw_cb(const char *fpath, const struct stat *sb, int type, struct FTW *ftwbuf _unused)
|
ftw_cb(const char *fpath, const struct stat *sb, int type, struct FTW *ftwbuf _unused)
|
||||||
{
|
{
|
||||||
struct xentry *xe = NULL;
|
struct xentry *xe = NULL;
|
||||||
|
xbps_dictionary_t fileinfo = NULL;
|
||||||
const char *filep = NULL;
|
const char *filep = NULL;
|
||||||
char *buf, *p, *p2, *dname;
|
char *buf, *p, *p2, *dname;
|
||||||
ssize_t r;
|
ssize_t r;
|
||||||
@ -321,14 +322,24 @@ ftw_cb(const char *fpath, const struct stat *sb, int type, struct FTW *ftwbuf _u
|
|||||||
|
|
||||||
/* sanitized file path */
|
/* sanitized file path */
|
||||||
filep = strchr(fpath, '.') + 1;
|
filep = strchr(fpath, '.') + 1;
|
||||||
|
fileinfo = xbps_dictionary_create();
|
||||||
xe = calloc(1, sizeof(*xe));
|
xe = calloc(1, sizeof(*xe));
|
||||||
assert(xe);
|
assert(xe);
|
||||||
|
/* XXX: fileinfo contains the sanatized path, whereas xe contains the
|
||||||
|
* unsanatized path!
|
||||||
|
*
|
||||||
|
* when handing the files over, do not use the dictionary directly. Instead
|
||||||
|
* use the keysym, as this value has the unsanatized path.
|
||||||
|
*/
|
||||||
|
xbps_dictionary_set_cstring(fileinfo, "file", filep);
|
||||||
|
xbps_dictionary_set(all_filesd, fpath, fileinfo);
|
||||||
xe->file = strdup(fpath);
|
xe->file = strdup(fpath);
|
||||||
assert(xe->file);
|
assert(xe->file);
|
||||||
|
|
||||||
if ((strcmp(fpath, "./INSTALL") == 0) ||
|
if ((strcmp(fpath, "./INSTALL") == 0) ||
|
||||||
(strcmp(fpath, "./REMOVE") == 0)) {
|
(strcmp(fpath, "./REMOVE") == 0)) {
|
||||||
/* metadata file */
|
/* metadata file */
|
||||||
|
xbps_dictionary_set_cstring_nocopy(fileinfo, "type", "metadata");
|
||||||
xe->type = strdup("metadata");
|
xe->type = strdup("metadata");
|
||||||
assert(xe->type);
|
assert(xe->type);
|
||||||
goto out;
|
goto out;
|
||||||
@ -340,10 +351,13 @@ ftw_cb(const char *fpath, const struct stat *sb, int type, struct FTW *ftwbuf _u
|
|||||||
*
|
*
|
||||||
* Find out target file.
|
* Find out target file.
|
||||||
*/
|
*/
|
||||||
|
xbps_dictionary_set_cstring_nocopy(fileinfo, "type", "links");
|
||||||
xe->type = strdup("links");
|
xe->type = strdup("links");
|
||||||
assert(xe->type);
|
assert(xe->type);
|
||||||
/* store modification time for regular files and links */
|
/* store modification time for regular files and links */
|
||||||
|
xbps_dictionary_set_cstring_nocopy(fileinfo, "type", "links");
|
||||||
xe->mtime = (uint64_t)sb->st_mtime;
|
xe->mtime = (uint64_t)sb->st_mtime;
|
||||||
|
xbps_dictionary_set_uint64(fileinfo, "mtime", (uint64_t)sb->st_mtime);
|
||||||
buf = malloc(sb->st_size+1);
|
buf = malloc(sb->st_size+1);
|
||||||
assert(buf);
|
assert(buf);
|
||||||
r = readlink(fpath, buf, sb->st_size+1);
|
r = readlink(fpath, buf, sb->st_size+1);
|
||||||
@ -364,6 +378,7 @@ ftw_cb(const char *fpath, const struct stat *sb, int type, struct FTW *ftwbuf _u
|
|||||||
* So let's use the same target.
|
* So let's use the same target.
|
||||||
*/
|
*/
|
||||||
xe->target = strdup(buf);
|
xe->target = strdup(buf);
|
||||||
|
xbps_dictionary_set_cstring(fileinfo, "target", buf);
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Sanitize destdir just in case.
|
* Sanitize destdir just in case.
|
||||||
@ -372,6 +387,7 @@ ftw_cb(const char *fpath, const struct stat *sb, int type, struct FTW *ftwbuf _u
|
|||||||
die("failed to sanitize destdir %s: %s", destdir, strerror(errno));
|
die("failed to sanitize destdir %s: %s", destdir, strerror(errno));
|
||||||
|
|
||||||
xe->target = strdup(p+strlen(p2));
|
xe->target = strdup(p+strlen(p2));
|
||||||
|
xbps_dictionary_set_cstring(fileinfo, "target", p+strlen(p2));
|
||||||
free(p2);
|
free(p2);
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
@ -382,11 +398,16 @@ ftw_cb(const char *fpath, const struct stat *sb, int type, struct FTW *ftwbuf _u
|
|||||||
dname = dirname(p);
|
dname = dirname(p);
|
||||||
assert(dname);
|
assert(dname);
|
||||||
xe->target = xbps_xasprintf("%s/%s", dname, buf);
|
xe->target = xbps_xasprintf("%s/%s", dname, buf);
|
||||||
|
p2 = xbps_xasprintf("%s/%s", dname, buf);
|
||||||
|
xbps_dictionary_set_cstring(fileinfo, "target", p2);
|
||||||
|
free(p2);
|
||||||
free(p);
|
free(p);
|
||||||
} else {
|
} else {
|
||||||
xe->target = strdup(buf);
|
xe->target = strdup(buf);
|
||||||
|
xbps_dictionary_set_cstring(fileinfo, "target", buf);
|
||||||
}
|
}
|
||||||
assert(xe->target);
|
assert(xe->target);
|
||||||
|
assert(xbps_dictionary_get(fileinfo, "target"));
|
||||||
free(buf);
|
free(buf);
|
||||||
} else if (type == FTW_F) {
|
} else if (type == FTW_F) {
|
||||||
struct xentry *xep;
|
struct xentry *xep;
|
||||||
@ -410,26 +431,37 @@ ftw_cb(const char *fpath, const struct stat *sb, int type, struct FTW *ftwbuf _u
|
|||||||
* Find out if it's a configuration file or not
|
* Find out if it's a configuration file or not
|
||||||
* and calculate sha256 hash.
|
* and calculate sha256 hash.
|
||||||
*/
|
*/
|
||||||
if (entry_is_conf_file(filep))
|
if (entry_is_conf_file(filep)) {
|
||||||
|
xbps_dictionary_set_cstring_nocopy(fileinfo, "type", "conf_files");
|
||||||
xe->type = strdup("conf_files");
|
xe->type = strdup("conf_files");
|
||||||
else
|
} else {
|
||||||
|
xbps_dictionary_set_cstring_nocopy(fileinfo, "type", "files");
|
||||||
xe->type = strdup("files");
|
xe->type = strdup("files");
|
||||||
|
}
|
||||||
|
|
||||||
assert(xe->type);
|
assert(xe->type);
|
||||||
|
if ((p = xbps_file_hash(fpath)) == NULL)
|
||||||
|
die("failed to process hash for %s:", fpath);
|
||||||
|
xbps_dictionary_set_cstring(fileinfo, "sha256", p);
|
||||||
|
free(p);
|
||||||
if ((xe->hash = xbps_file_hash(fpath)) == NULL)
|
if ((xe->hash = xbps_file_hash(fpath)) == NULL)
|
||||||
die("failed to process hash for %s:", fpath);
|
die("failed to process hash for %s:", fpath);
|
||||||
|
|
||||||
|
xbps_dictionary_set_uint64(fileinfo, "inode", sb->st_ino);
|
||||||
xe->inode = sb->st_ino;
|
xe->inode = sb->st_ino;
|
||||||
/* store modification time for regular files and links */
|
/* store modification time for regular files and links */
|
||||||
|
xbps_dictionary_set_uint64(fileinfo, "mtime", sb->st_mtime);
|
||||||
xe->mtime = (uint64_t)sb->st_mtime;
|
xe->mtime = (uint64_t)sb->st_mtime;
|
||||||
|
|
||||||
} else if (type == FTW_D || type == FTW_DP) {
|
} else if (type == FTW_D || type == FTW_DP) {
|
||||||
/* directory */
|
/* directory */
|
||||||
|
xbps_dictionary_set_cstring_nocopy(fileinfo, "type", "dirs");
|
||||||
xe->type = strdup("dirs");
|
xe->type = strdup("dirs");
|
||||||
assert(xe->type);
|
assert(xe->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
xbps_object_release(fileinfo);
|
||||||
TAILQ_INSERT_TAIL(&xentry_list, xe, entries);
|
TAILQ_INSERT_TAIL(&xentry_list, xe, entries);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -889,6 +921,8 @@ main(int argc, char **argv)
|
|||||||
*/
|
*/
|
||||||
pkg_filesd = xbps_dictionary_create();
|
pkg_filesd = xbps_dictionary_create();
|
||||||
assert(pkg_filesd);
|
assert(pkg_filesd);
|
||||||
|
all_filesd = xbps_dictionary_create();
|
||||||
|
assert(all_filesd);
|
||||||
process_destdir(mutable_files);
|
process_destdir(mutable_files);
|
||||||
|
|
||||||
/* Back to original cwd after file tree walk processing */
|
/* Back to original cwd after file tree walk processing */
|
||||||
|
Loading…
Reference in New Issue
Block a user