[rtems commit] untar: do not exit with error when created directory already exists.

Gedare Bloom gedare at rtems.org
Mon Nov 23 15:40:42 UTC 2015


Module:    rtems
Branch:    4.11
Commit:    a6d176f25e28c153b304ee6c8ca6690b04722448
Changeset: http://git.rtems.org/rtems/commit/?id=a6d176f25e28c153b304ee6c8ca6690b04722448

Author:    Pavel Pisa <pisa at cmp.felk.cvut.cz>
Date:      Mon Nov 23 10:09:06 2015 +0100

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.

---

 cpukit/libfs/src/imfs/imfs_load_tar.c | 18 +++++++++++++++++-
 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 7228978..adc91dd 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 aed8fed..e4b0aeb 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);



More information about the vc mailing list