summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2019-11-26 08:07:55 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2019-11-26 08:10:27 +0100
commit4551f5f0dbb4971633c8aeae3d29a7437da5316d (patch)
treef43fea4f5305c4cea4ed69f85cbf2a1faa0c9aac
parent4a056523cf7f721d674e4898e434184128d3d9f4 (diff)
downloadrtems-4551f5f0dbb4971633c8aeae3d29a7437da5316d.tar.bz2
untar: Properly make parent path
Close #3823.
-rw-r--r--cpukit/libmisc/untar/untar.c190
-rw-r--r--testsuites/libtests/Makefile.am8
-rwxr-xr-xtestsuites/libtests/tar01/home/abc/def/test_script (renamed from testsuites/libtests/tar01/home/test_script)0
-rw-r--r--testsuites/libtests/tar01/init.c30
4 files changed, 65 insertions, 163 deletions
diff --git a/cpukit/libmisc/untar/untar.c b/cpukit/libmisc/untar/untar.c
index ec4a5479cd..a2f09fb99f 100644
--- a/cpukit/libmisc/untar/untar.c
+++ b/cpukit/libmisc/untar/untar.c
@@ -1,14 +1,9 @@
/**
* @file
-
+ *
* @brief Untar an Image
+ *
* @ingroup libmisc_untar_img Untar Image
-
- * FIXME:
- * 1. Symbolic links are not created.
- * 2. Untar_FromMemory uses FILE *fp.
- * 3. How to determine end of archive?
-
*/
/*
@@ -106,142 +101,60 @@ Print_Error(const rtems_printer *printer, const char* message, const char* path)
}
/*
- * Get the type of node on in the file system if present.
- */
-static int
-Stat_Node(const char* path)
-{
- struct stat sb;
- if (stat(path, &sb) < 0)
- return -1;
- if (S_ISDIR(sb.st_mode))
- return DIRTYPE;
- return REGTYPE;
-}
-
-/*
* Make the directory path for a file if it does not exist.
*/
static int
-Make_Path(const rtems_printer *printer, const char* filename, int linktype)
+Make_Path(const rtems_printer *printer, char *path)
{
- char* copy = strdup(filename);
- char* path = copy;
+ char *p;
/*
* Skip leading path separators.
*/
- while (*path == '/')
+ while (*path == '/') {
++path;
+ }
- /*
- * Any path left?
- */
- if (*path != '\0') {
- bool path_end = false;
- char* end = path;
- int r;
-
- /*
- * Split the path into directory components. Check the node and if a file
- * and not the end of the path remove it and create a directory. If a
- * directory and not the end of the path decend into the directory.
- */
- while (!path_end) {
- while (*end != '\0' && *end != '/')
- ++end;
-
- /*
- * Are we at the end of the path?
- */
- if (*end == '\0')
- path_end = true;
+ p = path;
- /*
- * Split the path.
- */
- *end = '\0';
+ for (; ; ++p) {
+ if (p[0] == '\0') {
+ return 0;
+ } else if (p[0] != '/') {
+ continue;
+ }
- /*
- * Get the node's status, exists, error, directory or regular? Regular
- * means not a directory.
- */
- r = Stat_Node(path);
+ *p = '\0';
+ if (p[1] == '\0') {
+ /* Speculatively unlink the last component so that it can be re-created */
+ unlink(path);
+ return 0;
+ }
- /*
- * If there are errors other than not existing we are finished.
- */
- if (r < 0 && errno != ENOENT) {
- Print_Error(printer, "stat", path);
- return -1;
- }
+ if (mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) != 0) {
+ if (errno == EEXIST || errno == EISDIR) {
+ struct stat sb;
- /*
- * If a file remove and create a directory if not the end.
- */
- if (r == REGTYPE) {
- r = unlink(path);
- if (r < 0) {
- Print_Error(printer, "unlink", path);
- free(copy);
+ if (stat(path, &sb) != 0) {
return -1;
}
- if (!path_end) {
- r = mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO);
- if (r < 0) {
- Print_Error(printer, "mkdir (unlink)", path);
- free(copy);
+
+ if (!S_ISDIR(sb.st_mode)) {
+ if (unlink(path) != 0) {
+ Print_Error(printer, "unlink", path);
return -1;
}
- }
- }
- else if (r < 0) {
- /*
- * Node does not exist which means the rest of the path will not exist.
- */
- while (!path_end) {
- r = mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO);
- if (r < 0) {
- Print_Error(printer, "mkdir", path);
- free(copy);
+
+ if (mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) != 0) {
+ Print_Error(printer, "mkdir (unlink)", path);
return -1;
}
- if (!path_end) {
- *end = '/';
- ++end;
- }
- while (*end != '\0' && *end != '/')
- ++end;
- if (*end == '\0')
- path_end = true;
- }
- }
- else if (path_end && r == DIRTYPE && linktype != DIRTYPE) {
- /*
- * We only handle a directory if at the end of the path and the end is
- * a file. If we cannot remove the directory because it is not empty we
- * raise an error. Otherwise this is a directory and we do nothing
- * which lets us decend into it.
- */
- r = rmdir(path);
- if (r < 0) {
- Print_Error(printer, "rmdir", path);
- free(copy);
- return -1;
}
}
-
- /*
- * If not the end of the path put back the directory separator.
- */
- if (!path_end) {
- *end = '/';
- ++end;
- }
}
- }
- free(copy);
+ *p = '/';
+ }
return 0;
}
@@ -252,9 +165,10 @@ Untar_ProcessHeader(
const char *bufr
)
{
- int sum;
- int hdr_chksum;
- int retval = UNTAR_SUCCESSFUL;
+ int sum;
+ int hdr_chksum;
+ int retval = UNTAR_SUCCESSFUL;
+ int r;
ctx->file_name[0] = '\0';
ctx->file_size = 0;
@@ -290,7 +204,7 @@ Untar_ProcessHeader(
* with it.
*/
- if (Make_Path(ctx->printer, ctx->file_path, ctx->linkflag) < 0) {
+ if (Make_Path(ctx->printer, ctx->file_path) != 0) {
retval = UNTAR_FAIL;
}
@@ -298,33 +212,21 @@ Untar_ProcessHeader(
strlcpy(ctx->link_name, &bufr[157], sizeof(ctx->link_name));
rtems_printf(ctx->printer, "untar: symlink: %s -> %s\n",
ctx->link_name, ctx->file_path);
- symlink(ctx->link_name, ctx->file_path);
+ r = symlink(ctx->link_name, ctx->file_path);
+ if (r != 0) {
+ Print_Error(ctx->printer, "symlink", ctx->file_path);
+ retval = UNTAR_FAIL;
+ }
} else if (ctx->linkflag == REGTYPE) {
rtems_printf(ctx->printer, "untar: file: %s (s:%lu,m:%04lo)\n",
ctx->file_path, ctx->file_size, ctx->mode);
ctx->nblocks = (((ctx->file_size) + 511) & ~511) / 512;
} else if (ctx->linkflag == DIRTYPE) {
- int r;
rtems_printf(ctx->printer, "untar: dir: %s\n", ctx->file_path);
- r = mkdir(ctx->file_path, S_IRWXU | S_IRWXG | S_IRWXO);
- if (r < 0) {
- if (errno == EEXIST) {
- struct stat stat_buf;
- if (stat(ctx->file_path, &stat_buf) == 0) {
- if (S_ISDIR(stat_buf.st_mode)) {
- r = 0;
- } else {
- r = unlink(ctx->file_path);
- if (r == 0) {
- r = mkdir(ctx->file_path, ctx->mode);
- }
- }
- }
- }
- if (r < 0) {
- Print_Error(ctx->printer, "mkdir", ctx->file_path);
- retval = UNTAR_FAIL;
- }
+ r = mkdir(ctx->file_path, ctx->mode);
+ if (r != 0) {
+ Print_Error(ctx->printer, "mkdir", ctx->file_path);
+ retval = UNTAR_FAIL;
}
}
diff --git a/testsuites/libtests/Makefile.am b/testsuites/libtests/Makefile.am
index 9af8098062..a22e153c30 100644
--- a/testsuites/libtests/Makefile.am
+++ b/testsuites/libtests/Makefile.am
@@ -1288,9 +1288,9 @@ endif
tar01_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_FLAGS_tar01) \
$(support_includes) $(test_includes) -I$(top_srcdir)/include
tar01_LDADD = $(RTEMS_ROOT)cpukit/librtemscpu.a $(RTEMS_ROOT)cpukit/libz.a $(LDADD)
-tar01.tar: Makefile
+tar01.tar: $(srcdir)/tar01/home/test_file $(srcdir)/tar01/home/abc/def/test_script $(srcdir)/tar01/symlink
@rm -f $@
- $(AM_V_GEN)$(PAX) -w -f $@ -s ,$(srcdir)/tar01/,, $(srcdir)/tar01/home $(srcdir)/tar01/symlink
+ $(AM_V_GEN)$(PAX) -w -f $@ -s ,$(srcdir)/tar01/,, $+
tar01-tar.c: tar01.tar
$(AM_V_GEN)$(BIN2C) -C $< $@
tar01-tar.h: tar01.tar
@@ -1327,9 +1327,9 @@ tar02_SOURCES = tar02/init.c ../psxtests/psxfile01/test_cat.c \
tar02-tar.c tar02-tar.h
tar02_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_FLAGS_tar02) \
$(support_includes) $(test_includes) -I$(top_srcdir)/include
-tar02.tar: Makefile
+tar02.tar: $(srcdir)/tar01/home/test_file $(srcdir)/tar01/home/abc/def/test_script $(srcdir)/tar01/symlink
@rm -f $@
- $(AM_V_GEN)$(PAX) -w -f $@ -s ,$(srcdir)/tar01/,, $(srcdir)/tar01/home $(srcdir)/tar01/symlink
+ $(AM_V_GEN)$(PAX) -w -f $@ -s ,$(srcdir)/tar01/,, $+
tar02-tar.c: tar02.tar
$(AM_V_GEN)$(BIN2C) -C $< $@
tar02-tar.h: tar02.tar
diff --git a/testsuites/libtests/tar01/home/test_script b/testsuites/libtests/tar01/home/abc/def/test_script
index 884924820b..884924820b 100755
--- a/testsuites/libtests/tar01/home/test_script
+++ b/testsuites/libtests/tar01/home/abc/def/test_script
diff --git a/testsuites/libtests/tar01/init.c b/testsuites/libtests/tar01/init.c
index 8891911288..371ea71920 100644
--- a/testsuites/libtests/tar01/init.c
+++ b/testsuites/libtests/tar01/init.c
@@ -85,9 +85,9 @@ void test_untar_from_memory(void)
test_cat( "/home/test_file", 0, 0 );
/******************/
- printf( "========= /home/test_script =========\n" );
- test_cat( "/home/test_script", 0, 0 );
- test_untar_check_mode("/home/test_script", 0755);
+ printf( "========= /home/abc/def/test_script =========\n" );
+ test_cat( "/home/abc/def/test_script", 0, 0 );
+ test_untar_check_mode("/home/abc/def/test_script", 0755);
/******************/
printf( "========= /symlink =========\n" );
@@ -133,9 +133,9 @@ void test_untar_from_file(void)
test_cat( "/dest/home/test_file", 0, 0 );
/******************/
- printf( "========= /dest/home/test_script =========\n" );
- test_cat( "/dest/home/test_script", 0, 0 );
- test_untar_check_mode("/dest/home/test_script", 0755);
+ printf( "========= /dest/home/abc/def/test_script =========\n" );
+ test_cat( "/dest/home/abc/def/test_script", 0, 0 );
+ test_untar_check_mode("/dest/home/abc/def/test_script", 0755);
/******************/
printf( "========= /dest/symlink =========\n" );
@@ -179,9 +179,9 @@ void test_untar_chunks_from_memory(void)
test_cat( "/dest2/home/test_file", 0, 0 );
/******************/
- printf( "========= /dest2/home/test_script =========\n" );
- test_cat( "/dest2/home/test_script", 0, 0 );
- test_untar_check_mode("/dest2/home/test_script", 0755);
+ printf( "========= /dest2/home/abc/def/test_script =========\n" );
+ test_cat( "/dest2/home/abc/def/test_script", 0, 0 );
+ test_untar_check_mode("/dest2/home/abc/def/test_script", 0755);
/******************/
printf( "========= /dest2/symlink =========\n" );
@@ -225,9 +225,9 @@ void test_untar_unzip_tgz(void)
test_cat( "/dest3/home/test_file", 0, 0 );
/******************/
- printf( "========= /dest3/home/test_script =========\n" );
- test_cat( "/dest3/home/test_script", 0, 0 );
- test_untar_check_mode("/dest3/home/test_script", 0755);
+ printf( "========= /dest3/home/abc/def/test_script =========\n" );
+ test_cat( "/dest3/home/abc/def/test_script", 0, 0 );
+ test_untar_check_mode("/dest3/home/abc/def/test_script", 0755);
/******************/
printf( "========= /dest3/symlink =========\n" );
@@ -275,9 +275,9 @@ void test_untar_unzip_txz(void)
test_cat( "/dest4/home/test_file", 0, 0 );
/******************/
- printf( "========= /dest4/home/test_script =========\n" );
- test_cat( "/dest4/home/test_script", 0, 0 );
- test_untar_check_mode("/dest4/home/test_script", 0755);
+ printf( "========= /dest4/home/abc/def/test_script =========\n" );
+ test_cat( "/dest4/home/abc/def/test_script", 0, 0 );
+ test_untar_check_mode("/dest4/home/abc/def/test_script", 0755);
/******************/
printf( "========= /dest4/symlink =========\n" );