xbps-create: multiple fixes and new additions, 1 item left to finish.
- Added "build-date" object to XBPS_PKGPROPS. - Added "installed_size" object to XBPS_PKGPROPS. - Add entries to archive with "./" as prefix to match xbps-src. - Create binpkg atomically (from caller's perspective) in cwd. (cherry picked from commit efeae7c346e914bca045ffe44627c18321e45be9)
This commit is contained in:
parent
6d6d31ccc0
commit
215f6d6f31
@ -40,6 +40,9 @@
|
||||
#include <xbps_api.h>
|
||||
#include "queue.h"
|
||||
|
||||
/*
|
||||
* XXX: Add a flag to set "packaged-with" object in XBPS_PKGPROPS?
|
||||
*/
|
||||
#define _PROGNAME "xbps-create"
|
||||
|
||||
struct xentry {
|
||||
@ -50,6 +53,7 @@ struct xentry {
|
||||
static TAILQ_HEAD(xentry_head, xentry) xentry_list =
|
||||
TAILQ_HEAD_INITIALIZER(xentry_list);
|
||||
|
||||
static uint64_t instsize;
|
||||
static prop_dictionary_t pkg_propsd, pkg_filesd;
|
||||
static const char *destdir;
|
||||
|
||||
@ -166,17 +170,18 @@ ftw_cb(const char *fpath, const struct stat *sb, int type, struct FTW *ftwbuf)
|
||||
(void)sb;
|
||||
(void)ftwbuf;
|
||||
|
||||
/* Ignore metadata files generated by xbps-src and destdir */
|
||||
if ((strcmp(fpath, ".") == 0) ||
|
||||
(strcmp(fpath, "./props.plist") == 0) ||
|
||||
(strcmp(fpath, "./files.plist") == 0))
|
||||
(strcmp(fpath, "./files.plist") == 0) ||
|
||||
(strcmp(fpath, "./flist") == 0))
|
||||
return 0;
|
||||
|
||||
/* sanitized file path */
|
||||
filep = strchr(fpath, '/') + 1;
|
||||
|
||||
filep = strchr(fpath, '.') + 1;
|
||||
xe = calloc(1, sizeof(*xe));
|
||||
assert(xe);
|
||||
xe->file = strdup(filep);
|
||||
xe->file = strdup(fpath);
|
||||
assert(xe->file);
|
||||
|
||||
if ((strcmp(fpath, "./INSTALL") == 0) ||
|
||||
@ -188,10 +193,13 @@ ftw_cb(const char *fpath, const struct stat *sb, int type, struct FTW *ftwbuf)
|
||||
}
|
||||
|
||||
if (type == FTW_SL) {
|
||||
/* symlink */
|
||||
/*
|
||||
* Symlinks.
|
||||
*
|
||||
* Find out target file.
|
||||
*/
|
||||
xe->type = strdup("links");
|
||||
assert(xe->type);
|
||||
/* Find out target file */
|
||||
memset(&buf, 0, sizeof(buf));
|
||||
if (realpath(fpath, buf) == NULL)
|
||||
die("failed to process symlink `%s':", filep);
|
||||
@ -200,9 +208,10 @@ ftw_cb(const char *fpath, const struct stat *sb, int type, struct FTW *ftwbuf)
|
||||
xe->target = strdup(filep);
|
||||
assert(xe->target);
|
||||
} else if (type == FTW_F) {
|
||||
/* file */
|
||||
/*
|
||||
* Find out if it's a configuration file or not.
|
||||
* Regular files.
|
||||
* Find out if it's a configuration file or not
|
||||
* and calculate sha256 hash.
|
||||
*/
|
||||
if (entry_is_conf_file(filep))
|
||||
xe->type = strdup("conf_files");
|
||||
@ -210,9 +219,11 @@ ftw_cb(const char *fpath, const struct stat *sb, int type, struct FTW *ftwbuf)
|
||||
xe->type = strdup("files");
|
||||
|
||||
assert(xe->type);
|
||||
/* calculate sha256 hash */
|
||||
if ((xe->hash = xbps_file_hash(fpath)) == NULL)
|
||||
die("failed to process hash for %s:", fpath);
|
||||
|
||||
instsize += sb->st_size;
|
||||
|
||||
} else if (type == FTW_D) {
|
||||
/* directory */
|
||||
xe->type = strdup("dirs");
|
||||
@ -230,6 +241,7 @@ process_xentry(const char *key)
|
||||
prop_array_t a;
|
||||
prop_dictionary_t d;
|
||||
struct xentry *xe;
|
||||
char *p;
|
||||
bool found = false;
|
||||
|
||||
a = prop_array_create();
|
||||
@ -242,7 +254,9 @@ process_xentry(const char *key)
|
||||
found = true;
|
||||
d = prop_dictionary_create();
|
||||
assert(d);
|
||||
prop_dictionary_set_cstring(d, "file", xe->file);
|
||||
/* sanitize file path */
|
||||
p = strchr(xe->file, '.') + 1;
|
||||
prop_dictionary_set_cstring(d, "file", p);
|
||||
if (xe->target)
|
||||
prop_dictionary_set_cstring(d, "target", xe->target);
|
||||
else if (xe->hash)
|
||||
@ -280,7 +294,7 @@ process_entry_file(struct archive *ar, struct xentry *xe, const char *filematch)
|
||||
{
|
||||
struct archive *ard;
|
||||
struct archive_entry *entry;
|
||||
char buf[BUFSIZ];
|
||||
char buf[BUFSIZ], *p;
|
||||
int fd;
|
||||
size_t len;
|
||||
|
||||
@ -299,8 +313,11 @@ process_entry_file(struct archive *ar, struct xentry *xe, const char *filematch)
|
||||
assert(entry);
|
||||
archive_entry_set_pathname(entry, xe->file);
|
||||
|
||||
if ((fd = open(xe->file, O_RDONLY)) == -1)
|
||||
die("failed to add entry (open) %s to archive:", xe->file);
|
||||
p = xbps_xasprintf("%s/%s", destdir, xe->file);
|
||||
assert(p);
|
||||
|
||||
if ((fd = open(p, O_RDONLY)) == -1)
|
||||
die("failed to add entry (open) %s %s to archive:", xe->file);
|
||||
|
||||
if ((archive_read_disk_entry_from_file(ard, entry, fd, NULL)) != 0)
|
||||
die("failed to add entry %s to archive:", xe->file);
|
||||
@ -310,6 +327,7 @@ process_entry_file(struct archive *ar, struct xentry *xe, const char *filematch)
|
||||
while ((len = read(fd, buf, sizeof(buf))) > 0)
|
||||
archive_write_data(ar, buf, len);
|
||||
|
||||
free(p);
|
||||
close(fd);
|
||||
archive_entry_free(entry);
|
||||
archive_read_free(ard);
|
||||
@ -365,20 +383,24 @@ process_archive(struct archive *ar, const char *pkgver)
|
||||
|
||||
/* Add INSTALL/REMOVE metadata scripts first */
|
||||
TAILQ_FOREACH(xe, &xentry_list, entries) {
|
||||
process_entry_file(ar, xe, "INSTALL");
|
||||
process_entry_file(ar, xe, "REMOVE");
|
||||
process_entry_file(ar, xe, "./INSTALL");
|
||||
process_entry_file(ar, xe, "./REMOVE");
|
||||
}
|
||||
/*
|
||||
* Add the installed-size object.
|
||||
*/
|
||||
prop_dictionary_set_uint64(pkg_propsd, "installed_size", instsize);
|
||||
|
||||
/* Add props.plist metadata file */
|
||||
xml = prop_dictionary_externalize(pkg_propsd);
|
||||
assert(xml);
|
||||
process_entry_memory(ar, xml, "props.plist");
|
||||
process_entry_memory(ar, xml, "./props.plist");
|
||||
free(xml);
|
||||
|
||||
/* Add files.plist metadata file */
|
||||
xml = prop_dictionary_externalize(pkg_filesd);
|
||||
assert(xml);
|
||||
process_entry_memory(ar, xml, "files.plist");
|
||||
process_entry_memory(ar, xml, "./files.plist");
|
||||
free(xml);
|
||||
|
||||
/* Add all package data files and release resources */
|
||||
@ -396,6 +418,24 @@ process_archive(struct archive *ar, const char *pkgver)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_build_date(void)
|
||||
{
|
||||
char outstr[64];
|
||||
time_t t;
|
||||
struct tm *tmp;
|
||||
|
||||
t = time(NULL);
|
||||
tmp = localtime(&t);
|
||||
assert(tmp);
|
||||
|
||||
if (strftime(outstr, sizeof(outstr)-1, "%F %R %Z", tmp) == 0)
|
||||
die("failed to set build-date object (strftime):");
|
||||
|
||||
if (!prop_dictionary_set_cstring(pkg_propsd, "build-date", outstr))
|
||||
die("failed to add build-date object:");
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@ -423,9 +463,10 @@ main(int argc, char **argv)
|
||||
const char *conflicts, *deps, *homepage, *license, *maint;
|
||||
const char *provides, *pkgver, *replaces, *desc, *ldesc;
|
||||
const char *arch, *config_files, *mutable_files, *version;
|
||||
char *pkgname, *binpkg;
|
||||
char *pkgname, *binpkg, *tname, *p, cwd[PATH_MAX-1];
|
||||
bool preserve = false;
|
||||
int c;
|
||||
int c, pkg_fd;
|
||||
mode_t myumask;
|
||||
|
||||
arch = conflicts = deps = homepage = license = maint = NULL;
|
||||
provides = pkgver = replaces = desc = ldesc = NULL;
|
||||
@ -524,6 +565,7 @@ main(int argc, char **argv)
|
||||
prop_dictionary_set_cstring_nocopy(pkg_propsd, "version", version);
|
||||
prop_dictionary_set_cstring_nocopy(pkg_propsd, "pkgver", pkgver);
|
||||
prop_dictionary_set_cstring_nocopy(pkg_propsd, "short_desc", desc);
|
||||
set_build_date();
|
||||
|
||||
/* Optional properties */
|
||||
if (homepage)
|
||||
@ -544,8 +586,13 @@ main(int argc, char **argv)
|
||||
process_array("provides", provides);
|
||||
process_array("replaces", replaces);
|
||||
|
||||
/* save cwd */
|
||||
memset(&cwd, 0, sizeof(cwd));
|
||||
p = getcwd(cwd, sizeof(cwd));
|
||||
assert(p);
|
||||
|
||||
if (chdir(destdir) == -1)
|
||||
die("cannot chdir() to destdir:");
|
||||
die("cannot chdir() to destdir %s:", destdir);
|
||||
/*
|
||||
* Process XBPS_PKGFILES metadata file.
|
||||
*/
|
||||
@ -553,29 +600,56 @@ main(int argc, char **argv)
|
||||
assert(pkg_filesd);
|
||||
process_destdir();
|
||||
|
||||
/* Back to original cwd after file tree walk processing */
|
||||
if (chdir(cwd) == -1)
|
||||
die("cannot chdir() to cwd %s:", cwd);
|
||||
|
||||
/*
|
||||
* Create the real XBPS binary package (ustar compressed with xz).
|
||||
* Create a temp file to store archive data.
|
||||
*/
|
||||
tname = xbps_xasprintf(".xbps-pkg-XXXXXX");
|
||||
assert(tname);
|
||||
pkg_fd = mkstemp(tname);
|
||||
assert(pkg_fd != -1);
|
||||
/*
|
||||
* Process the binary package's archive (ustar compressed with xz).
|
||||
*/
|
||||
ar = archive_write_new();
|
||||
assert(ar);
|
||||
archive_write_add_filter_xz(ar);
|
||||
archive_write_set_format_ustar(ar);
|
||||
archive_write_set_options(ar, "compression-level=9");
|
||||
|
||||
binpkg = xbps_xasprintf("%s.%s.xbps", pkgver, arch);
|
||||
assert(binpkg);
|
||||
if (archive_write_open_filename(ar, binpkg) != 0)
|
||||
die("failed to create %s:", binpkg);
|
||||
if (archive_write_open_fd(ar, pkg_fd) != 0)
|
||||
die("Failed to open %s fd for writing:", tname);
|
||||
|
||||
process_archive(ar, pkgver);
|
||||
archive_write_free(ar);
|
||||
/*
|
||||
* Archive was created successfully; flush data to storage,
|
||||
* set permissions and rename to dest file; from the caller's
|
||||
* perspective it's atomic.
|
||||
*/
|
||||
binpkg = xbps_xasprintf("%s.%s.xbps", pkgver, arch);
|
||||
assert(binpkg);
|
||||
|
||||
printf("%s: binary package created successfully: %s.\n", pkgver, binpkg);
|
||||
(void)fsync(pkg_fd);
|
||||
myumask = umask(0);
|
||||
(void)umask(myumask);
|
||||
|
||||
if (fchmod(pkg_fd, 0666 & ~myumask) == -1)
|
||||
die("cannot fchmod() %s:", tname);
|
||||
|
||||
if (rename(tname, binpkg) == -1)
|
||||
die("cannot rename %s to %s:", tname, binpkg);
|
||||
|
||||
/* Success, release resources */
|
||||
printf("%s: binary package created successfully (%s)\n", pkgver, binpkg);
|
||||
|
||||
prop_object_release(pkg_propsd);
|
||||
prop_object_release(pkg_filesd);
|
||||
free(binpkg);
|
||||
free(pkgname);
|
||||
close(pkg_fd);
|
||||
prop_object_release(pkg_propsd);
|
||||
prop_object_release(pkg_filesd);
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user