Changeset b6f66d9 in rtems


Ignore:
Timestamp:
Nov 21, 2019, 7:06:28 AM (13 months ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
5, master
Children:
2de05dd
Parents:
a0304e8d
git-author:
Sebastian Huber <sebastian.huber@…> (11/21/19 07:06:28)
git-committer:
Sebastian Huber <sebastian.huber@…> (11/25/19 10:32:19)
Message:

untar: Unify untar support

Update #3823.

Location:
cpukit
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • cpukit/include/rtems/untar.h

    ra0304e8d rb6f66d9  
    4949int Untar_FromFile_Print(const char *tar_name, const rtems_printer* printer);
    5050
    51 typedef struct {
     51#define UNTAR_FILE_NAME_SIZE 100
     52
     53typedef struct {
     54  char *file_path;
     55  char *file_name;
     56  char link_name[UNTAR_FILE_NAME_SIZE];
     57  unsigned long mode;
     58  unsigned long file_size;
     59  unsigned long nblocks;
     60  unsigned char linkflag;
     61  const rtems_printer *printer;
     62} Untar_HeaderContext;
     63
     64typedef struct {
     65  Untar_HeaderContext base;
     66
     67  /**
     68   * @brief File path buffer.
     69   */
     70  char buf[UNTAR_FILE_NAME_SIZE];
     71
    5272  /**
    5373   * @brief Current context state.
     
    6686
    6787  /**
    68    * @brief Name buffer.
    69    */
    70   char fname[100];
    71 
    72   /**
    7388   * @brief Number of bytes of overall length are already processed.
    7489   */
    7590  size_t done_bytes;
    76 
    77   /**
    78    * @brief Mode of the file.
    79    */
    80   unsigned long mode;
    81 
    82   /**
    83    * @brief Overall amount of bytes to be processed.
    84    */
    85   unsigned long todo_bytes;
    86 
    87   /**
    88    * @brief Overall amount of blocks to be processed.
    89    */
    90   unsigned long todo_blocks;
    9191
    9292  /**
     
    239239);
    240240
    241 /**************************************************************************
    242  * This converts octal ASCII number representations into an
    243  * unsigned long.  Only support 32-bit numbers for now.
    244  *************************************************************************/
    245 extern unsigned long
    246 _rtems_octal2ulong(const char *octascii, size_t len);
    247 
    248 /************************************************************************
    249  * Compute the TAR checksum and check with the value in
    250  * the archive.  The checksum is computed over the entire
    251  * header, but the checksum field is substituted with blanks.
    252  ************************************************************************/
    253 extern int
    254 _rtems_tar_header_checksum(const char *bufr);
     241int Untar_ProcessHeader(Untar_HeaderContext *ctx, const char *bufr);
    255242
    256243#ifdef __cplusplus
  • cpukit/libfs/src/imfs/imfs_load_tar.c

    ra0304e8d rb6f66d9  
    2020
    2121#include <rtems/imfs.h>
    22 
    23 #include <sys/param.h>
    24 #include <sys/stat.h>
    25 #include <string.h>
    26 #include <tar.h>
    27 #include <unistd.h>
    28 
    2922#include <rtems/untar.h>
    3023
    31 #define MAX_NAME_FIELD_SIZE      99
     24#include <string.h>
    3225
    3326int rtems_tarfs_load(
    3427  const char *mountpoint,
    35   uint8_t *tar_image,
    36   size_t tar_size
     28  uint8_t    *tar_image,
     29  size_t      tar_size
    3730)
    3831{
    39    const char                       *hdr_ptr;
    40    char                             filename[100];
    41    char                             full_filename[256];
    42    int                              hdr_chksum;
    43    unsigned char                    linkflag;
    44    unsigned long                    file_size;
    45    unsigned long                    file_mode;
    46    int                              offset;
    47    unsigned long                    nblocks;
    48    int rv = 0;
    49    int eval_flags = RTEMS_FS_FOLLOW_LINK;
    50    rtems_filesystem_eval_path_context_t ctx;
    51    rtems_filesystem_location_info_t rootloc;
    52    rtems_filesystem_location_info_t *currentloc =
    53      rtems_filesystem_eval_path_start( &ctx, mountpoint, eval_flags );
     32  rtems_filesystem_eval_path_context_t  eval_ctx;
     33  int                                   eval_flags;
     34  rtems_filesystem_location_info_t     *loc;
     35  bool                                  is_imfs;
     36  char                                  buf[ 156 + UNTAR_FILE_NAME_SIZE ];
     37  size_t                                len;
     38  Untar_HeaderContext                   ctx;
     39  unsigned long                         ptr;
    5440
    55    rtems_filesystem_eval_path_extract_currentloc( &ctx, &rootloc );
    56    rtems_filesystem_eval_path_set_flags(
    57      &ctx,
    58      RTEMS_FS_MAKE | RTEMS_FS_EXCLUSIVE
    59    );
     41  len = strlen( mountpoint );
     42  if ( len >= sizeof( buf ) - UNTAR_FILE_NAME_SIZE - 2 ) {
     43    return -1;
     44  }
    6045
    61    if ( !IMFS_is_imfs_instance( &rootloc ) ) {
    62      rv = -1;
    63    }
     46  eval_flags = RTEMS_FS_FOLLOW_LINK;
     47  loc = rtems_filesystem_eval_path_start( &eval_ctx, mountpoint, eval_flags );
     48  is_imfs = IMFS_is_imfs_instance( loc );
     49  rtems_filesystem_eval_path_cleanup( &eval_ctx );
     50  if ( !is_imfs ) {
     51    return -1;
     52  }
    6453
    65    /*
    66     * Create an IMFS node structure pointing to tar image memory.
    67     */
    68    offset = 0;
    69    while ( rv == 0 ) {
    70     if (offset + 512 > tar_size)
    71       break;
     54  ctx.printer = NULL;
     55  ctx.file_path = memcpy( buf, mountpoint, len );
    7256
    73     /*
    74      * Read a header.
    75      */
    76     hdr_ptr = (char *) &tar_image[offset];
    77     offset += 512;
    78     if (strncmp(&hdr_ptr[257], "ustar", 5))
    79       break;
     57  if ( len > 0 && ctx.file_path[ len - 1 ] != '/') {
     58    ctx.file_path[ len ] = '/';
     59    ctx.file_name = ctx.file_path + len + 1;
     60  } else {
     61    ctx.file_name = ctx.file_path + len;
     62  }
    8063
    81     strncpy(filename, hdr_ptr, MAX_NAME_FIELD_SIZE);
    82     filename[MAX_NAME_FIELD_SIZE] = '\0';
     64  ptr = 0;
    8365
    84     linkflag   = hdr_ptr[156];
    85     file_mode  = _rtems_octal2ulong(&hdr_ptr[100], 8);
    86     file_size  = _rtems_octal2ulong(&hdr_ptr[124], 12);
    87     hdr_chksum = _rtems_octal2ulong(&hdr_ptr[148], 8);
     66  while ( ptr + 512 <= tar_size ) {
     67    int retval;
    8868
    89     if (_rtems_tar_header_checksum(hdr_ptr) != hdr_chksum)
    90       break;
    91 
    92     /*
    93      * Generate an IMFS node depending on the file type.
    94      * - For directories, just create directories as usual.  IMFS
    95      *   will take care of the rest.
    96      * - For symbolic links, create as usual
    97      * - For files, create a file node with special tarfs properties.
    98      */
    99     if (linkflag == DIRTYPE) {
    100       int len;
    101       strncpy(full_filename, mountpoint, 255);
    102       if (full_filename[(len=strlen(full_filename))-1] != '/')
    103         strcat(full_filename, "/");
    104       ++len;
    105       strncat(full_filename, filename, 256-len-1);
    106       if ( mkdir(full_filename, S_IRWXU | S_IRWXG | S_IRWXO) != 0 ) {
    107         if (errno == EEXIST) {
    108           struct stat stat_buf;
    109           if ( stat(full_filename, &stat_buf) == 0 ) {
    110             if (  S_ISDIR(stat_buf.st_mode) ) {
    111               continue;
    112             } else {
    113               if ( unlink(full_filename) != -1 ) {
    114                 if ( mkdir(full_filename, S_IRWXU | S_IRWXG | S_IRWXO) == 0 )
    115                   continue;
    116               }
    117             }
    118           }
    119         }
    120         rv = -1;
    121       }
     69    retval = Untar_ProcessHeader( &ctx, (const char *) &tar_image[ ptr ] );
     70    if ( retval != UNTAR_SUCCESSFUL ) {
     71      return -1;
    12272    }
    12373
    124     /*
    125      * Create a LINEAR_FILE node
    126      */
    127     else if (linkflag == REGTYPE) {
    128       rtems_filesystem_location_free( currentloc );
    129       rtems_filesystem_location_clone( currentloc, &rootloc );
    130       rtems_filesystem_eval_path_set_path(
    131         &ctx,
    132         filename,
    133         strlen( filename )
     74    ptr += 512;
     75
     76    if ( ctx.linkflag == REGTYPE ) {
     77      retval = IMFS_make_linearfile(
     78        ctx.file_path,
     79        ctx.mode,
     80        &tar_image[ ptr ],
     81        ctx.file_size
    13482      );
    135       rtems_filesystem_eval_path_continue( &ctx );
    136 
    137       if ( !rtems_filesystem_location_is_null( currentloc ) ) {
    138         IMFS_linearfile_context linctx = {
    139           .data = &tar_image[offset],
    140           .size = file_size
    141         };
    142 
    143         IMFS_create_node(
    144           currentloc,
    145           &IMFS_node_control_linfile,
    146           sizeof( IMFS_file_t ),
    147           rtems_filesystem_eval_path_get_token( &ctx ),
    148           rtems_filesystem_eval_path_get_tokenlen( &ctx ),
    149           (file_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG,
    150           &linctx
    151         );
     83      if ( retval != 0 ) {
     84        return -1;
    15285      }
    15386
    154       nblocks = (((file_size) + 511) & ~511) / 512;
    155       offset += 512 * nblocks;
    156     }
    157     /*
    158      * Create a symbolic link
    159      */
    160     else if (linkflag == SYMTYPE) {
    161       const char *linkto = hdr_ptr + 157;
    162       int len;
    163 
    164       strncpy(full_filename, mountpoint, 255);
    165       if (full_filename[(len=strlen(full_filename))-1] != '/')
    166         strcat(full_filename, "/");
    167       ++len;
    168       strncat(full_filename, filename, 256-len-1);
    169 
    170       rv = symlink(linkto, full_filename);
     87      ptr += 512 * ctx.nblocks;
    17188    }
    17289  }
    17390
    174   rtems_filesystem_location_free( &rootloc );
    175   rtems_filesystem_eval_path_cleanup( &ctx );
    176 
    177   return rv;
     91  return 0;
    17892}
    179 
  • cpukit/libmisc/untar/untar.c

    ra0304e8d rb6f66d9  
    7171#define MAX_NAME_FIELD_SIZE      99
    7272
     73static int _rtems_tar_header_checksum(const char *bufr);
     74
    7375/*
    7476 * This converts octal ASCII number representations into an
    7577 * unsigned long.  Only support 32-bit numbers for now.
    76  *
    77  * warning: this code is referenced in the IMFS.
    78  */
    79 unsigned long
     78 */
     79static unsigned long
    8080_rtems_octal2ulong(
    8181  const char *octascii,
     
    247247}
    248248
    249 static int
     249int
    250250Untar_ProcessHeader(
    251   const char          *bufr,
    252   char                *fname,
    253   unsigned long       *mode,
    254   unsigned long       *file_size,
    255   unsigned long       *nblocks,
    256   unsigned char       *linkflag,
    257   const rtems_printer *printer
    258 )
    259 {
    260   char           linkname[100];
     251  Untar_HeaderContext *ctx,
     252  const char          *bufr
     253)
     254{
    261255  int            sum;
    262256  int            hdr_chksum;
    263257  int            retval = UNTAR_SUCCESSFUL;
    264258
    265   fname[0] = '\0';
    266   *file_size = 0;
    267   *nblocks = 0;
    268   *linkflag = -1;
     259  ctx->file_name[0] = '\0';
     260  ctx->file_size = 0;
     261  ctx->nblocks = 0;
     262  ctx->linkflag = -1;
    269263
    270264  if (strncmp(&bufr[257], "ustar", 5)) {
     
    281275
    282276  if (sum != hdr_chksum) {
    283     rtems_printf(printer, "untar: file header checksum error\n");
     277    rtems_printf(ctx->printer, "untar: file header checksum error\n");
    284278    return UNTAR_INVALID_CHECKSUM;
    285279  }
    286280
    287   strncpy(fname, bufr, MAX_NAME_FIELD_SIZE);
    288   fname[MAX_NAME_FIELD_SIZE] = '\0';
    289 
    290   *mode = strtoul(&bufr[100], NULL, 8);
    291 
    292   *linkflag   = bufr[156];
    293   *file_size = _rtems_octal2ulong(&bufr[124], 12);
     281  strlcpy(ctx->file_name, bufr, UNTAR_FILE_NAME_SIZE);
     282
     283  ctx->mode = strtoul(&bufr[100], NULL, 8);
     284
     285  ctx->linkflag   = bufr[156];
     286  ctx->file_size = _rtems_octal2ulong(&bufr[124], 12);
    294287
    295288  /*
     
    297290   * with it.
    298291   */
    299   if (*linkflag == SYMTYPE) {
    300     strncpy(linkname, &bufr[157], MAX_NAME_FIELD_SIZE);
    301     linkname[MAX_NAME_FIELD_SIZE] = '\0';
    302     rtems_printf(printer, "untar: symlink: %s -> %s\n", linkname, fname);
    303     symlink(linkname, fname);
    304   } else if (*linkflag == REGTYPE) {
    305     rtems_printf(printer, "untar: file: %s (s:%i,m:%04o)\n",
    306                  fname, (int) *file_size, (int) *mode);
    307     *nblocks = (((*file_size) + 511) & ~511) / 512;
    308     if (Make_Path(printer, fname, false) < 0) {
     292  if (ctx->linkflag == SYMTYPE) {
     293    strlcpy(ctx->link_name, &bufr[157], sizeof(ctx->link_name));
     294    rtems_printf(ctx->printer, "untar: symlink: %s -> %s\n",
     295                 ctx->link_name, ctx->file_path);
     296    symlink(ctx->link_name, ctx->file_path);
     297  } else if (ctx->linkflag == REGTYPE) {
     298    rtems_printf(ctx->printer, "untar: file: %s (s:%lu,m:%04lo)\n",
     299                 ctx->file_path, ctx->file_size, ctx->mode);
     300    ctx->nblocks = (((ctx->file_size) + 511) & ~511) / 512;
     301    if (Make_Path(ctx->printer, ctx->file_path, false) < 0) {
    309302      retval  = UNTAR_FAIL;
    310303    }
    311   } else if (*linkflag == DIRTYPE) {
     304  } else if (ctx->linkflag == DIRTYPE) {
    312305    int r;
    313     rtems_printf(printer, "untar:  dir: %s\n", fname);
    314     if (Make_Path(printer, fname, true) < 0) {
     306    rtems_printf(ctx->printer, "untar:  dir: %s\n", ctx->file_path);
     307    if (Make_Path(ctx->printer, ctx->file_path, true) < 0) {
    315308      retval  = UNTAR_FAIL;
    316309    }
    317     r = mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO);
     310    r = mkdir(ctx->file_path, S_IRWXU | S_IRWXG | S_IRWXO);
    318311    if (r < 0) {
    319312      if (errno == EEXIST) {
    320313        struct stat stat_buf;
    321         if (stat(fname, &stat_buf) == 0) {
     314        if (stat(ctx->file_path, &stat_buf) == 0) {
    322315          if (S_ISDIR(stat_buf.st_mode)) {
    323316            r = 0;
    324317          } else {
    325             r = unlink(fname);
     318            r = unlink(ctx->file_path);
    326319            if (r == 0) {
    327               r = mkdir(fname, *mode);
     320              r = mkdir(ctx->file_path, ctx->mode);
    328321            }
    329322          }
     
    331324      }
    332325      if (r < 0) {
    333         Print_Error(printer, "mkdir", fname);
     326        Print_Error(ctx->printer, "mkdir", ctx->file_path);
    334327        retval = UNTAR_FAIL;
    335328      }
     
    369362)
    370363{
    371   int            fd;
    372   const char     *tar_ptr = (const char *)tar_buf;
    373   const char     *bufr;
    374   char           fname[100];
    375   int            retval = UNTAR_SUCCESSFUL;
    376   unsigned long  ptr;
    377   unsigned long  nblocks = 0;
    378   unsigned long  file_size = 0;
    379   unsigned long  mode = 0;
    380   unsigned char  linkflag = 0;
    381 
     364  int                  fd;
     365  const char          *tar_ptr = (const char *)tar_buf;
     366  const char          *bufr;
     367  char                 buf[UNTAR_FILE_NAME_SIZE];
     368  Untar_HeaderContext  ctx;
     369  int                  retval = UNTAR_SUCCESSFUL;
     370  unsigned long        ptr;
     371
     372  ctx.file_path = buf;
     373  ctx.file_name = buf;
     374  ctx.printer = printer;
    382375  rtems_printf(printer, "untar: memory at %p (%zu)\n", tar_buf, size);
    383376
     
    393386    ptr += 512;
    394387
    395     retval = Untar_ProcessHeader(bufr, fname, &mode, &file_size,
    396                                  &nblocks, &linkflag, printer);
     388    retval = Untar_ProcessHeader(&ctx, bufr);
    397389
    398390    if (retval != UNTAR_SUCCESSFUL)
    399391      break;
    400392
    401     if (linkflag == REGTYPE) {
    402       if ((fd = open(fname, O_TRUNC | O_CREAT | O_WRONLY, mode)) == -1) {
    403         Print_Error(printer, "open", fname);
    404         ptr += 512 * nblocks;
     393    if (ctx.linkflag == REGTYPE) {
     394      if ((fd = open(ctx.file_path,
     395                     O_TRUNC | O_CREAT | O_WRONLY, ctx.mode)) == -1) {
     396        Print_Error(printer, "open", ctx.file_path);
     397        ptr += 512 * ctx.nblocks;
    405398      } else {
    406         unsigned long sizeToGo = file_size;
     399        unsigned long sizeToGo = ctx.file_size;
    407400        ssize_t       len;
    408401        ssize_t       i;
     
    413406         * file_size rounded to the nearest 512-byte boundary.
    414407         */
    415         for (i = 0; i < nblocks; i++) {
     408        for (i = 0; i < ctx.nblocks; i++) {
    416409          len = ((sizeToGo < 512L) ? (sizeToGo) : (512L));
    417410          n = write(fd, &tar_ptr[ptr], len);
    418411          if (n != len) {
    419             Print_Error(printer, "write", fname);
     412            Print_Error(printer, "write", ctx.file_path);
    420413            retval  = UNTAR_FAIL;
    421414            break;
     
    488481)
    489482{
    490   int            fd;
    491   char           *bufr;
    492   ssize_t        n;
    493   char           fname[100];
    494   int            retval;
    495   unsigned long  i;
    496   unsigned long  nblocks = 0;
    497   unsigned long  file_size = 0;
    498   unsigned long  mode = 0;
    499   unsigned char  linkflag = 0;
     483  int                  fd;
     484  char                *bufr;
     485  ssize_t              n;
     486  int                  retval;
     487  unsigned long        i;
     488  char                 buf[UNTAR_FILE_NAME_SIZE];
     489  Untar_HeaderContext  ctx;
    500490
    501491  retval = UNTAR_SUCCESSFUL;
     
    510500    return(UNTAR_FAIL);
    511501  }
     502
     503  ctx.file_path = buf;
     504  ctx.file_name = buf;
     505  ctx.printer = printer;
    512506
    513507  while (1) {
     
    518512    }
    519513
    520     retval = Untar_ProcessHeader(bufr, fname, &mode, &file_size,
    521                                  &nblocks, &linkflag, printer);
     514    retval = Untar_ProcessHeader(&ctx, bufr);
    522515
    523516    if (retval != UNTAR_SUCCESSFUL)
    524517      break;
    525518
    526     if (linkflag == REGTYPE) {
     519    if (ctx.linkflag == REGTYPE) {
    527520      int out_fd;
    528521
     
    532525       */
    533526
    534       if ((out_fd = creat(fname, mode)) == -1) {
    535         (void) lseek(fd, SEEK_CUR, 512UL * nblocks);
     527      if ((out_fd = creat(ctx.file_path, ctx.mode)) == -1) {
     528        (void) lseek(fd, SEEK_CUR, 512UL * ctx.nblocks);
    536529      } else {
    537         for (i = 0; i < nblocks; i++) {
     530        for (i = 0; i < ctx.nblocks; i++) {
    538531          n = read(fd, bufr, 512);
    539           n = MIN(n, file_size - (i * 512UL));
     532          n = MIN(n, ctx.file_size - (i * 512UL));
    540533          (void) write(out_fd, bufr, n);
    541534        }
     
    554547void Untar_ChunkContext_Init(Untar_ChunkContext *context)
    555548{
     549  context->base.file_path = context->buf;
     550  context->base.file_name = context->buf;
    556551  context->state = UNTAR_CHUNK_HEADER;
    557552  context->done_bytes = 0;
     
    572567  size_t consume;
    573568  int retval;
    574   unsigned char linkflag;
    575569
    576570  buf = chunk;
    577571  done = 0;
    578572  todo = chunk_size;
     573
     574  context->base.printer = printer;
    579575
    580576  while (todo > 0) {
     
    588584        if (context->done_bytes == 512) {
    589585          retval = Untar_ProcessHeader(
    590             &context->header[0],
    591             &context->fname[0],
    592             &context->mode,
    593             &context->todo_bytes,
    594             &context->todo_blocks,
    595             &linkflag,
    596             printer
     586            &context->base,
     587            &context->header[0]
    597588          );
    598589
     
    602593          }
    603594
    604           if (linkflag == REGTYPE) {
    605             context->out_fd = creat(&context->fname[0], context->mode);
     595          if (context->base.linkflag == REGTYPE) {
     596            context->out_fd = creat(context->base.file_path,
     597                                    context->base.mode);
    606598
    607599            if (context->out_fd >= 0) {
     
    610602            } else {
    611603              context->state = UNTAR_CHUNK_SKIP;
    612               context->todo_bytes = 512 * context->todo_blocks;
     604              context->base.file_size = 512 * context->base.nblocks;
    613605              context->done_bytes = 0;
    614606            }
     
    620612        break;
    621613      case UNTAR_CHUNK_SKIP:
    622         remaining = context->todo_bytes - context->done_bytes;
     614        remaining = context->base.file_size - context->done_bytes;
    623615        consume = MIN(remaining, todo);
    624616        context->done_bytes += consume;
    625617
    626         if (context->done_bytes == context->todo_bytes) {
     618        if (context->done_bytes == context->base.file_size) {
    627619          context->state = UNTAR_CHUNK_HEADER;
    628620          context->done_bytes = 0;
     
    631623        break;
    632624      case UNTAR_CHUNK_WRITE:
    633         remaining = context->todo_bytes - context->done_bytes;
     625        remaining = context->base.file_size - context->done_bytes;
    634626        consume = MIN(remaining, todo);
    635627        write(context->out_fd, &buf[done], consume);
    636628        context->done_bytes += consume;
    637629
    638         if (context->done_bytes == context->todo_bytes) {
     630        if (context->done_bytes == context->base.file_size) {
    639631          close(context->out_fd);
    640632          context->out_fd = -1;
    641633          context->state = UNTAR_CHUNK_SKIP;
    642           context->todo_bytes = 512 * context->todo_blocks - context->todo_bytes;
     634          context->base.file_size = 512 * context->base.nblocks
     635            - context->base.file_size;
    643636          context->done_bytes = 0;
    644637        }
     
    687680 * header, but the checksum field is substituted with blanks.
    688681 */
    689 int
     682static int
    690683_rtems_tar_header_checksum(
    691684  const char *bufr
Note: See TracChangeset for help on using the changeset viewer.