Skip to content

Commit 15f6374

Browse files
committed
lib: clean rewrite of the configuration file handling
1 parent 91a63a1 commit 15f6374

File tree

1 file changed

+107
-18
lines changed

1 file changed

+107
-18
lines changed

lib/package_unpack.c

Lines changed: 107 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*-
22
* Copyright (c) 2008-2015 Juan Romero Pardines.
3+
* Copyright (c) 2024 Duncan Overbruck <[email protected]>.
34
* All rights reserved.
45
*
56
* Redistribution and use in source and binary forms, with or without
@@ -79,15 +80,97 @@ match_preserved_file(struct xbps_handle *xhp, const char *entry)
7980
return xbps_match_string_in_array(xhp->preserved_files, file);
8081
}
8182

83+
enum {
84+
CONFFILE_SKIP = 0,
85+
CONFFILE_UPDATE = 1,
86+
CONFFILE_NEW = 2,
87+
};
88+
89+
static int
90+
handle_conffile(struct xbps_handle *xhp,
91+
const char *path,
92+
const struct xbps_file *old,
93+
const struct xbps_file *new,
94+
const struct stat *st)
95+
{
96+
char sha256_cur[XBPS_SHA256_SIZE];
97+
enum {
98+
MATCH_SAME = 1 << 0,
99+
MATCH_OLD = 1 << 1,
100+
MATCH_NEW = 1 << 2,
101+
} match = 0;
102+
103+
(void) xhp;
104+
105+
/* 1. File exist on disk, but was untracked, extract as new. */
106+
if (!old)
107+
return CONFFILE_NEW;
108+
109+
/* 2. File exists as link, extract as new. */
110+
if (S_ISLNK(st->st_mode))
111+
return CONFFILE_NEW;
112+
113+
if (!xbps_file_sha256(sha256_cur, sizeof(sha256_cur), path)) {
114+
if (errno == ENOENT)
115+
return 0;
116+
return -errno;
117+
}
118+
119+
if (old && strcmp(old->sha256, new->sha256) == 0)
120+
match |= MATCH_SAME;
121+
if (old && strcmp(sha256_cur, old->sha256) == 0)
122+
match |= MATCH_OLD;
123+
if (strcmp(sha256_cur, new->sha256) == 0)
124+
match |= MATCH_NEW;
125+
126+
if (match == (MATCH_SAME|MATCH_OLD|MATCH_NEW)) {
127+
/*
128+
* All files are the same, do nothing.
129+
*/
130+
return CONFFILE_SKIP;
131+
} else if (match == MATCH_SAME) {
132+
/*
133+
* Old and new package files are the same,
134+
* but on disk differs, extract as new.
135+
*/
136+
return CONFFILE_NEW;
137+
} else if (match == MATCH_NEW) {
138+
/*
139+
* File matches the new config file, do nothing.
140+
*/
141+
return CONFFILE_SKIP;
142+
} else if (match == MATCH_OLD) {
143+
/*
144+
* File matches the old config file:
145+
* If keep_conf is on, extract as new, otherwise
146+
* update the file.
147+
*/
148+
if (xhp->flags & XBPS_FLAG_KEEP_CONFIG)
149+
return CONFFILE_NEW;
150+
return CONFFILE_UPDATE;
151+
} else if (match == 0) {
152+
/*
153+
* Old and new file changes and on disk is also differnt,
154+
* extract as new.
155+
*/
156+
return CONFFILE_NEW;
157+
} else {
158+
return -EINVAL;
159+
}
160+
161+
return 0;
162+
}
163+
82164
static int
83165
unpack_archive(struct xbps_handle *xhp,
84166
xbps_dictionary_t pkg_repod,
85167
const char *pkgver,
86168
const char *fname,
87169
struct archive *ar)
88170
{
171+
char buf[PATH_MAX];
89172
const struct xbps_file *old = NULL, *new = NULL;
90-
xbps_dictionary_t binpkg_filesd, pkg_filesd, obsd;
173+
xbps_dictionary_t binpkg_filesd, obsd;
91174
xbps_array_t array, obsoletes;
92175
xbps_trans_type_t ttype;
93176
const struct stat *entry_statp;
@@ -96,13 +179,12 @@ unpack_archive(struct xbps_handle *xhp,
96179
struct archive_entry *entry;
97180
ssize_t entry_size;
98181
const char *entry_pname, *pkgname;
99-
char *buf = NULL;
100182
int ar_rv, rv, error, entry_type, flags;
101183
bool preserve, update, file_exists, keep_conf_file;
102184
bool skip_extract, force, xucd_stats;
103185
uid_t euid;
104186

105-
binpkg_filesd = pkg_filesd = NULL;
187+
binpkg_filesd = NULL;
106188
force = preserve = update = file_exists = false;
107189
xucd_stats = false;
108190
ar_rv = rv = error = entry_type = flags = 0;
@@ -207,11 +289,6 @@ unpack_archive(struct xbps_handle *xhp,
207289
goto out;
208290
}
209291

210-
/*
211-
* Internalize current pkg metadata files plist.
212-
*/
213-
pkg_filesd = xbps_pkgdb_get_pkg_files(xhp, pkgname);
214-
215292
/*
216293
* Unpack all files on archive now.
217294
*/
@@ -327,17 +404,32 @@ unpack_archive(struct xbps_handle *xhp,
327404
if (xhp->unpack_cb != NULL)
328405
xucd.entry_is_conf = true;
329406

330-
rv = xbps_entry_install_conf_file(xhp,
331-
binpkg_filesd, pkg_filesd, entry,
332-
entry_pname, pkgver, S_ISLNK(st.st_mode));
333-
if (rv == -1) {
407+
rv = handle_conffile(xhp, entry_pname, old, new, &st);
408+
if (rv < 0) {
334409
/* error */
410+
rv = -rv;
335411
goto out;
336-
} else if (rv == 0) {
412+
} else if (rv == CONFFILE_SKIP) {
337413
/*
338414
* Keep curfile as is.
339415
*/
340416
skip_extract = true;
417+
} else if (rv == CONFFILE_UPDATE) {
418+
/*
419+
* Update file.
420+
*/
421+
} else if (rv == CONFFILE_NEW) {
422+
/*
423+
* Extract as .new-$version.
424+
*/
425+
const char *version = xbps_pkg_version(pkgver);
426+
snprintf(buf, sizeof(buf), "%s.new-%s",
427+
entry_pname, version);
428+
xbps_set_cb_state(xhp, XBPS_STATE_CONFIG_FILE,
429+
0, pkgver, "File `%s' exists,"
430+
" installing configuration file"
431+
" to `%s'.", entry_pname+1, buf+1);
432+
archive_entry_copy_pathname(entry, buf);
341433
}
342434
rv = 0;
343435
} else {
@@ -460,27 +552,24 @@ unpack_archive(struct xbps_handle *xhp,
460552
if (xbps_dictionary_count(binpkg_filesd)) {
461553
mode_t prev_umask;
462554
prev_umask = umask(022);
463-
buf = xbps_xasprintf("%s/.%s-files.plist", xhp->metadir, pkgname);
555+
snprintf(buf, sizeof(buf), "%s/.%s-files.plist", xhp->metadir, pkgname);
464556
if (!xbps_dictionary_externalize_to_file(binpkg_filesd, buf)) {
465557
rv = errno;
466558
umask(prev_umask);
467-
free(buf);
468559
xbps_set_cb_state(xhp, XBPS_STATE_UNPACK_FAIL,
469560
rv, pkgver, "%s: [unpack] failed to externalize pkg "
470561
"pkg metadata files: %s", pkgver, strerror(rv));
471562
goto out;
472563
}
473564
umask(prev_umask);
474-
free(buf);
475565
}
476566
out:
477567
/*
478568
* If unpacked pkg has no files, remove its files metadata plist.
479569
*/
480570
if (!xbps_dictionary_count(binpkg_filesd)) {
481-
buf = xbps_xasprintf("%s/.%s-files.plist", xhp->metadir, pkgname);
571+
snprintf(buf, sizeof(buf), "%s/.%s-files.plist", xhp->metadir, pkgname);
482572
unlink(buf);
483-
free(buf);
484573
}
485574
xbps_object_release(binpkg_filesd);
486575

0 commit comments

Comments
 (0)