summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Pisa <pisa@cmp.felk.cvut.cz>2015-11-23 10:09:06 +0100
committerGedare Bloom <gedare@rtems.org>2015-11-23 10:40:15 -0500
commit9394aa5ed7ef6db28045e0103a6a174d9540d6c2 (patch)
treeff22baff66da45a5cbdd0c01f2789af00a78b4b4
parentbsp/tms570: unite code duplication in pinmux and clean SCI close per review r... (diff)
downloadrtems-9394aa5ed7ef6db28045e0103a6a174d9540d6c2.tar.bz2
untar: do not exit with error when created directory already exists.
The problem exists for both RTEMS untar implementations and their variants: Untar_FromMemory(), Untar_FromFile() and rtems_tarfs_load(). If filesystem object already exists at extracted directory path then if it is directory, creation is ignored. Attempt to delete/unlink object and make directory is tried for other cases. This simple approach problem reported in ticket fixes #2413. Behavior follows GNU tar and BSD tar practice for directories but much more work is required to achieve full semantics of the full featured tar implementation still.
-rw-r--r--cpukit/libfs/src/imfs/imfs_load_tar.c18
-rw-r--r--cpukit/libmisc/untar/untar.c30
2 files changed, 46 insertions, 2 deletions
diff --git a/cpukit/libfs/src/imfs/imfs_load_tar.c b/cpukit/libfs/src/imfs/imfs_load_tar.c
index 7228978094..adc91dd054 100644
--- a/cpukit/libfs/src/imfs/imfs_load_tar.c
+++ b/cpukit/libfs/src/imfs/imfs_load_tar.c
@@ -103,8 +103,24 @@ int rtems_tarfs_load(
strcat(full_filename, "/");
++len;
strncat(full_filename, filename, 256-len-1);
- rv = mkdir(full_filename, S_IRWXU | S_IRWXG | S_IRWXO);
+ if ( mkdir(full_filename, S_IRWXU | S_IRWXG | S_IRWXO) != 0 ) {
+ if (errno == EEXIST) {
+ struct stat stat_buf;
+ if ( stat(full_filename, &stat_buf) == 0 ) {
+ if ( S_ISDIR(stat_buf.st_mode) ) {
+ continue;
+ } else {
+ if ( unlink(full_filename) != -1 ) {
+ if ( mkdir(full_filename, S_IRWXU | S_IRWXG | S_IRWXO) == 0 )
+ continue;
+ }
+ }
+ }
+ }
+ rv = -1;
+ }
}
+
/*
* Create a LINEAR_FILE node
*/
diff --git a/cpukit/libmisc/untar/untar.c b/cpukit/libmisc/untar/untar.c
index aed8fed356..e4b0aeb968 100644
--- a/cpukit/libmisc/untar/untar.c
+++ b/cpukit/libmisc/untar/untar.c
@@ -28,6 +28,7 @@
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
+#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <rtems/untar.h>
@@ -203,6 +204,19 @@ Untar_FromMemory(
}
} else if (linkflag == DIRTYPE) {
if ( mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO) != 0 ) {
+ if (errno == EEXIST) {
+ struct stat stat_buf;
+ if ( stat(fname, &stat_buf) == 0 ) {
+ if ( S_ISDIR(stat_buf.st_mode) ) {
+ continue;
+ } else {
+ if ( unlink(fname) != -1 ) {
+ if ( mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO) == 0 )
+ continue;
+ }
+ }
+ }
+ }
printk("Untar: failed to create directory %s\n", fname);
retval = UNTAR_FAIL;
break;
@@ -319,7 +333,21 @@ Untar_FromFile(
close(out_fd);
}
} else if (linkflag == DIRTYPE) {
- (void) mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO);
+ if ( mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO) != 0 ) {
+ if (errno == EEXIST) {
+ struct stat stat_buf;
+ if ( stat(fname, &stat_buf) == 0 ) {
+ if ( S_ISDIR(stat_buf.st_mode) ) {
+ continue;
+ } else {
+ if ( unlink(fname) != -1 ) {
+ if ( mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO) == 0 )
+ continue;
+ }
+ }
+ }
+ }
+ }
}
}
free(bufr);