]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Separate code to set formats/filters into different source files. 23/head
authorAndres Mejia <amejia004@gmail.com>
Sun, 9 Dec 2012 18:12:01 +0000 (13:12 -0500)
committerAndres Mejia <amejia004@gmail.com>
Sun, 9 Dec 2012 18:13:42 +0000 (13:13 -0500)
This needs close_filters and free_filters to be globally available
as global symbols __archive_read_close_filters and
__archive_read_free_filters.

Makefile.am
libarchive/CMakeLists.txt
libarchive/archive_read.c
libarchive/archive_read_append_filter.c [new file with mode: 0644]
libarchive/archive_read_private.h
libarchive/archive_read_set_format.c [new file with mode: 0644]

index 06c8bc06faa5b3598579888853ce511d9b485257..99b3af507686dbfbd852db27ec12cb2f4aa0318b 100644 (file)
@@ -120,6 +120,7 @@ libarchive_la_SOURCES=                                              \
        libarchive/archive_rb.c                                 \
        libarchive/archive_rb.h                                 \
        libarchive/archive_read.c                               \
+       libarchive/archive_read_append_filter.c                 \
        libarchive/archive_read_data_into_fd.c                  \
        libarchive/archive_read_disk_entry_from_file.c          \
        libarchive/archive_read_disk_posix.c                    \
@@ -131,6 +132,7 @@ libarchive_la_SOURCES=                                              \
        libarchive/archive_read_open_filename.c                 \
        libarchive/archive_read_open_memory.c                   \
        libarchive/archive_read_private.h                       \
+       libarchive/archive_read_set_format.c                    \
        libarchive/archive_read_set_options.c                   \
        libarchive/archive_read_support_filter_all.c            \
        libarchive/archive_read_support_filter_bzip2.c          \
index a57244d01f404fda8185ccc94eecb092dc514b38..ecb0409bd9d881b98608098f9f72a6f8bc287809 100644 (file)
@@ -45,6 +45,7 @@ SET(libarchive_SOURCES
   archive_rb.c
   archive_rb.h
   archive_read.c
+  archive_read_append_filter.c
   archive_read_data_into_fd.c
   archive_read_disk_entry_from_file.c
   archive_read_disk_posix.c
@@ -56,6 +57,7 @@ SET(libarchive_SOURCES
   archive_read_open_filename.c
   archive_read_open_memory.c
   archive_read_private.h
+  archive_read_set_format.c
   archive_read_set_options.c
   archive_read_support_filter_all.c
   archive_read_support_filter_bzip2.c
index 2a66d4089446dd6df0a04dff6adda9c6925ed7f0..12b08af61bdd734df7b7cfafd1af472653e32b17 100644 (file)
@@ -57,8 +57,6 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read.c 201157 2009-12-29 05:30:2
 
 static int     choose_filters(struct archive_read *);
 static int     choose_format(struct archive_read *);
-static void    free_filters(struct archive_read *);
-static int     close_filters(struct archive_read *);
 static struct archive_vtable *archive_read_vtable(void);
 static int64_t _archive_filter_bytes(struct archive *, int);
 static int     _archive_filter_code(struct archive *, int);
@@ -524,7 +522,7 @@ archive_read_open1(struct archive *_a)
        {
                slot = choose_format(a);
                if (slot < 0) {
-                       close_filters(a);
+                       __archive_read_close_filters(a);
                        a->archive.state = ARCHIVE_STATE_FATAL;
                        return (ARCHIVE_FATAL);
                }
@@ -574,8 +572,8 @@ choose_filters(struct archive_read *a)
                        /* Verify the filter by asking it for some data. */
                        __archive_read_filter_ahead(a->filter, 1, &avail);
                        if (avail < 0) {
-                               close_filters(a);
-                               free_filters(a);
+                               __archive_read_close_filters(a);
+                               __archive_read_free_filters(a);
                                return (ARCHIVE_FATAL);
                        }
                        a->archive.compression_name = a->filter->name;
@@ -593,8 +591,8 @@ choose_filters(struct archive_read *a)
                a->filter = filter;
                r = (best_bidder->init)(a->filter);
                if (r != ARCHIVE_OK) {
-                       close_filters(a);
-                       free_filters(a);
+                       __archive_read_close_filters(a);
+                       __archive_read_free_filters(a);
                        return (ARCHIVE_FATAL);
                }
        }
@@ -903,8 +901,8 @@ _archive_read_data_block(struct archive *_a,
        return (a->format->read_data)(a, buff, size, offset);
 }
 
-static int
-close_filters(struct archive_read *a)
+int
+__archive_read_close_filters(struct archive_read *a)
 {
        struct archive_read_filter *f = a->filter;
        int r = ARCHIVE_OK;
@@ -924,8 +922,8 @@ close_filters(struct archive_read *a)
        return r;
 }
 
-static void
-free_filters(struct archive_read *a)
+void
+__archive_read_free_filters(struct archive_read *a)
 {
        while (a->filter != NULL) {
                struct archive_read_filter *t = a->filter->upstream;
@@ -969,7 +967,7 @@ _archive_read_close(struct archive *_a)
        /* TODO: Clean up the formatters. */
 
        /* Release the filter objects. */
-       r1 = close_filters(a);
+       r1 = __archive_read_close_filters(a);
        if (r1 < r)
                r = r1;
 
@@ -1008,7 +1006,7 @@ _archive_read_free(struct archive *_a)
        }
 
        /* Free the filters */
-       free_filters(a);
+       __archive_read_free_filters(a);
 
        /* Release the bidder objects. */
        n = sizeof(a->bidders)/sizeof(a->bidders[0]);
@@ -1634,236 +1632,3 @@ __archive_read_filter_seek(struct archive_read_filter *filter, int64_t offset,
        }
        return r;
 }
-
-int
-archive_read_set_format(struct archive *_a, int code)
-{
-  int r1, r2, slots, i;
-  char str[10];
-  struct archive_read *a = (struct archive_read *)_a;
-
-  if ((r1 = archive_read_support_format_by_code(_a, code)) < (ARCHIVE_OK))
-    return r1;
-
-  r1 = r2 = (ARCHIVE_OK);
-  if (a->format)
-    r2 = (ARCHIVE_WARN);
-  switch (code & ARCHIVE_FORMAT_BASE_MASK)
-  {
-    case ARCHIVE_FORMAT_7ZIP:
-      strcpy(str, "7zip");
-      break;
-    case ARCHIVE_FORMAT_AR:
-      strcpy(str, "ar");
-      break;
-    case ARCHIVE_FORMAT_CAB:
-      strcpy(str, "cab");
-      break;
-    case ARCHIVE_FORMAT_CPIO:
-      strcpy(str, "cpio");
-      break;
-    case ARCHIVE_FORMAT_ISO9660:
-      strcpy(str, "iso9660");
-      break;
-    case ARCHIVE_FORMAT_LHA:
-      strcpy(str, "lha");
-      break;
-    case ARCHIVE_FORMAT_MTREE:
-      strcpy(str, "mtree");
-      break;
-    case ARCHIVE_FORMAT_RAR:
-      strcpy(str, "rar");
-      break;
-    case ARCHIVE_FORMAT_TAR:
-      strcpy(str, "tar");
-      break;
-    case ARCHIVE_FORMAT_XAR:
-      strcpy(str, "xar");
-      break;
-    case ARCHIVE_FORMAT_ZIP:
-      strcpy(str, "zip");
-      break;
-    default:
-      archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-          "Invalid format code specified");
-      return (ARCHIVE_FATAL);
-  }
-
-  slots = sizeof(a->formats) / sizeof(a->formats[0]);
-  a->format = &(a->formats[0]);
-  for (i = 0; i < slots; i++, a->format++) {
-    if (!a->format->name || !strcmp(a->format->name, str))
-      break;
-  }
-  if (!a->format->name || strcmp(a->format->name, str))
-  {
-    archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-        "Internal error: Unable to set format");
-    r1 = (ARCHIVE_FATAL);
-  }
-
-  return (r1 < r2) ? r1 : r2;
-}
-
-int
-archive_read_append_filter(struct archive *_a, int code)
-{
-  int r1, r2, number_bidders, i;
-  char str[10];
-  struct archive_read_filter_bidder *bidder;
-  struct archive_read_filter *filter;
-  struct archive_read *a = (struct archive_read *)_a;
-
-  r1 = r2 = (ARCHIVE_OK);
-  switch (code)
-  {
-    case ARCHIVE_FILTER_NONE:
-      /* No filter to add, so do nothing.
-       * NOTE: An initial "NONE" type filter is always set at the end of the
-       * filter chain.
-       */
-      r1 = (ARCHIVE_OK);
-      break;
-    case ARCHIVE_FILTER_GZIP:
-      strcpy(str, "gzip");
-      r1 = archive_read_support_filter_gzip(_a);
-      break;
-    case ARCHIVE_FILTER_BZIP2:
-      strcpy(str, "bzip2");
-      r1 = archive_read_support_filter_bzip2(_a);
-      break;
-    case ARCHIVE_FILTER_COMPRESS:
-      strcpy(str, "compress (.Z)");
-      r1 = archive_read_support_filter_compress(_a);
-      break;
-    case ARCHIVE_FILTER_PROGRAM:
-      archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-          "Cannot append program filter using archive_read_append_filter");
-      return (ARCHIVE_FATAL);
-    case ARCHIVE_FILTER_LZMA:
-      strcpy(str, "lzma");
-      r1 = archive_read_support_filter_lzma(_a);
-      break;
-    case ARCHIVE_FILTER_XZ:
-      strcpy(str, "xz");
-      r1 = archive_read_support_filter_xz(_a);
-      break;
-    case ARCHIVE_FILTER_UU:
-      strcpy(str, "uu");
-      r1 = archive_read_support_filter_uu(_a);
-      break;
-    case ARCHIVE_FILTER_RPM:
-      strcpy(str, "rpm");
-      r1 = archive_read_support_filter_rpm(_a);
-      break;
-    case ARCHIVE_FILTER_LZIP:
-      strcpy(str, "lzip");
-      r1 = archive_read_support_filter_lzip(_a);
-      break;
-    case ARCHIVE_FILTER_LRZIP:
-      strcpy(str, "lrzip");
-      r1 = archive_read_support_filter_lrzip(_a);
-      break;
-    default:
-      archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-          "Invalid filter code specified");
-      return (ARCHIVE_FATAL);
-  }
-
-  if (code != ARCHIVE_FILTER_NONE)
-  {
-    number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]);
-
-    bidder = a->bidders;
-    for (i = 0; i < number_bidders; i++, bidder++)
-    {
-      if (!bidder->name || !strcmp(bidder->name, str))
-        break;
-    }
-    if (!bidder->name || strcmp(bidder->name, str))
-    {
-      archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-          "Internal error: Unable to append filter");
-      return (ARCHIVE_FATAL);
-    }
-
-    filter
-        = (struct archive_read_filter *)calloc(1, sizeof(*filter));
-    if (filter == NULL)
-    {
-      archive_set_error(&a->archive, ENOMEM, "Out of memory");
-      return (ARCHIVE_FATAL);
-    }
-    filter->bidder = bidder;
-    filter->archive = a;
-    filter->upstream = a->filter;
-    a->filter = filter;
-    r2 = (bidder->init)(a->filter);
-    if (r2 != ARCHIVE_OK) {
-      close_filters(a);
-      free_filters(a);
-      return (ARCHIVE_FATAL);
-    }
-  }
-
-  a->bypass_filter_bidding = 1;
-  return (r1 < r2) ? r1 : r2;
-}
-
-int
-archive_read_append_filter_program(struct archive *_a, const char *cmd)
-{
-  return (archive_read_append_filter_program_signature(_a, cmd, NULL, 0));
-}
-
-int
-archive_read_append_filter_program_signature(struct archive *_a,
-  const char *cmd, const void *signature, size_t signature_len)
-{
-  int r, number_bidders, i;
-  struct archive_read_filter_bidder *bidder;
-  struct archive_read_filter *filter;
-  struct archive_read *a = (struct archive_read *)_a;
-
-  if (archive_read_support_filter_program_signature(_a, cmd, signature,
-    signature_len) != (ARCHIVE_OK))
-    return (ARCHIVE_FATAL);
-
-  number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]);
-
-  bidder = a->bidders;
-  for (i = 0; i < number_bidders; i++, bidder++)
-  {
-    /* Program bidder name set to filter name after initialization */
-    if (bidder->data && !bidder->name)
-      break;
-  }
-  if (!bidder->data)
-  {
-    archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-        "Internal error: Unable to append program filter");
-    return (ARCHIVE_FATAL);
-  }
-
-  filter
-      = (struct archive_read_filter *)calloc(1, sizeof(*filter));
-  if (filter == NULL)
-  {
-    archive_set_error(&a->archive, ENOMEM, "Out of memory");
-    return (ARCHIVE_FATAL);
-  }
-  filter->bidder = bidder;
-  filter->archive = a;
-  filter->upstream = a->filter;
-  a->filter = filter;
-  r = (bidder->init)(a->filter);
-  if (r != ARCHIVE_OK) {
-    close_filters(a);
-    free_filters(a);
-    return (ARCHIVE_FATAL);
-  }
-  bidder->name = a->filter->name;
-
-  a->bypass_filter_bidding = 1;
-  return r;
-}
diff --git a/libarchive/archive_read_append_filter.c b/libarchive/archive_read_append_filter.c
new file mode 100644 (file)
index 0000000..50fdcf9
--- /dev/null
@@ -0,0 +1,198 @@
+/*-
+ * Copyright (c) 2003-2012 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "archive.h"
+#include "archive_private.h"
+#include "archive_read_private.h"
+
+int
+archive_read_append_filter(struct archive *_a, int code)
+{
+  int r1, r2, number_bidders, i;
+  char str[10];
+  struct archive_read_filter_bidder *bidder;
+  struct archive_read_filter *filter;
+  struct archive_read *a = (struct archive_read *)_a;
+
+  r1 = r2 = (ARCHIVE_OK);
+  switch (code)
+  {
+    case ARCHIVE_FILTER_NONE:
+      /* No filter to add, so do nothing.
+       * NOTE: An initial "NONE" type filter is always set at the end of the
+       * filter chain.
+       */
+      r1 = (ARCHIVE_OK);
+      break;
+    case ARCHIVE_FILTER_GZIP:
+      strcpy(str, "gzip");
+      r1 = archive_read_support_filter_gzip(_a);
+      break;
+    case ARCHIVE_FILTER_BZIP2:
+      strcpy(str, "bzip2");
+      r1 = archive_read_support_filter_bzip2(_a);
+      break;
+    case ARCHIVE_FILTER_COMPRESS:
+      strcpy(str, "compress (.Z)");
+      r1 = archive_read_support_filter_compress(_a);
+      break;
+    case ARCHIVE_FILTER_PROGRAM:
+      archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
+          "Cannot append program filter using archive_read_append_filter");
+      return (ARCHIVE_FATAL);
+    case ARCHIVE_FILTER_LZMA:
+      strcpy(str, "lzma");
+      r1 = archive_read_support_filter_lzma(_a);
+      break;
+    case ARCHIVE_FILTER_XZ:
+      strcpy(str, "xz");
+      r1 = archive_read_support_filter_xz(_a);
+      break;
+    case ARCHIVE_FILTER_UU:
+      strcpy(str, "uu");
+      r1 = archive_read_support_filter_uu(_a);
+      break;
+    case ARCHIVE_FILTER_RPM:
+      strcpy(str, "rpm");
+      r1 = archive_read_support_filter_rpm(_a);
+      break;
+    case ARCHIVE_FILTER_LZIP:
+      strcpy(str, "lzip");
+      r1 = archive_read_support_filter_lzip(_a);
+      break;
+    case ARCHIVE_FILTER_LRZIP:
+      strcpy(str, "lrzip");
+      r1 = archive_read_support_filter_lrzip(_a);
+      break;
+    default:
+      archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
+          "Invalid filter code specified");
+      return (ARCHIVE_FATAL);
+  }
+
+  if (code != ARCHIVE_FILTER_NONE)
+  {
+    number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]);
+
+    bidder = a->bidders;
+    for (i = 0; i < number_bidders; i++, bidder++)
+    {
+      if (!bidder->name || !strcmp(bidder->name, str))
+        break;
+    }
+    if (!bidder->name || strcmp(bidder->name, str))
+    {
+      archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
+          "Internal error: Unable to append filter");
+      return (ARCHIVE_FATAL);
+    }
+
+    filter
+        = (struct archive_read_filter *)calloc(1, sizeof(*filter));
+    if (filter == NULL)
+    {
+      archive_set_error(&a->archive, ENOMEM, "Out of memory");
+      return (ARCHIVE_FATAL);
+    }
+    filter->bidder = bidder;
+    filter->archive = a;
+    filter->upstream = a->filter;
+    a->filter = filter;
+    r2 = (bidder->init)(a->filter);
+    if (r2 != ARCHIVE_OK) {
+      __archive_read_close_filters(a);
+      __archive_read_free_filters(a);
+      return (ARCHIVE_FATAL);
+    }
+  }
+
+  a->bypass_filter_bidding = 1;
+  return (r1 < r2) ? r1 : r2;
+}
+
+int
+archive_read_append_filter_program(struct archive *_a, const char *cmd)
+{
+  return (archive_read_append_filter_program_signature(_a, cmd, NULL, 0));
+}
+
+int
+archive_read_append_filter_program_signature(struct archive *_a,
+  const char *cmd, const void *signature, size_t signature_len)
+{
+  int r, number_bidders, i;
+  struct archive_read_filter_bidder *bidder;
+  struct archive_read_filter *filter;
+  struct archive_read *a = (struct archive_read *)_a;
+
+  if (archive_read_support_filter_program_signature(_a, cmd, signature,
+    signature_len) != (ARCHIVE_OK))
+    return (ARCHIVE_FATAL);
+
+  number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]);
+
+  bidder = a->bidders;
+  for (i = 0; i < number_bidders; i++, bidder++)
+  {
+    /* Program bidder name set to filter name after initialization */
+    if (bidder->data && !bidder->name)
+      break;
+  }
+  if (!bidder->data)
+  {
+    archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
+        "Internal error: Unable to append program filter");
+    return (ARCHIVE_FATAL);
+  }
+
+  filter
+      = (struct archive_read_filter *)calloc(1, sizeof(*filter));
+  if (filter == NULL)
+  {
+    archive_set_error(&a->archive, ENOMEM, "Out of memory");
+    return (ARCHIVE_FATAL);
+  }
+  filter->bidder = bidder;
+  filter->archive = a;
+  filter->upstream = a->filter;
+  a->filter = filter;
+  r = (bidder->init)(a->filter);
+  if (r != ARCHIVE_OK) {
+    __archive_read_close_filters(a);
+    __archive_read_free_filters(a);
+    return (ARCHIVE_FATAL);
+  }
+  bidder->name = a->filter->name;
+
+  a->bypass_filter_bidding = 1;
+  return r;
+}
index 0ef686f9a7dc1973cac0a41695a1e5dec4e2600b..587c8a33eee419a19909230837a28479a7f82315 100644 (file)
@@ -231,4 +231,6 @@ int64_t     __archive_read_filter_seek(struct archive_read_filter *, int64_t, int);
 int64_t        __archive_read_consume(struct archive_read *, int64_t);
 int64_t        __archive_read_filter_consume(struct archive_read_filter *, int64_t);
 int __archive_read_program(struct archive_read_filter *, const char *);
+void __archive_read_free_filters(struct archive_read *);
+int  __archive_read_close_filters(struct archive_read *);
 #endif
diff --git a/libarchive/archive_read_set_format.c b/libarchive/archive_read_set_format.c
new file mode 100644 (file)
index 0000000..190f436
--- /dev/null
@@ -0,0 +1,105 @@
+/*-
+ * Copyright (c) 2003-2012 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "archive.h"
+#include "archive_private.h"
+#include "archive_read_private.h"
+
+int
+archive_read_set_format(struct archive *_a, int code)
+{
+  int r1, r2, slots, i;
+  char str[10];
+  struct archive_read *a = (struct archive_read *)_a;
+
+  if ((r1 = archive_read_support_format_by_code(_a, code)) < (ARCHIVE_OK))
+    return r1;
+
+  r1 = r2 = (ARCHIVE_OK);
+  if (a->format)
+    r2 = (ARCHIVE_WARN);
+  switch (code & ARCHIVE_FORMAT_BASE_MASK)
+  {
+    case ARCHIVE_FORMAT_7ZIP:
+      strcpy(str, "7zip");
+      break;
+    case ARCHIVE_FORMAT_AR:
+      strcpy(str, "ar");
+      break;
+    case ARCHIVE_FORMAT_CAB:
+      strcpy(str, "cab");
+      break;
+    case ARCHIVE_FORMAT_CPIO:
+      strcpy(str, "cpio");
+      break;
+    case ARCHIVE_FORMAT_ISO9660:
+      strcpy(str, "iso9660");
+      break;
+    case ARCHIVE_FORMAT_LHA:
+      strcpy(str, "lha");
+      break;
+    case ARCHIVE_FORMAT_MTREE:
+      strcpy(str, "mtree");
+      break;
+    case ARCHIVE_FORMAT_RAR:
+      strcpy(str, "rar");
+      break;
+    case ARCHIVE_FORMAT_TAR:
+      strcpy(str, "tar");
+      break;
+    case ARCHIVE_FORMAT_XAR:
+      strcpy(str, "xar");
+      break;
+    case ARCHIVE_FORMAT_ZIP:
+      strcpy(str, "zip");
+      break;
+    default:
+      archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
+          "Invalid format code specified");
+      return (ARCHIVE_FATAL);
+  }
+
+  slots = sizeof(a->formats) / sizeof(a->formats[0]);
+  a->format = &(a->formats[0]);
+  for (i = 0; i < slots; i++, a->format++) {
+    if (!a->format->name || !strcmp(a->format->name, str))
+      break;
+  }
+  if (!a->format->name || strcmp(a->format->name, str))
+  {
+    archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
+        "Internal error: Unable to set format");
+    r1 = (ARCHIVE_FATAL);
+  }
+
+  return (r1 < r2) ? r1 : r2;
+}