[v2,1/1] archive handler: set locale for libarchive

Message ID 1546737784-6893-1-git-send-email-james.hilliard1@gmail.com
State New
Headers show
Series
  • [v2,1/1] archive handler: set locale for libarchive
Related show

Commit Message

James Hilliard Jan. 6, 2019, 1:23 a.m.
From: James Hilliard <james.hilliard1@gmail.com>

Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
---
 handlers/archive_handler.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

Comments

Stefano Babic Jan. 7, 2019, 6:10 p.m. | #1
Hi James,

On 06/01/19 02:23, james.hilliard1@gmail.com wrote:
> From: James Hilliard <james.hilliard1@gmail.com>
> 
> Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
> ---
>  handlers/archive_handler.c | 21 +++++++++++++++++++++
>  1 file changed, 21 insertions(+)
> 
> diff --git a/handlers/archive_handler.c b/handlers/archive_handler.c
> index a44819d..35b1167 100644
> --- a/handlers/archive_handler.c
> +++ b/handlers/archive_handler.c
> @@ -6,6 +6,7 @@
>   */
>  
>  #include <sys/types.h>
> +#include <locale.h>
>  #include <stdio.h>
>  #include <sys/stat.h>
>  #include <unistd.h>
> @@ -67,6 +68,8 @@ copy_data(struct archive *ar, struct archive *aw)
>  static void *
>  extract(void *p)
>  {
> +	locale_t archive_locale;
> +	locale_t old_locale;
>  	struct archive *a;
>  	struct archive *ext;
>  	struct archive_entry *entry;
> @@ -75,6 +78,20 @@ extract(void *p)
>  	struct extract_data *data = (struct extract_data *)p;
>  	flags = data->flags;
>  
> +	/*
> +	 * Enable system locale - change from the standard (C) to system locale.
> +	 * This allows libarchive (in case it is activated) to handle filenames.
> +	 * We only change LC_CTYPE since libarchive only needs the charset set.
> +	 * We don't use LC_ALL because it causes problems on some systems.
> +	 * We restore the original LC_CTYPE after extraction to avoid side effects.
> +	 * We use uselocale instead of setlocale to avoid setting LC_CTYPE globally.
> +	 * See on libarchive Websiete for a more complete description of the issue:
> +	 *  https://github.com/libarchive/libarchive/issues/587
> +	 *  https://github.com/libarchive/libarchive/wiki/Filenames
> +	 */
> +	archive_locale = newlocale(LC_CTYPE_MASK, "", (locale_t)0);
> +	old_locale = uselocale(archive_locale);
> +
>  	a = archive_read_new();
>  	ext = archive_write_disk_new();
>  	archive_write_disk_set_options(ext, flags);
> @@ -97,6 +114,7 @@ extract(void *p)
>  	if ((r = archive_read_open_filename(a, FIFO, 4096))) {
>  		ERROR("archive_read_open_filename(): %s %d",
>  		    archive_error_string(a), r);
> +		uselocale(old_locale);
>  		pthread_exit((void *)-1);
>  	}
>  	for (;;) {
> @@ -106,6 +124,7 @@ extract(void *p)
>  		if (r != ARCHIVE_OK) {
>  			ERROR("archive_read_next_header(): %s %d",
>  			    archive_error_string(a), 1);
> +			uselocale(old_locale);
>  			pthread_exit((void *)-1);
>  		}
>  
> @@ -122,6 +141,7 @@ extract(void *p)
>  			if (r != ARCHIVE_OK)  {
>  				ERROR("archive_write_finish_entry(): %s",
>  				    archive_error_string(ext));
> +				uselocale(old_locale);
>  				pthread_exit((void *)-1);
>  			}
>  		}
> @@ -130,6 +150,7 @@ extract(void *p)
>  
>  	archive_read_close(a);
>  	archive_read_free(a);
> +	uselocale(old_locale);
>  	pthread_exit((void *)0);
>  }
>  
> 

Patch is clean - I would like just to test it before applying.

Acked-by: Stefano Babic <sbabic@denx.de>

Best regards,
Stefano Babic

Patch

diff --git a/handlers/archive_handler.c b/handlers/archive_handler.c
index a44819d..35b1167 100644
--- a/handlers/archive_handler.c
+++ b/handlers/archive_handler.c
@@ -6,6 +6,7 @@ 
  */
 
 #include <sys/types.h>
+#include <locale.h>
 #include <stdio.h>
 #include <sys/stat.h>
 #include <unistd.h>
@@ -67,6 +68,8 @@  copy_data(struct archive *ar, struct archive *aw)
 static void *
 extract(void *p)
 {
+	locale_t archive_locale;
+	locale_t old_locale;
 	struct archive *a;
 	struct archive *ext;
 	struct archive_entry *entry;
@@ -75,6 +78,20 @@  extract(void *p)
 	struct extract_data *data = (struct extract_data *)p;
 	flags = data->flags;
 
+	/*
+	 * Enable system locale - change from the standard (C) to system locale.
+	 * This allows libarchive (in case it is activated) to handle filenames.
+	 * We only change LC_CTYPE since libarchive only needs the charset set.
+	 * We don't use LC_ALL because it causes problems on some systems.
+	 * We restore the original LC_CTYPE after extraction to avoid side effects.
+	 * We use uselocale instead of setlocale to avoid setting LC_CTYPE globally.
+	 * See on libarchive Websiete for a more complete description of the issue:
+	 *  https://github.com/libarchive/libarchive/issues/587
+	 *  https://github.com/libarchive/libarchive/wiki/Filenames
+	 */
+	archive_locale = newlocale(LC_CTYPE_MASK, "", (locale_t)0);
+	old_locale = uselocale(archive_locale);
+
 	a = archive_read_new();
 	ext = archive_write_disk_new();
 	archive_write_disk_set_options(ext, flags);
@@ -97,6 +114,7 @@  extract(void *p)
 	if ((r = archive_read_open_filename(a, FIFO, 4096))) {
 		ERROR("archive_read_open_filename(): %s %d",
 		    archive_error_string(a), r);
+		uselocale(old_locale);
 		pthread_exit((void *)-1);
 	}
 	for (;;) {
@@ -106,6 +124,7 @@  extract(void *p)
 		if (r != ARCHIVE_OK) {
 			ERROR("archive_read_next_header(): %s %d",
 			    archive_error_string(a), 1);
+			uselocale(old_locale);
 			pthread_exit((void *)-1);
 		}
 
@@ -122,6 +141,7 @@  extract(void *p)
 			if (r != ARCHIVE_OK)  {
 				ERROR("archive_write_finish_entry(): %s",
 				    archive_error_string(ext));
+				uselocale(old_locale);
 				pthread_exit((void *)-1);
 			}
 		}
@@ -130,6 +150,7 @@  extract(void *p)
 
 	archive_read_close(a);
 	archive_read_free(a);
+	uselocale(old_locale);
 	pthread_exit((void *)0);
 }