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; }
int IMFS_make_generic_node( const char *path, mode_t mode, const IMFS_node_control *node_control, void *context ) { int rv = 0; mode &= ~rtems_filesystem_umask; switch (mode & S_IFMT) { case S_IFBLK: case S_IFCHR: case S_IFIFO: case S_IFREG: break; default: errno = EINVAL; rv = -1; break; } if ( rv == 0 ) { if ( node_control->imfs_type == IMFS_GENERIC ) { rtems_filesystem_eval_path_context_t ctx; int eval_flags = RTEMS_FS_FOLLOW_LINK | RTEMS_FS_MAKE | RTEMS_FS_EXCLUSIVE; const rtems_filesystem_location_info_t *currentloc = rtems_filesystem_eval_path_start( &ctx, path, eval_flags ); if ( IMFS_is_imfs_instance( currentloc ) ) { IMFS_types_union info; IMFS_jnode_t *new_node; info.generic.context = context; new_node = IMFS_create_node_with_control( currentloc, node_control, rtems_filesystem_eval_path_get_token( &ctx ), rtems_filesystem_eval_path_get_tokenlen( &ctx ), mode, &info ); if ( new_node != NULL ) { IMFS_jnode_t *parent = currentloc->node_access; IMFS_update_ctime( parent ); IMFS_update_mtime( parent ); } else { rv = -1; } } else { rtems_filesystem_eval_path_error( &ctx, ENOTSUP ); rv = -1; } rtems_filesystem_eval_path_cleanup( &ctx ); } else { errno = EINVAL; rv = -1; } } return rv; }