summaryrefslogtreecommitdiffstats
path: root/cpukit/libfs/src/imfs
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2019-11-21 08:06:28 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2019-11-25 11:32:19 +0100
commitb6f66d9345a6deea43310e31b519dd35bdbb5908 (patch)
tree344f0149e536d06b675a75c1195a70948194d229 /cpukit/libfs/src/imfs
parentlibtest: Output basename of source files (diff)
downloadrtems-b6f66d9345a6deea43310e31b519dd35bdbb5908.tar.bz2
untar: Unify untar support
Update #3823.
Diffstat (limited to 'cpukit/libfs/src/imfs')
-rw-r--r--cpukit/libfs/src/imfs/imfs_load_tar.c197
1 files changed, 55 insertions, 142 deletions
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 <rtems/imfs.h>
-
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <string.h>
-#include <tar.h>
-#include <unistd.h>
-
#include <rtems/untar.h>
-#define MAX_NAME_FIELD_SIZE 99
+#include <string.h>
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;
}
-