From b08d3ed989cf3d4fc8ecf49e2f6781c612edb6d2 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Tue, 6 Apr 1999 21:45:06 +0000 Subject: Untar support submitted by Jake Janovetz . --- c/src/lib/libmisc/Makefile.in | 2 +- c/src/lib/libmisc/untar/Makefile.in | 63 ++++++ c/src/lib/libmisc/untar/untar.c | 381 +++++++++++++++++++++++++++++++++++ c/src/lib/libmisc/untar/untar.h | 25 +++ c/src/lib/libmisc/wrapup/Makefile.in | 1 + c/src/libmisc/untar/Makefile.in | 63 ++++++ c/src/libmisc/untar/untar.c | 381 +++++++++++++++++++++++++++++++++++ c/src/libmisc/untar/untar.h | 25 +++ c/src/libmisc/wrapup/Makefile.in | 1 + 9 files changed, 941 insertions(+), 1 deletion(-) create mode 100644 c/src/lib/libmisc/untar/Makefile.in create mode 100644 c/src/lib/libmisc/untar/untar.c create mode 100644 c/src/lib/libmisc/untar/untar.h create mode 100644 c/src/libmisc/untar/Makefile.in create mode 100644 c/src/libmisc/untar/untar.c create mode 100644 c/src/libmisc/untar/untar.h (limited to 'c') 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 + * + * 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 "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= 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 + * + * 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 + * + * 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 "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= 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 + * + * 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 \ -- cgit v1.2.3