summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimo Teras <timo.teras@iki.fi>2009-11-06 11:31:03 +0200
committerTimo Teras <timo.teras@iki.fi>2009-11-06 11:31:03 +0200
commita93a35eecaf580d97f6a451d7e951be0ff18372c (patch)
treecec5984f85821ad8aff5cfe317e98c0e5f4ab36e
parent44ac0b06af20bd32010502a10d8bb7752215c627 (diff)
downloadapk-tools-a93a35eecaf580d97f6a451d7e951be0ff18372c.tar.bz2
apk-tools-a93a35eecaf580d97f6a451d7e951be0ff18372c.tar.xz
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.
-rw-r--r--src/apk.c4
-rw-r--r--src/apk_defines.h1
-rw-r--r--src/archive.c22
3 files changed, 25 insertions, 2 deletions
diff --git a/src/apk.c b/src/apk.c
index 6c4acd7..eff31ac 100644
--- a/src/apk.c
+++ b/src/apk.c
@@ -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,
diff --git a/src/apk_defines.h b/src/apk_defines.h
index a0b297a..c0f4b0f 100644
--- a/src/apk_defines.h
+++ b/src/apk_defines.h
@@ -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)
diff --git a/src/archive.c b/src/archive.c
index 58d2573..0ba17c5 100644
--- a/src/archive.c
+++ b/src/archive.c
@@ -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;
}