summaryrefslogtreecommitdiffstats
path: root/c/src/libfs/src/imfs/imfs_load_tar.c
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2000-12-13 17:53:55 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2000-12-13 17:53:55 +0000
commit0ef748fb45137bac811ded19dfad2034f924505a (patch)
tree781c137a2c5303c3ad851c5982c2641fedc45bbf /c/src/libfs/src/imfs/imfs_load_tar.c
parent2000-12-13 Joel Sherrill <joel@OARcorp.com> (diff)
downloadrtems-0ef748fb45137bac811ded19dfad2034f924505a.tar.bz2
2000-12-12 Jake Janovetz <janovetz@uiuc.edu>
* 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.
Diffstat (limited to 'c/src/libfs/src/imfs/imfs_load_tar.c')
-rw-r--r--c/src/libfs/src/imfs/imfs_load_tar.c209
1 files changed, 209 insertions, 0 deletions
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 <rtems.h>
+#include <rtems/libio.h>
+#include <string.h>
+#include <chain.h>
+#include <imfs.h>
+
+
+/**************************************************************************
+ * 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);
+}
+