[PATCHv2] libmisc/untar: Set the perms to the value in the tar file.

Chris Johns chrisj at rtems.org
Mon Aug 1 04:23:23 UTC 2016


This patch parses the mode field in the tar header and sets the
directory or file to the mode value in the header.

Closes #2768.
---
 cpukit/libmisc/untar/untar.c          | 47 +++++++++++++++++++++--------------
 cpukit/libmisc/untar/untar.h          |  7 +++++-
 testsuites/libtests/tar01/Makefile.am |  5 +++-
 testsuites/libtests/tar01/init.c      | 30 ++++++++++++++++++++++
 4 files changed, 68 insertions(+), 21 deletions(-)

diff --git a/cpukit/libmisc/untar/untar.c b/cpukit/libmisc/untar/untar.c
index 9a14f67..ecf1877 100644
--- a/cpukit/libmisc/untar/untar.c
+++ b/cpukit/libmisc/untar/untar.c
@@ -250,6 +250,7 @@ static int
 Untar_ProcessHeader(
   const char          *bufr,
   char                *fname,
+  unsigned long       *mode,
   unsigned long       *file_size,
   unsigned long       *nblocks,
   unsigned char       *linkflag,
@@ -286,6 +287,8 @@ Untar_ProcessHeader(
   strncpy(fname, bufr, MAX_NAME_FIELD_SIZE);
   fname[MAX_NAME_FIELD_SIZE] = '\0';
 
+  *mode = strtoul(&bufr[100], NULL, 8);
+
   *linkflag   = bufr[156];
   *file_size = _rtems_octal2ulong(&bufr[124], 12);
 
@@ -299,7 +302,8 @@ Untar_ProcessHeader(
     rtems_printf(printer, "untar: symlink: %s -> %s\n", linkname, fname);
     symlink(linkname, fname);
   } else if (*linkflag == REGTYPE) {
-    rtems_printf(printer, "untar: file: %s (%i)\n", fname, (int) *file_size);
+    rtems_printf(printer, "untar: file: %s (s:%i,m:%04o)\n",
+                 fname, (int) *file_size, (int) *mode);
     *nblocks = (((*file_size) + 511) & ~511) / 512;
     if (Make_Path(printer, fname, false) < 0) {
       retval  = UNTAR_FAIL;
@@ -318,7 +322,7 @@ Untar_ProcessHeader(
           if (!S_ISDIR(stat_buf.st_mode)) {
             r = unlink(fname);
             if (r == 0) {
-              r = mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO);
+              r = mkdir(fname, *mode);
             }
           }
         }
@@ -362,15 +366,16 @@ Untar_FromMemory_Print(
   const rtems_printer *printer
 )
 {
-  FILE           *fp;
+  int            fd;
   const char     *tar_ptr = (const char *)tar_buf;
   const char     *bufr;
   char           fname[100];
   int            retval = UNTAR_SUCCESSFUL;
   unsigned long  ptr;
-  unsigned long  nblocks;
-  unsigned long  file_size;
-  unsigned char  linkflag;
+  unsigned long  nblocks = 0;
+  unsigned long  file_size = 0;
+  unsigned long  mode = 0;
+  unsigned char  linkflag = 0;
 
   rtems_printf(printer, "untar: memory at %p (%zu)\n", tar_buf, size);
 
@@ -385,20 +390,21 @@ Untar_FromMemory_Print(
     bufr = &tar_ptr[ptr];
     ptr += 512;
 
-    retval = Untar_ProcessHeader(bufr, fname, &file_size, &nblocks, &linkflag, printer);
+    retval = Untar_ProcessHeader(bufr, fname, &mode, &file_size,
+                                 &nblocks, &linkflag, printer);
 
     if (retval != UNTAR_SUCCESSFUL)
       break;
 
     if (linkflag == REGTYPE) {
-      if ((fp = fopen(fname, "w")) == NULL) {
+      if ((fd = open(fname, O_TRUNC | O_CREAT | O_WRONLY, mode)) == -1) {
         Print_Error(printer, "open", fname);
         ptr += 512 * nblocks;
       } else {
         unsigned long sizeToGo = file_size;
-        size_t        len;
-        size_t        i;
-        size_t        n;
+        ssize_t       len;
+        ssize_t       i;
+        ssize_t       n;
 
         /*
          * Read out the data.  There are nblocks of data where nblocks is the
@@ -406,7 +412,7 @@ Untar_FromMemory_Print(
          */
         for (i = 0; i < nblocks; i++) {
           len = ((sizeToGo < 512L) ? (sizeToGo) : (512L));
-          n = fwrite(&tar_ptr[ptr], 1, len, fp);
+          n = write(fd, &tar_ptr[ptr], len);
           if (n != len) {
             Print_Error(printer, "write", fname);
             retval  = UNTAR_FAIL;
@@ -415,7 +421,7 @@ Untar_FromMemory_Print(
           ptr += 512;
           sizeToGo -= n;
         }
-        fclose(fp);
+        close(fd);
       }
 
     }
@@ -485,9 +491,10 @@ Untar_FromFile_Print(
   char           fname[100];
   int            retval;
   unsigned long  i;
-  unsigned long  nblocks;
-  unsigned long  file_size;
-  unsigned char  linkflag;
+  unsigned long  nblocks = 0;
+  unsigned long  file_size = 0;
+  unsigned long  mode = 0;
+  unsigned char  linkflag = 0;
 
   retval = UNTAR_SUCCESSFUL;
 
@@ -508,7 +515,8 @@ Untar_FromFile_Print(
       break;
     }
 
-    retval = Untar_ProcessHeader(bufr, fname, &file_size, &nblocks, &linkflag, printer);
+    retval = Untar_ProcessHeader(bufr, fname, &mode, &file_size,
+                                 &nblocks, &linkflag, printer);
 
     if (retval != UNTAR_SUCCESSFUL)
       break;
@@ -521,7 +529,7 @@ Untar_FromFile_Print(
        * is the size rounded to the nearest 512-byte boundary.
        */
 
-      if ((out_fd = creat(fname, 0644)) == -1) {
+      if ((out_fd = creat(fname, mode)) == -1) {
         (void) lseek(fd, SEEK_CUR, 512UL * nblocks);
       } else {
         for (i = 0; i < nblocks; i++) {
@@ -579,6 +587,7 @@ int Untar_FromChunk_Print(
           retval = Untar_ProcessHeader(
             &context->header[0],
             &context->fname[0],
+            &context->mode,
             &context->todo_bytes,
             &context->todo_blocks,
             &linkflag,
@@ -591,7 +600,7 @@ int Untar_FromChunk_Print(
           }
 
           if (linkflag == REGTYPE) {
-            context->out_fd = creat(&context->fname[0], 0644);
+            context->out_fd = creat(&context->fname[0], context->mode);
 
             if (context->out_fd >= 0) {
               context->state = UNTAR_CHUNK_WRITE;
diff --git a/cpukit/libmisc/untar/untar.h b/cpukit/libmisc/untar/untar.h
index 4d00d36..3c8bb74 100644
--- a/cpukit/libmisc/untar/untar.h
+++ b/cpukit/libmisc/untar/untar.h
@@ -74,9 +74,14 @@ typedef struct {
   size_t done_bytes;
 
   /**
+   * @brief Mode of the file.
+   */
+  unsigned long mode;
+
+  /**
    * @brief Overall amount of bytes to be processed.
    */
-  long unsigned todo_bytes;
+  unsigned long todo_bytes;
 
   /**
    * @brief Overall amount of blocks to be processed.
diff --git a/testsuites/libtests/tar01/Makefile.am b/testsuites/libtests/tar01/Makefile.am
index d7257bc..8b03e59 100644
--- a/testsuites/libtests/tar01/Makefile.am
+++ b/testsuites/libtests/tar01/Makefile.am
@@ -9,7 +9,7 @@ tar01_SOURCES += initial_filesystem_tar_gz.c
 tar01_SOURCES += initial_filesystem_tar_gz.h
 
 tar01_LDADD = -lrtemscpu -lz
-  
+
 BUILT_SOURCES =
 BUILT_SOURCES += initial_filesystem_tar.c
 BUILT_SOURCES += initial_filesystem_tar.h
@@ -57,6 +57,9 @@ initial_filesystem.tar:
 	$(MKDIR_P) initial_fs/home
 	(echo "This is a test of loading an RTEMS filesystem from an" ; \
 	echo "initial tar image.") >initial_fs/home/test_file
+	(echo "#! joel" ; \
+	echo "ls -las /dev") >initial_fs/home/test_script
+	chmod +x initial_fs/home/test_script
 	(cd initial_fs; \
 	$(LN_S) home/test_file symlink; \
 	$(PAX) -w -f ../initial_filesystem.tar home symlink)
diff --git a/testsuites/libtests/tar01/init.c b/testsuites/libtests/tar01/init.c
index 4bfa29c..7d4f1b9 100644
--- a/testsuites/libtests/tar01/init.c
+++ b/testsuites/libtests/tar01/init.c
@@ -46,6 +46,16 @@ void test_cat(
   int   length
 );
 
+static void test_untar_check_mode(const char* file, int mode)
+{
+  struct stat sb;
+  int         fmode;
+  rtems_test_assert(stat(file, &sb) == 0);
+  fmode = sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
+  printf(" %s: mode: %04o want: %04o\n", file, fmode, mode);
+  rtems_test_assert(fmode == mode);
+}
+
 void test_untar_from_memory(void)
 {
   rtems_status_code sc;
@@ -66,6 +76,11 @@ void test_untar_from_memory(void)
   test_cat( "/home/test_file", 0, 0 );
 
   /******************/
+  printf( "========= /home/test_script =========\n" );
+  test_cat( "/home/test_script", 0, 0 );
+  test_untar_check_mode("/home/test_script", 0755);
+
+  /******************/
   printf( "========= /symlink =========\n" );
   test_cat( "/symlink", 0, 0 );
 
@@ -107,6 +122,11 @@ void test_untar_from_file(void)
   test_cat( "/dest/home/test_file", 0, 0 );
 
   /******************/
+  printf( "========= /dest/home/test_script =========\n" );
+  test_cat( "/dest/home/test_script", 0, 0 );
+  test_untar_check_mode("/dest/home/test_script", 0755);
+
+  /******************/
   printf( "========= /dest/symlink =========\n" );
   test_cat( "/dest/symlink", 0, 0 );
 }
@@ -144,6 +164,11 @@ void test_untar_chunks_from_memory(void)
   test_cat( "/dest2/home/test_file", 0, 0 );
 
   /******************/
+  printf( "========= /dest2/home/test_script =========\n" );
+  test_cat( "/dest2/home/test_script", 0, 0 );
+  test_untar_check_mode("/dest2/home/test_script", 0755);
+
+  /******************/
   printf( "========= /dest2/symlink =========\n" );
   test_cat( "/dest2/symlink", 0, 0 );
 
@@ -184,6 +209,11 @@ void test_untar_unzip_tgz(void)
   test_cat( "/dest3/home/test_file", 0, 0 );
 
   /******************/
+  printf( "========= /dest3/home/test_script =========\n" );
+  test_cat( "/dest3/home/test_script", 0, 0 );
+  test_untar_check_mode("/dest3/home/test_script", 0755);
+
+  /******************/
   printf( "========= /dest3/symlink =========\n" );
   test_cat( "/dest3/symlink", 0, 0 );
 }
-- 
2.4.6



More information about the devel mailing list