2 * dpkg-deb - construction and deconstruction of *.deb archives
3 * extract.c - extracting archives
5 * Copyright © 1994,1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
6 * Copyright © 2006-2014 Guillem Jover <guillem@debian.org>
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.
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.
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/>.
25 #include <sys/types.h>
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>
49 #include <dpkg/deb-version.h>
50 #include <dpkg/options.h>
54 static void movecontrolfiles(const char *thing
) {
58 sprintf(buf
, "mv %s/* . && rmdir %s", thing
, thing
);
61 command_shell(buf
, _("shell command to move files"));
63 subproc_reap(pid
, _("shell command to move files"), 0);
66 static void DPKG_ATTR_NORET
67 read_fail(int rc
, const char *filename
, const char *what
)
70 ohshit(_("unexpected end of file in %s in %.255s"),what
,filename
);
72 ohshite(_("error reading %s from file %.255s"), what
, filename
);
76 read_line(int fd
, char *buf
, size_t min_size
, size_t max_size
)
78 ssize_t line_size
= 0;
81 while (line_size
< (ssize_t
)max_size
) {
85 r
= fd_read(fd
, buf
+ line_size
, n
);
89 nl
= memchr(buf
+ line_size
, '\n', r
);
100 buf
[line_size
] = '\0';
105 extracthalf(const char *debar
, const char *dir
,
106 enum dpkg_tar_options taroption
, int admininfo
)
108 struct dpkg_error err
;
112 struct deb_version version
;
113 off_t ctrllennum
, memberlen
= 0;
120 int adminmember
= -1;
122 enum compressor_type decompressor
= COMPRESSOR_TYPE_GZIP
;
124 ar
= dpkg_ar_open(debar
);
125 if (taroption
== DPKG_TAR_PASSTHROUGH
&& !admininfo
)
126 open_shadow(ar
->fd
, "deb-extract-ar");
128 r
= read_line(ar
->fd
, versionbuf
, strlen(DPKG_AR_MAGIC
), sizeof(versionbuf
) - 1);
130 read_fail(r
, debar
, _("archive magic version number"));
132 if (strcmp(versionbuf
, DPKG_AR_MAGIC
) == 0) {
136 struct dpkg_ar_hdr arh
;
138 r
= fd_read(ar
->fd
, &arh
, sizeof(arh
));
139 if (r
!= sizeof(arh
))
140 read_fail(r
, debar
, _("archive member header"));
142 dpkg_ar_normalize_name(&arh
);
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
);
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?)"),
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';
159 if (strchr(infobuf
, '\n') == NULL
)
160 ohshit(_("archive has no newlines in header"));
161 errstr
= deb_version_parse(&version
, infobuf
);
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
);
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
);
177 if (strncmp(arh
.ar_name
, ADMINMEMBER
, strlen(ADMINMEMBER
)) == 0) {
178 const char *extension
= arh
.ar_name
+ strlen(ADMINMEMBER
);
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', "
187 debar
, (int)sizeof(arh
.ar_name
), arh
.ar_name
);
189 if (adminmember
!= 1)
190 ohshit(_("archive '%s' has premature member '%.*s' before '%s', "
192 debar
, (int)sizeof(arh
.ar_name
), arh
.ar_name
, ADMINMEMBER
);
194 if (strncmp(arh
.ar_name
, DATAMEMBER
, strlen(DATAMEMBER
)) == 0) {
195 const char *extension
= arh
.ar_name
+ strlen(DATAMEMBER
);
198 decompressor
= compressor_find_by_extension(extension
);
199 if (decompressor
== COMPRESSOR_TYPE_UNKNOWN
)
200 ohshit(_("archive '%s' uses unknown compression for member '%.*s', "
202 debar
, (int)sizeof(arh
.ar_name
), arh
.ar_name
);
204 ohshit(_("archive '%s' has premature member '%.*s' before '%s', "
206 debar
, (int)sizeof(arh
.ar_name
), arh
.ar_name
, DATAMEMBER
);
209 if (adminmember
== 1) {
211 ohshit(_("archive '%.250s' contains two control members, giving up"),
213 ctrllennum
= memberlen
;
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
);
219 /* Yes! - found it. */
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>"));
232 } else if (strncmp(versionbuf
, "0.93", 4) == 0) {
236 l
= strlen(versionbuf
);
238 if (strchr(versionbuf
, '\n') == NULL
)
239 ohshit(_("archive has no newlines in header"));
240 errstr
= deb_version_parse(&version
, versionbuf
);
242 ohshit(_("archive has invalid format version: %s"), errstr
);
244 r
= read_line(ar
->fd
, ctrllenbuf
, 1, sizeof(ctrllenbuf
) - 1);
246 read_fail(r
, debar
, _("archive control member size"));
247 if (sscanf(ctrllenbuf
, "%jd%c%d", (intmax_t *)&ctrllennum
, &nlc
, &dummy
) != 2 ||
249 ohshit(_("archive has malformed control member size '%s'"), ctrllenbuf
);
252 memberlen
= ctrllennum
;
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
,
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>"));
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"));
274 ohshit(_("'%.255s' is not a debian format archive"), debar
);
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"),
287 ohshite(_("cannot close decompressor pipe"));
291 close_shadow(ar
->fd
);
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");
308 decompress_filter(decompressor
, p1
[0], p2_out
,
309 _("decompressing archive member"));
314 if (taroption
) close(p2
[1]);
321 command_init(&cmd
, TAR
, "tar");
322 command_add_arg(&cmd
, "tar");
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");
331 internerr("unknown or missing tar action '%d'", taroption
);
333 if (taroption
& DPKG_TAR_PERMS
)
334 command_add_arg(&cmd
, "-p");
335 if (taroption
& DPKG_TAR_NOMTIME
)
336 command_add_arg(&cmd
, "-m");
338 command_add_arg(&cmd
, "-f");
339 command_add_arg(&cmd
, "-");
340 command_add_arg(&cmd
, "--warning=no-timestamp");
345 unsetenv("TAR_OPTIONS");
348 if (mkdir(dir
, 0777) != 0) {
350 ohshite(_("failed to create directory"));
352 if (taroption
& DPKG_TAR_CREATE_DIR
)
353 ohshite(_("unexpected pre-existing pathname %s"), dir
);
356 ohshite(_("failed to chdir to directory"));
362 subproc_reap(c3
, "tar", 0);
365 subproc_reap(c2
, _("<decompress>"), SUBPROC_NOPIPE
);
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)
375 if (version
.minor
== 931)
376 movecontrolfiles(OLDOLDDEBDIR
);
377 else if (version
.minor
== 932 || version
.minor
== 933)
378 movecontrolfiles(OLDDEBDIR
);
383 do_ctrltarfile(const char *const *argv
)
389 badusage(_("--%s needs a .deb filename argument"), cipaction
->olong
);
391 badusage(_("--%s takes only one argument (.deb filename)"),
394 extracthalf(debar
, NULL
, DPKG_TAR_PASSTHROUGH
, 1);
400 do_fsystarfile(const char *const *argv
)
406 badusage(_("--%s needs a .deb filename argument"),cipaction
->olong
);
408 badusage(_("--%s takes only one argument (.deb filename)"),cipaction
->olong
);
409 extracthalf(debar
, NULL
, DPKG_TAR_PASSTHROUGH
, 0);
415 do_control(const char *const *argv
)
417 const char *debar
, *dir
;
421 badusage(_("--%s needs a .deb filename argument"), cipaction
->olong
);
425 dir
= EXTRACTCONTROLDIR
;
427 badusage(_("--%s takes at most two arguments (.deb and directory)"),
430 extracthalf(debar
, dir
, DPKG_TAR_EXTRACT
, 1);
436 do_extract(const char *const *argv
)
438 const char *debar
, *dir
;
439 enum dpkg_tar_options options
= DPKG_TAR_EXTRACT
| DPKG_TAR_PERMS
;
442 options
|= DPKG_TAR_LIST
;
446 badusage(_("--%s needs .deb filename and directory arguments"),
451 badusage(_("--%s needs a target directory.\n"
452 "Perhaps you should be using dpkg --install ?"),
455 badusage(_("--%s takes at most two arguments (.deb and directory)"),
458 extracthalf(debar
, dir
, options
, 0);
464 do_vextract(const char *const *argv
)
466 /* XXX: Backward compatibility. */
468 return do_extract(argv
);
472 do_raw_extract(const char *const *argv
)
474 enum dpkg_tar_options data_options
;
475 const char *debar
, *dir
;
480 badusage(_("--%s needs .deb filename and directory arguments"),
482 else if (strcmp(debar
, "-") == 0)
483 badusage(_("--%s does not support (yet) reading the .deb from standard input"),
488 badusage(_("--%s needs a target directory.\n"
489 "Perhaps you should be using dpkg --install ?"),
492 badusage(_("--%s takes at most two arguments (.deb and directory)"),
495 control_dir
= str_fmt("%s/%s", dir
, EXTRACTCONTROLDIR
);
497 data_options
= DPKG_TAR_EXTRACT
| DPKG_TAR_PERMS
;
499 data_options
|= DPKG_TAR_LIST
;
501 extracthalf(debar
, dir
, data_options
, 0);
502 extracthalf(debar
, control_dir
, DPKG_TAR_EXTRACT
| DPKG_TAR_CREATE_DIR
, 1);