Index: c/src/lib/libmisc/Makefile.in
===================================================================
--- c/src/lib/libmisc/Makefile.in	(revision 01a9d941b32deade4225b410911f8ee76a9f0762)
+++ c/src/lib/libmisc/Makefile.in	(revision b08d3ed989cf3d4fc8ecf49e2f6781c612edb6d2)
@@ -19,5 +19,5 @@
 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
Index: c/src/lib/libmisc/untar/Makefile.in
===================================================================
--- c/src/lib/libmisc/untar/Makefile.in	(revision b08d3ed989cf3d4fc8ecf49e2f6781c612edb6d2)
+++ c/src/lib/libmisc/untar/Makefile.in	(revision b08d3ed989cf3d4fc8ecf49e2f6781c612edb6d2)
@@ -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
Index: c/src/lib/libmisc/untar/untar.c
===================================================================
--- c/src/lib/libmisc/untar/untar.c	(revision b08d3ed989cf3d4fc8ecf49e2f6781c612edb6d2)
+++ c/src/lib/libmisc/untar/untar.c	(revision b08d3ed989cf3d4fc8ecf49e2f6781c612edb6d2)
@@ -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);
+}
+
Index: c/src/lib/libmisc/untar/untar.h
===================================================================
--- c/src/lib/libmisc/untar/untar.h	(revision b08d3ed989cf3d4fc8ecf49e2f6781c612edb6d2)
+++ c/src/lib/libmisc/untar/untar.h	(revision b08d3ed989cf3d4fc8ecf49e2f6781c612edb6d2)
@@ -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__ */
Index: c/src/lib/libmisc/wrapup/Makefile.in
===================================================================
--- c/src/lib/libmisc/wrapup/Makefile.in	(revision 01a9d941b32deade4225b410911f8ee76a9f0762)
+++ c/src/lib/libmisc/wrapup/Makefile.in	(revision b08d3ed989cf3d4fc8ecf49e2f6781c612edb6d2)
@@ -24,4 +24,5 @@
 
 LIBS=../monitor/$(ARCH)/libmonitor-tmp.a \
+     ../untar/$(ARCH)/libuntar-tmp.a \
      ../error/$(ARCH)/liberror-tmp.a \
      ../assoc/$(ARCH)/libassoc-tmp.a \
Index: c/src/libmisc/untar/Makefile.in
===================================================================
--- c/src/libmisc/untar/Makefile.in	(revision b08d3ed989cf3d4fc8ecf49e2f6781c612edb6d2)
+++ c/src/libmisc/untar/Makefile.in	(revision b08d3ed989cf3d4fc8ecf49e2f6781c612edb6d2)
@@ -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
Index: c/src/libmisc/untar/untar.c
===================================================================
--- c/src/libmisc/untar/untar.c	(revision b08d3ed989cf3d4fc8ecf49e2f6781c612edb6d2)
+++ c/src/libmisc/untar/untar.c	(revision b08d3ed989cf3d4fc8ecf49e2f6781c612edb6d2)
@@ -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);
+}
+
Index: c/src/libmisc/untar/untar.h
===================================================================
--- c/src/libmisc/untar/untar.h	(revision b08d3ed989cf3d4fc8ecf49e2f6781c612edb6d2)
+++ c/src/libmisc/untar/untar.h	(revision b08d3ed989cf3d4fc8ecf49e2f6781c612edb6d2)
@@ -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__ */
Index: c/src/libmisc/wrapup/Makefile.in
===================================================================
--- c/src/libmisc/wrapup/Makefile.in	(revision 01a9d941b32deade4225b410911f8ee76a9f0762)
+++ c/src/libmisc/wrapup/Makefile.in	(revision b08d3ed989cf3d4fc8ecf49e2f6781c612edb6d2)
@@ -24,4 +24,5 @@
 
 LIBS=../monitor/$(ARCH)/libmonitor-tmp.a \
+     ../untar/$(ARCH)/libuntar-tmp.a \
      ../error/$(ARCH)/liberror-tmp.a \
      ../assoc/$(ARCH)/libassoc-tmp.a \
Index: cpukit/libmisc/untar/untar.c
===================================================================
--- cpukit/libmisc/untar/untar.c	(revision b08d3ed989cf3d4fc8ecf49e2f6781c612edb6d2)
+++ cpukit/libmisc/untar/untar.c	(revision b08d3ed989cf3d4fc8ecf49e2f6781c612edb6d2)
@@ -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);
+}
+
Index: cpukit/libmisc/untar/untar.h
===================================================================
--- cpukit/libmisc/untar/untar.h	(revision b08d3ed989cf3d4fc8ecf49e2f6781c612edb6d2)
+++ cpukit/libmisc/untar/untar.h	(revision b08d3ed989cf3d4fc8ecf49e2f6781c612edb6d2)
@@ -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__ */
