#2413 closed defect (fixed)

Untar_FromMemory breaks on create directory if they exists, even on root one.

Reported by: Pavel Pisa Owned by: Pavel Pisa <pisa@…>
Priority: normal Milestone: 4.11
Component: unspecified Version: 4.11
Severity: normal Keywords:
Cc: Blocked By:
Blocking:

Description

When directory specified by TAR file already exists then Untar_FromMemory bails out with error EEXIST (File exists).

Untar: failed to create directory ./
Untar_FromMemory returned RTEMS_TASK_EXITTED

Because TAR includes "./" directory in archive by default and IMFS includes root directory, UNTAR fails for standard configurations.

Attachments (1)

0001-untar-do-not-exit-with-error-when-created-directory-.patch (2.7 KB) - added by Pavel Pisa on 11/11/15 at 13:44:15.

Download all attachments as: .zip

Change History (5)

comment:1 Changed on 09/07/15 at 09:13:15 by Pavel Pisa

Simple workaround is to ignore EEXIST for directory create (mkdir).

diff --git a/cpukit/libmisc/untar/untar.c b/cpukit/libmisc/untar/untar.c
index aed8fed..4acb4dc 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,8 @@ Untar_FromMemory(
       }
     } else if (linkflag == DIRTYPE) {
       if ( mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO) != 0 ) {
+        if (errno == EEXIST)
+          continue;
         printk("Untar: failed to create directory %s\n", fname);
         retval = UNTAR_FAIL;
         break;
(

Alternative providing more strict checking with stat call

diff --git a/cpukit/libmisc/untar/untar.c b/cpukit/libmisc/untar/untar.c
index aed8fed..4591a8b 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,13 @@ 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;
+          }
+        }
         printk("Untar: failed to create directory %s\n", fname);
         retval = UNTAR_FAIL;
         break;

comment:2 Changed on 11/18/15 at 22:14:28 by Chris Johns

I do not think the patch is enough. For example on OS X:

$ rm -rf x && mkdir x && mkdir x/1 && touch x/1/1 touch x/2 && tar cf t1.tar x
$ rm -rf x && mkdir x && mkdir x/2 && touch x/2/1 touch x/1 && tar cf t2.tar x
$ rm -rf x && tar xf t1.tar && tar xf t2.tar
x/1: Can't remove already-existing dir
tar: Error exit delayed from previous errors.

and on FreeBSD:

$ rm -rf x && mkdir x && mkdir x/1 && touch x/1/1 touch x/2 && tar cf t1.tar x 
$ rm -rf x && mkdir x && mkdir x/2 && touch x/2/1 touch x/1 && tar cf t2.tar x
$ rm -rf x && tar xf t1.tar && tar xf t2.tar
x/1: Can't replace existing directory with non-directory
tar: Error exit delayed from previous errors.

I think we need to add more checking and error if nodes are not the same. I cannot see a way around this.

The current implementation is overly cautious and it has made me move away a direction and untar a fresh image. In the end I think it is better as stray files do not hang around. I would rather we handle the special cases correctly or not at all.

Version 0, edited on 11/18/15 at 22:14:28 by Chris Johns (next)

comment:3 Changed on 11/23/15 at 15:40:35 by Pavel Pisa <pisa@…>

Owner: set to Pavel Pisa <pisa@…>
Resolution: fixed
Status: newclosed

In 9394aa5ed7ef6db28045e0103a6a174d9540d6c2/rtems:

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.

comment:4 Changed on 11/23/15 at 15:40:47 by Pavel Pisa <pisa@…>

In a6d176f25e28c153b304ee6c8ca6690b04722448/rtems:

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.

Note: See TracTickets for help on using tickets.