Changeset 4551f5f in rtems


Ignore:
Timestamp:
Nov 26, 2019, 7:07:55 AM (12 months ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
5, master
Children:
1fca1665
Parents:
4a05652
git-author:
Sebastian Huber <sebastian.huber@…> (11/26/19 07:07:55)
git-committer:
Sebastian Huber <sebastian.huber@…> (11/26/19 07:10:27)
Message:

untar: Properly make parent path

Close #3823.

Files:
3 edited
1 moved

Legend:

Unmodified
Added
Removed
  • cpukit/libmisc/untar/untar.c

    r4a05652 r4551f5f  
    11/**
    22 * @file
    3 
     3 *
    44 * @brief Untar an Image
     5 *
    56 * @ingroup libmisc_untar_img Untar Image
    6 
    7  * FIXME:
    8  *   1. Symbolic links are not created.
    9  *   2. Untar_FromMemory uses FILE *fp.
    10  *   3. How to determine end of archive?
    11 
    127 */
    138
     
    107102
    108103/*
    109  * Get the type of node on in the file system if present.
     104 * Make the directory path for a file if it does not exist.
    110105 */
    111106static int
    112 Stat_Node(const char* path)
    113 {
    114   struct stat sb;
    115   if (stat(path, &sb) < 0)
    116     return -1;
    117   if (S_ISDIR(sb.st_mode))
    118     return DIRTYPE;
    119   return REGTYPE;
    120 }
    121 
    122 /*
    123  * Make the directory path for a file if it does not exist.
    124  */
    125 static int
    126 Make_Path(const rtems_printer *printer, const char* filename, int linktype)
    127 {
    128   char* copy = strdup(filename);
    129   char* path = copy;
     107Make_Path(const rtems_printer *printer, char *path)
     108{
     109  char *p;
    130110
    131111  /*
    132112   * Skip leading path separators.
    133113   */
    134   while (*path == '/')
     114  while (*path == '/') {
    135115    ++path;
    136 
    137   /*
    138    * Any path left?
    139    */
    140   if (*path != '\0') {
    141     bool  path_end = false;
    142     char* end = path;
    143     int   r;
    144 
    145     /*
    146      * Split the path into directory components. Check the node and if a file
    147      * and not the end of the path remove it and create a directory. If a
    148      * directory and not the end of the path decend into the directory.
    149      */
    150     while (!path_end) {
    151       while (*end != '\0' && *end != '/')
    152         ++end;
    153 
    154       /*
    155        * Are we at the end of the path?
    156        */
    157       if (*end == '\0')
    158         path_end = true;
    159 
    160       /*
    161        * Split the path.
    162        */
    163       *end = '\0';
    164 
    165       /*
    166        * Get the node's status, exists, error, directory or regular? Regular
    167        * means not a directory.
    168        */
    169       r = Stat_Node(path);
    170 
    171       /*
    172        * If there are errors other than not existing we are finished.
    173        */
    174       if (r < 0 && errno != ENOENT) {
    175         Print_Error(printer, "stat", path);
    176         return -1;
    177       }
    178 
    179       /*
    180        * If a file remove and create a directory if not the end.
    181        */
    182       if (r == REGTYPE) {
    183         r = unlink(path);
    184         if (r < 0) {
    185           Print_Error(printer, "unlink", path);
    186           free(copy);
     116  }
     117
     118  p = path;
     119
     120  for (; ; ++p) {
     121    if (p[0] == '\0') {
     122      return 0;
     123    } else if (p[0] != '/') {
     124      continue;
     125    }
     126
     127    *p = '\0';
     128    if (p[1] == '\0') {
     129      /* Speculatively unlink the last component so that it can be re-created */
     130      unlink(path);
     131      return 0;
     132    }
     133
     134    if (mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) != 0) {
     135      if (errno == EEXIST || errno == EISDIR) {
     136        struct stat sb;
     137
     138        if (stat(path, &sb) != 0) {
    187139          return -1;
    188140        }
    189         if (!path_end) {
    190           r = mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO);
    191           if (r < 0) {
    192             Print_Error(printer, "mkdir (unlink)", path);
    193             free(copy);
     141
     142        if (!S_ISDIR(sb.st_mode)) {
     143          if (unlink(path) != 0) {
     144            Print_Error(printer, "unlink", path);
    194145            return -1;
    195146          }
    196         }
    197       }
    198       else if (r < 0) {
    199         /*
    200          * Node does not exist which means the rest of the path will not exist.
    201          */
    202         while (!path_end) {
    203           r = mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO);
    204           if (r < 0) {
    205             Print_Error(printer, "mkdir", path);
    206             free(copy);
     147
     148          if (mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) != 0) {
     149            Print_Error(printer, "mkdir (unlink)", path);
    207150            return -1;
    208151          }
    209           if (!path_end) {
    210             *end = '/';
    211             ++end;
    212           }
    213           while (*end != '\0' && *end != '/')
    214             ++end;
    215           if (*end == '\0')
    216             path_end = true;
    217152        }
    218153      }
    219       else if (path_end && r == DIRTYPE && linktype != DIRTYPE) {
    220         /*
    221          * We only handle a directory if at the end of the path and the end is
    222          * a file. If we cannot remove the directory because it is not empty we
    223          * raise an error. Otherwise this is a directory and we do nothing
    224          * which lets us decend into it.
    225          */
    226         r = rmdir(path);
    227         if (r < 0) {
    228           Print_Error(printer, "rmdir", path);
    229           free(copy);
    230           return -1;
    231         }
    232       }
    233 
    234       /*
    235        * If not the end of the path put back the directory separator.
    236        */
    237       if (!path_end) {
    238         *end = '/';
    239         ++end;
    240       }
    241     }
    242   }
    243 
    244   free(copy);
     154    }
     155
     156    *p = '/';
     157  }
    245158
    246159  return 0;
     
    253166)
    254167{
    255   int            sum;
    256   int            hdr_chksum;
    257   int            retval = UNTAR_SUCCESSFUL;
     168  int sum;
     169  int hdr_chksum;
     170  int retval = UNTAR_SUCCESSFUL;
     171  int r;
    258172
    259173  ctx->file_name[0] = '\0';
     
    291205   */
    292206
    293   if (Make_Path(ctx->printer, ctx->file_path, ctx->linkflag) < 0) {
     207  if (Make_Path(ctx->printer, ctx->file_path) != 0) {
    294208    retval = UNTAR_FAIL;
    295209  }
     
    299213    rtems_printf(ctx->printer, "untar: symlink: %s -> %s\n",
    300214                 ctx->link_name, ctx->file_path);
    301     symlink(ctx->link_name, ctx->file_path);
     215    r = symlink(ctx->link_name, ctx->file_path);
     216    if (r != 0) {
     217      Print_Error(ctx->printer, "symlink", ctx->file_path);
     218      retval = UNTAR_FAIL;
     219    }
    302220  } else if (ctx->linkflag == REGTYPE) {
    303221    rtems_printf(ctx->printer, "untar: file: %s (s:%lu,m:%04lo)\n",
     
    305223    ctx->nblocks = (((ctx->file_size) + 511) & ~511) / 512;
    306224  } else if (ctx->linkflag == DIRTYPE) {
    307     int r;
    308225    rtems_printf(ctx->printer, "untar: dir: %s\n", ctx->file_path);
    309     r = mkdir(ctx->file_path, S_IRWXU | S_IRWXG | S_IRWXO);
    310     if (r < 0) {
    311       if (errno == EEXIST) {
    312         struct stat stat_buf;
    313         if (stat(ctx->file_path, &stat_buf) == 0) {
    314           if (S_ISDIR(stat_buf.st_mode)) {
    315             r = 0;
    316           } else {
    317             r = unlink(ctx->file_path);
    318             if (r == 0) {
    319               r = mkdir(ctx->file_path, ctx->mode);
    320             }
    321           }
    322         }
    323       }
    324       if (r < 0) {
    325         Print_Error(ctx->printer, "mkdir", ctx->file_path);
    326         retval = UNTAR_FAIL;
    327       }
     226    r = mkdir(ctx->file_path, ctx->mode);
     227    if (r != 0) {
     228      Print_Error(ctx->printer, "mkdir", ctx->file_path);
     229      retval = UNTAR_FAIL;
    328230    }
    329231  }
  • testsuites/libtests/Makefile.am

    r4a05652 r4551f5f  
    12891289        $(support_includes) $(test_includes) -I$(top_srcdir)/include
    12901290tar01_LDADD = $(RTEMS_ROOT)cpukit/librtemscpu.a $(RTEMS_ROOT)cpukit/libz.a $(LDADD)
    1291 tar01.tar: Makefile
    1292         @rm -f $@
    1293         $(AM_V_GEN)$(PAX) -w -f $@ -s ,$(srcdir)/tar01/,, $(srcdir)/tar01/home $(srcdir)/tar01/symlink
     1291tar01.tar: $(srcdir)/tar01/home/test_file $(srcdir)/tar01/home/abc/def/test_script $(srcdir)/tar01/symlink
     1292        @rm -f $@
     1293        $(AM_V_GEN)$(PAX) -w -f $@ -s ,$(srcdir)/tar01/,, $+
    12941294tar01-tar.c: tar01.tar
    12951295        $(AM_V_GEN)$(BIN2C) -C $< $@
     
    13281328tar02_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_FLAGS_tar02) \
    13291329        $(support_includes) $(test_includes) -I$(top_srcdir)/include
    1330 tar02.tar: Makefile
    1331         @rm -f $@
    1332         $(AM_V_GEN)$(PAX) -w -f $@ -s ,$(srcdir)/tar01/,, $(srcdir)/tar01/home $(srcdir)/tar01/symlink
     1330tar02.tar: $(srcdir)/tar01/home/test_file $(srcdir)/tar01/home/abc/def/test_script $(srcdir)/tar01/symlink
     1331        @rm -f $@
     1332        $(AM_V_GEN)$(PAX) -w -f $@ -s ,$(srcdir)/tar01/,, $+
    13331333tar02-tar.c: tar02.tar
    13341334        $(AM_V_GEN)$(BIN2C) -C $< $@
  • testsuites/libtests/tar01/init.c

    r4a05652 r4551f5f  
    8686
    8787  /******************/
    88   printf( "========= /home/test_script =========\n" );
    89   test_cat( "/home/test_script", 0, 0 );
    90   test_untar_check_mode("/home/test_script", 0755);
     88  printf( "========= /home/abc/def/test_script =========\n" );
     89  test_cat( "/home/abc/def/test_script", 0, 0 );
     90  test_untar_check_mode("/home/abc/def/test_script", 0755);
    9191
    9292  /******************/
     
    134134
    135135  /******************/
    136   printf( "========= /dest/home/test_script =========\n" );
    137   test_cat( "/dest/home/test_script", 0, 0 );
    138   test_untar_check_mode("/dest/home/test_script", 0755);
     136  printf( "========= /dest/home/abc/def/test_script =========\n" );
     137  test_cat( "/dest/home/abc/def/test_script", 0, 0 );
     138  test_untar_check_mode("/dest/home/abc/def/test_script", 0755);
    139139
    140140  /******************/
     
    180180
    181181  /******************/
    182   printf( "========= /dest2/home/test_script =========\n" );
    183   test_cat( "/dest2/home/test_script", 0, 0 );
    184   test_untar_check_mode("/dest2/home/test_script", 0755);
     182  printf( "========= /dest2/home/abc/def/test_script =========\n" );
     183  test_cat( "/dest2/home/abc/def/test_script", 0, 0 );
     184  test_untar_check_mode("/dest2/home/abc/def/test_script", 0755);
    185185
    186186  /******************/
     
    226226
    227227  /******************/
    228   printf( "========= /dest3/home/test_script =========\n" );
    229   test_cat( "/dest3/home/test_script", 0, 0 );
    230   test_untar_check_mode("/dest3/home/test_script", 0755);
     228  printf( "========= /dest3/home/abc/def/test_script =========\n" );
     229  test_cat( "/dest3/home/abc/def/test_script", 0, 0 );
     230  test_untar_check_mode("/dest3/home/abc/def/test_script", 0755);
    231231
    232232  /******************/
     
    276276
    277277  /******************/
    278   printf( "========= /dest4/home/test_script =========\n" );
    279   test_cat( "/dest4/home/test_script", 0, 0 );
    280   test_untar_check_mode("/dest4/home/test_script", 0755);
     278  printf( "========= /dest4/home/abc/def/test_script =========\n" );
     279  test_cat( "/dest4/home/abc/def/test_script", 0, 0 );
     280  test_untar_check_mode("/dest4/home/abc/def/test_script", 0755);
    281281
    282282  /******************/
Note: See TracChangeset for help on using the changeset viewer.