diff options
author | Pavel Pisa <pisa@cmp.felk.cvut.cz> | 2015-11-23 10:09:06 +0100 |
---|---|---|
committer | Gedare Bloom <gedare@rtems.org> | 2015-11-23 10:40:15 -0500 |
commit | 9394aa5ed7ef6db28045e0103a6a174d9540d6c2 (patch) | |
tree | ff22baff66da45a5cbdd0c01f2789af00a78b4b4 | |
parent | 3e1196d9e1e65f3a77bc4537934438f105b35d98 (diff) |
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.c | 18 | ||||
-rw-r--r-- | cpukit/libmisc/untar/untar.c | 30 |
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); |