summaryrefslogtreecommitdiff
path: root/cpukit
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 /cpukit
parent3e1196d9e1e65f3a77bc4537934438f105b35d98 (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.
Diffstat (limited to 'cpukit')
-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);