summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>1999-04-06 21:45:06 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>1999-04-06 21:45:06 +0000
commitb08d3ed989cf3d4fc8ecf49e2f6781c612edb6d2 (patch)
treeed948f6560763ae363061b480c41ada18dde7a70
parentPatch from Andrew Bray <andy@chaos.org.uk>: (diff)
downloadrtems-b08d3ed989cf3d4fc8ecf49e2f6781c612edb6d2.tar.bz2
Untar support submitted by Jake Janovetz <janovetz@tempest.ece.uiuc.edu>.
-rw-r--r--c/src/lib/libmisc/Makefile.in2
-rw-r--r--c/src/lib/libmisc/untar/Makefile.in63
-rw-r--r--c/src/lib/libmisc/untar/untar.c381
-rw-r--r--c/src/lib/libmisc/untar/untar.h25
-rw-r--r--c/src/lib/libmisc/wrapup/Makefile.in1
-rw-r--r--c/src/libmisc/untar/Makefile.in63
-rw-r--r--c/src/libmisc/untar/untar.c381
-rw-r--r--c/src/libmisc/untar/untar.h25
-rw-r--r--c/src/libmisc/wrapup/Makefile.in1
-rw-r--r--cpukit/libmisc/untar/untar.c381
-rw-r--r--cpukit/libmisc/untar/untar.h25
11 files changed, 1347 insertions, 1 deletions
diff --git a/c/src/lib/libmisc/Makefile.in b/c/src/lib/libmisc/Makefile.in
index 833a80d575..4db7779d35 100644
--- a/c/src/lib/libmisc/Makefile.in
+++ b/c/src/lib/libmisc/Makefile.in
@@ -18,7 +18,7 @@ VPATH = @srcdir@
include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
include $(RTEMS_ROOT)/make/directory.cfg
-SUB_DIRS=assoc dumpbuf error stackchk monitor cpuuse rtmonuse wrapup
+SUB_DIRS=assoc dumpbuf error stackchk monitor cpuuse rtmonuse untar wrapup
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
diff --git a/c/src/lib/libmisc/untar/Makefile.in b/c/src/lib/libmisc/untar/Makefile.in
new file mode 100644
index 0000000000..10f7238762
--- /dev/null
+++ b/c/src/lib/libmisc/untar/Makefile.in
@@ -0,0 +1,63 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+top_builddir = ../../../../..
+subdir = c/src/lib/libmisc/untar
+
+INSTALL = @INSTALL@
+
+RTEMS_ROOT = $(top_srcdir)/@RTEMS_TOPdir@
+PROJECT_ROOT = @PROJECT_ROOT@
+
+VPATH = @srcdir@
+
+LIB=${ARCH}/libuntar-tmp.a
+
+# C source names, if any, go here -- minus the .c
+C_PIECES=untar
+C_FILES=$(C_PIECES:%=%.c)
+C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
+
+H_FILES=$(srcdir)/untar.h
+
+SRCS=$(C_FILES) $(H_FILES) $(INSTALLED_H_FILES)
+OBJS=$(C_O_FILES)
+
+include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
+include $(RTEMS_ROOT)/make/lib.cfg
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+DEFINES +=
+CPPFLAGS += -I.
+CFLAGS +=
+
+LD_PATHS +=
+LD_LIBS +=
+LDFLAGS +=
+
+#
+# Add your list of files to delete here. The config files
+# already know how to delete some stuff, so you may want
+# to just run 'make clean' first to see what gets missed.
+# 'make clobber' already includes 'make clean'
+#
+
+CLEAN_ADDITIONS +=
+CLOBBER_ADDITIONS +=
+
+${LIB}: ${SRCS} ${OBJS}
+ $(make-library)
+
+all: ${ARCH} $(SRCS) $(LIB)
+ $(INSTALL_CHANGE) -m 444 ${H_FILES} $(PROJECT_INCLUDE)/rtems
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
diff --git a/c/src/lib/libmisc/untar/untar.c b/c/src/lib/libmisc/untar/untar.c
new file mode 100644
index 0000000000..ea5c1430d2
--- /dev/null
+++ b/c/src/lib/libmisc/untar/untar.c
@@ -0,0 +1,381 @@
+/* FIXME:
+ * 1. Symbolic links are not created.
+ * 2. Untar_FromMemory has printfs.
+ * 3. Untar_FromMemory uses FILE *fp.
+ * 4. How to determine end of archive?
+ *
+ * Written by: Jake Janovetz <janovetz@tempest.ece.uiuc.edu>
+ *
+ * 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "untar.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);
+}
+
+
+/**************************************************************************
+ * Function: Untar_FromMemory *
+ **************************************************************************
+ * Description: *
+ * *
+ * This is a simple subroutine used to rip links, directories, and *
+ * files out of a block of memory. *
+ * *
+ * *
+ * Inputs: *
+ * *
+ * unsigned char *tar_buf - Pointer to TAR buffer. *
+ * unsigned long size - Length of TAR buffer. *
+ * *
+ * *
+ * Output: *
+ * *
+ * int - UNTAR_SUCCESSFUL (0) on successful completion. *
+ * UNTAR_INVALID_CHECKSUM for an invalid header checksum. *
+ * UNTAR_INVALID_HEADER for an invalid header. *
+ * *
+ **************************************************************************
+ * Change History: *
+ * 12/30/1998 - Creation (JWJ) *
+ *************************************************************************/
+int
+Untar_FromMemory(unsigned char *tar_buf, unsigned long size)
+{
+ FILE *fp;
+ char *bufr;
+ size_t n;
+ char fname[100];
+ char linkname[100];
+ int sum;
+ int hdr_chksum;
+ int retval;
+ unsigned long ptr;
+ unsigned long i;
+ unsigned long nblocks;
+ unsigned long file_size;
+ unsigned char linkflag;
+
+
+ ptr = 0;
+ while (1)
+ {
+ if (ptr + 512 > size)
+ {
+ retval = UNTAR_SUCCESSFUL;
+ break;
+ }
+
+ /* Read the header */
+ bufr = &tar_buf[ptr];
+ ptr += 512;
+ if (strncmp(&bufr[257], "ustar ", 7))
+ {
+ retval = UNTAR_SUCCESSFUL;
+ break;
+ }
+
+ strncpy(fname, bufr, MAX_NAME_FIELD_SIZE);
+ fname[MAX_NAME_FIELD_SIZE] = '\0';
+
+ linkflag = bufr[156];
+ file_size = octal2ulong(&bufr[124], 12);
+
+ /******************************************************************
+ * 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.
+ ******************************************************************/
+ hdr_chksum = (int)octal2ulong(&bufr[148], 8);
+ sum = 0;
+ for (i=0; i<512; i++)
+ {
+ if ((i >= 148) && (i < 156))
+ {
+ sum += 0xff & ' ';
+ }
+ else
+ {
+ sum += 0xff & bufr[i];
+ }
+ }
+ if (sum != hdr_chksum)
+ {
+ retval = UNTAR_INVALID_CHECKSUM;
+ break;
+ }
+
+
+ /******************************************************************
+ * We've decoded the header, now figure out what it contains and
+ * do something with it.
+ *****************************************************************/
+ if (linkflag == LF_SYMLINK)
+ {
+ strncpy(linkname, &bufr[157], MAX_NAME_FIELD_SIZE);
+ linkname[MAX_NAME_FIELD_SIZE] = '\0';
+ /* symlink(fname, linkname); */
+ }
+ else if (linkflag == LF_NORMAL)
+ {
+ nblocks = (((file_size) + 511) & ~511) / 512;
+ if ((fp = fopen(fname, "w")) == NULL)
+ {
+ printf("Untar failed to create file %s\n", fname);
+ ptr += 512 * nblocks;
+ }
+ else
+ {
+ unsigned long sizeToGo = file_size;
+ unsigned long len;
+
+ /***************************************************************
+ * Read out the data. There are nblocks of data where nblocks
+ * is the file_size rounded to the nearest 512-byte boundary.
+ **************************************************************/
+ for (i=0; i<nblocks; i++)
+ {
+ len = ((sizeToGo < 512L)?(sizeToGo):(512L));
+ n = fwrite(&tar_buf[ptr], 1, len, fp);
+ if (n != len)
+ {
+ printf("Error during write\n");
+ break;
+ }
+ ptr += 512;
+ sizeToGo -= n;
+ }
+ fclose(fp);
+ }
+ }
+ else if (linkflag == LF_DIR)
+ {
+ mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO);
+ }
+ }
+
+ return(retval);
+}
+
+
+/**************************************************************************
+ * Function: Untar_FromFile *
+ **************************************************************************
+ * Description: *
+ * *
+ * This is a simple subroutine used to rip links, directories, and *
+ * files out of a TAR file. *
+ * *
+ * *
+ * Inputs: *
+ * *
+ * char *tar_name - TAR filename. *
+ * *
+ * *
+ * Output: *
+ * *
+ * int - UNTAR_SUCCESSFUL (0) on successful completion. *
+ * UNTAR_INVALID_CHECKSUM for an invalid header checksum. *
+ * UNTAR_INVALID_HEADER for an invalid header. *
+ * *
+ **************************************************************************
+ * Change History: *
+ * 12/30/1998 - Creation (JWJ) *
+ *************************************************************************/
+int
+Untar_FromFile(char *tar_name)
+{
+ int fd;
+ char *bufr;
+ size_t n;
+ char fname[100];
+ char linkname[100];
+ int sum;
+ int hdr_chksum;
+ int retval;
+ unsigned long i;
+ unsigned long nblocks;
+ unsigned long size;
+ unsigned char linkflag;
+
+
+ retval = UNTAR_SUCCESSFUL;
+ bufr = (char *)malloc(512);
+ if (bufr == NULL)
+ {
+ return(UNTAR_FAIL);
+ }
+
+ fd = open(tar_name, O_RDONLY);
+ while (1)
+ {
+ /* Read the header */
+ /* If the header read fails, we just consider it the end
+ of the tarfile. */
+ if ((n = read(fd, bufr, 512)) != 512)
+ {
+ break;
+ }
+
+ if (strncmp(&bufr[257], "ustar ", 7))
+ {
+ break;
+ }
+
+ strncpy(fname, bufr, MAX_NAME_FIELD_SIZE);
+ fname[MAX_NAME_FIELD_SIZE] = '\0';
+
+ linkflag = bufr[156];
+ size = octal2ulong(&bufr[124], 12);
+
+ /******************************************************************
+ * 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.
+ ******************************************************************/
+ hdr_chksum = (int)octal2ulong(&bufr[148], 8);
+ sum = 0;
+ for (i=0; i<512; i++)
+ {
+ if ((i >= 148) && (i < 156))
+ {
+ sum += 0xff & ' ';
+ }
+ else
+ {
+ sum += 0xff & bufr[i];
+ }
+ }
+ if (sum != hdr_chksum)
+ {
+ retval = UNTAR_INVALID_CHECKSUM;
+ break;
+ }
+
+
+ /******************************************************************
+ * We've decoded the header, now figure out what it contains and
+ * do something with it.
+ *****************************************************************/
+ if (linkflag == LF_SYMLINK)
+ {
+ strncpy(linkname, &bufr[157], MAX_NAME_FIELD_SIZE);
+ linkname[MAX_NAME_FIELD_SIZE] = '\0';
+ }
+ else if (linkflag == LF_NORMAL)
+ {
+ int out_fd;
+
+ /******************************************************************
+ * Read out the data. There are nblocks of data where nblocks
+ * is the size rounded to the nearest 512-byte boundary.
+ *****************************************************************/
+ nblocks = (((size) + 511) & ~511) / 512;
+
+ if ((out_fd = creat(fname, 0644)) == -1)
+ {
+ for (i=0; i<nblocks; i++)
+ {
+ n = read(fd, bufr, 512);
+ }
+ }
+ else
+ {
+ for (i=0; i<nblocks; i++)
+ {
+ n = read(fd, bufr, 512);
+ n = MIN(n, size - i*512);
+ write(out_fd, bufr, n);
+ }
+ close(out_fd);
+ }
+ }
+ else if (linkflag == LF_DIR)
+ {
+ mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO);
+ }
+ }
+ free(bufr);
+ close(fd);
+
+ return(retval);
+}
+
diff --git a/c/src/lib/libmisc/untar/untar.h b/c/src/lib/libmisc/untar/untar.h
new file mode 100644
index 0000000000..d8c5bcfc01
--- /dev/null
+++ b/c/src/lib/libmisc/untar/untar.h
@@ -0,0 +1,25 @@
+/*
+ * Written by: Jake Janovetz <janovetz@tempest.ece.uiuc.edu>
+ *
+ * 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$
+ */
+
+#ifndef __UNTAR_H__
+#define __UNTAR_H__
+
+
+#define UNTAR_SUCCESSFUL 0
+#define UNTAR_FAIL 1
+#define UNTAR_INVALID_CHECKSUM 2
+#define UNTAR_INVALID_HEADER 3
+
+
+int Untar_FromMemory(unsigned char *tar_buf, unsigned long size);
+int Untar_FromFile(char *tar_name);
+
+
+#endif /* __UNTAR_H__ */
diff --git a/c/src/lib/libmisc/wrapup/Makefile.in b/c/src/lib/libmisc/wrapup/Makefile.in
index b43a7c6115..fbba22658a 100644
--- a/c/src/lib/libmisc/wrapup/Makefile.in
+++ b/c/src/lib/libmisc/wrapup/Makefile.in
@@ -23,6 +23,7 @@ include $(RTEMS_ROOT)/make/lib.cfg
# Using the wildcard on the Purify support makes sure it may not be there
LIBS=../monitor/$(ARCH)/libmonitor-tmp.a \
+ ../untar/$(ARCH)/libuntar-tmp.a \
../error/$(ARCH)/liberror-tmp.a \
../assoc/$(ARCH)/libassoc-tmp.a \
../stackchk/$(ARCH)/libstackchk-tmp.a \
diff --git a/c/src/libmisc/untar/Makefile.in b/c/src/libmisc/untar/Makefile.in
new file mode 100644
index 0000000000..10f7238762
--- /dev/null
+++ b/c/src/libmisc/untar/Makefile.in
@@ -0,0 +1,63 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+top_builddir = ../../../../..
+subdir = c/src/lib/libmisc/untar
+
+INSTALL = @INSTALL@
+
+RTEMS_ROOT = $(top_srcdir)/@RTEMS_TOPdir@
+PROJECT_ROOT = @PROJECT_ROOT@
+
+VPATH = @srcdir@
+
+LIB=${ARCH}/libuntar-tmp.a
+
+# C source names, if any, go here -- minus the .c
+C_PIECES=untar
+C_FILES=$(C_PIECES:%=%.c)
+C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
+
+H_FILES=$(srcdir)/untar.h
+
+SRCS=$(C_FILES) $(H_FILES) $(INSTALLED_H_FILES)
+OBJS=$(C_O_FILES)
+
+include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
+include $(RTEMS_ROOT)/make/lib.cfg
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+DEFINES +=
+CPPFLAGS += -I.
+CFLAGS +=
+
+LD_PATHS +=
+LD_LIBS +=
+LDFLAGS +=
+
+#
+# Add your list of files to delete here. The config files
+# already know how to delete some stuff, so you may want
+# to just run 'make clean' first to see what gets missed.
+# 'make clobber' already includes 'make clean'
+#
+
+CLEAN_ADDITIONS +=
+CLOBBER_ADDITIONS +=
+
+${LIB}: ${SRCS} ${OBJS}
+ $(make-library)
+
+all: ${ARCH} $(SRCS) $(LIB)
+ $(INSTALL_CHANGE) -m 444 ${H_FILES} $(PROJECT_INCLUDE)/rtems
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
diff --git a/c/src/libmisc/untar/untar.c b/c/src/libmisc/untar/untar.c
new file mode 100644
index 0000000000..ea5c1430d2
--- /dev/null
+++ b/c/src/libmisc/untar/untar.c
@@ -0,0 +1,381 @@
+/* FIXME:
+ * 1. Symbolic links are not created.
+ * 2. Untar_FromMemory has printfs.
+ * 3. Untar_FromMemory uses FILE *fp.
+ * 4. How to determine end of archive?
+ *
+ * Written by: Jake Janovetz <janovetz@tempest.ece.uiuc.edu>
+ *
+ * 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "untar.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);
+}
+
+
+/**************************************************************************
+ * Function: Untar_FromMemory *
+ **************************************************************************
+ * Description: *
+ * *
+ * This is a simple subroutine used to rip links, directories, and *
+ * files out of a block of memory. *
+ * *
+ * *
+ * Inputs: *
+ * *
+ * unsigned char *tar_buf - Pointer to TAR buffer. *
+ * unsigned long size - Length of TAR buffer. *
+ * *
+ * *
+ * Output: *
+ * *
+ * int - UNTAR_SUCCESSFUL (0) on successful completion. *
+ * UNTAR_INVALID_CHECKSUM for an invalid header checksum. *
+ * UNTAR_INVALID_HEADER for an invalid header. *
+ * *
+ **************************************************************************
+ * Change History: *
+ * 12/30/1998 - Creation (JWJ) *
+ *************************************************************************/
+int
+Untar_FromMemory(unsigned char *tar_buf, unsigned long size)
+{
+ FILE *fp;
+ char *bufr;
+ size_t n;
+ char fname[100];
+ char linkname[100];
+ int sum;
+ int hdr_chksum;
+ int retval;
+ unsigned long ptr;
+ unsigned long i;
+ unsigned long nblocks;
+ unsigned long file_size;
+ unsigned char linkflag;
+
+
+ ptr = 0;
+ while (1)
+ {
+ if (ptr + 512 > size)
+ {
+ retval = UNTAR_SUCCESSFUL;
+ break;
+ }
+
+ /* Read the header */
+ bufr = &tar_buf[ptr];
+ ptr += 512;
+ if (strncmp(&bufr[257], "ustar ", 7))
+ {
+ retval = UNTAR_SUCCESSFUL;
+ break;
+ }
+
+ strncpy(fname, bufr, MAX_NAME_FIELD_SIZE);
+ fname[MAX_NAME_FIELD_SIZE] = '\0';
+
+ linkflag = bufr[156];
+ file_size = octal2ulong(&bufr[124], 12);
+
+ /******************************************************************
+ * 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.
+ ******************************************************************/
+ hdr_chksum = (int)octal2ulong(&bufr[148], 8);
+ sum = 0;
+ for (i=0; i<512; i++)
+ {
+ if ((i >= 148) && (i < 156))
+ {
+ sum += 0xff & ' ';
+ }
+ else
+ {
+ sum += 0xff & bufr[i];
+ }
+ }
+ if (sum != hdr_chksum)
+ {
+ retval = UNTAR_INVALID_CHECKSUM;
+ break;
+ }
+
+
+ /******************************************************************
+ * We've decoded the header, now figure out what it contains and
+ * do something with it.
+ *****************************************************************/
+ if (linkflag == LF_SYMLINK)
+ {
+ strncpy(linkname, &bufr[157], MAX_NAME_FIELD_SIZE);
+ linkname[MAX_NAME_FIELD_SIZE] = '\0';
+ /* symlink(fname, linkname); */
+ }
+ else if (linkflag == LF_NORMAL)
+ {
+ nblocks = (((file_size) + 511) & ~511) / 512;
+ if ((fp = fopen(fname, "w")) == NULL)
+ {
+ printf("Untar failed to create file %s\n", fname);
+ ptr += 512 * nblocks;
+ }
+ else
+ {
+ unsigned long sizeToGo = file_size;
+ unsigned long len;
+
+ /***************************************************************
+ * Read out the data. There are nblocks of data where nblocks
+ * is the file_size rounded to the nearest 512-byte boundary.
+ **************************************************************/
+ for (i=0; i<nblocks; i++)
+ {
+ len = ((sizeToGo < 512L)?(sizeToGo):(512L));
+ n = fwrite(&tar_buf[ptr], 1, len, fp);
+ if (n != len)
+ {
+ printf("Error during write\n");
+ break;
+ }
+ ptr += 512;
+ sizeToGo -= n;
+ }
+ fclose(fp);
+ }
+ }
+ else if (linkflag == LF_DIR)
+ {
+ mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO);
+ }
+ }
+
+ return(retval);
+}
+
+
+/**************************************************************************
+ * Function: Untar_FromFile *
+ **************************************************************************
+ * Description: *
+ * *
+ * This is a simple subroutine used to rip links, directories, and *
+ * files out of a TAR file. *
+ * *
+ * *
+ * Inputs: *
+ * *
+ * char *tar_name - TAR filename. *
+ * *
+ * *
+ * Output: *
+ * *
+ * int - UNTAR_SUCCESSFUL (0) on successful completion. *
+ * UNTAR_INVALID_CHECKSUM for an invalid header checksum. *
+ * UNTAR_INVALID_HEADER for an invalid header. *
+ * *
+ **************************************************************************
+ * Change History: *
+ * 12/30/1998 - Creation (JWJ) *
+ *************************************************************************/
+int
+Untar_FromFile(char *tar_name)
+{
+ int fd;
+ char *bufr;
+ size_t n;
+ char fname[100];
+ char linkname[100];
+ int sum;
+ int hdr_chksum;
+ int retval;
+ unsigned long i;
+ unsigned long nblocks;
+ unsigned long size;
+ unsigned char linkflag;
+
+
+ retval = UNTAR_SUCCESSFUL;
+ bufr = (char *)malloc(512);
+ if (bufr == NULL)
+ {
+ return(UNTAR_FAIL);
+ }
+
+ fd = open(tar_name, O_RDONLY);
+ while (1)
+ {
+ /* Read the header */
+ /* If the header read fails, we just consider it the end
+ of the tarfile. */
+ if ((n = read(fd, bufr, 512)) != 512)
+ {
+ break;
+ }
+
+ if (strncmp(&bufr[257], "ustar ", 7))
+ {
+ break;
+ }
+
+ strncpy(fname, bufr, MAX_NAME_FIELD_SIZE);
+ fname[MAX_NAME_FIELD_SIZE] = '\0';
+
+ linkflag = bufr[156];
+ size = octal2ulong(&bufr[124], 12);
+
+ /******************************************************************
+ * 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.
+ ******************************************************************/
+ hdr_chksum = (int)octal2ulong(&bufr[148], 8);
+ sum = 0;
+ for (i=0; i<512; i++)
+ {
+ if ((i >= 148) && (i < 156))
+ {
+ sum += 0xff & ' ';
+ }
+ else
+ {
+ sum += 0xff & bufr[i];
+ }
+ }
+ if (sum != hdr_chksum)
+ {
+ retval = UNTAR_INVALID_CHECKSUM;
+ break;
+ }
+
+
+ /******************************************************************
+ * We've decoded the header, now figure out what it contains and
+ * do something with it.
+ *****************************************************************/
+ if (linkflag == LF_SYMLINK)
+ {
+ strncpy(linkname, &bufr[157], MAX_NAME_FIELD_SIZE);
+ linkname[MAX_NAME_FIELD_SIZE] = '\0';
+ }
+ else if (linkflag == LF_NORMAL)
+ {
+ int out_fd;
+
+ /******************************************************************
+ * Read out the data. There are nblocks of data where nblocks
+ * is the size rounded to the nearest 512-byte boundary.
+ *****************************************************************/
+ nblocks = (((size) + 511) & ~511) / 512;
+
+ if ((out_fd = creat(fname, 0644)) == -1)
+ {
+ for (i=0; i<nblocks; i++)
+ {
+ n = read(fd, bufr, 512);
+ }
+ }
+ else
+ {
+ for (i=0; i<nblocks; i++)
+ {
+ n = read(fd, bufr, 512);
+ n = MIN(n, size - i*512);
+ write(out_fd, bufr, n);
+ }
+ close(out_fd);
+ }
+ }
+ else if (linkflag == LF_DIR)
+ {
+ mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO);
+ }
+ }
+ free(bufr);
+ close(fd);
+
+ return(retval);
+}
+
diff --git a/c/src/libmisc/untar/untar.h b/c/src/libmisc/untar/untar.h
new file mode 100644
index 0000000000..d8c5bcfc01
--- /dev/null
+++ b/c/src/libmisc/untar/untar.h
@@ -0,0 +1,25 @@
+/*
+ * Written by: Jake Janovetz <janovetz@tempest.ece.uiuc.edu>
+ *
+ * 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$
+ */
+
+#ifndef __UNTAR_H__
+#define __UNTAR_H__
+
+
+#define UNTAR_SUCCESSFUL 0
+#define UNTAR_FAIL 1
+#define UNTAR_INVALID_CHECKSUM 2
+#define UNTAR_INVALID_HEADER 3
+
+
+int Untar_FromMemory(unsigned char *tar_buf, unsigned long size);
+int Untar_FromFile(char *tar_name);
+
+
+#endif /* __UNTAR_H__ */
diff --git a/c/src/libmisc/wrapup/Makefile.in b/c/src/libmisc/wrapup/Makefile.in
index b43a7c6115..fbba22658a 100644
--- a/c/src/libmisc/wrapup/Makefile.in
+++ b/c/src/libmisc/wrapup/Makefile.in
@@ -23,6 +23,7 @@ include $(RTEMS_ROOT)/make/lib.cfg
# Using the wildcard on the Purify support makes sure it may not be there
LIBS=../monitor/$(ARCH)/libmonitor-tmp.a \
+ ../untar/$(ARCH)/libuntar-tmp.a \
../error/$(ARCH)/liberror-tmp.a \
../assoc/$(ARCH)/libassoc-tmp.a \
../stackchk/$(ARCH)/libstackchk-tmp.a \
diff --git a/cpukit/libmisc/untar/untar.c b/cpukit/libmisc/untar/untar.c
new file mode 100644
index 0000000000..ea5c1430d2
--- /dev/null
+++ b/cpukit/libmisc/untar/untar.c
@@ -0,0 +1,381 @@
+/* FIXME:
+ * 1. Symbolic links are not created.
+ * 2. Untar_FromMemory has printfs.
+ * 3. Untar_FromMemory uses FILE *fp.
+ * 4. How to determine end of archive?
+ *
+ * Written by: Jake Janovetz <janovetz@tempest.ece.uiuc.edu>
+ *
+ * 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "untar.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);
+}
+
+
+/**************************************************************************
+ * Function: Untar_FromMemory *
+ **************************************************************************
+ * Description: *
+ * *
+ * This is a simple subroutine used to rip links, directories, and *
+ * files out of a block of memory. *
+ * *
+ * *
+ * Inputs: *
+ * *
+ * unsigned char *tar_buf - Pointer to TAR buffer. *
+ * unsigned long size - Length of TAR buffer. *
+ * *
+ * *
+ * Output: *
+ * *
+ * int - UNTAR_SUCCESSFUL (0) on successful completion. *
+ * UNTAR_INVALID_CHECKSUM for an invalid header checksum. *
+ * UNTAR_INVALID_HEADER for an invalid header. *
+ * *
+ **************************************************************************
+ * Change History: *
+ * 12/30/1998 - Creation (JWJ) *
+ *************************************************************************/
+int
+Untar_FromMemory(unsigned char *tar_buf, unsigned long size)
+{
+ FILE *fp;
+ char *bufr;
+ size_t n;
+ char fname[100];
+ char linkname[100];
+ int sum;
+ int hdr_chksum;
+ int retval;
+ unsigned long ptr;
+ unsigned long i;
+ unsigned long nblocks;
+ unsigned long file_size;
+ unsigned char linkflag;
+
+
+ ptr = 0;
+ while (1)
+ {
+ if (ptr + 512 > size)
+ {
+ retval = UNTAR_SUCCESSFUL;
+ break;
+ }
+
+ /* Read the header */
+ bufr = &tar_buf[ptr];
+ ptr += 512;
+ if (strncmp(&bufr[257], "ustar ", 7))
+ {
+ retval = UNTAR_SUCCESSFUL;
+ break;
+ }
+
+ strncpy(fname, bufr, MAX_NAME_FIELD_SIZE);
+ fname[MAX_NAME_FIELD_SIZE] = '\0';
+
+ linkflag = bufr[156];
+ file_size = octal2ulong(&bufr[124], 12);
+
+ /******************************************************************
+ * 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.
+ ******************************************************************/
+ hdr_chksum = (int)octal2ulong(&bufr[148], 8);
+ sum = 0;
+ for (i=0; i<512; i++)
+ {
+ if ((i >= 148) && (i < 156))
+ {
+ sum += 0xff & ' ';
+ }
+ else
+ {
+ sum += 0xff & bufr[i];
+ }
+ }
+ if (sum != hdr_chksum)
+ {
+ retval = UNTAR_INVALID_CHECKSUM;
+ break;
+ }
+
+
+ /******************************************************************
+ * We've decoded the header, now figure out what it contains and
+ * do something with it.
+ *****************************************************************/
+ if (linkflag == LF_SYMLINK)
+ {
+ strncpy(linkname, &bufr[157], MAX_NAME_FIELD_SIZE);
+ linkname[MAX_NAME_FIELD_SIZE] = '\0';
+ /* symlink(fname, linkname); */
+ }
+ else if (linkflag == LF_NORMAL)
+ {
+ nblocks = (((file_size) + 511) & ~511) / 512;
+ if ((fp = fopen(fname, "w")) == NULL)
+ {
+ printf("Untar failed to create file %s\n", fname);
+ ptr += 512 * nblocks;
+ }
+ else
+ {
+ unsigned long sizeToGo = file_size;
+ unsigned long len;
+
+ /***************************************************************
+ * Read out the data. There are nblocks of data where nblocks
+ * is the file_size rounded to the nearest 512-byte boundary.
+ **************************************************************/
+ for (i=0; i<nblocks; i++)
+ {
+ len = ((sizeToGo < 512L)?(sizeToGo):(512L));
+ n = fwrite(&tar_buf[ptr], 1, len, fp);
+ if (n != len)
+ {
+ printf("Error during write\n");
+ break;
+ }
+ ptr += 512;
+ sizeToGo -= n;
+ }
+ fclose(fp);
+ }
+ }
+ else if (linkflag == LF_DIR)
+ {
+ mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO);
+ }
+ }
+
+ return(retval);
+}
+
+
+/**************************************************************************
+ * Function: Untar_FromFile *
+ **************************************************************************
+ * Description: *
+ * *
+ * This is a simple subroutine used to rip links, directories, and *
+ * files out of a TAR file. *
+ * *
+ * *
+ * Inputs: *
+ * *
+ * char *tar_name - TAR filename. *
+ * *
+ * *
+ * Output: *
+ * *
+ * int - UNTAR_SUCCESSFUL (0) on successful completion. *
+ * UNTAR_INVALID_CHECKSUM for an invalid header checksum. *
+ * UNTAR_INVALID_HEADER for an invalid header. *
+ * *
+ **************************************************************************
+ * Change History: *
+ * 12/30/1998 - Creation (JWJ) *
+ *************************************************************************/
+int
+Untar_FromFile(char *tar_name)
+{
+ int fd;
+ char *bufr;
+ size_t n;
+ char fname[100];
+ char linkname[100];
+ int sum;
+ int hdr_chksum;
+ int retval;
+ unsigned long i;
+ unsigned long nblocks;
+ unsigned long size;
+ unsigned char linkflag;
+
+
+ retval = UNTAR_SUCCESSFUL;
+ bufr = (char *)malloc(512);
+ if (bufr == NULL)
+ {
+ return(UNTAR_FAIL);
+ }
+
+ fd = open(tar_name, O_RDONLY);
+ while (1)
+ {
+ /* Read the header */
+ /* If the header read fails, we just consider it the end
+ of the tarfile. */
+ if ((n = read(fd, bufr, 512)) != 512)
+ {
+ break;
+ }
+
+ if (strncmp(&bufr[257], "ustar ", 7))
+ {
+ break;
+ }
+
+ strncpy(fname, bufr, MAX_NAME_FIELD_SIZE);
+ fname[MAX_NAME_FIELD_SIZE] = '\0';
+
+ linkflag = bufr[156];
+ size = octal2ulong(&bufr[124], 12);
+
+ /******************************************************************
+ * 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.
+ ******************************************************************/
+ hdr_chksum = (int)octal2ulong(&bufr[148], 8);
+ sum = 0;
+ for (i=0; i<512; i++)
+ {
+ if ((i >= 148) && (i < 156))
+ {
+ sum += 0xff & ' ';
+ }
+ else
+ {
+ sum += 0xff & bufr[i];
+ }
+ }
+ if (sum != hdr_chksum)
+ {
+ retval = UNTAR_INVALID_CHECKSUM;
+ break;
+ }
+
+
+ /******************************************************************
+ * We've decoded the header, now figure out what it contains and
+ * do something with it.
+ *****************************************************************/
+ if (linkflag == LF_SYMLINK)
+ {
+ strncpy(linkname, &bufr[157], MAX_NAME_FIELD_SIZE);
+ linkname[MAX_NAME_FIELD_SIZE] = '\0';
+ }
+ else if (linkflag == LF_NORMAL)
+ {
+ int out_fd;
+
+ /******************************************************************
+ * Read out the data. There are nblocks of data where nblocks
+ * is the size rounded to the nearest 512-byte boundary.
+ *****************************************************************/
+ nblocks = (((size) + 511) & ~511) / 512;
+
+ if ((out_fd = creat(fname, 0644)) == -1)
+ {
+ for (i=0; i<nblocks; i++)
+ {
+ n = read(fd, bufr, 512);
+ }
+ }
+ else
+ {
+ for (i=0; i<nblocks; i++)
+ {
+ n = read(fd, bufr, 512);
+ n = MIN(n, size - i*512);
+ write(out_fd, bufr, n);
+ }
+ close(out_fd);
+ }
+ }
+ else if (linkflag == LF_DIR)
+ {
+ mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO);
+ }
+ }
+ free(bufr);
+ close(fd);
+
+ return(retval);
+}
+
diff --git a/cpukit/libmisc/untar/untar.h b/cpukit/libmisc/untar/untar.h
new file mode 100644
index 0000000000..d8c5bcfc01
--- /dev/null
+++ b/cpukit/libmisc/untar/untar.h
@@ -0,0 +1,25 @@
+/*
+ * Written by: Jake Janovetz <janovetz@tempest.ece.uiuc.edu>
+ *
+ * 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$
+ */
+
+#ifndef __UNTAR_H__
+#define __UNTAR_H__
+
+
+#define UNTAR_SUCCESSFUL 0
+#define UNTAR_FAIL 1
+#define UNTAR_INVALID_CHECKSUM 2
+#define UNTAR_INVALID_HEADER 3
+
+
+int Untar_FromMemory(unsigned char *tar_buf, unsigned long size);
+int Untar_FromFile(char *tar_name);
+
+
+#endif /* __UNTAR_H__ */