From: Michihiro NAKAJIMA Date: Sun, 21 Sep 2014 06:00:45 +0000 (+0900) Subject: Add a new API, archive_write_set_passphrase_callback, for encryption. X-Git-Tag: v3.1.900a~206 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=96c38181092faa7b76773f00bb3260f87d9ffc0d;p=thirdparty%2Flibarchive.git Add a new API, archive_write_set_passphrase_callback, for encryption. --- diff --git a/libarchive/archive.h b/libarchive/archive.h index aa1f8a14a..81ed63a13 100644 --- a/libarchive/archive.h +++ b/libarchive/archive.h @@ -834,6 +834,8 @@ __LA_DECL int archive_write_set_options(struct archive *_a, * Set a encryption passphrase. */ __LA_DECL int archive_write_set_passphrase(struct archive *_a, const char *p); +__LA_DECL int archive_write_set_passphrase_callback(struct archive *, + void *client_data, archive_passphrase_callback *); /*- * ARCHIVE_WRITE_DISK API diff --git a/libarchive/archive_write_private.h b/libarchive/archive_write_private.h index a2b5c0f87..0c3cc0c6f 100644 --- a/libarchive/archive_write_private.h +++ b/libarchive/archive_write_private.h @@ -124,6 +124,8 @@ struct archive_write { * Encryption passphrase. */ char *passphrase; + archive_passphrase_callback *passphrase_callback; + void *passphrase_client_data; }; /* diff --git a/libarchive/archive_write_set_passphrase.3 b/libarchive/archive_write_set_passphrase.3 index b2e47d4a9..ba517dd0f 100644 --- a/libarchive/archive_write_set_passphrase.3 +++ b/libarchive/archive_write_set_passphrase.3 @@ -24,11 +24,12 @@ .\" .\" $FreeBSD$ .\" -.Dd September 13, 2014 +.Dd September 21, 2014 .Dt ARCHIVE_WRITE_SET_PASSPHRASE 3 .Os .Sh NAME -.Nm archive_write_set_passphrase +.Nm archive_write_set_passphrase , +.Nm archive_write_set_passphrase_callback .Nd functions for writing encrypted archives .Sh LIBRARY Streaming Archive Library (libarchive, -larchive) @@ -39,7 +40,15 @@ Streaming Archive Library (libarchive, -larchive) .Fa "struct archive *" .Fa "const char *passphrase" .Fc +.Ft int +.Fo archive_write_set_passphrase_callback +.Fa "struct archive *" +.Fa "void *client_data" +.Fa "archive_passphrase_callback *" +.Fc .Sh DESCRIPTION +.Bl -tag -width indent +.It Fn archive_write_set_passphrase Set a passphrase for writing an encryption archive. If .Ar passphrase @@ -51,6 +60,11 @@ will be returned. Otherwise, .Cm ARCHIVE_OK will be returned. +.It Fn archive_write_set_passphrase_callback +Register callback function that will be invoked to get a passphrase +for encrption if the passphrase was not set by the +.Fn archive_write_set_passphrase +function. .\" .Sh ERRORS .Sh SEE ALSO .Xr tar 1 , diff --git a/libarchive/archive_write_set_passphrase.c b/libarchive/archive_write_set_passphrase.c index 92f59898c..710ecba52 100644 --- a/libarchive/archive_write_set_passphrase.c +++ b/libarchive/archive_write_set_passphrase.c @@ -54,9 +54,42 @@ archive_write_set_passphrase(struct archive *_a, const char *p) return (ARCHIVE_OK); } + +int +archive_write_set_passphrase_callback(struct archive *_a, void *client_data, + archive_passphrase_callback *cb) +{ + struct archive_write *a = (struct archive_write *)_a; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, + "archive_write_set_passphrase_callback"); + + a->passphrase_callback = cb; + a->passphrase_client_data = client_data; + return (ARCHIVE_OK); +} + + const char * __archive_write_get_passphrase(struct archive_write *a) { - return (a->passphrase); + if (a->passphrase != NULL) + return (a->passphrase); + + if (a->passphrase_callback != NULL) { + const char *p; + p = a->passphrase_callback(&a->archive, + a->passphrase_client_data); + if (p != NULL) { + a->passphrase = strdup(p); + if (a->passphrase == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate data for passphrase"); + return (NULL); + } + return (a->passphrase); + } + } + return (NULL); } diff --git a/libarchive/test/test_archive_write_set_passphrase.c b/libarchive/test/test_archive_write_set_passphrase.c index 20171e2df..4bfcbb2c2 100644 --- a/libarchive/test/test_archive_write_set_passphrase.c +++ b/libarchive/test/test_archive_write_set_passphrase.c @@ -60,3 +60,36 @@ DEFINE_TEST(test_archive_write_set_passphrase) test(1); test(0); } + + +static const char * +callback1(struct archive *a, void *_client_data) +{ + int *cnt; + + (void)a; /* UNUSED */ + + cnt = (int *)_client_data; + *cnt += 1; + return ("passCallBack"); +} + +DEFINE_TEST(test_archive_write_set_passphrase_callback) +{ + struct archive* a = archive_write_new(); + struct archive_write* aw = (struct archive_write *)a; + int cnt = 0; + + archive_write_set_format_zip(a); + + assertEqualInt(ARCHIVE_OK, + archive_write_set_passphrase_callback(a, &cnt, callback1)); + /* Check a passphrase. */ + assertEqualString("passCallBack", __archive_write_get_passphrase(aw)); + assertEqualInt(1, cnt); + /* Callback function should be called just once. */ + assertEqualString("passCallBack", __archive_write_get_passphrase(aw)); + assertEqualInt(1, cnt); + + archive_write_free(a); +}