Commit a93a35ee authored by Timo Teräs's avatar Timo Teräs

apk: add --never-overwrite flag (ref #197)

to never ever overwrite a while in the filesystem the user knows
about. it gives the impression of extraction succeeding even though
nothing was done. this is inteded to be used only for bootstrapping
with overlay.
parent 44ac0b06
......@@ -57,6 +57,7 @@ static struct apk_option generic_options[] = {
{ 0x108, "repositories-file", "Override repositories file",
required_argument, "REPOFILE" },
{ 0x109, "no-network", "Do not use network (cache is still used)" },
{ 0x110, "never-overwrite", "Never overwrite existing files" },
};
const char *apk_error_str(int error)
......@@ -384,6 +385,9 @@ int main(int argc, char **argv)
case 0x109:
apk_flags |= APK_NO_NETWORK;
break;
case 0x110:
apk_flags |= APK_NEVER_OVERWRITE;
break;
default:
if (applet == NULL || applet->parse == NULL ||
applet->parse(ctx, &dbopts, r,
......
......@@ -64,6 +64,7 @@ extern unsigned int apk_flags;
#define APK_INTERACTIVE 0x0400
#define APK_RECURSIVE_DELETE 0x0800
#define APK_NO_NETWORK 0x1000
#define APK_NEVER_OVERWRITE 0x2000
#define apk_error(args...) do { apk_log("ERROR: ", args); } while (0)
#define apk_warning(args...) do { if (apk_verbosity > 0) { apk_log("WARNING: ", args); } } while (0)
......
......@@ -339,7 +339,17 @@ int apk_archive_entry_extract(int atfd, const struct apk_file_info *ae,
fn = alloca(PATH_MAX);
snprintf(fn, PATH_MAX, "%s%s", ae->name, suffix);
}
unlinkat(atfd, fn, 0);
if ((!S_ISDIR(ae->mode) && !S_ISREG(ae->mode)) ||
(ae->link_target != NULL)) {
/* non-standard entries need to be deleted first */
if (apk_flags & APK_NEVER_OVERWRITE) {
if (faccessat(atfd, fn, F_OK, AT_SYMLINK_NOFOLLOW) == 0)
return 0;
} else {
unlinkat(atfd, fn, 0);
}
}
switch (ae->mode & S_IFMT) {
case S_IFDIR:
......@@ -349,8 +359,16 @@ int apk_archive_entry_extract(int atfd, const struct apk_file_info *ae,
break;
case S_IFREG:
if (ae->link_target == NULL) {
fd = openat(atfd, fn, O_RDWR | O_CREAT, ae->mode & 07777);
int flags = O_RDWR | O_CREAT | O_TRUNC;
if (apk_flags & APK_NEVER_OVERWRITE)
flags |= O_EXCL;
fd = openat(atfd, fn, flags, ae->mode & 07777);
if (fd < 0) {
if ((apk_flags & APK_NEVER_OVERWRITE) &&
(errno == EEXIST))
return 0;
r = -1;
break;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment