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. --- c/src/libfs/src/imfs/imfs_load_tar.c | 209 +++++++++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 c/src/libfs/src/imfs/imfs_load_tar.c (limited to 'c/src/libfs/src/imfs/imfs_load_tar.c') diff --git a/c/src/libfs/src/imfs/imfs_load_tar.c b/c/src/libfs/src/imfs/imfs_load_tar.c new file mode 100644 index 0000000000..7dc7df8a61 --- /dev/null +++ b/c/src/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); +} + -- cgit v1.2.3