aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/archive_extractor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/archive_extractor.c')
-rw-r--r--src/plugins/archive_extractor.c124
1 files changed, 124 insertions, 0 deletions
diff --git a/src/plugins/archive_extractor.c b/src/plugins/archive_extractor.c
new file mode 100644
index 0000000..ef4e7c7
--- /dev/null
+++ b/src/plugins/archive_extractor.c
@@ -0,0 +1,124 @@
1/*
2 This file is part of libextractor.
3 (C) 2012 Christian Grothoff
4
5 libextractor is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 libextractor is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with libextractor; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20/**
21 * @file plugins/archive_extractor.c
22 * @brief plugin to support archives (such as TAR)
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "extractor.h"
27#include <archive.h>
28#include <archive_entry.h>
29
30/**
31 * Callback for libarchive for 'reading'.
32 *
33 * @param a archive handle
34 * @param client_data our 'struct EXTRACTOR_ExtractContext'
35 * @param buff where to store data with pointer to data
36 * @return number of bytes read
37 */
38static ssize_t
39read_cb (struct archive *a,
40 void *client_data,
41 const void **buff)
42{
43 struct EXTRACTOR_ExtractContext *ec = client_data;
44 ssize_t ret;
45
46 *buff = NULL;
47 if (-1 == (ret = ec->read (ec->cls, (void **) buff, 16 * 1024)))
48 return ARCHIVE_FATAL;
49 return ret;
50}
51
52
53/**
54 * Callback for libarchive for 'skipping'.
55 *
56 * @param a archive handle
57 * @param client_data our 'struct EXTRACTOR_ExtractContext'
58 * @param request number of bytes to skip
59 * @return number of bytes skipped
60 */
61static __LA_INT64_T
62skip_cb (struct archive *a,
63 void *client_data,
64 __LA_INT64_T request)
65{
66 struct EXTRACTOR_ExtractContext *ec = client_data;
67
68 if (-1 == ec->seek (ec->cls, request, SEEK_CUR))
69 return 0;
70 return request;
71}
72
73
74/**
75 * Main entry method for the ARCHIVE extraction plugin.
76 *
77 * @param ec extraction context provided to the plugin
78 */
79void
80EXTRACTOR_archive_extract_method (struct EXTRACTOR_ExtractContext *ec)
81{
82 struct archive *a;
83 struct archive_entry *entry;
84 const char *fname;
85 const char *s;
86 char *format;
87
88 format = NULL;
89 a = archive_read_new ();
90 archive_read_support_compression_all (a);
91 archive_read_support_format_all (a);
92 archive_read_open2 (a, ec, NULL, &read_cb, &skip_cb, NULL);
93 while (ARCHIVE_OK == archive_read_next_header(a, &entry))
94 {
95 if ( (NULL == format) &&
96 (NULL != (fname = archive_format_name (a))) )
97 format = strdup (fname);
98 s = archive_entry_pathname (entry);
99 if (0 != ec->proc (ec->cls,
100 "tar",
101 EXTRACTOR_METATYPE_FILENAME,
102 EXTRACTOR_METAFORMAT_UTF8,
103 "text/plain",
104 s, strlen (s) + 1))
105 break;
106 }
107 archive_read_finish (a);
108 if (NULL != format)
109 {
110 if (0 != ec->proc (ec->cls,
111 "tar",
112 EXTRACTOR_METATYPE_FORMAT,
113 EXTRACTOR_METAFORMAT_UTF8,
114 "text/plain", format, strlen (format) + 1))
115 {
116 free (format);
117 return;
118 }
119 free (format);
120 }
121}
122
123
124/* end of tar_extractor.c */