From 0ef748fb45137bac811ded19dfad2034f924505a Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Wed, 13 Dec 2000 17:53:55 +0000 Subject: 2000-12-12 Jake Janovetz * src/imfs/linearfile.c, src/imfs/imfs_load_tar.c: New files. * src/imfs/Makefile.am, src/imfs/imfs.h, src/imfs/imfs_creat.c, src/imfs/imfs_debug.c, src/imfs/imfs_eval.c, src/imfs/imfs_handlers_memfile.c, src/imfs/imfs_init.c, src/imfs/imfs_initsupp.c, src/imfs/imfs_stat.c, src/imfs/miniimfs_init.c: Added "tarfs". This is not really a tar filesystem. It is a way to load a tar image into the IMFS but actually leave bulky file contents in the original tar image. It essentially adds the linear file type and associated support and a loader routine. --- cpukit/libfs/src/imfs/Makefile.am | 4 +- cpukit/libfs/src/imfs/imfs.h | 29 +++- cpukit/libfs/src/imfs/imfs_creat.c | 4 + cpukit/libfs/src/imfs/imfs_debug.c | 10 +- cpukit/libfs/src/imfs/imfs_eval.c | 3 + cpukit/libfs/src/imfs/imfs_handlers_memfile.c | 17 +++ cpukit/libfs/src/imfs/imfs_init.c | 1 + cpukit/libfs/src/imfs/imfs_initsupp.c | 8 +- cpukit/libfs/src/imfs/imfs_load_tar.c | 209 ++++++++++++++++++++++++++ cpukit/libfs/src/imfs/imfs_stat.c | 1 + cpukit/libfs/src/imfs/linearfile.c | 110 ++++++++++++++ cpukit/libfs/src/imfs/miniimfs_init.c | 1 + 12 files changed, 390 insertions(+), 7 deletions(-) create mode 100644 cpukit/libfs/src/imfs/imfs_load_tar.c create mode 100644 cpukit/libfs/src/imfs/linearfile.c (limited to 'cpukit/libfs/src') diff --git a/cpukit/libfs/src/imfs/Makefile.am b/cpukit/libfs/src/imfs/Makefile.am index 420cad28f2..9d401c86d9 100644 --- a/cpukit/libfs/src/imfs/Makefile.am +++ b/cpukit/libfs/src/imfs/Makefile.am @@ -11,10 +11,10 @@ IMFS_C_FILES = imfs_chown.c imfs_config.c imfs_creat.c imfs_directory.c \ imfs_eval.c imfs_free.c imfs_fsunmount.c imfs_gtkn.c imfs_init.c \ imfs_initsupp.c imfs_link.c imfs_mknod.c imfs_mount.c imfs_fchmod.c \ imfs_unlink.c imfs_unmount.c imfs_utime.c imfs_ntype.c imfs_stat.c \ - imfs_getchild.c memfile.c deviceio.c imfs_handlers_device.c \ + imfs_getchild.c memfile.c linearfile.c deviceio.c imfs_handlers_device.c \ imfs_handlers_directory.c imfs_handlers_link.c imfs_handlers_memfile.c \ imfs_debug.c imfs_rmnod.c imfs_symlink.c imfs_readlink.c imfs_fdatasync.c \ - imfs_fcntl.c ioman.c miniimfs_init.c + imfs_fcntl.c ioman.c miniimfs_init.c imfs_load_tar.c UNIX_C_FILES = imfs_unixstub.c diff --git a/cpukit/libfs/src/imfs/imfs.h b/cpukit/libfs/src/imfs/imfs.h index 3a44c50ee3..2b2d84806f 100644 --- a/cpukit/libfs/src/imfs/imfs.h +++ b/cpukit/libfs/src/imfs/imfs.h @@ -94,6 +94,11 @@ typedef struct { block_ptr triply_indirect; /* 128 doubly indirect blocks */ } IMFS_memfile_t; +typedef struct { + off_t size; /* size of file in bytes */ + block_p direct; /* pointer to file image */ +} IMFS_linearfile_t; + /* * Important block numbers for "memfiles" */ @@ -125,8 +130,9 @@ typedef struct { #define IMFS_HARD_LINK RTEMS_FILESYSTEM_HARD_LINK #define IMFS_SYM_LINK RTEMS_FILESYSTEM_SYM_LINK #define IMFS_MEMORY_FILE RTEMS_FILESYSTEM_MEMORY_FILE +#define IMFS_LINEAR_FILE (RTEMS_FILESYSTEM_MEMORY_FILE + 1) -#define IMFS_NUMBER_OF_TYPES (IMFS_MEMORY_FILE + 1) +#define IMFS_NUMBER_OF_TYPES (IMFS_LINEAR_FILE + 1) typedef union { IMFS_directory_t directory; @@ -134,6 +140,7 @@ typedef union { IMFS_link_t hard_link; IMFS_sym_link_t sym_link; IMFS_memfile_t file; + IMFS_linearfile_t linearfile; } IMFS_types_union; /* @@ -195,6 +202,7 @@ struct IMFS_jnode_tt { typedef struct { ino_t ino_count; + rtems_filesystem_file_handlers_r *linearfile_handlers; rtems_filesystem_file_handlers_r *memfile_handlers; rtems_filesystem_file_handlers_r *directory_handlers; } IMFS_fs_info_t; @@ -226,6 +234,7 @@ typedef enum { extern rtems_filesystem_file_handlers_r IMFS_directory_handlers; extern rtems_filesystem_file_handlers_r IMFS_device_handlers; extern rtems_filesystem_file_handlers_r IMFS_link_handlers; +extern rtems_filesystem_file_handlers_r IMFS_linearfile_handlers; extern rtems_filesystem_file_handlers_r IMFS_memfile_handlers; extern rtems_filesystem_operations_table IMFS_ops; extern rtems_filesystem_operations_table miniIMFS_ops; @@ -246,6 +255,7 @@ int miniIMFS_initialize( int IMFS_initialize_support( rtems_filesystem_mount_table_entry_t *mt_entry, rtems_filesystem_operations_table *op_table, + rtems_filesystem_file_handlers_r *linearfile_handlers, rtems_filesystem_file_handlers_r *memfile_handlers, rtems_filesystem_file_handlers_r *directory_handlers ); @@ -254,6 +264,11 @@ int IMFS_fsunmount( rtems_filesystem_mount_table_entry_t *mt_entry ); +int rtems_tarfs_mount( + char *mountpoint, + unsigned char *addr, + unsigned long length +); /* * Returns the number of characters copied from path to token. @@ -398,6 +413,18 @@ int imfs_dir_rmnod( rtems_filesystem_location_info_t *pathloc /* IN */ ); +int linearfile_read( + rtems_libio_t *iop, /* IN */ + void *buffer, /* IN */ + unsigned32 count /* IN */ +); + +int linearfile_lseek( + rtems_libio_t *iop, /* IN */ + off_t offset, /* IN */ + int whence /* IN */ +); + int memfile_open( rtems_libio_t *iop, /* IN */ const char *pathname, /* IN */ diff --git a/cpukit/libfs/src/imfs/imfs_creat.c b/cpukit/libfs/src/imfs/imfs_creat.c index b0934c0463..29c49cc34b 100644 --- a/cpukit/libfs/src/imfs/imfs_creat.c +++ b/cpukit/libfs/src/imfs/imfs_creat.c @@ -100,6 +100,10 @@ IMFS_jnode_t *IMFS_create_node( node->info.device.minor = info->device.minor; break; + case IMFS_LINEAR_FILE: + node->info.linearfile.size = 0; + node->info.linearfile.direct = 0; + case IMFS_MEMORY_FILE: node->info.file.size = 0; node->info.file.indirect = 0; diff --git a/cpukit/libfs/src/imfs/imfs_debug.c b/cpukit/libfs/src/imfs/imfs_debug.c index 42d19abddf..89e1bc91ce 100644 --- a/cpukit/libfs/src/imfs/imfs_debug.c +++ b/cpukit/libfs/src/imfs/imfs_debug.c @@ -34,7 +34,8 @@ char *IMFS_types[ IMFS_NUMBER_OF_TYPES ] = { "directory", "device", "link", - "memory file" + "memory file", + "linear file" }; /* @@ -60,6 +61,13 @@ void IMFS_print_jnode( the_jnode->info.device.major, the_jnode->info.device.minor ); break; + case IMFS_LINEAR_FILE: + printf( " (file %d %p)", + (int)the_jnode->info.linearfile.size, + the_jnode->info.linearfile.direct + ); + break; + case IMFS_MEMORY_FILE: printf( " (file %d %p %p %p)", (int)the_jnode->info.file.size, diff --git a/cpukit/libfs/src/imfs/imfs_eval.c b/cpukit/libfs/src/imfs/imfs_eval.c index 913fddeaa7..da2231f16a 100644 --- a/cpukit/libfs/src/imfs/imfs_eval.c +++ b/cpukit/libfs/src/imfs/imfs_eval.c @@ -46,6 +46,9 @@ int IMFS_Set_handlers( case IMFS_HARD_LINK: loc->handlers = &IMFS_link_handlers; break; + case IMFS_LINEAR_FILE: + loc->handlers = fs_info->linearfile_handlers; + break; case IMFS_MEMORY_FILE: loc->handlers = fs_info->memfile_handlers; break; diff --git a/cpukit/libfs/src/imfs/imfs_handlers_memfile.c b/cpukit/libfs/src/imfs/imfs_handlers_memfile.c index 5133b87198..eb2ab47b39 100644 --- a/cpukit/libfs/src/imfs/imfs_handlers_memfile.c +++ b/cpukit/libfs/src/imfs/imfs_handlers_memfile.c @@ -19,6 +19,23 @@ * Set of operations handlers for operations on memfile entities. */ +rtems_filesystem_file_handlers_r IMFS_linearfile_handlers = { + memfile_open, + memfile_close, + linearfile_read, + NULL, /* write */ + memfile_ioctl, + linearfile_lseek, + IMFS_stat, + NULL, /* chmod */ + NULL, /* ftruncate */ + NULL, /* fpathconf */ + IMFS_fdatasync, /* fsync */ + IMFS_fdatasync, + IMFS_fcntl, + NULL /* rmnod */ +}; + rtems_filesystem_file_handlers_r IMFS_memfile_handlers = { memfile_open, memfile_close, diff --git a/cpukit/libfs/src/imfs/imfs_init.c b/cpukit/libfs/src/imfs/imfs_init.c index 0f9342b381..46a578f586 100644 --- a/cpukit/libfs/src/imfs/imfs_init.c +++ b/cpukit/libfs/src/imfs/imfs_init.c @@ -59,6 +59,7 @@ int IMFS_initialize( IMFS_initialize_support( temp_mt_entry, &IMFS_ops, + &IMFS_linearfile_handlers, &IMFS_memfile_handlers, &IMFS_directory_handlers ); diff --git a/cpukit/libfs/src/imfs/imfs_initsupp.c b/cpukit/libfs/src/imfs/imfs_initsupp.c index 1e9bb380b1..cf1a48e480 100644 --- a/cpukit/libfs/src/imfs/imfs_initsupp.c +++ b/cpukit/libfs/src/imfs/imfs_initsupp.c @@ -32,6 +32,7 @@ int IMFS_initialize_support( rtems_filesystem_mount_table_entry_t *temp_mt_entry, rtems_filesystem_operations_table *op_table, + rtems_filesystem_file_handlers_r *linearfile_handlers, rtems_filesystem_file_handlers_r *memfile_handlers, rtems_filesystem_file_handlers_r *directory_handlers ) @@ -69,9 +70,10 @@ int IMFS_initialize_support( * Set st_ino for the root to 1. */ - fs_info->ino_count = 1; - fs_info->memfile_handlers = memfile_handlers; - fs_info->directory_handlers = directory_handlers; + fs_info->ino_count = 1; + fs_info->linearfile_handlers = linearfile_handlers; + fs_info->memfile_handlers = memfile_handlers; + fs_info->directory_handlers = directory_handlers; jnode = temp_mt_entry->mt_fs_root.node_access; jnode->st_ino = fs_info->ino_count; diff --git a/cpukit/libfs/src/imfs/imfs_load_tar.c b/cpukit/libfs/src/imfs/imfs_load_tar.c new file mode 100644 index 0000000000..7dc7df8a61 --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_load_tar.c @@ -0,0 +1,209 @@ +/************************************************************************** + * This file implements the "mount" procedure for tar-based IMFS + * extensions. The TAR is not actually mounted under the IMFS. + * Directories from the TAR file are created as usual in the IMFS. + * File entries are created as IMFS_LINEAR_FILE nodes with their nods + * pointing to addresses in the TAR image. + * + * $Id$ + * + *************************************************************************/ + +#include +#include +#include +#include +#include + + +/************************************************************************** + * TAR file format: + * + * Offset Length Contents + * 0 100 bytes File name ('\0' terminated, 99 maxmum length) + * 100 8 bytes File mode (in octal ascii) + * 108 8 bytes User ID (in octal ascii) + * 116 8 bytes Group ID (in octal ascii) + * 124 12 bytes File size (s) (in octal ascii) + * 136 12 bytes Modify time (in octal ascii) + * 148 8 bytes Header checksum (in octal ascii) + * 156 1 bytes Link flag + * 157 100 bytes Linkname ('\0' terminated, 99 maxmum length) + * 257 8 bytes Magic ("ustar \0") + * 265 32 bytes User name ('\0' terminated, 31 maxmum length) + * 297 32 bytes Group name ('\0' terminated, 31 maxmum length) + * 329 8 bytes Major device ID (in octal ascii) + * 337 8 bytes Minor device ID (in octal ascii) + * 345 167 bytes Padding + * 512 (s+p)bytes File contents (s+p) := (((s) + 511) & ~511), + * round up to 512 bytes + * + * Checksum: + * int i, sum; + * char* header = tar_header_pointer; + * sum = 0; + * for(i = 0; i < 512; i++) + * sum += 0xFF & header[i]; + *************************************************************************/ + +#define LF_OLDNORMAL '\0' /* Normal disk file, Unix compatible */ +#define LF_NORMAL '0' /* Normal disk file */ +#define LF_LINK '1' /* Link to previously dumped file */ +#define LF_SYMLINK '2' /* Symbolic link */ +#define LF_CHR '3' /* Character special file */ +#define LF_BLK '4' /* Block special file */ +#define LF_DIR '5' /* Directory */ +#define LF_FIFO '6' /* FIFO special file */ +#define LF_CONFIG '7' /* Contiguous file */ + +#define MAX_NAME_FIELD_SIZE 99 + +#define MIN(a,b) ((a)>(b)?(b):(a)) + + +/************************************************************************** + * This converts octal ASCII number representations into an + * unsigned long. Only support 32-bit numbers for now. + *************************************************************************/ +static unsigned long +octal2ulong(char *octascii, int len) +{ + int i; + unsigned long num; + unsigned long mult; + + num = 0; + mult = 1; + for (i=len-1; i>=0; i--) + { + if ((octascii[i] < '0') || (octascii[i] > '9')) + continue; + + num += mult*((unsigned long)(octascii[i] - '0')); + mult *= 8; + } + return(num); +} + + +/************************************************************************ + * 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. + ************************************************************************/ +static int +compute_tar_header_checksum(char *bufr) +{ + int i, sum; + + + sum = 0; + for (i=0; i<512; i++) + { + if ((i >= 148) && (i < 156)) + sum += 0xff & ' '; + else + sum += 0xff & bufr[i]; + } + return(sum); +} + + +/************************************************************************** + * rtems_tarfs_mount + * + * Here we create the mountpoint directory and mount 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_mount(char *mountpoint, + unsigned char *tar_image, + unsigned long tar_size) +{ + rtems_filesystem_location_info_t root_loc; + rtems_filesystem_location_info_t loc; + char *hdr_ptr; + char filename[100]; + char full_filename[256]; + int hdr_chksum; + unsigned char linkflag; + unsigned long file_size; + int offset; + unsigned long nblocks; + IMFS_jnode_t *node; + int status; + + + status = rtems_filesystem_evaluate_path(mountpoint, 0, &root_loc, 0); + if (status != 0) + 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 = &tar_image[offset]; + offset += 512; + if (strncmp(&hdr_ptr[257], "ustar ", 7)) + break; + + strncpy(filename, hdr_ptr, MAX_NAME_FIELD_SIZE); + filename[MAX_NAME_FIELD_SIZE] = '\0'; + + linkflag = hdr_ptr[156]; + file_size = octal2ulong(&hdr_ptr[124], 12); + + hdr_chksum = (int)octal2ulong(&hdr_ptr[148], 8); + if (compute_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 == LF_DIR) + { + strcpy(full_filename, mountpoint); + strcat(full_filename, "/"); + strcat(full_filename, filename); + mkdir(full_filename, S_IRWXU | S_IRWXG | S_IRWXO); + } + else if (linkflag == LF_NORMAL) + { + 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, + (S_IRUSR | S_IRGRP | S_IROTH) | 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); +} + diff --git a/cpukit/libfs/src/imfs/imfs_stat.c b/cpukit/libfs/src/imfs/imfs_stat.c index e01f33794b..ee4971df4e 100644 --- a/cpukit/libfs/src/imfs/imfs_stat.c +++ b/cpukit/libfs/src/imfs/imfs_stat.c @@ -35,6 +35,7 @@ int IMFS_stat( buf->st_dev = rtems_filesystem_make_dev_t( io->major, io->minor ); break; + case IMFS_LINEAR_FILE: case IMFS_MEMORY_FILE: buf->st_size = the_jnode->info.file.size; break; diff --git a/cpukit/libfs/src/imfs/linearfile.c b/cpukit/libfs/src/imfs/linearfile.c new file mode 100644 index 0000000000..e8d28fe31d --- /dev/null +++ b/cpukit/libfs/src/imfs/linearfile.c @@ -0,0 +1,110 @@ +/* + * IMFS Linear File Handlers + * + * This file contains the set of handlers used to process operations on + * IMFS linear memory file nodes. Linear memory files are contiguous + * blocks of memory created from a TAR or other filesystem image. + * The blocks are nonwriteable and nonresizeable. + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include +#include +#include + +#include +#include +#include "imfs.h" +#include + +/* + * linearfile_read + * + * This routine processes the read() system call. + */ + +int linearfile_read( + rtems_libio_t *iop, + void *buffer, + unsigned32 count +) +{ + IMFS_jnode_t *the_jnode; + unsigned char *dest; + unsigned char *file_ptr; + int file_offset; + + + the_jnode = iop->file_info; + + /* + * Perform internal consistency checks + */ + + assert( the_jnode ); + if ( !the_jnode ) + set_errno_and_return_minus_one( EIO ); + + assert( the_jnode->type == IMFS_LINEAR_FILE ); + if ( the_jnode->type != IMFS_LINEAR_FILE ) + set_errno_and_return_minus_one( EIO ); + + /* + * Error checks on arguments + */ + + dest = (unsigned char *)buffer; + assert( dest ); + if ( !dest ) + set_errno_and_return_minus_one( EINVAL ); + + /* + * Perform a simple memory copy. + */ + + if (count == 0) + return(0); + + the_jnode = iop->file_info; + file_ptr = (unsigned char *)the_jnode->info.linearfile.direct; + file_offset = (unsigned long)iop->offset; + + if (count > (the_jnode->info.linearfile.size - file_offset)) + count = the_jnode->info.linearfile.size - file_offset; + + memcpy(dest, &file_ptr[file_offset], count); + + return(count); +} + + +/* + * linearfile_lseek + * + * This routine processes the lseek() system call. + */ + +int linearfile_lseek( + rtems_libio_t *iop, + off_t offset, + int whence +) +{ + IMFS_jnode_t *the_jnode; + + the_jnode = iop->file_info; + + if (iop->offset > the_jnode->info.linearfile.size) + iop->offset = the_jnode->info.linearfile.size; + + return iop->offset; +} + diff --git a/cpukit/libfs/src/imfs/miniimfs_init.c b/cpukit/libfs/src/imfs/miniimfs_init.c index f752fc1f87..138cab8b27 100644 --- a/cpukit/libfs/src/imfs/miniimfs_init.c +++ b/cpukit/libfs/src/imfs/miniimfs_init.c @@ -59,6 +59,7 @@ int miniIMFS_initialize( IMFS_initialize_support( temp_mt_entry, &miniIMFS_ops, + &rtems_filesystem_null_handlers, /* for linearfiles */ &rtems_filesystem_null_handlers, /* for memfiles */ &rtems_filesystem_null_handlers /* for directories */ ); -- cgit v1.2.3