XBPS Library API  0.19
The X Binary Package System
plist_fetch.c
1 /*-
2  * Copyright (c) 2009-2012 Juan Romero Pardines.
3  * Copyright (c) 2008, 2009 Joerg Sonnenberger <joerg (at) NetBSD.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *-
26  * From: $NetBSD: pkg_io.c,v 1.9 2009/08/16 21:10:15 joerg Exp $
27  */
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <errno.h>
33 
34 #include "xbps_api_impl.h"
35 
36 /**
37  * @file lib/plist_fetch.c
38  * @brief Package URL metadata files handling
39  * @defgroup plist_fetch Package URL metadata files handling
40  */
41 
42 struct fetch_archive {
43  struct url *url;
44  struct fetchIO *fetch;
45  char buffer[32768];
46 };
47 
48 static int
49 fetch_archive_open(struct archive *a, void *client_data)
50 {
51  struct fetch_archive *f = client_data;
52 
53  (void)a;
54 
55  f->fetch = fetchGet(f->url, NULL);
56  if (f->fetch == NULL)
57  return ENOENT;
58 
59  return 0;
60 }
61 
62 static ssize_t
63 fetch_archive_read(struct archive *a, void *client_data, const void **buf)
64 {
65  struct fetch_archive *f = client_data;
66 
67  (void)a;
68  *buf = f->buffer;
69 
70  return fetchIO_read(f->fetch, f->buffer, sizeof(f->buffer));
71 }
72 
73 static int
74 fetch_archive_close(struct archive *a, void *client_data)
75 {
76  struct fetch_archive *f = client_data;
77 
78  (void)a;
79 
80  if (f->fetch != NULL)
81  fetchIO_close(f->fetch);
82  free(f);
83 
84  return 0;
85 }
86 
87 static struct archive *
88 open_archive_by_url(struct url *url)
89 {
90  struct fetch_archive *f;
91  struct archive *a;
92 
93  f = malloc(sizeof(struct fetch_archive));
94  if (f == NULL)
95  return NULL;
96 
97  f->url = url;
98  if ((a = archive_read_new()) == NULL) {
99  free(f);
100  return NULL;
101  }
102  archive_read_support_compression_gzip(a);
103  archive_read_support_compression_bzip2(a);
104  archive_read_support_compression_xz(a);
105  archive_read_support_format_tar(a);
106 
107  if (archive_read_open(a, f, fetch_archive_open, fetch_archive_read,
108  fetch_archive_close)) {
109  archive_read_finish(a);
110  return NULL;
111  }
112 
113  return a;
114 }
115 
116 static struct archive *
117 open_archive(const char *url)
118 {
119  struct url *u;
120  struct archive *a;
121 
122  if (!xbps_repository_is_remote(url)) {
123  if ((a = archive_read_new()) == NULL)
124  return NULL;
125 
126  archive_read_support_compression_gzip(a);
127  archive_read_support_compression_bzip2(a);
128  archive_read_support_compression_xz(a);
129  archive_read_support_format_tar(a);
130 
131  if (archive_read_open_filename(a, url,
132  ARCHIVE_READ_BLOCKSIZE)) {
133  archive_read_close(a);
134  return NULL;
135  }
136  return a;
137  }
138 
139  if ((u = fetchParseURL(url)) == NULL)
140  return NULL;
141 
142  a = open_archive_by_url(u);
143  fetchFreeURL(u);
144 
145  return a;
146 }
147 
148 prop_dictionary_t
149 xbps_get_pkg_plist_from_binpkg(const char *fname, const char *plistf)
150 {
151  prop_dictionary_t plistd = NULL;
152  struct archive *a;
153  struct archive_entry *entry;
154  const char *curpath, *comptype;
155  int i = 0;
156 
157  assert(fname != NULL);
158  assert(plistf != NULL);
159 
160  if ((a = open_archive(fname)) == NULL)
161  return NULL;
162 
163  /*
164  * Save compression type string for future use.
165  */
166  comptype = archive_compression_name(a);
167 
168  while ((archive_read_next_header(a, &entry)) == ARCHIVE_OK) {
169  curpath = archive_entry_pathname(entry);
170  if (strcmp(curpath, plistf)) {
171  archive_read_data_skip(a);
172  if (i >= 3) {
173  /*
174  * Archive does not contain required
175  * plist file, discard it completely.
176  */
177  errno = ENOENT;
178  break;
179  }
180  i++;
181  continue;
182  }
183  plistd = xbps_dictionary_from_archive_entry(a, entry);
184  if (plistd == NULL) {
185  errno = EINVAL;
186  break;
187  }
188  prop_dictionary_set_cstring_nocopy(plistd,
189  "archive-compression-type", comptype);
190 
191  break;
192  }
193  archive_read_close(a);
194  archive_read_free(a);
195 
196  return plistd;
197 }