Branch data Line data Source code
1 : : /*
2 : : * dpkg-deb - construction and deconstruction of *.deb archives
3 : : * extract.c - extracting archives
4 : : *
5 : : * Copyright © 1994,1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
6 : : * Copyright © 2006-2014 Guillem Jover <guillem@debian.org>
7 : : *
8 : : * This is free software; you can redistribute it and/or modify
9 : : * it under the terms of the GNU General Public License as published by
10 : : * the Free Software Foundation; either version 2 of the License, or
11 : : * (at your option) any later version.
12 : : *
13 : : * This is distributed in the hope that it will be useful,
14 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : : * GNU General Public License for more details.
17 : : *
18 : : * You should have received a copy of the GNU General Public License
19 : : * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 : : */
21 : :
22 : : #include <config.h>
23 : : #include <compat.h>
24 : :
25 : : #include <sys/types.h>
26 : : #include <sys/stat.h>
27 : : #include <sys/wait.h>
28 : :
29 : : #include <errno.h>
30 : : #include <limits.h>
31 : : #include <string.h>
32 : : #include <dirent.h>
33 : : #include <fcntl.h>
34 : : #include <unistd.h>
35 : : #include <stdbool.h>
36 : : #include <stdint.h>
37 : : #include <stdlib.h>
38 : : #include <stdio.h>
39 : :
40 : : #include <dpkg/i18n.h>
41 : : #include <dpkg/dpkg.h>
42 : : #include <dpkg/fdio.h>
43 : : #include <dpkg/buffer.h>
44 : : #include <dpkg/subproc.h>
45 : : #include <dpkg/command.h>
46 : : #include <dpkg/compress.h>
47 : : #include <dpkg/ar.h>
48 : : #include <dpkg/deb-version.h>
49 : : #include <dpkg/options.h>
50 : :
51 : : #include "dpkg-deb.h"
52 : :
53 : : static void
54 : 3 : movecontrolfiles(const char *dir, const char *thing)
55 : : {
56 : : char buf[200];
57 : : pid_t pid;
58 : :
59 : 3 : sprintf(buf, "mv %s/%s/* %s/ && rmdir %s/%s", dir, thing, dir, dir, thing);
60 : 3 : pid = subproc_fork();
61 [ + + ]: 6 : if (pid == 0) {
62 : 3 : command_shell(buf, _("shell command to move files"));
63 : : }
64 : 3 : subproc_reap(pid, _("shell command to move files"), 0);
65 : 3 : }
66 : :
67 : : static void DPKG_ATTR_NORET
68 : 3 : read_fail(int rc, const char *filename, const char *what)
69 : : {
70 [ + - ]: 3 : if (rc >= 0)
71 : 3 : ohshit(_("unexpected end of file in %s in %.255s"),what,filename);
72 : : else
73 : 0 : ohshite(_("error reading %s from file %.255s"), what, filename);
74 : : }
75 : :
76 : : static ssize_t
77 : 47 : read_line(int fd, char *buf, size_t min_size, size_t max_size)
78 : : {
79 : 47 : ssize_t line_size = 0;
80 : 47 : size_t n = min_size;
81 : :
82 [ + - ]: 83 : while (line_size < (ssize_t)max_size) {
83 : : ssize_t r;
84 : : char *nl;
85 : :
86 : 83 : r = fd_read(fd, buf + line_size, n);
87 [ + + ]: 83 : if (r <= 0)
88 : 2 : return r;
89 : :
90 : 81 : nl = memchr(buf + line_size, '\n', r);
91 : 81 : line_size += r;
92 : :
93 [ + + ]: 81 : if (nl != NULL) {
94 : 45 : nl[1] = '\0';
95 : 45 : return line_size;
96 : : }
97 : :
98 : 36 : n = 1;
99 : : }
100 : :
101 : 0 : buf[line_size] = '\0';
102 : 0 : return line_size;
103 : : }
104 : :
105 : : void
106 : 37 : extracthalf(const char *debar, const char *dir,
107 : : enum dpkg_tar_options taroption, int admininfo)
108 : : {
109 : : struct dpkg_error err;
110 : : const char *errstr;
111 : : struct dpkg_ar *ar;
112 : : char versionbuf[40];
113 : : struct deb_version version;
114 : 37 : off_t ctrllennum, memberlen = 0;
115 : : ssize_t r;
116 : : int dummy;
117 : 37 : pid_t c1=0,c2,c3;
118 : : int p1[2], p2[2];
119 : : int p2_out;
120 : : char nlc;
121 : 37 : int adminmember = -1;
122 : : bool header_done;
123 : 37 : struct compress_params decompress_params = {
124 : : .type = COMPRESSOR_TYPE_GZIP,
125 : 37 : .threads_max = compress_params.threads_max,
126 : : };
127 : :
128 : 37 : ar = dpkg_ar_open(debar);
129 : :
130 : 37 : r = read_line(ar->fd, versionbuf, strlen(DPKG_AR_MAGIC), sizeof(versionbuf) - 1);
131 [ + + ]: 37 : if (r <= 0)
132 : 1 : read_fail(r, debar, _("archive magic version number"));
133 : :
134 [ + + ]: 36 : if (strcmp(versionbuf, DPKG_AR_MAGIC) == 0) {
135 : 26 : ctrllennum= 0;
136 : 26 : header_done = false;
137 : 37 : for (;;) {
138 : : struct dpkg_ar_hdr arh;
139 : :
140 : 63 : r = fd_read(ar->fd, &arh, sizeof(arh));
141 [ + + ]: 63 : if (r != sizeof(arh))
142 : 1 : read_fail(r, debar, _("archive member header"));
143 : :
144 [ - + ]: 62 : if (dpkg_ar_member_is_illegal(&arh))
145 : 0 : ohshit(_("file '%.250s' is corrupt - bad archive header magic"), debar);
146 : :
147 : 62 : dpkg_ar_normalize_name(&arh);
148 : :
149 : 62 : memberlen = dpkg_ar_member_get_size(ar, &arh);
150 [ + + ]: 62 : if (!header_done) {
151 : : char *infobuf;
152 : :
153 [ + + ]: 26 : if (strncmp(arh.ar_name, DEBMAGIC, sizeof(arh.ar_name)) != 0)
154 : 1 : ohshit(_("file '%.250s' is not a Debian binary archive (try dpkg-split?)"),
155 : : debar);
156 : 25 : infobuf= m_malloc(memberlen+1);
157 : 25 : r = fd_read(ar->fd, infobuf, memberlen + (memberlen & 1));
158 [ - + ]: 25 : if (r != (memberlen + (memberlen & 1)))
159 : 0 : read_fail(r, debar, _("archive information header member"));
160 : 25 : infobuf[memberlen] = '\0';
161 : :
162 [ - + ]: 25 : if (strchr(infobuf, '\n') == NULL)
163 : 0 : ohshit(_("archive has no newlines in header"));
164 : 25 : errstr = deb_version_parse(&version, infobuf);
165 [ - + ]: 25 : if (errstr)
166 : 0 : ohshit(_("archive has invalid format version: %s"), errstr);
167 [ - + ]: 25 : if (version.major != 2)
168 : 0 : ohshit(_("archive is format version %d.%d; get a newer dpkg-deb"),
169 : : version.major, version.minor);
170 : :
171 : 25 : free(infobuf);
172 : :
173 : 25 : header_done = true;
174 [ + + ]: 36 : } else if (arh.ar_name[0] == '_') {
175 : : /* Members with ‘_’ are noncritical, and if we don't understand
176 : : * them we skip them. */
177 [ - + ]: 1 : if (fd_skip(ar->fd, memberlen + (memberlen & 1), &err) < 0)
178 : 0 : ohshit(_("cannot skip archive member from '%s': %s"), ar->name, err.str);
179 : : } else {
180 [ + + ]: 35 : if (strncmp(arh.ar_name, ADMINMEMBER, strlen(ADMINMEMBER)) == 0) {
181 : 22 : const char *extension = arh.ar_name + strlen(ADMINMEMBER);
182 : :
183 : 22 : adminmember = 1;
184 : 22 : decompress_params.type = compressor_find_by_extension(extension);
185 [ + + ]: 22 : if (decompress_params.type != COMPRESSOR_TYPE_NONE &&
186 [ + + ]: 12 : decompress_params.type != COMPRESSOR_TYPE_GZIP &&
187 [ - + ]: 6 : decompress_params.type != COMPRESSOR_TYPE_XZ)
188 : 0 : ohshit(_("archive '%s' uses unknown compression for member '%.*s', "
189 : : "giving up"),
190 : : debar, (int)sizeof(arh.ar_name), arh.ar_name);
191 : :
192 [ + + ]: 22 : if (ctrllennum != 0)
193 : 1 : ohshit(_("archive '%.250s' contains two control members, giving up"),
194 : : debar);
195 : 21 : ctrllennum = memberlen;
196 : : } else {
197 [ + + ]: 13 : if (adminmember != 1)
198 : 4 : ohshit(_("archive '%s' has premature member '%.*s' before '%s', "
199 : : "giving up"),
200 : : debar, (int)sizeof(arh.ar_name), arh.ar_name, ADMINMEMBER);
201 : :
202 [ + + ]: 9 : if (strncmp(arh.ar_name, DATAMEMBER, strlen(DATAMEMBER)) == 0) {
203 : 8 : const char *extension = arh.ar_name + strlen(DATAMEMBER);
204 : :
205 : 8 : adminmember= 0;
206 : 8 : decompress_params.type = compressor_find_by_extension(extension);
207 [ + + ]: 8 : if (decompress_params.type == COMPRESSOR_TYPE_UNKNOWN)
208 : 1 : ohshit(_("archive '%s' uses unknown compression for member '%.*s', "
209 : : "giving up"),
210 : : debar, (int)sizeof(arh.ar_name), arh.ar_name);
211 : : } else {
212 : 1 : ohshit(_("archive '%s' has premature member '%.*s' before '%s', "
213 : : "giving up"),
214 : : debar, (int)sizeof(arh.ar_name), arh.ar_name, DATAMEMBER);
215 : : }
216 : : }
217 [ + + ]: 28 : if (!adminmember != !admininfo) {
218 [ - + ]: 11 : if (fd_skip(ar->fd, memberlen + (memberlen & 1), &err) < 0)
219 : 0 : ohshit(_("cannot skip archive member from '%s': %s"), ar->name, err.str);
220 : : } else {
221 : : /* Yes! - found it. */
222 : 17 : break;
223 : : }
224 : : }
225 : : }
226 : :
227 [ + + ]: 17 : if (admininfo >= 2) {
228 : 6 : printf(_(" new Debian package, version %d.%d.\n"
229 : : " size %jd bytes: control archive=%jd bytes.\n"),
230 : : version.major, version.minor,
231 : 6 : (intmax_t)ar->size, (intmax_t)ctrllennum);
232 : 6 : m_output(stdout, _("<standard output>"));
233 : : }
234 [ + - ]: 10 : } else if (strncmp(versionbuf, "0.93", 4) == 0) {
235 : : char ctrllenbuf[40];
236 : : int l;
237 : :
238 : 10 : l = strlen(versionbuf);
239 : :
240 [ - + ]: 10 : if (strchr(versionbuf, '\n') == NULL)
241 : 0 : ohshit(_("archive has no newlines in header"));
242 : 10 : errstr = deb_version_parse(&version, versionbuf);
243 [ - + ]: 10 : if (errstr)
244 : 0 : ohshit(_("archive has invalid format version: %s"), errstr);
245 : :
246 : 10 : r = read_line(ar->fd, ctrllenbuf, 1, sizeof(ctrllenbuf) - 1);
247 [ + + ]: 10 : if (r <= 0)
248 : 1 : read_fail(r, debar, _("archive control member size"));
249 [ + - ]: 9 : if (sscanf(ctrllenbuf, "%jd%c%d", (intmax_t *)&ctrllennum, &nlc, &dummy) != 2 ||
250 [ - + ]: 9 : nlc != '\n')
251 : 0 : ohshit(_("archive has malformed control member size '%s'"), ctrllenbuf);
252 : :
253 [ + + ]: 9 : if (admininfo) {
254 : 4 : memberlen = ctrllennum;
255 : : } else {
256 : 5 : memberlen = ar->size - ctrllennum - strlen(ctrllenbuf) - l;
257 [ - + ]: 5 : if (fd_skip(ar->fd, ctrllennum, &err) < 0)
258 : 0 : ohshit(_("cannot skip archive control member from '%s': %s"), ar->name,
259 : : err.str);
260 : : }
261 : :
262 [ + + ]: 9 : if (admininfo >= 2) {
263 : 4 : printf(_(" old Debian package, version %d.%d.\n"
264 : : " size %jd bytes: control archive=%jd, main archive=%jd.\n"),
265 : : version.major, version.minor,
266 : 4 : (intmax_t)ar->size, (intmax_t)ctrllennum,
267 : 4 : (intmax_t)(ar->size - ctrllennum - strlen(ctrllenbuf) - l));
268 : 4 : m_output(stdout, _("<standard output>"));
269 : : }
270 : : } else {
271 [ # # ]: 0 : if (strncmp(versionbuf, "!<arch>", 7) == 0) {
272 : 0 : notice(_("file looks like it might be an archive which has been\n"
273 : : " corrupted by being downloaded in ASCII mode"));
274 : : }
275 : :
276 : 0 : ohshit(_("'%.255s' is not a Debian format archive"), debar);
277 : : }
278 : :
279 : 26 : m_pipe(p1);
280 : 26 : c1 = subproc_fork();
281 [ + + ]: 52 : if (!c1) {
282 : 26 : close(p1[0]);
283 [ - + ]: 26 : if (fd_fd_copy(ar->fd, p1[1], memberlen, &err) < 0)
284 : 0 : ohshit(_("cannot copy archive member from '%s' to decompressor pipe: %s"),
285 : : ar->name, err.str);
286 [ - + ]: 26 : if (close(p1[1]))
287 : 0 : ohshite(_("cannot close decompressor pipe"));
288 : 26 : exit(0);
289 : : }
290 : 26 : close(p1[1]);
291 : :
292 [ + + ]: 26 : if (taroption) {
293 : 25 : m_pipe(p2);
294 : 25 : p2_out = p2[1];
295 : : } else {
296 : 1 : p2_out = 1;
297 : : }
298 : :
299 : 26 : c2 = subproc_fork();
300 [ + + ]: 52 : if (!c2) {
301 [ + + ]: 26 : if (taroption)
302 : 25 : close(p2[0]);
303 [ + + ]: 26 : decompress_filter(&decompress_params, p1[0], p2_out,
304 : 26 : _("decompressing archive '%s' (size=%jd) member '%s'"),
305 : 26 : ar->name, (intmax_t)ar->size,
306 : : admininfo ? ADMINMEMBER : DATAMEMBER);
307 : 26 : exit(0);
308 : : }
309 : 26 : close(p1[0]);
310 : 26 : dpkg_ar_close(ar);
311 : :
312 [ + + ]: 26 : if (taroption) {
313 : 25 : close(p2[1]);
314 : :
315 : 25 : c3 = subproc_fork();
316 [ + + ]: 50 : if (!c3) {
317 : : struct command cmd;
318 : :
319 : 25 : command_init(&cmd, TAR, "tar");
320 : 25 : command_add_arg(&cmd, "tar");
321 : :
322 [ + + - + ]: 25 : if ((taroption & DPKG_TAR_LIST) && (taroption & DPKG_TAR_EXTRACT))
323 : 0 : command_add_arg(&cmd, "-xv");
324 [ + + ]: 25 : else if (taroption & DPKG_TAR_EXTRACT)
325 : 14 : command_add_arg(&cmd, "-x");
326 [ + - ]: 11 : else if (taroption & DPKG_TAR_LIST)
327 : 11 : command_add_arg(&cmd, "-tv");
328 : : else
329 : 0 : internerr("unknown or missing tar action '%d'", taroption);
330 : :
331 [ - + ]: 25 : if (taroption & DPKG_TAR_PERMS)
332 : 0 : command_add_arg(&cmd, "-p");
333 [ + + ]: 25 : if (taroption & DPKG_TAR_NOMTIME)
334 : 14 : command_add_arg(&cmd, "-m");
335 : :
336 : 25 : command_add_arg(&cmd, "-f");
337 : 25 : command_add_arg(&cmd, "-");
338 : 25 : command_add_arg(&cmd, "--warning=no-timestamp");
339 : :
340 : 25 : m_dup2(p2[0],0);
341 : 25 : close(p2[0]);
342 : :
343 : 25 : unsetenv("TAR_OPTIONS");
344 : :
345 [ + + ]: 25 : if (dir) {
346 [ + - ]: 14 : if (mkdir(dir, 0777) != 0) {
347 [ - + ]: 14 : if (errno != EEXIST)
348 : 0 : ohshite(_("failed to create directory"));
349 : :
350 [ - + ]: 14 : if (taroption & DPKG_TAR_CREATE_DIR)
351 : 0 : ohshite(_("unexpected pre-existing pathname %s"), dir);
352 : : }
353 [ - + ]: 14 : if (chdir(dir) != 0)
354 : 0 : ohshite(_("failed to chdir to directory"));
355 : : }
356 : :
357 : 25 : command_exec(&cmd);
358 : : }
359 : 25 : close(p2[0]);
360 : 25 : subproc_reap(c3, "tar", 0);
361 : : }
362 : :
363 : 26 : subproc_reap(c2, _("<decompress>"), SUBPROC_NOPIPE);
364 [ + - ]: 26 : if (c1 != -1)
365 : 26 : subproc_reap(c1, _("paste"), 0);
366 [ + + + + ]: 26 : if (version.major == 0 && admininfo) {
367 : : /* Handle the version as a float to preserve the behaviour of old code,
368 : : * because even if the format is defined to be padded by 0's that might
369 : : * not have been always true for really ancient versions... */
370 [ + - + + ]: 16 : while (version.minor && (version.minor % 10) == 0)
371 : 12 : version.minor /= 10;
372 : :
373 [ + + ]: 4 : if (version.minor == 931)
374 : 1 : movecontrolfiles(dir, OLDOLDDEBDIR);
375 [ + + + + ]: 3 : else if (version.minor == 932 || version.minor == 933)
376 : 2 : movecontrolfiles(dir, OLDDEBDIR);
377 : : }
378 : 26 : }
379 : :
380 : : int
381 : 0 : do_ctrltarfile(const char *const *argv)
382 : : {
383 : : const char *debar;
384 : :
385 : 0 : debar = *argv++;
386 [ # # ]: 0 : if (debar == NULL)
387 : 0 : badusage(_("--%s needs a .deb filename argument"), cipaction->olong);
388 [ # # ]: 0 : if (*argv)
389 : 0 : badusage(_("--%s takes only one argument (.deb filename)"),
390 : 0 : cipaction->olong);
391 : :
392 : 0 : extracthalf(debar, NULL, DPKG_TAR_PASSTHROUGH, 1);
393 : :
394 : 0 : return 0;
395 : : }
396 : :
397 : : int
398 : 1 : do_fsystarfile(const char *const *argv)
399 : : {
400 : : const char *debar;
401 : :
402 : 1 : debar = *argv++;
403 [ - + ]: 1 : if (debar == NULL)
404 : 0 : badusage(_("--%s needs a .deb filename argument"),cipaction->olong);
405 [ - + ]: 1 : if (*argv)
406 : 0 : badusage(_("--%s takes only one argument (.deb filename)"),cipaction->olong);
407 : 1 : extracthalf(debar, NULL, DPKG_TAR_PASSTHROUGH, 0);
408 : :
409 : 1 : return 0;
410 : : }
411 : :
412 : : int
413 : 0 : do_control(const char *const *argv)
414 : : {
415 : : const char *debar, *dir;
416 : :
417 : 0 : debar = *argv++;
418 [ # # ]: 0 : if (debar == NULL)
419 : 0 : badusage(_("--%s needs a .deb filename argument"), cipaction->olong);
420 : :
421 : 0 : dir = *argv++;
422 [ # # ]: 0 : if (dir == NULL)
423 : 0 : dir = EXTRACTCONTROLDIR;
424 [ # # ]: 0 : else if (*argv)
425 : 0 : badusage(_("--%s takes at most two arguments (.deb and directory)"),
426 : 0 : cipaction->olong);
427 : :
428 : 0 : extracthalf(debar, dir, DPKG_TAR_EXTRACT, 1);
429 : :
430 : 0 : return 0;
431 : : }
432 : :
433 : : int
434 : 0 : do_extract(const char *const *argv)
435 : : {
436 : : const char *debar, *dir;
437 : 0 : enum dpkg_tar_options options = DPKG_TAR_EXTRACT | DPKG_TAR_PERMS;
438 : :
439 [ # # ]: 0 : if (opt_verbose)
440 : 0 : options |= DPKG_TAR_LIST;
441 : :
442 : 0 : debar = *argv++;
443 [ # # ]: 0 : if (debar == NULL)
444 : 0 : badusage(_("--%s needs .deb filename and directory arguments"),
445 : 0 : cipaction->olong);
446 : :
447 : 0 : dir = *argv++;
448 [ # # ]: 0 : if (dir == NULL)
449 : 0 : badusage(_("--%s needs a target directory.\n"
450 : : "Perhaps you should be using dpkg --install ?"),
451 : 0 : cipaction->olong);
452 [ # # ]: 0 : else if (*argv)
453 : 0 : badusage(_("--%s takes at most two arguments (.deb and directory)"),
454 : 0 : cipaction->olong);
455 : :
456 : 0 : extracthalf(debar, dir, options, 0);
457 : :
458 : 0 : return 0;
459 : : }
460 : :
461 : : int
462 : 0 : do_vextract(const char *const *argv)
463 : : {
464 : : /* XXX: Backward compatibility. */
465 : 0 : opt_verbose = 1;
466 : 0 : return do_extract(argv);
467 : : }
468 : :
469 : : int
470 : 0 : do_raw_extract(const char *const *argv)
471 : : {
472 : : enum dpkg_tar_options data_options;
473 : : const char *debar, *dir;
474 : : char *control_dir;
475 : :
476 : 0 : debar = *argv++;
477 [ # # ]: 0 : if (debar == NULL)
478 : 0 : badusage(_("--%s needs .deb filename and directory arguments"),
479 : 0 : cipaction->olong);
480 [ # # ]: 0 : else if (strcmp(debar, "-") == 0)
481 : 0 : badusage(_("--%s does not support (yet) reading the .deb from standard input"),
482 : 0 : cipaction->olong);
483 : :
484 : 0 : dir = *argv++;
485 [ # # ]: 0 : if (dir == NULL)
486 : 0 : badusage(_("--%s needs a target directory.\n"
487 : : "Perhaps you should be using dpkg --install ?"),
488 : 0 : cipaction->olong);
489 [ # # ]: 0 : else if (*argv)
490 : 0 : badusage(_("--%s takes at most two arguments (.deb and directory)"),
491 : 0 : cipaction->olong);
492 : :
493 : 0 : control_dir = str_fmt("%s/%s", dir, EXTRACTCONTROLDIR);
494 : :
495 : 0 : data_options = DPKG_TAR_EXTRACT | DPKG_TAR_PERMS;
496 [ # # ]: 0 : if (opt_verbose)
497 : 0 : data_options |= DPKG_TAR_LIST;
498 : :
499 : 0 : extracthalf(debar, dir, data_options, 0);
500 : 0 : extracthalf(debar, control_dir, DPKG_TAR_EXTRACT | DPKG_TAR_CREATE_DIR, 1);
501 : :
502 : 0 : free(control_dir);
503 : :
504 : 0 : return 0;
505 : : }
|