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

Chris Johns chrisj at rtems.org
Tue Aug 9 07:24:13 UTC 2016


Module:    rtems
Branch:    master
Commit:    b0f08c83e23e69c7b19b04d38910f90b5f7af51b
Changeset: http://git.rtems.org/rtems/commit/?id=b0f08c83e23e69c7b19b04d38910f90b5f7af51b

Author:    Chris Johns <chrisj at rtems.org>
Date:      Mon Aug  1 11:02:13 2016 +1000

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

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 );
 }



More information about the vc mailing list