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);
126 r = read_line(ar->fd, versionbuf, strlen(DPKG_AR_MAGIC), sizeof(versionbuf) - 1);
128 read_fail(r, debar, _("archive magic version number"));
130 if (strcmp(versionbuf, DPKG_AR_MAGIC) == 0) {
134 struct dpkg_ar_hdr arh;
136 r = fd_read(ar->fd, &arh, sizeof(arh));
137 if (r != sizeof(arh))
138 read_fail(r, debar, _("archive member header"));
140 dpkg_ar_normalize_name(&arh);
142 if (dpkg_ar_member_is_illegal(&arh))
143 ohshit(_("file '%.250s' is corrupt - bad archive header magic"), debar);
144 memberlen = dpkg_ar_member_get_size(ar, &arh);
148 if (strncmp(arh.ar_name, DEBMAGIC, sizeof(arh.ar_name)) != 0)
149 ohshit(_("file '%.250s' is not a debian binary archive (try dpkg-split?)"),
151 infobuf= m_malloc(memberlen+1);
152 r = fd_read(ar->fd, infobuf, memberlen + (memberlen & 1));
153 if (r != (memberlen + (memberlen & 1)))
154 read_fail(r, debar, _("archive information header member"));
155 infobuf[memberlen] = '\0';
157 if (strchr(infobuf, '\n') == NULL)
158 ohshit(_("archive has no newlines in header"));
159 errstr = deb_version_parse(&version, infobuf);
161 ohshit(_("archive has invalid format version: %s"), errstr);
162 if (version.major != 2)
163 ohshit(_("archive is format version %d.%d; get a newer dpkg-deb"),
164 version.major, version.minor);
169 } else if (arh.ar_name[0] == '_') {
170 /* Members with ‘_’ are noncritical, and if we don't understand
171 * them we skip them. */
172 if (fd_skip(ar->fd, memberlen + (memberlen & 1), &err) < 0)
173 ohshit(_("cannot skip archive member from '%s': %s"), ar->name, err.str);
175 if (strncmp(arh.ar_name, ADMINMEMBER, strlen(ADMINMEMBER)) == 0) {
176 const char *extension = arh.ar_name + strlen(ADMINMEMBER);
179 decompressor = compressor_find_by_extension(extension);
180 if (decompressor != COMPRESSOR_TYPE_NONE &&
181 decompressor != COMPRESSOR_TYPE_GZIP &&
182 decompressor != COMPRESSOR_TYPE_XZ)
183 ohshit(_("archive '%s' uses unknown compression for member '%.*s', "
185 debar, (int)sizeof(arh.ar_name), arh.ar_name);
187 if (adminmember != 1)
188 ohshit(_("archive '%s' has premature member '%.*s' before '%s', "
190 debar, (int)sizeof(arh.ar_name), arh.ar_name, ADMINMEMBER);
192 if (strncmp(arh.ar_name, DATAMEMBER, strlen(DATAMEMBER)) == 0) {
193 const char *extension = arh.ar_name + strlen(DATAMEMBER);
196 decompressor = compressor_find_by_extension(extension);
197 if (decompressor == COMPRESSOR_TYPE_UNKNOWN)
198 ohshit(_("archive '%s' uses unknown compression for member '%.*s', "
200 debar, (int)sizeof(arh.ar_name), arh.ar_name);
202 ohshit(_("archive '%s' has premature member '%.*s' before '%s', "
204 debar, (int)sizeof(arh.ar_name), arh.ar_name, DATAMEMBER);
207 if (adminmember == 1) {
209 ohshit(_("archive '%.250s' contains two control members, giving up"),
211 ctrllennum= memberlen;
213 if (!adminmember != !admininfo) {
214 if (fd_skip(ar->fd, memberlen + (memberlen & 1), &err) < 0)
215 ohshit(_("cannot skip archive member from '%s': %s"), ar->name, err.str);
217 /* Yes! - found it. */
223 if (admininfo >= 2) {
224 printf(_(" new debian package, version %d.%d.\n"
225 " size %jd bytes: control archive=%jd bytes.\n"),
226 version.major, version.minor,
227 (intmax_t)ar->size, (intmax_t)ctrllennum);
228 m_output(stdout, _("<standard output>"));
230 } else if (strncmp(versionbuf, "0.93", 4) == 0) {
234 l = strlen(versionbuf);
236 if (strchr(versionbuf, '\n') == NULL)
237 ohshit(_("archive has no newlines in header"));
238 errstr = deb_version_parse(&version, versionbuf);
240 ohshit(_("archive has invalid format version: %s"), errstr);
242 r = read_line(ar->fd, ctrllenbuf, 1, sizeof(ctrllenbuf) - 1);
244 read_fail(r, debar, _("archive control member size"));
245 if (sscanf(ctrllenbuf, "%jd%c%d", (intmax_t *)&ctrllennum, &nlc, &dummy) != 2 ||
247 ohshit(_("archive has malformed control member size '%s'"), ctrllenbuf);
250 memberlen = ctrllennum;
252 memberlen = ar->size - ctrllennum - strlen(ctrllenbuf) - l;
253 if (fd_skip(ar->fd, ctrllennum, &err) < 0)
254 ohshit(_("cannot skip archive control member from '%s': %s"), ar->name,
258 if (admininfo >= 2) {
259 printf(_(" old debian package, version %d.%d.\n"
260 " size %jd bytes: control archive=%jd, main archive=%jd.\n"),
261 version.major, version.minor,
262 (intmax_t)ar->size, (intmax_t)ctrllennum,
263 (intmax_t)(ar->size - ctrllennum - strlen(ctrllenbuf) - l));
264 m_output(stdout, _("<standard output>"));
267 if (strncmp(versionbuf, "!<arch>", 7) == 0) {
268 notice(_("file looks like it might be an archive which has been\n"
269 " corrupted by being downloaded in ASCII mode"));
272 ohshit(_("'%.255s' is not a debian format archive"), debar);
279 if (fd_fd_copy(ar->fd, p1[1], memberlen, &err) < 0)
280 ohshit(_("cannot copy archive member from '%s' to decompressor pipe: %s"),
283 ohshite(_("cannot close decompressor pipe"));
299 decompress_filter(decompressor, p1[0], p2_out,
300 _("decompressing archive member"));
305 if (taroption) close(p2[1]);
312 command_init(&cmd, TAR, "tar");
313 command_add_arg(&cmd, "tar");
315 if ((taroption & DPKG_TAR_LIST) && (taroption & DPKG_TAR_EXTRACT))
316 command_add_arg(&cmd, "-xv");
317 else if (taroption & DPKG_TAR_EXTRACT)
318 command_add_arg(&cmd, "-x");
319 else if (taroption & DPKG_TAR_LIST)
320 command_add_arg(&cmd, "-tv");
322 internerr("unknown or missing tar action '%d'", taroption);
324 if (taroption & DPKG_TAR_PERMS)
325 command_add_arg(&cmd, "-p");
326 if (taroption & DPKG_TAR_NOMTIME)
327 command_add_arg(&cmd, "-m");
329 command_add_arg(&cmd, "-f");
330 command_add_arg(&cmd, "-");
331 command_add_arg(&cmd, "--warning=no-timestamp");
336 unsetenv("TAR_OPTIONS");
339 if (mkdir(dir, 0777) != 0) {
341 ohshite(_("failed to create directory"));
343 if (taroption & DPKG_TAR_CREATE_DIR)
344 ohshite(_("unexpected pre-existing pathname %s"), dir);
347 ohshite(_("failed to chdir to directory"));
353 subproc_reap(c3, "tar", 0);
356 subproc_reap(c2, _("<decompress>"), SUBPROC_NOPIPE);
358 subproc_reap(c1, _("paste"), 0);
359 if (version.major == 0 && admininfo) {
360 /* Handle the version as a float to preserve the behaviour of old code,
361 * because even if the format is defined to be padded by 0's that might
362 * not have been always true for really ancient versions... */
363 while (version.minor && (version.minor % 10) == 0)
366 if (version.minor == 931)
367 movecontrolfiles(OLDOLDDEBDIR);
368 else if (version.minor == 932 || version.minor == 933)
369 movecontrolfiles(OLDDEBDIR);
374 do_ctrltarfile(const char *const *argv)
380 badusage(_("--%s needs a .deb filename argument"), cipaction->olong);
382 badusage(_("--%s takes only one argument (.deb filename)"),
385 extracthalf(debar, NULL, DPKG_TAR_PASSTHROUGH, 1);
391 do_fsystarfile(const char *const *argv)
397 badusage(_("--%s needs a .deb filename argument"),cipaction->olong);
399 badusage(_("--%s takes only one argument (.deb filename)"),cipaction->olong);
400 extracthalf(debar, NULL, DPKG_TAR_PASSTHROUGH, 0);
406 do_control(const char *const *argv)
408 const char *debar, *dir;
412 badusage(_("--%s needs a .deb filename argument"), cipaction->olong);
416 dir = EXTRACTCONTROLDIR;
418 badusage(_("--%s takes at most two arguments (.deb and directory)"),
421 extracthalf(debar, dir, DPKG_TAR_EXTRACT, 1);
427 do_extract(const char *const *argv)
429 const char *debar, *dir;
430 enum dpkg_tar_options options = DPKG_TAR_EXTRACT | DPKG_TAR_PERMS;
433 options |= DPKG_TAR_LIST;
437 badusage(_("--%s needs .deb filename and directory arguments"),
442 badusage(_("--%s needs a target directory.\n"
443 "Perhaps you should be using dpkg --install ?"),
446 badusage(_("--%s takes at most two arguments (.deb and directory)"),
449 extracthalf(debar, dir, options, 0);
455 do_vextract(const char *const *argv)
457 /* XXX: Backward compatibility. */
459 return do_extract(argv);
463 do_raw_extract(const char *const *argv)
465 enum dpkg_tar_options data_options;
466 const char *debar, *dir;
471 badusage(_("--%s needs .deb filename and directory arguments"),
473 else if (strcmp(debar, "-") == 0)
474 badusage(_("--%s does not support (yet) reading the .deb from standard input"),
479 badusage(_("--%s needs a target directory.\n"
480 "Perhaps you should be using dpkg --install ?"),
483 badusage(_("--%s takes at most two arguments (.deb and directory)"),
486 control_dir = str_fmt("%s/%s", dir, EXTRACTCONTROLDIR);
488 data_options = DPKG_TAR_EXTRACT | DPKG_TAR_PERMS;
490 data_options |= DPKG_TAR_LIST;
492 extracthalf(debar, dir, data_options, 0);
493 extracthalf(debar, control_dir, DPKG_TAR_EXTRACT | DPKG_TAR_CREATE_DIR, 1);