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

Chris Johns chrisj at rtems.org
Mon Aug 1 01:03:47 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 ++++++-
 2 files changed, 34 insertions(+), 20 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.
-- 
2.4.6



More information about the devel mailing list