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