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