636 lines
19 KiB
Diff
636 lines
19 KiB
Diff
![]() |
From f888547b1bb7f2354d66912fed62e2a5053b76e6 Mon Sep 17 00:00:00 2001
|
||
|
From: Josef Moellers <jmoellers@suse.de>
|
||
|
Date: Fri, 12 Oct 2018 16:45:47 +0200
|
||
|
Subject: [PATCH 09/19] Code cleanup in "bins".
|
||
|
|
||
|
---
|
||
|
bins/unzzip.c | 113 +++++++++++++++++++++++++++++++++++++++++
|
||
|
bins/unzzipcat-big.c | 91 ++-------------------------------
|
||
|
bins/unzzipcat-mem.c | 91 ++-------------------------------
|
||
|
bins/unzzipcat-mix.c | 116 ++-----------------------------------------
|
||
|
bins/unzzipcat-zip.c | 116 ++-----------------------------------------
|
||
|
5 files changed, 125 insertions(+), 402 deletions(-)
|
||
|
|
||
|
diff --git a/bins/unzzip.c b/bins/unzzip.c
|
||
|
index f91c5eb..5426049 100644
|
||
|
--- a/bins/unzzip.c
|
||
|
+++ b/bins/unzzip.c
|
||
|
@@ -5,8 +5,14 @@
|
||
|
* This file is used as an example to clarify zzip api usage.
|
||
|
*/
|
||
|
|
||
|
+#include <sys/stat.h>
|
||
|
#include <zzip/zzip.h>
|
||
|
+#include <zzip/__string.h>
|
||
|
+#include <zzip/__mkdir.h>
|
||
|
+#include <zzip/__debug.h>
|
||
|
+#include <zzip/file.h>
|
||
|
#include <stdio.h>
|
||
|
+#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include "unzzipcat-zip.h"
|
||
|
#include "unzzipdir-zip.h"
|
||
|
@@ -32,6 +38,113 @@ static int unzzip_help(void)
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+/* Functions used by unzzipcat-*.c: */
|
||
|
+int exitcode(int e)
|
||
|
+{
|
||
|
+ switch (e)
|
||
|
+ {
|
||
|
+ case ZZIP_NO_ERROR:
|
||
|
+ return EXIT_OK;
|
||
|
+ case ZZIP_OUTOFMEM: /* out of memory */
|
||
|
+ return EXIT_ENOMEM;
|
||
|
+ case ZZIP_DIR_OPEN: /* failed to open zipfile, see errno for details */
|
||
|
+ return EXIT_ZIP_NOT_FOUND;
|
||
|
+ case ZZIP_DIR_STAT: /* failed to fstat zipfile, see errno for details */
|
||
|
+ case ZZIP_DIR_SEEK: /* failed to lseek zipfile, see errno for details */
|
||
|
+ case ZZIP_DIR_READ: /* failed to read zipfile, see errno for details */
|
||
|
+ case ZZIP_DIR_TOO_SHORT:
|
||
|
+ case ZZIP_DIR_EDH_MISSING:
|
||
|
+ return EXIT_FILEFORMAT;
|
||
|
+ case ZZIP_DIRSIZE:
|
||
|
+ return EXIT_EARLY_END_OF_FILE;
|
||
|
+ case ZZIP_ENOENT:
|
||
|
+ return EXIT_FILE_NOT_FOUND;
|
||
|
+ case ZZIP_UNSUPP_COMPR:
|
||
|
+ return EXIT_UNSUPPORTED_COMPRESSION;
|
||
|
+ case ZZIP_CORRUPTED:
|
||
|
+ case ZZIP_UNDEF:
|
||
|
+ case ZZIP_DIR_LARGEFILE:
|
||
|
+ return EXIT_FILEFORMAT;
|
||
|
+ }
|
||
|
+ return EXIT_ERRORS;
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
+ * NAME: remove_dotdotslash
|
||
|
+ * PURPOSE: To remove any "../" components from the given pathname
|
||
|
+ * ARGUMENTS: path: path name with maybe "../" components
|
||
|
+ * RETURNS: Nothing, "path" is modified in-place
|
||
|
+ * NOTE: removing "../" from the path ALWAYS shortens the path, never adds to it!
|
||
|
+ * Also, "path" is not used after creating it.
|
||
|
+ * So modifying "path" in-place is safe to do.
|
||
|
+ */
|
||
|
+static inline void
|
||
|
+remove_dotdotslash(char *path)
|
||
|
+{
|
||
|
+ /* Note: removing "../" from the path ALWAYS shortens the path, never adds to it! */
|
||
|
+ char *dotdotslash;
|
||
|
+ int warned = 0;
|
||
|
+
|
||
|
+ dotdotslash = path;
|
||
|
+ while ((dotdotslash = strstr(dotdotslash, "../")) != NULL)
|
||
|
+ {
|
||
|
+ /*
|
||
|
+ * Remove only if at the beginning of the pathname ("../path/name")
|
||
|
+ * or when preceded by a slash ("path/../name"),
|
||
|
+ * otherwise not ("path../name..")!
|
||
|
+ */
|
||
|
+ if (dotdotslash == path || dotdotslash[-1] == '/')
|
||
|
+ {
|
||
|
+ char *src, *dst;
|
||
|
+ if (!warned)
|
||
|
+ {
|
||
|
+ /* Note: the first time through the pathname is still intact */
|
||
|
+ fprintf(stderr, "Removing \"../\" path component(s) in %s\n", path);
|
||
|
+ warned = 1;
|
||
|
+ }
|
||
|
+ /* We cannot use strcpy(), as there "The strings may not overlap" */
|
||
|
+ for (src = dotdotslash+3, dst=dotdotslash; (*dst = *src) != '\0'; src++, dst++)
|
||
|
+ ;
|
||
|
+ }
|
||
|
+ else
|
||
|
+ dotdotslash +=3; /* skip this instance to prevent infinite loop */
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static void makedirs(const char* name)
|
||
|
+{
|
||
|
+ char* p = strrchr(name, '/');
|
||
|
+ if (p) {
|
||
|
+ char* dir_name = _zzip_strndup(name, p-name);
|
||
|
+ makedirs(dir_name);
|
||
|
+ free (dir_name);
|
||
|
+ }
|
||
|
+ if (_zzip_mkdir(name, 0775) == -1 && errno != EEXIST)
|
||
|
+ {
|
||
|
+ DBG3("while mkdir %s : %s", name, strerror(errno));
|
||
|
+ }
|
||
|
+ errno = 0;
|
||
|
+}
|
||
|
+
|
||
|
+FILE* create_fopen(char* name, char* mode, int subdirs)
|
||
|
+{
|
||
|
+ char name_stripped[PATH_MAX];
|
||
|
+
|
||
|
+ strncpy(name_stripped, name, PATH_MAX);
|
||
|
+ remove_dotdotslash(name_stripped);
|
||
|
+
|
||
|
+ if (subdirs)
|
||
|
+ {
|
||
|
+ char* p = strrchr(name_stripped, '/');
|
||
|
+ if (p) {
|
||
|
+ char* dir_name = _zzip_strndup(name_stripped, p-name);
|
||
|
+ makedirs(dir_name);
|
||
|
+ free (dir_name);
|
||
|
+ }
|
||
|
+ }
|
||
|
+ return fopen(name_stripped, mode);
|
||
|
+}
|
||
|
+
|
||
|
int
|
||
|
main (int argc, char ** argv)
|
||
|
{
|
||
|
diff --git a/bins/unzzipcat-big.c b/bins/unzzipcat-big.c
|
||
|
index 88c4d65..111ef47 100644
|
||
|
--- a/bins/unzzipcat-big.c
|
||
|
+++ b/bins/unzzipcat-big.c
|
||
|
@@ -16,10 +16,9 @@
|
||
|
#include "unzzipcat-zip.h"
|
||
|
#include "unzzip-states.h"
|
||
|
|
||
|
-static int exitcode(int e)
|
||
|
-{
|
||
|
- return EXIT_ERRORS;
|
||
|
-}
|
||
|
+/* Functions in unzzip.c: */
|
||
|
+extern int exitcode(int);
|
||
|
+extern FILE* create_fopen(char*, char*, int);
|
||
|
|
||
|
static void unzzip_big_entry_fprint(ZZIP_ENTRY* entry, FILE* out)
|
||
|
{
|
||
|
@@ -53,90 +52,6 @@ static void unzzip_cat_file(FILE* disk, char* name, FILE* out)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
-/*
|
||
|
- * NAME: remove_dotdotslash
|
||
|
- * PURPOSE: To remove any "../" components from the given pathname
|
||
|
- * ARGUMENTS: path: path name with maybe "../" components
|
||
|
- * RETURNS: Nothing, "path" is modified in-place
|
||
|
- * NOTE: removing "../" from the path ALWAYS shortens the path, never adds to it!
|
||
|
- * Also, "path" is not used after creating it.
|
||
|
- * So modifying "path" in-place is safe to do.
|
||
|
- */
|
||
|
-static inline void
|
||
|
-remove_dotdotslash(char *path)
|
||
|
-{
|
||
|
- /* Note: removing "../" from the path ALWAYS shortens the path, never adds to it! */
|
||
|
- char *dotdotslash;
|
||
|
- int warned = 0;
|
||
|
-
|
||
|
- dotdotslash = path;
|
||
|
- while ((dotdotslash = strstr(dotdotslash, "../")) != NULL)
|
||
|
- {
|
||
|
- /*
|
||
|
- * Remove only if at the beginning of the pathname ("../path/name")
|
||
|
- * or when preceded by a slash ("path/../name"),
|
||
|
- * otherwise not ("path../name..")!
|
||
|
- */
|
||
|
- if (dotdotslash == path || dotdotslash[-1] == '/')
|
||
|
- {
|
||
|
- char *src, *dst;
|
||
|
- if (!warned)
|
||
|
- {
|
||
|
- /* Note: the first time through the pathname is still intact */
|
||
|
- fprintf(stderr, "Removing \"../\" path component(s) in %s\n", path);
|
||
|
- warned = 1;
|
||
|
- }
|
||
|
- /* We cannot use strcpy(), as there "The strings may not overlap" */
|
||
|
- for (src = dotdotslash+3, dst=dotdotslash; (*dst = *src) != '\0'; src++, dst++)
|
||
|
- ;
|
||
|
- }
|
||
|
- else
|
||
|
- dotdotslash +=3; /* skip this instance to prevent infinite loop */
|
||
|
- }
|
||
|
-}
|
||
|
-
|
||
|
-static void makedirs(const char* name)
|
||
|
-{
|
||
|
- char* p = strrchr(name, '/');
|
||
|
- if (p) {
|
||
|
- char* dir_name = _zzip_strndup(name, p-name);
|
||
|
- makedirs(dir_name);
|
||
|
- free (dir_name);
|
||
|
- }
|
||
|
- if (_zzip_mkdir(name, 0775) == -1 && errno != EEXIST)
|
||
|
- {
|
||
|
- DBG3("while mkdir %s : %s", name, strerror(errno));
|
||
|
- }
|
||
|
- errno = 0;
|
||
|
-}
|
||
|
-
|
||
|
-static FILE* create_fopen(char* name, char* mode, int subdirs)
|
||
|
-{
|
||
|
- char *name_stripped;
|
||
|
- FILE *fp;
|
||
|
- int mustfree = 0;
|
||
|
-
|
||
|
- if ((name_stripped = strdup(name)) != NULL)
|
||
|
- {
|
||
|
- remove_dotdotslash(name_stripped);
|
||
|
- name = name_stripped;
|
||
|
- mustfree = 1;
|
||
|
- }
|
||
|
- if (subdirs)
|
||
|
- {
|
||
|
- char* p = strrchr(name, '/');
|
||
|
- if (p) {
|
||
|
- char* dir_name = _zzip_strndup(name, p-name);
|
||
|
- makedirs(dir_name);
|
||
|
- free (dir_name);
|
||
|
- }
|
||
|
- }
|
||
|
- fp = fopen(name, mode);
|
||
|
- if (mustfree)
|
||
|
- free(name_stripped);
|
||
|
- return fp;
|
||
|
-}
|
||
|
-
|
||
|
|
||
|
static int unzzip_cat (int argc, char ** argv, int extract)
|
||
|
{
|
||
|
diff --git a/bins/unzzipcat-mem.c b/bins/unzzipcat-mem.c
|
||
|
index 793bde8..cfa27ab 100644
|
||
|
--- a/bins/unzzipcat-mem.c
|
||
|
+++ b/bins/unzzipcat-mem.c
|
||
|
@@ -24,10 +24,9 @@
|
||
|
#include <io.h>
|
||
|
#endif
|
||
|
|
||
|
-static int exitcode(int e)
|
||
|
-{
|
||
|
- return EXIT_ERRORS;
|
||
|
-}
|
||
|
+/* Functions in unzzip.c: */
|
||
|
+extern int exitcode(int);
|
||
|
+extern FILE* create_fopen(char*, char*, int);
|
||
|
|
||
|
static void unzzip_mem_entry_fprint(ZZIP_MEM_DISK* disk,
|
||
|
ZZIP_MEM_ENTRY* entry, FILE* out)
|
||
|
@@ -58,90 +57,6 @@ static void unzzip_mem_disk_cat_file(ZZIP_MEM_DISK* disk, char* name, FILE* out)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
-/*
|
||
|
- * NAME: remove_dotdotslash
|
||
|
- * PURPOSE: To remove any "../" components from the given pathname
|
||
|
- * ARGUMENTS: path: path name with maybe "../" components
|
||
|
- * RETURNS: Nothing, "path" is modified in-place
|
||
|
- * NOTE: removing "../" from the path ALWAYS shortens the path, never adds to it!
|
||
|
- * Also, "path" is not used after creating it.
|
||
|
- * So modifying "path" in-place is safe to do.
|
||
|
- */
|
||
|
-static inline void
|
||
|
-remove_dotdotslash(char *path)
|
||
|
-{
|
||
|
- /* Note: removing "../" from the path ALWAYS shortens the path, never adds to it! */
|
||
|
- char *dotdotslash;
|
||
|
- int warned = 0;
|
||
|
-
|
||
|
- dotdotslash = path;
|
||
|
- while ((dotdotslash = strstr(dotdotslash, "../")) != NULL)
|
||
|
- {
|
||
|
- /*
|
||
|
- * Remove only if at the beginning of the pathname ("../path/name")
|
||
|
- * or when preceded by a slash ("path/../name"),
|
||
|
- * otherwise not ("path../name..")!
|
||
|
- */
|
||
|
- if (dotdotslash == path || dotdotslash[-1] == '/')
|
||
|
- {
|
||
|
- char *src, *dst;
|
||
|
- if (!warned)
|
||
|
- {
|
||
|
- /* Note: the first time through the pathname is still intact */
|
||
|
- fprintf(stderr, "Removing \"../\" path component(s) in %s\n", path);
|
||
|
- warned = 1;
|
||
|
- }
|
||
|
- /* We cannot use strcpy(), as there "The strings may not overlap" */
|
||
|
- for (src = dotdotslash+3, dst=dotdotslash; (*dst = *src) != '\0'; src++, dst++)
|
||
|
- ;
|
||
|
- }
|
||
|
- else
|
||
|
- dotdotslash +=3; /* skip this instance to prevent infinite loop */
|
||
|
- }
|
||
|
-}
|
||
|
-
|
||
|
-static void makedirs(const char* name)
|
||
|
-{
|
||
|
- char* p = strrchr(name, '/');
|
||
|
- if (p) {
|
||
|
- char* dir_name = _zzip_strndup(name, p-name);
|
||
|
- makedirs(dir_name);
|
||
|
- free (dir_name);
|
||
|
- }
|
||
|
- if (_zzip_mkdir(name, 0775) == -1 && errno != EEXIST)
|
||
|
- {
|
||
|
- DBG3("while mkdir %s : %s", name, strerror(errno));
|
||
|
- }
|
||
|
- errno = 0;
|
||
|
-}
|
||
|
-
|
||
|
-static FILE* create_fopen(char* name, char* mode, int subdirs)
|
||
|
-{
|
||
|
- char *name_stripped;
|
||
|
- FILE *fp;
|
||
|
- int mustfree = 0;
|
||
|
-
|
||
|
- if ((name_stripped = strdup(name)) != NULL)
|
||
|
- {
|
||
|
- remove_dotdotslash(name_stripped);
|
||
|
- name = name_stripped;
|
||
|
- mustfree = 1;
|
||
|
- }
|
||
|
- if (subdirs)
|
||
|
- {
|
||
|
- char* p = strrchr(name, '/');
|
||
|
- if (p) {
|
||
|
- char* dir_name = _zzip_strndup(name, p-name);
|
||
|
- makedirs(dir_name);
|
||
|
- free (dir_name);
|
||
|
- }
|
||
|
- }
|
||
|
- fp = fopen(name, mode);
|
||
|
- if (mustfree)
|
||
|
- free(name_stripped);
|
||
|
- return fp;
|
||
|
-}
|
||
|
-
|
||
|
static int unzzip_cat (int argc, char ** argv, int extract)
|
||
|
{
|
||
|
int done = 0;
|
||
|
diff --git a/bins/unzzipcat-mix.c b/bins/unzzipcat-mix.c
|
||
|
index 73b6ed6..5a32b1d 100644
|
||
|
--- a/bins/unzzipcat-mix.c
|
||
|
+++ b/bins/unzzipcat-mix.c
|
||
|
@@ -24,35 +24,9 @@
|
||
|
#include <io.h>
|
||
|
#endif
|
||
|
|
||
|
-static int exitcode(int e)
|
||
|
-{
|
||
|
- switch (e)
|
||
|
- {
|
||
|
- case ZZIP_NO_ERROR:
|
||
|
- return EXIT_OK;
|
||
|
- case ZZIP_OUTOFMEM: /* out of memory */
|
||
|
- return EXIT_ENOMEM;
|
||
|
- case ZZIP_DIR_OPEN: /* failed to open zipfile, see errno for details */
|
||
|
- return EXIT_ZIP_NOT_FOUND;
|
||
|
- case ZZIP_DIR_STAT: /* failed to fstat zipfile, see errno for details */
|
||
|
- case ZZIP_DIR_SEEK: /* failed to lseek zipfile, see errno for details */
|
||
|
- case ZZIP_DIR_READ: /* failed to read zipfile, see errno for details */
|
||
|
- case ZZIP_DIR_TOO_SHORT:
|
||
|
- case ZZIP_DIR_EDH_MISSING:
|
||
|
- return EXIT_FILEFORMAT;
|
||
|
- case ZZIP_DIRSIZE:
|
||
|
- return EXIT_EARLY_END_OF_FILE;
|
||
|
- case ZZIP_ENOENT:
|
||
|
- return EXIT_FILE_NOT_FOUND;
|
||
|
- case ZZIP_UNSUPP_COMPR:
|
||
|
- return EXIT_UNSUPPORTED_COMPRESSION;
|
||
|
- case ZZIP_CORRUPTED:
|
||
|
- case ZZIP_UNDEF:
|
||
|
- case ZZIP_DIR_LARGEFILE:
|
||
|
- return EXIT_FILEFORMAT;
|
||
|
- }
|
||
|
- return EXIT_ERRORS;
|
||
|
-}
|
||
|
+/* Functions in unzzip.c: */
|
||
|
+extern int exitcode(int);
|
||
|
+extern FILE* create_fopen(char*, char*, int);
|
||
|
|
||
|
static void unzzip_cat_file(ZZIP_DIR* disk, char* name, FILE* out)
|
||
|
{
|
||
|
@@ -69,90 +43,6 @@ static void unzzip_cat_file(ZZIP_DIR* disk, char* name, FILE* out)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
-/*
|
||
|
- * NAME: remove_dotdotslash
|
||
|
- * PURPOSE: To remove any "../" components from the given pathname
|
||
|
- * ARGUMENTS: path: path name with maybe "../" components
|
||
|
- * RETURNS: Nothing, "path" is modified in-place
|
||
|
- * NOTE: removing "../" from the path ALWAYS shortens the path, never adds to it!
|
||
|
- * Also, "path" is not used after creating it.
|
||
|
- * So modifying "path" in-place is safe to do.
|
||
|
- */
|
||
|
-static inline void
|
||
|
-remove_dotdotslash(char *path)
|
||
|
-{
|
||
|
- /* Note: removing "../" from the path ALWAYS shortens the path, never adds to it! */
|
||
|
- char *dotdotslash;
|
||
|
- int warned = 0;
|
||
|
-
|
||
|
- dotdotslash = path;
|
||
|
- while ((dotdotslash = strstr(dotdotslash, "../")) != NULL)
|
||
|
- {
|
||
|
- /*
|
||
|
- * Remove only if at the beginning of the pathname ("../path/name")
|
||
|
- * or when preceded by a slash ("path/../name"),
|
||
|
- * otherwise not ("path../name..")!
|
||
|
- */
|
||
|
- if (dotdotslash == path || dotdotslash[-1] == '/')
|
||
|
- {
|
||
|
- char *src, *dst;
|
||
|
- if (!warned)
|
||
|
- {
|
||
|
- /* Note: the first time through the pathname is still intact */
|
||
|
- fprintf(stderr, "Removing \"../\" path component(s) in %s\n", path);
|
||
|
- warned = 1;
|
||
|
- }
|
||
|
- /* We cannot use strcpy(), as there "The strings may not overlap" */
|
||
|
- for (src = dotdotslash+3, dst=dotdotslash; (*dst = *src) != '\0'; src++, dst++)
|
||
|
- ;
|
||
|
- }
|
||
|
- else
|
||
|
- dotdotslash +=3; /* skip this instance to prevent infinite loop */
|
||
|
- }
|
||
|
-}
|
||
|
-
|
||
|
-static void makedirs(const char* name)
|
||
|
-{
|
||
|
- char* p = strrchr(name, '/');
|
||
|
- if (p) {
|
||
|
- char* dir_name = _zzip_strndup(name, p-name);
|
||
|
- makedirs(dir_name);
|
||
|
- free (dir_name);
|
||
|
- }
|
||
|
- if (_zzip_mkdir(name, 0775) == -1 && errno != EEXIST)
|
||
|
- {
|
||
|
- DBG3("while mkdir %s : %s", name, strerror(errno));
|
||
|
- }
|
||
|
- errno = 0;
|
||
|
-}
|
||
|
-
|
||
|
-static FILE* create_fopen(char* name, char* mode, int subdirs)
|
||
|
-{
|
||
|
- char *name_stripped;
|
||
|
- FILE *fp;
|
||
|
- int mustfree = 0;
|
||
|
-
|
||
|
- if ((name_stripped = strdup(name)) != NULL)
|
||
|
- {
|
||
|
- remove_dotdotslash(name_stripped);
|
||
|
- name = name_stripped;
|
||
|
- mustfree = 1;
|
||
|
- }
|
||
|
- if (subdirs)
|
||
|
- {
|
||
|
- char* p = strrchr(name, '/');
|
||
|
- if (p) {
|
||
|
- char* dir_name = _zzip_strndup(name, p-name);
|
||
|
- makedirs(dir_name);
|
||
|
- free (dir_name);
|
||
|
- }
|
||
|
- }
|
||
|
- fp = fopen(name, mode);
|
||
|
- if (mustfree)
|
||
|
- free(name_stripped);
|
||
|
- return fp;
|
||
|
-}
|
||
|
-
|
||
|
static int unzzip_cat (int argc, char ** argv, int extract)
|
||
|
{
|
||
|
int done = 0;
|
||
|
diff --git a/bins/unzzipcat-zip.c b/bins/unzzipcat-zip.c
|
||
|
index 7f7f3fa..be5e7fa 100644
|
||
|
--- a/bins/unzzipcat-zip.c
|
||
|
+++ b/bins/unzzipcat-zip.c
|
||
|
@@ -24,35 +24,9 @@
|
||
|
#include <io.h>
|
||
|
#endif
|
||
|
|
||
|
-static int exitcode(int e)
|
||
|
-{
|
||
|
- switch (e)
|
||
|
- {
|
||
|
- case ZZIP_NO_ERROR:
|
||
|
- return EXIT_OK;
|
||
|
- case ZZIP_OUTOFMEM: /* out of memory */
|
||
|
- return EXIT_ENOMEM;
|
||
|
- case ZZIP_DIR_OPEN: /* failed to open zipfile, see errno for details */
|
||
|
- return EXIT_ZIP_NOT_FOUND;
|
||
|
- case ZZIP_DIR_STAT: /* failed to fstat zipfile, see errno for details */
|
||
|
- case ZZIP_DIR_SEEK: /* failed to lseek zipfile, see errno for details */
|
||
|
- case ZZIP_DIR_READ: /* failed to read zipfile, see errno for details */
|
||
|
- case ZZIP_DIR_TOO_SHORT:
|
||
|
- case ZZIP_DIR_EDH_MISSING:
|
||
|
- return EXIT_FILEFORMAT;
|
||
|
- case ZZIP_DIRSIZE:
|
||
|
- return EXIT_EARLY_END_OF_FILE;
|
||
|
- case ZZIP_ENOENT:
|
||
|
- return EXIT_FILE_NOT_FOUND;
|
||
|
- case ZZIP_UNSUPP_COMPR:
|
||
|
- return EXIT_UNSUPPORTED_COMPRESSION;
|
||
|
- case ZZIP_CORRUPTED:
|
||
|
- case ZZIP_UNDEF:
|
||
|
- case ZZIP_DIR_LARGEFILE:
|
||
|
- return EXIT_FILEFORMAT;
|
||
|
- }
|
||
|
- return EXIT_ERRORS;
|
||
|
-}
|
||
|
+/* Functions in unzzip.c: */
|
||
|
+extern int exitcode(int);
|
||
|
+extern FILE* create_fopen(char*, char*, int);
|
||
|
|
||
|
static void unzzip_cat_file(ZZIP_DIR* disk, char* name, FILE* out)
|
||
|
{
|
||
|
@@ -69,90 +43,6 @@ static void unzzip_cat_file(ZZIP_DIR* disk, char* name, FILE* out)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
-/*
|
||
|
- * NAME: remove_dotdotslash
|
||
|
- * PURPOSE: To remove any "../" components from the given pathname
|
||
|
- * ARGUMENTS: path: path name with maybe "../" components
|
||
|
- * RETURNS: Nothing, "path" is modified in-place
|
||
|
- * NOTE: removing "../" from the path ALWAYS shortens the path, never adds to it!
|
||
|
- * Also, "path" is not used after creating it.
|
||
|
- * So modifying "path" in-place is safe to do.
|
||
|
- */
|
||
|
-static inline void
|
||
|
-remove_dotdotslash(char *path)
|
||
|
-{
|
||
|
- /* Note: removing "../" from the path ALWAYS shortens the path, never adds to it! */
|
||
|
- char *dotdotslash;
|
||
|
- int warned = 0;
|
||
|
-
|
||
|
- dotdotslash = path;
|
||
|
- while ((dotdotslash = strstr(dotdotslash, "../")) != NULL)
|
||
|
- {
|
||
|
- /*
|
||
|
- * Remove only if at the beginning of the pathname ("../path/name")
|
||
|
- * or when preceded by a slash ("path/../name"),
|
||
|
- * otherwise not ("path../name..")!
|
||
|
- */
|
||
|
- if (dotdotslash == path || dotdotslash[-1] == '/')
|
||
|
- {
|
||
|
- char *src, *dst;
|
||
|
- if (!warned)
|
||
|
- {
|
||
|
- /* Note: the first time through the pathname is still intact */
|
||
|
- fprintf(stderr, "Removing \"../\" path component(s) in %s\n", path);
|
||
|
- warned = 1;
|
||
|
- }
|
||
|
- /* We cannot use strcpy(), as there "The strings may not overlap" */
|
||
|
- for (src = dotdotslash+3, dst=dotdotslash; (*dst = *src) != '\0'; src++, dst++)
|
||
|
- ;
|
||
|
- }
|
||
|
- else
|
||
|
- dotdotslash +=3; /* skip this instance to prevent infinite loop */
|
||
|
- }
|
||
|
-}
|
||
|
-
|
||
|
-static void makedirs(const char* name)
|
||
|
-{
|
||
|
- char* p = strrchr(name, '/');
|
||
|
- if (p) {
|
||
|
- char* dir_name = _zzip_strndup(name, p-name);
|
||
|
- makedirs(dir_name);
|
||
|
- free (dir_name);
|
||
|
- }
|
||
|
- if (_zzip_mkdir(name, 0775) == -1 && errno != EEXIST)
|
||
|
- {
|
||
|
- DBG3("while mkdir %s : %s", name, strerror(errno));
|
||
|
- }
|
||
|
- errno = 0;
|
||
|
-}
|
||
|
-
|
||
|
-static FILE* create_fopen(char* name, char* mode, int subdirs)
|
||
|
-{
|
||
|
- char *name_stripped;
|
||
|
- FILE *fp;
|
||
|
- int mustfree = 0;
|
||
|
-
|
||
|
- if ((name_stripped = strdup(name)) != NULL)
|
||
|
- {
|
||
|
- remove_dotdotslash(name_stripped);
|
||
|
- name = name_stripped;
|
||
|
- mustfree = 1;
|
||
|
- }
|
||
|
- if (subdirs)
|
||
|
- {
|
||
|
- char* p = strrchr(name, '/');
|
||
|
- if (p) {
|
||
|
- char* dir_name = _zzip_strndup(name, p-name);
|
||
|
- makedirs(dir_name);
|
||
|
- free (dir_name);
|
||
|
- }
|
||
|
- }
|
||
|
- fp = fopen(name, mode);
|
||
|
- if (mustfree)
|
||
|
- free(name_stripped);
|
||
|
- return fp;
|
||
|
-}
|
||
|
-
|
||
|
static int unzzip_cat (int argc, char ** argv, int extract)
|
||
|
{
|
||
|
int done = 0;
|
||
|
--
|
||
|
2.22.0
|
||
|
|