bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Packaging Hurd translators for Debian


From: Manuel Menal
Subject: Re: Packaging Hurd translators for Debian
Date: Mon, 20 Sep 2010 22:24:06 +0200
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.12) Gecko/20100918 Icedove/3.0.8

Hi,

On 19/09/2010 03:08, Samuel Thibault wrote:
> Samuel Thibault, le Sun 19 Sep 2010 03:00:31 +0200, a écrit :
>> I have pushed debian packagings for gopherfs, netio, and tarfs to
>> pkg-hurd, and uploaded them to debian-ports.

> I forgot to say: unfortunately, it seems gopherfs and tarfs don't work
> atm.

Here is a patch that fixes tarfs. It's mostly updating the code taken
from mc (tweaked a little bit to remove mc-specific parts and to
integrate with tarfs). With this patch, it seems to be working fine
(read/write and with bzip2/gzip files).

diff -Nurp orig/tarfs-0.0.20100918/tar.c tarfs-0.0.20100918/tar.c
--- orig/tarfs-0.0.20100918/tar.c       2010-09-19 02:39:04.000000000 +0200
+++ tarfs-0.0.20100918/tar.c    2010-09-20 22:07:32.000000000 +0200
@@ -1,5 +1,6 @@
 /* GNU tar files parsing.
-   Copyright (C) 1995 The Free Software Foundation
+   Copyright (C) 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+   2006, 2007 Free Software Foundation, Inc.

    Written by: 1995 Jakub Jelinek
    Rewritten by: 1998 Pavel Machek
@@ -39,7 +40,7 @@
 #include "debug.h"

 /* A hook which is called each time a header has been parsed. */
-int (*tar_header_hook) (tar_record_t *, off_t) = NULL;
+int (*tar_header_hook) (tar_record_t *, struct archive *) = NULL;

 
 #define        isodigit(c)     ( ((c) >= '0') && ((c) <= '7') )
@@ -48,141 +49,102 @@ int (*tar_header_hook) (tar_record_t *,
 # define isspace(c)      ( (c) == ' ' )
 #endif

+/* Taken from glibc. */
+char *
+strconcat (const char *string1, ...)
+{
+  size_t l;
+  va_list args;
+  char *s;
+  char *concat;
+  char *ptr;
+
+  if (!string1)
+    return NULL;
+
+  l = 1 + strlen (string1);
+  va_start (args, string1);
+  s = va_arg (args, char *);
+  while (s)
+    {
+      l += strlen (s);
+      s = va_arg (args, char *);
+    }
+  va_end (args);
+
+  concat = malloc (l);
+  ptr = concat;
+
+  ptr = stpcpy (ptr, string1);
+  va_start (args, string1);
+  s = va_arg (args, char *);
+  while (s)
+    {
+      ptr = stpcpy (ptr, s);
+      s = va_arg (args, char *);
+    }
+  va_end (args);
+
+  return concat;
+}
+
 /*
  * Quick and dirty octal conversion.
  *
  * Result is -1 if the field is invalid (all blank, or nonoctal).
  */
-static long
-from_oct (int digs, char *where)
+static long tar_from_oct (int digs, char *where)
 {
-  register long value;
+    register long value;

-  while (isspace (*where))
-    {                          /* Skip spaces */
-      where++;
-      if (--digs <= 0)
-       return -1;              /* All blank field */
+    while (isspace ((unsigned char) *where)) { /* Skip spaces */
+       where++;
+       if (--digs <= 0)
+           return -1;          /* All blank field */
     }
-  value = 0;
-  while (digs > 0 && isodigit (*where))
-    {                          /* Scan till nonoctal */
-      value = (value << 3) | (*where++ - '0');
-      --digs;
+    value = 0;
+    while (digs > 0 && isodigit (*where)) {    /* Scan till nonoctal */
+       value = (value << 3) | (*where++ - '0');
+       --digs;
     }

-  if (digs > 0 && *where && !isspace (*where))
-    return -1;                 /* Ended on non-space/nul */
+    if (digs > 0 && *where && !isspace ((unsigned char) *where))
+       return -1;              /* Ended on non-space/nul */

-  return value;
+    return value;
 }

-/* As we open one archive at a time, it is safe to have this static */
-static store_offset_t current_tar_position = 0;
-
-static tar_record_t rec_buf;

-
-static tar_record_t *
-get_next_record (struct store *tar_file)
+static union record *
+tar_get_next_record (struct archive *archive)
 {
-  error_t err;
-  size_t n;
-  void *buf;
-
-  debug (("Reading at offset %lli", current_tar_position));
-  buf = rec_buf.charptr;
-  err = store_read (tar_file, current_tar_position, RECORDSIZE, &buf, &n);
-
-  if (err)
-    error (1, err, "Read error (offset=%lli)", current_tar_position);
-  assert (n <= RECORDSIZE);
+    error_t err;
+    void *buf = NULL;
+    size_t n = 0;
+
+    err = store_read (archive->tar_file, archive->current_tar_position,
RECORDSIZE, &buf, &n);
+    if (err)
+      error (1, err, "Read error (offset=%lli)",
archive->current_tar_position);
+    if (n != RECORDSIZE)
+      return NULL;             /* An error has occurred */
+
+    if (buf != archive->rec_buf.charptr)
+      {
+       memcpy (archive->rec_buf.charptr, buf, n);
+       munmap (buf, n);
+      }

-  if (buf != rec_buf.charptr)
-    {
-      memcpy (rec_buf.charptr, buf, n);
-      munmap (buf, n);
-    }
-
-  if (n != RECORDSIZE)
-    return NULL;               /* An error has occurred */
+    archive->current_tar_position += RECORDSIZE;

-  current_tar_position += n;
-
-  return &rec_buf;
+    return &(archive->rec_buf);
 }

-static void
-skip_n_records (struct store *tar_file, int n)
+static void tar_skip_n_records (struct archive *archive, int n)
 {
-  current_tar_position += n * RECORDSIZE;
-}
-
-void
-tar_header2stat (io_statbuf_t *st, tar_record_t *header)
-{
-  st->st_mode = from_oct (8, header->header.mode);
-
-  /* Adjust st->st_mode because there are tar-files with
-   * linkflag==LF_SYMLINK and S_ISLNK(mod)==0. I don't
-   * know about the other modes but I think I cause no new
-   * problem when I adjust them, too. -- Norbert.
-   */
-  if (header->header.linkflag == LF_DIR)
-    {
-      st->st_mode |= S_IFDIR;
-    }
-  else if (header->header.linkflag == LF_SYMLINK)
-    {
-      st->st_mode |= S_IFLNK;
-    }
-  else if (header->header.linkflag == LF_CHR)
-    {
-      st->st_mode |= S_IFCHR;
-    }
-  else if (header->header.linkflag == LF_BLK)
-    {
-      st->st_mode |= S_IFBLK;
-    }
-  else if (header->header.linkflag == LF_FIFO)
-    {
-      st->st_mode |= S_IFIFO;
-    }
-  else
-    st->st_mode |= S_IFREG;
-
-  st->st_rdev = 0;
-  if (!strcmp (header->header.magic, TMAGIC))
-    {
-      st->st_uid = *header->header.uname ? finduid (header->header.uname) :
-       from_oct (8, header->header.uid);
-      st->st_gid = *header->header.gname ? findgid (header->header.gname) :
-       from_oct (8, header->header.gid);
-      switch (header->header.linkflag)
-       {
-       case LF_BLK:
-       case LF_CHR:
-         st->st_rdev = (from_oct (8, header->header.devmajor) << 8) |
-           from_oct (8, header->header.devminor);
-       }
-    }
-  else
-    {                          /* Old Unix tar */
-      st->st_uid = from_oct (8, header->header.uid);
-      st->st_gid = from_oct (8, header->header.gid);
-    }
-  //st->st_size = hstat.st_size;
-  st->st_size  = from_oct (1 + 12, header->header.size);
-  if (st->st_size > 0)
-    st->st_blocks = ((st->st_size - 1) / 512) + 1;
-  else
-    st->st_blocks = 0;
-  st->st_mtime = from_oct (1 + 12, header->header.mtime);
-  st->st_atime = from_oct (1 + 12, header->header.atime);
-  st->st_ctime = from_oct (1 + 12, header->header.ctime);
+    (void) archive;
+    archive->current_tar_position += n * RECORDSIZE;
 }

-
 typedef enum
 {
   STATUS_BADCHECKSUM,
@@ -197,153 +159,282 @@ ReadStatus;
  *
  */
 static ReadStatus
-read_header (struct store *tar_file)
+tar_read_header (struct archive *archive, size_t *h_size)
 {
-  register int i;
-  register long sum, signed_sum, recsum;
-  register char *p;
-  register tar_record_t *header;
-  char *data;
-  int size, written;
-  static char *next_lonname = NULL, *next_lonlink = NULL;
-  char *current_file_name, *current_link_name;
-  struct stat hstat;           /* Stat struct corresponding */
-  char arch_name[NAMSIZ + 1];
-  char arch_linkname[NAMSIZ + 1];
-
-  memcpy (arch_name, header->header.arch_name, NAMSIZ);
-  arch_name [NAMSIZ] = '\0';
-  memcpy (arch_linkname, header->header.arch_linkname, NAMSIZ);
-  arch_linkname [NAMSIZ] = '\0';
-
-
-recurse:
-
-  header = get_next_record (tar_file);
-  if (NULL == header)
-    return STATUS_EOF;
-
-  recsum = from_oct (8, header->header.chksum);
-
-  sum = 0;
-  signed_sum = 0;
-  p = header->charptr;
-  for (i = sizeof (*header); --i >= 0;)
-    {
-      /*
-       * We can't use unsigned char here because of old compilers,
-       * e.g. V7.
-       */
-      signed_sum += *p;
-      sum += 0xFF & *p++;
-    }
-
-  /* Adjust checksum to count the "chksum" field as blanks. */
-  for (i = sizeof (header->header.chksum); --i >= 0;)
-    {
-      sum -= 0xFF & header->header.chksum[i];
-      signed_sum -= (char) header->header.chksum[i];
+    register int i;
+    register long sum, signed_sum, recsum;
+    register char *p;
+    register union record *header;
+    static char *next_long_name = NULL, *next_long_link = NULL;
+
+  recurse:
+
+    header = tar_get_next_record (archive);
+    if (NULL == header)
+       return STATUS_EOF;
+
+    recsum = tar_from_oct (8, header->header.chksum);
+
+    sum = 0;
+    signed_sum = 0;
+    p = header->charptr;
+    for (i = sizeof (*header); --i >= 0;) {
+       /*
+        * We can't use unsigned char here because of old compilers,
+        * e.g. V7.
+        */
+       signed_sum += *p;
+       sum += 0xFF & *p++;
+    }
+
+    /* Adjust checksum to count the "chksum" field as blanks. */
+    for (i = sizeof (header->header.chksum); --i >= 0;) {
+       sum -= 0xFF & header->header.chksum[i];
+       signed_sum -= (char) header->header.chksum[i];
+    }
+    sum += ' ' * sizeof header->header.chksum;
+    signed_sum += ' ' * sizeof header->header.chksum;
+
+    /*
+     * This is a zeroed record...whole record is 0's except
+     * for the 8 blanks we faked for the checksum field.
+     */
+    if (sum == 8 * ' ')
+       return STATUS_EOFMARK;
+
+    if (sum != recsum && signed_sum != recsum)
+       return STATUS_BADCHECKSUM;
+
+    /*
+     * Try to determine the archive format.
+     */
+    if (archive->type == TAR_UNKNOWN) {
+       if (!strcmp (header->header.magic, TMAGIC)) {
+           if (header->header.linkflag == LF_GLOBAL_EXTHDR)
+               archive->type = TAR_POSIX;
+           else
+               archive->type = TAR_USTAR;
+       } else if (!strcmp (header->header.magic, OLDGNU_MAGIC)) {
+           archive->type = TAR_GNU;
+       }
     }
-  sum += ' ' * sizeof header->header.chksum;
-  signed_sum += ' ' * sizeof header->header.chksum;

-  /*
-   * This is a zeroed record...whole record is 0's except
-   * for the 8 blanks we faked for the checksum field.
-   */
-  if (sum == 8 * ' ')
-    return STATUS_EOFMARK;
-
-  if (sum != recsum && signed_sum != recsum)
-    return STATUS_BADCHECKSUM;
-
-  /*
-   * linkflag on BSDI tar (pax) always '\000'
-   */
-
-  if (header->header.linkflag == '\000' &&
-      strlen (arch_name) &&
-      arch_name[strlen (arch_name) - 1] == '/')
-    header->header.linkflag = LF_DIR;
+    /*
+     * linkflag on BSDI tar (pax) always '\000'
+     */
+    if (header->header.linkflag == '\000') {
+       if (header->header.arch_name[NAMSIZ - 1] != '\0')
+           i = NAMSIZ;
+       else
+           i = strlen (header->header.arch_name);
+
+       if (i && header->header.arch_name[i - 1] == '/')
+           header->header.linkflag = LF_DIR;
+    }
+
+    /*
+     * Good record.  Decode file size and return.
+     */
+    if (header->header.linkflag == LF_LINK
+       || header->header.linkflag == LF_DIR)
+       *h_size = 0;            /* Links 0 size on tape */
+    else
+       *h_size = tar_from_oct (1 + 12, header->header.size);
+
+    /*
+     * Skip over directory snapshot info records that
+     * are stored in incremental tar archives.
+     */
+    if (header->header.linkflag == LF_DUMPDIR) {
+       if (archive->type == TAR_UNKNOWN)
+           archive->type = TAR_GNU;
+       return STATUS_SUCCESS;
+    }
+
+    /*
+     * Skip over pax extended header and global extended
+     * header records.
+     */
+    if (header->header.linkflag == LF_EXTHDR ||
+       header->header.linkflag == LF_GLOBAL_EXTHDR) {
+       if (archive->type == TAR_UNKNOWN)
+           archive->type = TAR_POSIX;
+       return STATUS_SUCCESS;
+    }
+
+    if (header->header.linkflag == LF_LONGNAME
+       || header->header.linkflag == LF_LONGLINK) {
+       char **longp;
+       char *bp, *data;
+       int size, written;
+
+       if (archive->type == TAR_UNKNOWN)
+           archive->type = TAR_GNU;
+
+       longp = ((header->header.linkflag == LF_LONGNAME)
+                ? &next_long_name : &next_long_link);
+
+       free (*longp);
+       bp = *longp = malloc (*h_size + 1);
+
+       for (size = *h_size; size > 0; size -= written) {
+           data = tar_get_next_record (archive)->charptr;
+           if (data == NULL) {
+               free (*longp);
+               *longp = NULL;
+               error (0, 0, "Unexpected EOF on archive file");
+               return STATUS_BADCHECKSUM;
+           }
+           written = RECORDSIZE;
+           if (written > size)
+               written = size;

-  /*
-   * Good record.  Decode file size and return.
-   */
-  if (header->header.linkflag == LF_LINK || header->header.linkflag ==
LF_DIR)
-    hstat.st_size = 0;         /* Links 0 size on tape */
-  else
-    hstat.st_size = from_oct (1 + 12, header->header.size);
+           memcpy (bp, data, written);
+           bp += written;
+       }

-  if (header->header.linkflag == LF_LONGNAME
-      || header->header.linkflag == LF_LONGLINK)
-    {
-      for (size = hstat.st_size; size > 0; size -= written)
-       {
-         data = get_next_record (tar_file)->charptr;
-         if (data == NULL)
-           {
-             error (0, 0, "Unexpected EOF on archive file");
-             return STATUS_BADCHECKSUM;
+       *bp = 0;
+       goto recurse;
+    } else {
+       long data_position;
+       char *q;
+       int len;
+       char *current_file_name, *current_link_name;
+
+       current_link_name =
+           (next_long_link ? next_long_link :
+            strndup (header->header.arch_linkname, NAMSIZ));
+       len = strlen (current_link_name);
+       if (len > 1 && current_link_name[len - 1] == '/')
+           current_link_name[len - 1] = 0;
+
+       current_file_name = NULL;
+       switch (archive->type) {
+       case TAR_USTAR:
+       case TAR_POSIX:
+           /* The ustar archive format supports pathnames of upto 256
+            * characters in length. This is achieved by concatenating
+            * the contents of the `prefix' and `arch_name' fields like
+            * this:
+            *
+            *   prefix + path_separator + arch_name
+            *
+            * If the `prefix' field contains an empty string i.e. its
+            * first characters is '\0' the prefix field is ignored.
+            */
+           if (header->header.unused.prefix[0] != '\0') {
+               char *temp_name, *temp_prefix;
+
+               temp_name = strndup (header->header.arch_name, NAMSIZ);
+               temp_prefix  = strndup (header->header.unused.prefix,
+                                       PREFIX_SIZE);
+               current_file_name = strconcat (temp_prefix, "/",
+                                              temp_name, (char *) NULL);
+               free (temp_name);
+               free (temp_prefix);
            }
-         written = RECORDSIZE;
-         if (written > size)
-           written = size;
-       }
-      goto recurse;
-    }
-  else
-    {
-      long data_position;
-      char *p, *q;
-      int len;
-      int isdir = 0;
-
-      current_file_name = (next_lonname
-                          ? next_lonname
-                          : strdup (arch_name));
-      len = strlen (current_file_name);
-      if (current_file_name[len - 1] == '/')
-       {
-         current_file_name[len - 1] = 0;
-         isdir = 1;
+           break;
+       case TAR_GNU:
+           if (next_long_name != NULL)
+               current_file_name = next_long_name;
+           break;
+       default:
+           break;
        }

+       if (current_file_name == NULL)
+           current_file_name = strndup (header->header.arch_name, NAMSIZ);

-      current_link_name = (next_lonlink
-                          ? next_lonlink
-                          : strdup (arch_linkname));
-      len = strlen (current_link_name);
-      if (len && current_link_name[len - 1] == '/')
-       current_link_name[len - 1] = 0;
-
-      next_lonlink = next_lonname = NULL;
-
-      data_position = current_tar_position;
-
-      p = strrchr (current_file_name, '/');
-      if (p == NULL)
-       {
-         p = current_file_name;
-         q = current_file_name + strlen (current_file_name);   /* "" */
-       }
-      else
-       {
-         *(p++) = 0;
-         q = current_file_name;
+       len = strlen (current_file_name);
+
+       data_position = archive->current_tar_position;
+
+       p = strrchr (current_file_name, '/');
+       if (p == NULL) {
+           p = current_file_name;
+           q = current_file_name + len;        /* "" */
+       } else {
+           *(p++) = 0;
+           q = current_file_name;
        }

-      if (tar_header_hook)
-       tar_header_hook (header, current_tar_position);
+       if (tar_header_hook)
+         tar_header_hook (header, archive);
+
+       free (current_file_name);
+
+       /*    done:*/
+       next_long_link = next_long_name = NULL;
+
+       if (archive->type == TAR_GNU &&
+           header->header.unused.oldgnu.isextended) {
+           while (tar_get_next_record (archive)->ext_hdr.
+                  isextended);
+       }
+       return STATUS_SUCCESS;
+    }
+}

-      free (current_file_name);
+void
+tar_fill_stat (struct archive *archive, struct stat *st, tar_record_t
*header)
+{
+    st->st_mode = tar_from_oct (8, header->header.mode);

-/*    done: */
-      if (header->header.isextended)
-       {
-         while (get_next_record (tar_file)->ext_hdr.isextended);
+    /* Adjust st->st_mode because there are tar-files with
+     * linkflag==LF_SYMLINK and S_ISLNK(mod)==0. I don't
+     * know about the other modes but I think I cause no new
+     * problem when I adjust them, too. -- Norbert.
+     */
+    if (header->header.linkflag == LF_DIR) {
+       st->st_mode |= S_IFDIR;
+    } else if (header->header.linkflag == LF_SYMLINK) {
+       st->st_mode |= S_IFLNK;
+    } else if (header->header.linkflag == LF_CHR) {
+       st->st_mode |= S_IFCHR;
+    } else if (header->header.linkflag == LF_BLK) {
+       st->st_mode |= S_IFBLK;
+    } else if (header->header.linkflag == LF_FIFO) {
+       st->st_mode |= S_IFIFO;
+    } else
+       st->st_mode |= S_IFREG;
+
+    st->st_rdev = 0;
+    switch (archive->type) {
+    case TAR_USTAR:
+    case TAR_POSIX:
+    case TAR_GNU:
+       st->st_uid =
+           *header->header.uname ? finduid (header->header.
+                                                uname) : tar_from_oct (8,
+                                                                       header->
+                                                                       header.
+                                                                       uid);
+       st->st_gid =
+           *header->header.gname ? findgid (header->header.
+                                                gname) : tar_from_oct (8,
+                                                                       header->
+                                                                       header.
+                                                                       gid);
+       switch (header->header.linkflag) {
+       case LF_BLK:
+       case LF_CHR:
+           st->st_rdev =
+               (tar_from_oct (8, header->header.devmajor) << 8) |
+               tar_from_oct (8, header->header.devminor);
        }
-      skip_n_records (tar_file, (hstat.st_size + RECORDSIZE - 1) /
RECORDSIZE);
-      return STATUS_SUCCESS;
+    default:
+       st->st_uid = tar_from_oct (8, header->header.uid);
+       st->st_gid = tar_from_oct (8, header->header.gid);
+    }
+    st->st_size = tar_from_oct (1 + 12, header->header.size);
+    st->st_mtime = tar_from_oct (1 + 12, header->header.mtime);
+    st->st_atime = 0;
+    st->st_ctime = 0;
+    if (archive->type == TAR_GNU) {
+       st->st_atime = tar_from_oct (1 + 12,
+                                    header->header.unused.oldgnu.atime);
+       st->st_ctime = tar_from_oct (1 + 12,
+                                    header->header.unused.oldgnu.ctime);
     }
 }

@@ -354,77 +445,65 @@ recurse:
 int
 tar_open_archive (struct store *tar_file)
 {
-  ReadStatus status = STATUS_EOFMARK;  /* Initial status at start of
archive */
-  ReadStatus prev_status = STATUS_SUCCESS;
+    /* Initial status at start of archive */
+    ReadStatus status = STATUS_EOFMARK;
+    ReadStatus prev_status;
+
+    struct archive archive;
+    archive.tar_file = tar_file;
+    archive.current_tar_position = 0;
+    archive.type = TAR_UNKNOWN;

-  current_tar_position = 0;
-
-  for (;;)
-    {
-      prev_status = status;
-      status = read_header (tar_file);
+    for (;;) {
+       size_t h_size;

+       prev_status = status;
+       status = tar_read_header (&archive, &h_size);

-      switch (status)
-       {
+       switch (status) {

        case STATUS_SUCCESS:
-         continue;
-
-         /*
-          * Invalid header:
-          *
-          * If the previous header was good, tell them
-          * that we are skipping bad ones.
-          */
+           tar_skip_n_records (&archive,
+                               (h_size + RECORDSIZE -
+                                1) / RECORDSIZE);
+           continue;
+
+           /*
+            * Invalid header:
+            *
+            * If the previous header was good, tell them
+            * that we are skipping bad ones.
+            */
        case STATUS_BADCHECKSUM:
-         switch (prev_status)
-           {
+           switch (prev_status) {

-             /* Error on first record */
+               /* Error on first record */
            case STATUS_EOFMARK:
-             return -1;
-             /* FALL THRU */
+               /* FALL THRU */

-             /* Error after header rec */
+               /* Error after header rec */
            case STATUS_SUCCESS:
-             prev_status = status;
-             {
-               /* FIXME: Bad hack */
-               size_t size;
-               tar_record_t *hdr;
-               current_tar_position -= RECORDSIZE;
-               error (0, 0, "Skipping to next header (offset=%lli)",
-                      current_tar_position);
-               hdr = get_next_record (tar_file);
-               size = from_oct (8, hdr->header.size);
-               size = size % RECORDSIZE
-                      ? size / RECORDSIZE
-                      : (size / RECORDSIZE) + RECORDSIZE;
-               current_tar_position += size;
-             }
-       
-             /* Error after error */
+               /* Error after error */

            case STATUS_BADCHECKSUM:
-             error (1, 0, "Bad checksum (offset=%lli)", current_tar_position);
-             return -1;
+               return -1;

            case STATUS_EOF:
-             return 0;
+               return 0;
            }

-         /* Record of zeroes */
+           /* Record of zeroes */
        case STATUS_EOFMARK:
-         status = prev_status; /* If error after 0's */
-         /* FALL THRU */
+           status = prev_status;       /* If error after 0's */
+           /* FALL THRU */

        case STATUS_EOF:        /* End of archive */
-         break;
+           break;
        }
-      break;
+       break;
     };
-  return 0;
+
+    return 0;
 }

 
@@ -497,7 +576,7 @@ tar_make_header (tar_record_t *header, i
   else
     header->header.linkflag = LF_NORMAL;

-  strncpy (header->header.magic, TMAGIC, TMAGLEN);
+  strncpy (header->header.magic, TMAGIC, strlen(TMAGIC));

   uid_to_uname (st->st_uid, header->header.uname);
   gid_to_gname (st->st_gid, header->header.gname);
diff -Nurp orig/tarfs-0.0.20100918/tar.h tarfs-0.0.20100918/tar.h
--- orig/tarfs-0.0.20100918/tar.h       2010-09-19 02:39:04.000000000 +0200
+++ tarfs-0.0.20100918/tar.h    2010-09-20 18:58:12.000000000 +0200
@@ -33,6 +33,14 @@
 #include <sys/mknod.h>
 #endif

+enum {
+    TAR_UNKNOWN = 0,
+    TAR_V7,
+    TAR_USTAR,
+    TAR_POSIX,
+    TAR_GNU
+};
+
 /*
  * Header block on tape.
  *
@@ -43,6 +51,7 @@
  */
 #define        RECORDSIZE      512
 #define        NAMSIZ          100
+#define        PREFIX_SIZE     155
 #define        TUNMLEN         32
 #define        TGNMLEN         32
 #define SPARSE_EXT_HDR  21
@@ -75,20 +84,27 @@ union record {
        char gname[TGNMLEN];
        char devmajor[8];
        char devminor[8];
-       /* these following fields were added by JF for gnu */
-       /* and are NOT standard */
-       char atime[12];
-       char ctime[12];
-       char offset[12];
-       char longnames[4];
-#ifdef NEEDPAD
-       char pad;
-#endif
-       struct sparse sp[SPARSE_IN_HDR];
-       char isextended;
-       char realsize[12];      /* true size of the sparse file */
-       /* char ending_blanks[12];*//* number of nulls at the
-          end of the file, if any */
+       /* The following bytes of the tar header record were originally unused.
+       
+          Archives following the ustar specification use almost all of those
+          bytes to support pathnames of 256 characters in length.
+
+          GNU tar archives use the "unused" space to support incremental
+          archives and sparse files. */
+       union unused {
+           char prefix[PREFIX_SIZE];
+           /* GNU extensions to the ustar (POSIX.1-1988) archive format. */
+           struct oldgnu {
+               char atime[12];
+               char ctime[12];
+               char offset[12];
+               char longnames[4];
+               char pad;
+               struct sparse sp[SPARSE_IN_HDR];
+               char isextended;
+               char realsize[12];      /* true size of the sparse file */
+           } oldgnu;
+       } unused;
     } header;
     struct extended_header {
        struct sparse sp[21];
@@ -100,10 +116,8 @@ union record {
 #define        CHKBLANKS       "        "      /* 8 blanks, no null */

 /* The magic field is filled with this if uname and gname are valid. */
-#define        TMAGIC          "ustar  "       /* 7 chars and a null */
-#define TMAGLEN  6
-#define TVERSION "00"          /* 00 and no null */
-#define TVERSLEN 2
+#define        TMAGIC          "ustar"         /* ustar and a null */
+#define        OLDGNU_MAGIC    "ustar  "       /* 7 chars and a null */

 /* The linkflag defines the type of file */
 #define        LF_OLDNORMAL    '\0'    /* Normal disk file, Unix compat */
@@ -115,6 +129,8 @@ union record {
 #define        LF_DIR          '5'     /* Directory */
 #define        LF_FIFO         '6'     /* FIFO special file */
 #define        LF_CONTIG       '7'     /* Contiguous file */
+#define        LF_EXTHDR       'x'     /* pax Extended Header */
+#define        LF_GLOBAL_EXTHDR 'g'    /* pax Global Extended Header */
 /* Further link types may be defined later. */

 /* Note that the standards committee allows only capital A through
@@ -137,8 +153,6 @@ union record {
 #define LF_VOLHDR      'V'     /* This file is a tape/volume header */
 /* Ignore it on extraction */

-#define LF_TRANS        'T'    /* GNU/Hurd passive translator */
-
 /*
  * Exit codes from the "tar" program
  */
@@ -151,6 +165,8 @@ union record {
                                   Tape volume doesn't match the one
                                   specified on the command line */

+#define        isodigit(c)     ( ((c) >= '0') && ((c) <= '7') )
+
 /*
  * We default to Unix Standard format rather than 4.2BSD tar format.
  * The code can actually produce all three:
@@ -171,8 +187,15 @@ union record {

 typedef union record tar_record_t;

+struct archive {
+  struct store *tar_file;
+  int type;
+  store_offset_t current_tar_position;
+  tar_record_t rec_buf;
+};
+
 extern int  tar_open_archive (struct store *tar_file);
-extern void tar_header2stat (io_statbuf_t *st, tar_record_t *header);
+extern void tar_fill_stat (struct archive *archive, io_statbuf_t *st,
tar_record_t *header);

 /* Create a tar header based on ST and NAME where NAME is a path.
    If NAME is a hard link (resp. symlink), HARDLINK (resp.
diff -Nurp orig/tarfs-0.0.20100918/tarfs.c tarfs-0.0.20100918/tarfs.c
--- orig/tarfs-0.0.20100918/tarfs.c     2010-09-19 02:39:04.000000000 +0200
+++ tarfs-0.0.20100918/tarfs.c  2010-09-20 22:13:28.000000000 +0200
@@ -80,7 +80,7 @@ static struct store *tar_file;
 static struct mutex  tar_file_lock;

 /* Archive parsing hook (see tar.c) */
-extern int (* tar_header_hook) (tar_record_t *, off_t);
+extern int (* tar_header_hook) (tar_record_t *, struct archive *);

 /* List of tar items for this file */
 static struct tar_list tar_list;
@@ -325,7 +325,7 @@ error_t tarfs_create_node (struct node *
    It simply creates the node corresponding to the header.
    OFFSET denotes the offset of the header in the archive.  */
 int
-tarfs_add_header (tar_record_t *hdr, off_t offset)
+tarfs_add_header (tar_record_t *hdr, struct archive *archive)
 {
   error_t err;
   static struct tar_item *last_item = NULL;
@@ -412,7 +412,7 @@ tarfs_add_header (tar_record_t *hdr, off

          /* Add the tar item into the list.  */
          err = tar_make_item (&NODE_INFO(new)->tar, new,
-                              0, offset);
+                              0, archive->current_tar_position);
          assert_perror (err);
        }
       }
@@ -431,7 +431,7 @@ tarfs_add_header (tar_record_t *hdr, off
       if (new)
       {
        NEW_NODE_INFO (new);
-       tar_header2stat (&new->nn_stat, hdr);
+       tar_fill_stat (archive, &new->nn_stat, hdr);

        /* Create a cache for the new node.  */
        err = cache_create (new);
@@ -440,7 +440,7 @@ tarfs_add_header (tar_record_t *hdr, off

        /* Add the tar item into the list.  */
        err = tar_make_item (&NODE_INFO(new)->tar, new,
-                            new->nn_stat.st_size, offset);
+                            new->nn_stat.st_size, 
archive->current_tar_position);
        assert_perror (err);
       }
   }

HTH,

-- 
Manuel Menal

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]