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