Example #1
0
/**************************************************************************
 * Function: Untar_FromFile                                               *
 **************************************************************************
 * Description:                                                           *
 *                                                                        *
 *    This is a simple subroutine used to rip links, directories, and     *
 *    files out of a TAR file.                                            *
 *                                                                        *
 *                                                                        *
 * Inputs:                                                                *
 *                                                                        *
 *    const char *tar_name   - TAR filename.                              *
 *                                                                        *
 *                                                                        *
 * Output:                                                                *
 *                                                                        *
 *    int - UNTAR_SUCCESSFUL (0)    on successful completion.             *
 *          UNTAR_INVALID_CHECKSUM  for an invalid header checksum.       *
 *          UNTAR_INVALID_HEADER    for an invalid header.                *
 *                                                                        *
 **************************************************************************
 * Change History:                                                        *
 *  12/30/1998 - Creation (JWJ)                                           *
 *************************************************************************/
int
Untar_FromFile(
  const char *tar_name
)
{
   int            fd;
   char           *bufr;
   ssize_t        n;
   char           fname[100];
   char           linkname[100];
   int            sum;
   int            hdr_chksum;
   int            retval;
   unsigned long  i;
   unsigned long  nblocks;
   unsigned long  size;
   unsigned char  linkflag;

   retval = UNTAR_SUCCESSFUL;

   if ((fd = open(tar_name, O_RDONLY)) < 0) {
       return UNTAR_FAIL;
   }

   bufr = (char *)malloc(512);
   if (bufr == NULL) {
      close(fd);
      return(UNTAR_FAIL);
   }

   while (1)
   {
      /* Read the header */
      /* If the header read fails, we just consider it the end
         of the tarfile. */
      if ((n = read(fd, bufr, 512)) != 512)
      {
         break;
      }

      if (strncmp(&bufr[257], "ustar", 5))
      {
         break;
      }

      strncpy(fname, bufr, MAX_NAME_FIELD_SIZE);
      fname[MAX_NAME_FIELD_SIZE] = '\0';

      linkflag   = bufr[156];
      size       = _rtems_octal2ulong(&bufr[124], 12);

      /******************************************************************
       * Compute the TAR checksum and check with the value in
       * the archive.  The checksum is computed over the entire
       * header, but the checksum field is substituted with blanks.
       ******************************************************************/
      hdr_chksum = _rtems_octal2ulong(&bufr[148], 8);
      sum = _rtems_tar_header_checksum(bufr);

      if (sum != hdr_chksum)
      {
         retval = UNTAR_INVALID_CHECKSUM;
         break;
      }

      /******************************************************************
       * We've decoded the header, now figure out what it contains and
       * do something with it.
       *****************************************************************/
      if (linkflag == SYMTYPE)
      {
         strncpy(linkname, &bufr[157], MAX_NAME_FIELD_SIZE);
         linkname[MAX_NAME_FIELD_SIZE] = '\0';
         symlink(linkname,fname);
      }
      else if (linkflag == REGTYPE)
      {
         int out_fd;

         /******************************************************************
          * Read out the data.  There are nblocks of data where nblocks
          * is the size rounded to the nearest 512-byte boundary.
          *****************************************************************/
         nblocks = (((size) + 511) & ~511) / 512;

         if ((out_fd = creat(fname, 0644)) == -1)
         {
            for (i=0; i<nblocks; i++)
            {
               n = read(fd, bufr, 512);
            }
         }
         else
         {
            for (i=0; i<nblocks; i++)
            {
               n = read(fd, bufr, 512);
               n = MIN(n, size - i*512);
               write(out_fd, bufr, n);
            }
            close(out_fd);
         }
      }
      else if (linkflag == DIRTYPE)
      {
         mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO);
      }
   }
   free(bufr);
   close(fd);

   return(retval);
}
Example #2
0
/**************************************************************************
 * Function: Untar_FromMemory                                             *
 **************************************************************************
 * Description:                                                           *
 *                                                                        *
 *    This is a simple subroutine used to rip links, directories, and     *
 *    files out of a block of memory.                                     *
 *                                                                        *
 *                                                                        *
 * Inputs:                                                                *
 *                                                                        *
 *    void *  tar_buf    - Pointer to TAR buffer.                         *
 *    size_t  size       - Length of TAR buffer.                          *
 *                                                                        *
 *                                                                        *
 * Output:                                                                *
 *                                                                        *
 *    int - UNTAR_SUCCESSFUL (0)    on successful completion.             *
 *          UNTAR_INVALID_CHECKSUM  for an invalid header checksum.       *
 *          UNTAR_INVALID_HEADER    for an invalid header.                *
 *                                                                        *
 **************************************************************************/
int
Untar_FromMemory(
  void   *tar_buf,
  size_t  size
)
{
   FILE           *fp;
   const char     *tar_ptr = (const char *)tar_buf;
   const char     *bufr;
   size_t         n;
   char           fname[100];
   char           linkname[100];
   int            sum;
   int            hdr_chksum;
   int            retval;
   unsigned long  ptr;
   unsigned long  i;
   unsigned long  nblocks;
   unsigned long  file_size;
   unsigned char  linkflag;


   ptr = 0;
   while (1)
   {
      if (ptr + 512 > size)
      {
         retval = UNTAR_SUCCESSFUL;
         break;
      }

      /* Read the header */
      bufr = &tar_ptr[ptr];
      ptr += 512;
      if (strncmp(&bufr[257], "ustar", 5))
      {
         retval = UNTAR_SUCCESSFUL;
         break;
      }

      strncpy(fname, bufr, MAX_NAME_FIELD_SIZE);
      fname[MAX_NAME_FIELD_SIZE] = '\0';

      linkflag   = bufr[156];
      file_size  = _rtems_octal2ulong(&bufr[124], 12);

      /******************************************************************
       * Compute the TAR checksum and check with the value in
       * the archive.  The checksum is computed over the entire
       * header, but the checksum field is substituted with blanks.
       ******************************************************************/
      hdr_chksum = _rtems_octal2ulong(&bufr[148], 8);
      sum = _rtems_tar_header_checksum(bufr);

      if (sum != hdr_chksum)
      {
         retval = UNTAR_INVALID_CHECKSUM;
         break;
      }


      /******************************************************************
       * We've decoded the header, now figure out what it contains and
       * do something with it.
       *****************************************************************/
      if (linkflag == SYMTYPE)
      {
         strncpy(linkname, &bufr[157], MAX_NAME_FIELD_SIZE);
         linkname[MAX_NAME_FIELD_SIZE] = '\0';
         symlink(linkname, fname);
      }
      else if (linkflag == REGTYPE)
      {
         nblocks = (((file_size) + 511) & ~511) / 512;
         if ((fp = fopen(fname, "w")) == NULL)
         {
            printk("Untar: failed to create file %s\n", fname);
            ptr += 512 * nblocks;
         }
         else
         {
            unsigned long sizeToGo = file_size;
            size_t len;

            /***************************************************************
             * Read out the data.  There are nblocks of data where nblocks
             * is the file_size rounded to the nearest 512-byte boundary.
             **************************************************************/
            for (i=0; i<nblocks; i++)
            {
               len = ((sizeToGo < 512L)?(sizeToGo):(512L));
               n = fwrite(&tar_ptr[ptr], 1, len, fp);
               if (n != len)
               {
                  printk("untar: Error during write\n");
                  retval  = UNTAR_FAIL;
                  break;
               }
               ptr += 512;
               sizeToGo -= n;
            }
            fclose(fp);
         }
      }
      else if (linkflag == DIRTYPE)
      {
         if ( mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO) != 0 ) {
           printk("Untar: failed to create directory %s\n", fname);
           retval = UNTAR_FAIL;
           break;
         }
      }
   }

   return(retval);
}
Example #3
0
/*
 * rtems_tarfs_load
 *
 * Here we create the mountpoint directory and load the tarfs at
 * that node.  Once the IMFS has been mounted, we work through the
 * tar image and perform as follows:
 *  - For directories, simply call mkdir().  The IMFS creates nodes as
 *    needed.
 *  - For files, we make our own calls to IMFS eval_for_make and
 *    create_node.
 */
int rtems_tarfs_load(
  char    *mountpoint,
  uint8_t *tar_image,
  size_t   tar_size
)
{
   rtems_filesystem_location_info_t  root_loc;
   rtems_filesystem_location_info_t  loc;
   const char                       *hdr_ptr;
   char                             filename[100];
   char                             full_filename[256];
   int                              hdr_chksum;
   unsigned char                    linkflag;
   unsigned long                    file_size;
   unsigned long                    file_mode;
   int                              offset;
   unsigned long                    nblocks;
   IMFS_jnode_t                    *node;
   int                              status;

   status = rtems_filesystem_evaluate_path(
      mountpoint,
      strlen(mountpoint),
      0,
      &root_loc,
      0
   );
   if (status != 0)
     return -1;

   if (root_loc.ops != &IMFS_ops && root_loc.ops != &fifoIMFS_ops)
     return -1;

   /*
    * Create an IMFS node structure pointing to tar image memory.
    */
   offset = 0;
   while (1) {
    if (offset + 512 > tar_size)
      break;

    /*
     * Read a header.
     */
    hdr_ptr = (char *) &tar_image[offset];
    offset += 512;
    if (strncmp(&hdr_ptr[257], "ustar", 5))
      break;

    strncpy(filename, hdr_ptr, MAX_NAME_FIELD_SIZE);
    filename[MAX_NAME_FIELD_SIZE] = '\0';

    linkflag   = hdr_ptr[156];
    file_mode  = _rtems_octal2ulong(&hdr_ptr[100], 8);
    file_size  = _rtems_octal2ulong(&hdr_ptr[124], 12);
    hdr_chksum = _rtems_octal2ulong(&hdr_ptr[148], 8);

    if (_rtems_tar_header_checksum(hdr_ptr) != hdr_chksum)
      break;

    /*
     * Generate an IMFS node depending on the file type.
     * - For directories, just create directories as usual.  IMFS
     *   will take care of the rest.
     * - For files, create a file node with special tarfs properties.
     */
    if (linkflag == DIRTYPE) {
      strcpy(full_filename, mountpoint);
      if (full_filename[strlen(full_filename)-1] != '/')
        strcat(full_filename, "/");
      strcat(full_filename, filename);
      mkdir(full_filename, S_IRWXU | S_IRWXG | S_IRWXO);
    }
    /*
     * Create a LINEAR_FILE node
     *
     *  NOTE: Coverity Id 20 reports this as a leak.
     *        While technically not a leak, it indicated that
     *        IMFS_create_node was ONLY passed a NULL when we created the
     *        root node.  We added a new IMFS_create_root_node() so this
     *        path no longer existed.  The result was simpler code which
     *        should not have this path. 
     */
    else if (linkflag == REGTYPE) {
      const char  *name;

      loc = root_loc;
      if (IMFS_evaluate_for_make(filename, &loc, &name) == 0) {
        node = IMFS_create_node(
          &loc,
          IMFS_LINEAR_FILE, (char *)name,
          (file_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG,
          NULL
        );
        node->info.linearfile.size   = file_size;
        node->info.linearfile.direct = &tar_image[offset];
      }

      nblocks = (((file_size) + 511) & ~511) / 512;
      offset += 512 * nblocks;
    }
  }
  return status;
}
Example #4
0
int rtems_tarfs_load(
  const char *mountpoint,
  uint8_t *tar_image,
  size_t tar_size
)
{
   const char                       *hdr_ptr;
   char                             filename[100];
   char                             full_filename[256];
   int                              hdr_chksum;
   unsigned char                    linkflag;
   unsigned long                    file_size;
   unsigned long                    file_mode;
   int                              offset;
   unsigned long                    nblocks;
   int rv = 0;
   int eval_flags = RTEMS_FS_FOLLOW_LINK;
   rtems_filesystem_eval_path_context_t ctx;
   rtems_filesystem_location_info_t rootloc;
   rtems_filesystem_location_info_t *currentloc =
     rtems_filesystem_eval_path_start( &ctx, mountpoint, eval_flags );

   rtems_filesystem_eval_path_extract_currentloc( &ctx, &rootloc );
   rtems_filesystem_eval_path_set_flags(
     &ctx,
     RTEMS_FS_MAKE | RTEMS_FS_EXCLUSIVE
   );

   if ( !IMFS_is_imfs_instance( &rootloc ) ) {
     rv = -1;
   }

   /*
    * Create an IMFS node structure pointing to tar image memory.
    */
   offset = 0;
   while ( rv == 0 ) {
    if (offset + 512 > tar_size)
      break;

    /*
     * Read a header.
     */
    hdr_ptr = (char *) &tar_image[offset];
    offset += 512;
    if (strncmp(&hdr_ptr[257], "ustar", 5))
      break;

    strncpy(filename, hdr_ptr, MAX_NAME_FIELD_SIZE);
    filename[MAX_NAME_FIELD_SIZE] = '\0';

    linkflag   = hdr_ptr[156];
    file_mode  = _rtems_octal2ulong(&hdr_ptr[100], 8);
    file_size  = _rtems_octal2ulong(&hdr_ptr[124], 12);
    hdr_chksum = _rtems_octal2ulong(&hdr_ptr[148], 8);

    if (_rtems_tar_header_checksum(hdr_ptr) != hdr_chksum)
      break;

    /*
     * Generate an IMFS node depending on the file type.
     * - For directories, just create directories as usual.  IMFS
     *   will take care of the rest.
     * - For symbolic links, create as usual
     * - For files, create a file node with special tarfs properties.
     */
    if (linkflag == DIRTYPE) {
      int len;
      strncpy(full_filename, mountpoint, 255);
      if (full_filename[(len=strlen(full_filename))-1] != '/')
        strcat(full_filename, "/");
      ++len;
      strncat(full_filename, filename, 256-len-1);
      if ( mkdir(full_filename, S_IRWXU | S_IRWXG | S_IRWXO) != 0 ) {
        if (errno == EEXIST) {
          struct stat stat_buf;
          if ( stat(full_filename, &stat_buf) == 0 ) {
            if (  S_ISDIR(stat_buf.st_mode) ) {
              continue;
            } else {
              if ( unlink(full_filename) != -1 ) {
                if ( mkdir(full_filename, S_IRWXU | S_IRWXG | S_IRWXO) == 0 )
                  continue;
              }
            }
          }
        }
        rv = -1;
      }
    }

    /*
     * Create a LINEAR_FILE node
     */
    else if (linkflag == REGTYPE) {
      rtems_filesystem_location_free( currentloc );
      rtems_filesystem_location_clone( currentloc, &rootloc );
      rtems_filesystem_eval_path_set_path(
        &ctx,
        filename,
        strlen( filename )
      );
      rtems_filesystem_eval_path_continue( &ctx );

      if ( !rtems_filesystem_location_is_null( currentloc ) ) {
        IMFS_linearfile_t *linfile = (IMFS_linearfile_t *)
          IMFS_create_node(
            currentloc,
            &IMFS_node_control_linfile,
            sizeof( IMFS_file_t ),
            rtems_filesystem_eval_path_get_token( &ctx ),
            rtems_filesystem_eval_path_get_tokenlen( &ctx ),
            (file_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG,
            NULL
          );

        if ( linfile != NULL ) {
          linfile->File.size = file_size;
          linfile->direct    = &tar_image[offset];
        }
      }

      nblocks = (((file_size) + 511) & ~511) / 512;
      offset += 512 * nblocks;
    }
    /*
     * Create a symbolic link
     */
    else if (linkflag == SYMTYPE) {
      const char *linkto = hdr_ptr + 157;
      int len;

      strncpy(full_filename, mountpoint, 255);
      if (full_filename[(len=strlen(full_filename))-1] != '/')
        strcat(full_filename, "/");
      ++len;
      strncat(full_filename, filename, 256-len-1);

      rv = symlink(linkto, full_filename);
    }
  }

  rtems_filesystem_location_free( &rootloc );
  rtems_filesystem_eval_path_cleanup( &ctx );

  return rv;
}
Example #5
0
int rtems_tarfs_load(
  const char *mountpoint,
  uint8_t *tar_image,
  size_t tar_size
)
{
   const char                       *hdr_ptr;
   char                             filename[100];
   char                             full_filename[256];
   int                              hdr_chksum;
   unsigned char                    linkflag;
   unsigned long                    file_size;
   unsigned long                    file_mode;
   int                              offset;
   unsigned long                    nblocks;
   IMFS_jnode_t                    *node;
   int rv = 0;
   int eval_flags = RTEMS_FS_FOLLOW_LINK;
   rtems_filesystem_eval_path_context_t ctx;
   rtems_filesystem_location_info_t rootloc;
   rtems_filesystem_location_info_t *currentloc =
     rtems_filesystem_eval_path_start( &ctx, mountpoint, eval_flags );

   rtems_filesystem_eval_path_extract_currentloc( &ctx, &rootloc );
   rtems_filesystem_eval_path_set_flags(
     &ctx,
     RTEMS_FS_MAKE | RTEMS_FS_EXCLUSIVE
   );

   if (
     rootloc.mt_entry->ops != &IMFS_ops
       && rootloc.mt_entry->ops != &fifoIMFS_ops
   ) {
     rv = -1;
   }

   /*
    * Create an IMFS node structure pointing to tar image memory.
    */
   offset = 0;
   while ( rv == 0 ) {
    if (offset + 512 > tar_size)
      break;

    /*
     * Read a header.
     */
    hdr_ptr = (char *) &tar_image[offset];
    offset += 512;
    if (strncmp(&hdr_ptr[257], "ustar", 5))
      break;

    strncpy(filename, hdr_ptr, MAX_NAME_FIELD_SIZE);
    filename[MAX_NAME_FIELD_SIZE] = '\0';

    linkflag   = hdr_ptr[156];
    file_mode  = _rtems_octal2ulong(&hdr_ptr[100], 8);
    file_size  = _rtems_octal2ulong(&hdr_ptr[124], 12);
    hdr_chksum = _rtems_octal2ulong(&hdr_ptr[148], 8);

    if (_rtems_tar_header_checksum(hdr_ptr) != hdr_chksum)
      break;

    /*
     * Generate an IMFS node depending on the file type.
     * - For directories, just create directories as usual.  IMFS
     *   will take care of the rest.
     * - For files, create a file node with special tarfs properties.
     */
    if (linkflag == DIRTYPE) {
      strcpy(full_filename, mountpoint);
      if (full_filename[strlen(full_filename)-1] != '/')
        strcat(full_filename, "/");
      strcat(full_filename, filename);
      mkdir(full_filename, S_IRWXU | S_IRWXG | S_IRWXO);
    }
    /*
     * Create a LINEAR_FILE node
     */
    else if (linkflag == REGTYPE) {
      rtems_filesystem_location_free( currentloc );
      rtems_filesystem_location_clone( currentloc, &rootloc );
      rtems_filesystem_eval_path_set_path(
        &ctx,
        filename,
        strlen( filename )
      );
      rtems_filesystem_eval_path_continue( &ctx );

      if ( !rtems_filesystem_location_is_null( currentloc ) ) {
        node = IMFS_create_node(
          currentloc,
          IMFS_LINEAR_FILE,
          rtems_filesystem_eval_path_get_token( &ctx ),
          rtems_filesystem_eval_path_get_tokenlen( &ctx ),
          (file_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG,
          NULL
        );
        node->info.linearfile.size   = file_size;
        node->info.linearfile.direct = &tar_image[offset];
      }

      nblocks = (((file_size) + 511) & ~511) / 512;
      offset += 512 * nblocks;
    }
  }

  rtems_filesystem_location_free( &rootloc );
  rtems_filesystem_eval_path_cleanup( &ctx );

  return rv;
}