From b6f66d9345a6deea43310e31b519dd35bdbb5908 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 21 Nov 2019 08:06:28 +0100 Subject: untar: Unify untar support Update #3823. --- cpukit/libfs/src/imfs/imfs_load_tar.c | 197 ++++++++++------------------------ 1 file changed, 55 insertions(+), 142 deletions(-) (limited to 'cpukit/libfs') diff --git a/cpukit/libfs/src/imfs/imfs_load_tar.c b/cpukit/libfs/src/imfs/imfs_load_tar.c index 6298a3f32d..ed2d2a0f97 100644 --- a/cpukit/libfs/src/imfs/imfs_load_tar.c +++ b/cpukit/libfs/src/imfs/imfs_load_tar.c @@ -19,161 +19,74 @@ #endif #include - -#include -#include -#include -#include -#include - #include -#define MAX_NAME_FIELD_SIZE 99 +#include int rtems_tarfs_load( const char *mountpoint, - uint8_t *tar_image, - size_t tar_size + 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; - } + rtems_filesystem_eval_path_context_t eval_ctx; + int eval_flags; + rtems_filesystem_location_info_t *loc; + bool is_imfs; + char buf[ 156 + UNTAR_FILE_NAME_SIZE ]; + size_t len; + Untar_HeaderContext ctx; + unsigned long ptr; + + len = strlen( mountpoint ); + if ( len >= sizeof( buf ) - UNTAR_FILE_NAME_SIZE - 2 ) { + return -1; + } + + eval_flags = RTEMS_FS_FOLLOW_LINK; + loc = rtems_filesystem_eval_path_start( &eval_ctx, mountpoint, eval_flags ); + is_imfs = IMFS_is_imfs_instance( loc ); + rtems_filesystem_eval_path_cleanup( &eval_ctx ); + if ( !is_imfs ) { + return -1; + } + + ctx.printer = NULL; + ctx.file_path = memcpy( buf, mountpoint, len ); + + if ( len > 0 && ctx.file_path[ len - 1 ] != '/') { + ctx.file_path[ len ] = '/'; + ctx.file_name = ctx.file_path + len + 1; + } else { + ctx.file_name = ctx.file_path + len; + } + + ptr = 0; + + while ( ptr + 512 <= tar_size ) { + int retval; + + retval = Untar_ProcessHeader( &ctx, (const char *) &tar_image[ ptr ] ); + if ( retval != UNTAR_SUCCESSFUL ) { + return -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 ) + ptr += 512; + + if ( ctx.linkflag == REGTYPE ) { + retval = IMFS_make_linearfile( + ctx.file_path, + ctx.mode, + &tar_image[ ptr ], + ctx.file_size ); - rtems_filesystem_eval_path_continue( &ctx ); - - if ( !rtems_filesystem_location_is_null( currentloc ) ) { - IMFS_linearfile_context linctx = { - .data = &tar_image[offset], - .size = file_size - }; - - 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, - &linctx - ); + if ( retval != 0 ) { + return -1; } - 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); + ptr += 512 * ctx.nblocks; } } - rtems_filesystem_location_free( &rootloc ); - rtems_filesystem_eval_path_cleanup( &ctx ); - - return rv; + return 0; } - -- cgit v1.2.3