Index: cpukit/libmisc/untar/untar.c
===================================================================
--- cpukit/libmisc/untar/untar.c	(revision 39e6f532986c580e1eef474f69d94412eefbfeae)
+++ cpukit/libmisc/untar/untar.c	(revision ffc57e3cf33ec0e2cc51ce214cedc24f390a7ea5)
@@ -127,28 +127,23 @@
     *p = '\0';
     if (p[1] == '\0') {
-      /* Speculatively unlink the last component so that it can be re-created */
-      unlink(path);
       return 0;
     }
 
     if (mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) != 0) {
-      if (errno == EEXIST || errno == EISDIR) {
+      if (errno == EEXIST) {
+        /* If it exists already: Check whether it is a directory */
         struct stat sb;
-
-        if (stat(path, &sb) != 0) {
+        if (lstat(path, &sb) != 0) {
+          Print_Error(printer, "lstat", path);
+          return -1;
+        } else if (!S_ISDIR(sb.st_mode)) {
+          rtems_printf(printer,
+                       "untar: mkdir: %s: exists but is not a directory\n",
+                       path);
           return -1;
         }
-
-        if (!S_ISDIR(sb.st_mode)) {
-          if (unlink(path) != 0) {
-            Print_Error(printer, "unlink", path);
-            return -1;
-          }
-
-          if (mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) != 0) {
-            Print_Error(printer, "mkdir (unlink)", path);
-            return -1;
-          }
-        }
+      } else {
+        Print_Error(printer, "mkdir", path);
+        return -1;
       }
     }
@@ -207,4 +202,10 @@
   if (Make_Path(ctx->printer, ctx->file_path) != 0) {
     retval = UNTAR_FAIL;
+  } else {
+    /*
+     * Speculatively unlink. This should unlink everything but non-empty
+     * directories or write protected stuff.
+     */
+    unlink(ctx->file_path);
   }
 
@@ -226,6 +227,20 @@
     r = mkdir(ctx->file_path, ctx->mode);
     if (r != 0) {
-      Print_Error(ctx->printer, "mkdir", ctx->file_path);
-      retval = UNTAR_FAIL;
+      if (errno == EEXIST) {
+        /* If it exists already: Check whether it is a directory */
+        struct stat sb;
+        if (lstat(ctx->file_path, &sb) != 0) {
+          Print_Error(ctx->printer, "lstat", ctx->file_path);
+          retval = UNTAR_FAIL;
+        } else if (!S_ISDIR(sb.st_mode)) {
+          rtems_printf(ctx->printer,
+                       "untar: mkdir: %s: exists but is not a directory\n",
+                       ctx->file_path);
+          retval = UNTAR_FAIL;
+        }
+      } else {
+        Print_Error(ctx->printer, "mkdir", ctx->file_path);
+        retval = UNTAR_FAIL;
+      }
     }
   }
@@ -427,5 +442,7 @@
 
       if ((out_fd = creat(ctx.file_path, ctx.mode)) == -1) {
-        (void) lseek(fd, SEEK_CUR, 512UL * ctx.nblocks);
+        /* Couldn't create that file. Abort. */
+        retval = UNTAR_FAIL;
+        break;
       } else {
         for (i = 0; i < ctx.nblocks; i++) {
Index: testsuites/libtests/tar01/init.c
===================================================================
--- testsuites/libtests/tar01/init.c	(revision 39e6f532986c580e1eef474f69d94412eefbfeae)
+++ testsuites/libtests/tar01/init.c	(revision ffc57e3cf33ec0e2cc51ce214cedc24f390a7ea5)
@@ -8,4 +8,31 @@
  */
 
+/*
+ * Note on the used tar file: Generate the file on a system that supports
+ * symlinks with the following commands (tested on Linux - you might have to
+ * adapt on other systems):
+ *
+ * export WORK=some_work_directory
+ * rm -r ${WORK}
+ * mkdir -p ${WORK}/home/abc/def
+ * mkdir -p ${WORK}/home/dir
+ * cd ${WORK}
+ * echo "#! joel" > home/abc/def/test_script
+ * echo "ls -las /dev" >> home/abc/def/test_script
+ * chmod 755 home/abc/def/test_script
+ * echo "This is a test of loading an RTEMS filesystem from an" > home/test_file
+ * echo "initial tar image." >> home/test_file
+ * echo "Hello world" >> home/dir/file
+ * ln -s home/test_file symlink
+ * tar cf tar01.tar --format=ustar \
+ *     symlink \
+ *     home/test_file \
+ *     home/abc/def/test_script \
+ *     home/dir
+ *
+ * Note that "home/dir" is in the archive as separate directory. "home/abc" is
+ * only in the archive as a parent of the file "test_script".
+ */
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -96,4 +123,82 @@
 }
 
+static void assert_file_content(
+    const char *name,
+    const char *expected_content,
+    ssize_t expected_size
+)
+{
+  char buf[16];
+  int fd;
+  int rd;
+
+  fd = open(name, O_RDONLY);
+  rtems_test_assert( fd >= 0 );
+  do {
+    rd = read(fd, buf, sizeof(buf));
+    rtems_test_assert( rd >= 0 );
+    if (rd > 0) {
+      rtems_test_assert( expected_size - rd >= 0 );
+      rtems_test_assert( memcmp(buf, expected_content, rd) == 0 );
+      expected_content += rd;
+      expected_size -= rd;
+    }
+  } while(rd > 0);
+  rtems_test_assert( expected_size == 0 );
+  close(fd);
+}
+
+static void assert_content_like_expected(void)
+{
+  const char *directories[] = {
+    "home",
+    "home/abc",
+    "home/abc/def",
+    "home/dir",
+  };
+  const char *symlinks[] = {
+    "symlink",
+  };
+  const struct {
+    const char *name;
+    const char *content;
+  } files[] = {
+    {
+      .name = "home/abc/def/test_script",
+      .content = "#! joel\nls -las /dev\n",
+    }, {
+      .name = "home/test_file",
+      .content = "This is a test of loading an RTEMS filesystem from an\n"
+                 "initial tar image.\n",
+    }, {
+      .name = "home/dir/file",
+      .content = "Hello world\n",
+    }
+  };
+  size_t i;
+  struct stat st;
+
+  for(i = 0; i < RTEMS_ARRAY_SIZE(directories); ++i) {
+    lstat(directories[i], &st);
+    rtems_test_assert( S_ISDIR(st.st_mode) );
+  }
+
+  for(i = 0; i < RTEMS_ARRAY_SIZE(symlinks); ++i) {
+    lstat(symlinks[i], &st);
+    rtems_test_assert( S_ISLNK(st.st_mode) );
+  }
+
+  for(i = 0; i < RTEMS_ARRAY_SIZE(files); ++i) {
+    lstat(files[i].name, &st);
+    rtems_test_assert( S_ISREG(st.st_mode) );
+
+    assert_file_content(
+        files[i].name,
+        files[i].content,
+        strlen(files[i].content)
+        );
+  }
+}
+
 void test_untar_from_file(void)
 {
@@ -120,5 +225,5 @@
   rtems_test_assert( rv == 0 );
 
-  /* Untar it */
+  /* Case 1: Untar it into empty directory */
   rv = Untar_FromFile( "/test.tar" );
   printf("Untaring from file - ");
@@ -127,4 +232,96 @@
     exit(1);
   }
+  assert_content_like_expected();
+  printf ("successful\n");
+
+  /* Case 2: Most files exist */
+  rv = unlink("/dest/home/test_file");
+  rtems_test_assert( rv == 0 );
+
+  rv = Untar_FromFile( "/test.tar" );
+  printf("Untar from file into existing structure with one missing file - ");
+  if (rv != UNTAR_SUCCESSFUL) {
+    printf ("error: untar failed: %i\n", rv);
+    exit(1);
+  }
+  assert_content_like_expected();
+  printf ("successful\n");
+
+  /* Case 3: An empty directory exists where a file should be */
+  rv = unlink("/dest/home/test_file");
+  rtems_test_assert( rv == 0 );
+  rv = mkdir("/dest/home/test_file", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+  rtems_test_assert( rv == 0 );
+
+  rv = Untar_FromFile( "/test.tar" );
+  printf("Untar from file; overwrite empty directory with file - ");
+  if (rv != UNTAR_SUCCESSFUL) {
+    printf ("error: untar failed: %i\n", rv);
+    exit(1);
+  }
+  assert_content_like_expected();
+  printf ("successful\n");
+
+  /* Case 4: A file exists where a parent directory should be created */
+  rv = unlink("/dest/home/abc/def/test_script");
+  rtems_test_assert( rv == 0 );
+  rv = unlink("/dest/home/abc/def");
+  rtems_test_assert( rv == 0 );
+  rv = unlink("/dest/home/abc");
+  rtems_test_assert( rv == 0 );
+  fd = creat("/dest/home/abc", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+  rtems_test_assert( fd >= 0 );
+  close(fd);
+
+  rv = Untar_FromFile( "/test.tar" );
+  printf("Untar from file; file exists where parent dir should be created - ");
+  if (rv != UNTAR_FAIL) {
+    printf ("error: untar didn't fail like expected: %i\n", rv);
+    exit(1);
+  }
+  printf ("expected fail\n");
+  /* cleanup so that the next one works */
+  rv = unlink("/dest/home/abc");
+  rtems_test_assert( rv == 0 );
+
+  /* Case 5: A non-empty directory exists where a file should be created */
+  rv = unlink("/dest/home/test_file");
+  rtems_test_assert( rv == 0 );
+  rv = mkdir("/dest/home/test_file", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+  rtems_test_assert( rv == 0 );
+  fd = creat("/dest/home/test_file/file",
+      S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+  rtems_test_assert( fd >= 0 );
+  close(fd);
+
+  rv = Untar_FromFile( "/test.tar" );
+  printf("Untar from file; non-empty dir where file should be created - ");
+  if (rv != UNTAR_FAIL) {
+    printf ("error: untar didn't fail like expected: %i\n", rv);
+    exit(1);
+  }
+  printf ("expected fail\n");
+  /* cleanup so that the next one works */
+  rv = unlink("/dest/home/test_file/file");
+  rtems_test_assert( rv == 0 );
+  rv = unlink("/dest/home/test_file");
+  rtems_test_assert( rv == 0 );
+
+  /* Case 6: A file exists where a directory is explicitly in the archive */
+  rv = unlink("/dest/home/dir/file");
+  rtems_test_assert( rv == 0 );
+  rv = unlink("/dest/home/dir");
+  rtems_test_assert( rv == 0 );
+  fd = creat("/dest/home/dir", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+  rtems_test_assert( fd >= 0 );
+  close(fd);
+
+  rv = Untar_FromFile( "/test.tar" );
+  printf("Untar from file; overwrite file with explicit directory - ");
+  if (rv != UNTAR_SUCCESSFUL) {
+    printf ("error: untar failed: %i\n", rv);
+    exit(1);
+  }
+  assert_content_like_expected();
   printf ("successful\n");
 
Index: testsuites/libtests/tar01/tar01.scn
===================================================================
--- testsuites/libtests/tar01/tar01.scn	(revision 39e6f532986c580e1eef474f69d94412eefbfeae)
+++ testsuites/libtests/tar01/tar01.scn	(revision ffc57e3cf33ec0e2cc51ce214cedc24f390a7ea5)
@@ -1,8 +1,23 @@
-*** TAR01 TEST ***
-Untaring from memory - successful
+*** BEGIN OF TEST TAR 1 ***
+*** TEST VERSION: 6.0.0.e1efb4eb8a9d6dd5f6f37dafc9feb0a9e6a888f1
+*** TEST STATE: EXPECTED_PASS
+*** TEST BUILD: RTEMS_POSIX_API
+*** TEST TOOLS: 10.3.1 20210409 (RTEMS 6, RSB ad54d1dd3cf8249d9d39deb1dd28b2f294df062d-modified, Newlib eb03ac1)
+Untaring from memory - untar: memory at 0x11ece8 (10240)
+untar: symlink: home/test_file -> symlink
+untar: file: home/test_file (s:73,m:0644)
+untar: file: home/abc/def/test_script (s:21,m:0755)
+untar: dir: home/dir
+untar: file: home/dir/file (s:12,m:0644)
+successful
 ========= /home/test_file =========
 (0)This is a test of loading an RTEMS filesystem from an
 initial tar image.
 
+========= /home/abc/def/test_script =========
+(0)#! joel
+ls -las /dev
+
+ /home/abc/def/test_script: mode: 0755 want: 0755
 ========= /symlink =========
 (0)This is a test of loading an RTEMS filesystem from an
@@ -12,8 +27,18 @@
 Copy tar image to test.tar
 Untaring from file - successful
+Untar from file into existing structure with one missing file - successful
+Untar from file; overwrite empty directory with file - successful
+Untar from file; file exists where parent dir should be created - expected fail
+Untar from file; non-empty dir where file should be created - expected fail
+Untar from file; overwrite file with explicit directory - successful
 ========= /dest/home/test_file =========
 (0)This is a test of loading an RTEMS filesystem from an
 initial tar image.
 
+========= /dest/home/abc/def/test_script =========
+(0)#! joel
+ls -las /dev
+
+ /dest/home/abc/def/test_script: mode: 0755 want: 0755
 ========= /dest/symlink =========
 (0)This is a test of loading an RTEMS filesystem from an
@@ -21,6 +46,9 @@
 
 
-Untaring chunks from memory - untar: dir: home
-untar: file: home/test_file (73)
+Untaring chunks from memory - untar: symlink: home/test_file -> symlink
+untar: file: home/test_file (s:73,m:0644)
+untar: file: home/abc/def/test_script (s:21,m:0755)
+untar: dir: home/dir
+untar: file: home/dir/file (s:12,m:0644)
 successful
 ========= /dest2/home/test_file =========
@@ -28,4 +56,9 @@
 initial tar image.
 
+========= /dest2/home/abc/def/test_script =========
+(0)#! joel
+ls -las /dev
+
+ /dest2/home/abc/def/test_script: mode: 0755 want: 0755
 ========= /dest2/symlink =========
 (0)This is a test of loading an RTEMS filesystem from an
@@ -33,13 +66,18 @@
 
 
-Untaring chunks from tgz- untar: dir: home
-untar: file: home/test_file (73)
-successful
+Untaring chunks from tgz - successful
 ========= /dest3/home/test_file =========
 (0)This is a test of loading an RTEMS filesystem from an
 initial tar image.
 
+========= /dest3/home/abc/def/test_script =========
+(0)#! joel
+ls -las /dev
+
+ /dest3/home/abc/def/test_script: mode: 0755 want: 0755
 ========= /dest3/symlink =========
 (0)This is a test of loading an RTEMS filesystem from an
 initial tar image.
-*** END OF TAR01 TEST ***
+
+
+*** END OF TEST TAR 1 ***
