dpkg (1.18.25) stretch; urgency=medium
[dpkg] / dpkg-deb / build.c
CommitLineData
1479465f
GJ
1/*
2 * dpkg-deb - construction and deconstruction of *.deb archives
3 * build.c - building archives
4 *
5 * Copyright © 1994,1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
6 * Copyright © 2000,2001 Wichert Akkerman <wakkerma@debian.org>
7 * Copyright © 2007-2015 Guillem Jover <guillem@debian.org>
8 *
9 * This is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 */
22
23#include <config.h>
24#include <compat.h>
25
26#include <sys/types.h>
27#include <sys/stat.h>
28#include <sys/wait.h>
29
30#include <errno.h>
31#include <limits.h>
32#include <string.h>
33#include <time.h>
34#include <dirent.h>
35#include <fcntl.h>
36#include <unistd.h>
37#include <stdbool.h>
38#include <stdint.h>
39#include <stdlib.h>
40#include <stdio.h>
41
42#include <dpkg/i18n.h>
43#include <dpkg/c-ctype.h>
44#include <dpkg/dpkg.h>
45#include <dpkg/dpkg-db.h>
46#include <dpkg/path.h>
47#include <dpkg/treewalk.h>
48#include <dpkg/varbuf.h>
49#include <dpkg/fdio.h>
50#include <dpkg/buffer.h>
51#include <dpkg/subproc.h>
52#include <dpkg/command.h>
53#include <dpkg/compress.h>
54#include <dpkg/ar.h>
55#include <dpkg/options.h>
56
57#include "dpkg-deb.h"
58
59static void
60control_treewalk_feed(const char *dir, int fd_out)
61{
62 struct treeroot *tree;
63 struct treenode *node;
64
65 tree = treewalk_open(dir, TREEWALK_NONE, NULL);
66 for (node = treewalk_node(tree); node; node = treewalk_next(tree)) {
67 char *nodename;
68
69 nodename = str_fmt("./%s", treenode_get_virtname(node));
70 if (fd_write(fd_out, nodename, strlen(nodename) + 1) < 0)
71 ohshite(_("failed to write filename to tar pipe (%s)"),
72 _("control member"));
73 free(nodename);
74 }
75 treewalk_close(tree);
76}
77
78/**
79 * Simple structure to store information about a file.
80 */
81struct file_info {
82 struct file_info *next;
83 char *fn;
84};
85
86static struct file_info *
87file_info_new(const char *filename)
88{
89 struct file_info *fi;
90
91 fi = m_malloc(sizeof(*fi));
92 fi->fn = m_strdup(filename);
93 fi->next = NULL;
94
95 return fi;
96}
97
98static void
99file_info_free(struct file_info *fi)
100{
101 free(fi->fn);
102 free(fi);
103}
104
105static struct file_info *
106file_info_find_name(struct file_info *list, const char *filename)
107{
108 struct file_info *node;
109
110 for (node = list; node; node = node->next)
111 if (strcmp(node->fn, filename) == 0)
112 return node;
113
114 return NULL;
115}
116
117/**
118 * Add a new file_info struct to a single linked list of file_info structs.
119 *
120 * We perform a slight optimization to work around a ‘feature’ in tar: tar
121 * always recurses into subdirectories if you list a subdirectory. So if an
122 * entry is added and the previous entry in the list is its subdirectory we
123 * remove the subdirectory.
124 *
125 * After a file_info struct is added to a list it may no longer be freed, we
126 * assume full responsibility for its memory.
127 */
128static void
129file_info_list_append(struct file_info **head, struct file_info **tail,
130 struct file_info *fi)
131{
132 if (*head == NULL)
133 *head = *tail = fi;
134 else
135 *tail = (*tail)->next =fi;
136}
137
138/**
139 * Free the memory for all entries in a list of file_info structs.
140 */
141static void
142file_info_list_free(struct file_info *fi)
143{
144 while (fi) {
145 struct file_info *fl;
146
147 fl=fi; fi=fi->next;
148 file_info_free(fl);
149 }
150}
151
152static void
153file_treewalk_feed(const char *dir, int fd_out)
154{
155 struct treeroot *tree;
156 struct treenode *node;
157 struct file_info *fi;
158 struct file_info *symlist = NULL;
159 struct file_info *symlist_end = NULL;
160
161 tree = treewalk_open(dir, TREEWALK_NONE, NULL);
162 for (node = treewalk_node(tree); node ; node = treewalk_next(tree)) {
163 const char *virtname = treenode_get_virtname(node);
164 char *nodename;
165
166 if (strncmp(virtname, BUILDCONTROLDIR, strlen(BUILDCONTROLDIR)) == 0)
167 continue;
168
169 nodename = str_fmt("./%s", virtname);
170
171 if (strchr(nodename, '\n'))
172 ohshit(_("newline not allowed in pathname '%s'"), nodename);
173
174 /* We need to reorder the files so we can make sure that symlinks
175 * will not appear before their target. */
176 if (S_ISLNK(treenode_get_mode(node))) {
177 fi = file_info_new(nodename);
178 file_info_list_append(&symlist, &symlist_end, fi);
179 } else {
180 if (fd_write(fd_out, nodename, strlen(nodename) + 1) < 0)
181 ohshite(_("failed to write filename to tar pipe (%s)"),
182 _("data member"));
183 }
184
185 free(nodename);
186 }
187 treewalk_close(tree);
188
189 for (fi = symlist; fi; fi = fi->next)
190 if (fd_write(fd_out, fi->fn, strlen(fi->fn) + 1) < 0)
191 ohshite(_("failed to write filename to tar pipe (%s)"), _("data member"));
192
193 file_info_list_free(symlist);
194}
195
196static const char *const maintainerscripts[] = {
197 PREINSTFILE,
198 POSTINSTFILE,
199 PRERMFILE,
200 POSTRMFILE,
201 NULL,
202};
203
204/**
205 * Check control directory and file permissions.
206 */
207static void
208check_file_perms(const char *ctrldir)
209{
210 struct varbuf path = VARBUF_INIT;
211 const char *const *mscriptp;
212 struct stat mscriptstab;
213
214 varbuf_printf(&path, "%s/", ctrldir);
215 if (lstat(path.buf, &mscriptstab))
216 ohshite(_("unable to stat control directory"));
217 if (!S_ISDIR(mscriptstab.st_mode))
218 ohshit(_("control directory is not a directory"));
219 if ((mscriptstab.st_mode & 07757) != 0755)
220 ohshit(_("control directory has bad permissions %03lo "
221 "(must be >=0755 and <=0775)"),
222 (unsigned long)(mscriptstab.st_mode & 07777));
223
224 for (mscriptp = maintainerscripts; *mscriptp; mscriptp++) {
225 varbuf_reset(&path);
226 varbuf_printf(&path, "%s/%s", ctrldir, *mscriptp);
227 if (!lstat(path.buf, &mscriptstab)) {
228 if (S_ISLNK(mscriptstab.st_mode))
229 continue;
230 if (!S_ISREG(mscriptstab.st_mode))
231 ohshit(_("maintainer script '%.50s' is not a plain file or symlink"),
232 *mscriptp);
233 if ((mscriptstab.st_mode & 07557) != 0555)
234 ohshit(_("maintainer script '%.50s' has bad permissions %03lo "
235 "(must be >=0555 and <=0775)"),
236 *mscriptp, (unsigned long)(mscriptstab.st_mode & 07777));
237 } else if (errno != ENOENT) {
238 ohshite(_("maintainer script '%.50s' is not stattable"), *mscriptp);
239 }
240 }
241
242 varbuf_destroy(&path);
243}
244
245/**
246 * Check if conffiles contains sane information.
247 */
248static void
249check_conffiles(const char *ctrldir, const char *rootdir)
250{
251 FILE *cf;
252 struct varbuf controlfile = VARBUF_INIT;
253 char conffilename[MAXCONFFILENAME + 1];
254 struct file_info *conffiles_head = NULL;
255 struct file_info *conffiles_tail = NULL;
256
257 varbuf_printf(&controlfile, "%s/%s", ctrldir, CONFFILESFILE);
258
259 cf = fopen(controlfile.buf, "r");
260 if (cf == NULL) {
261 if (errno == ENOENT)
262 return;
263
264 ohshite(_("error opening conffiles file"));
265 }
266
267 while (fgets(conffilename, MAXCONFFILENAME + 1, cf)) {
268 struct stat controlstab;
269 int n;
270
271 n = strlen(conffilename);
272 if (!n)
273 ohshite(_("empty string from fgets reading conffiles"));
274
275 if (conffilename[n - 1] != '\n')
276 ohshit(_("conffile name '%s' is too long, or missing final newline"),
277 conffilename);
278
279 conffilename[n - 1] = '\0';
280 varbuf_reset(&controlfile);
281 varbuf_printf(&controlfile, "%s/%s", rootdir, conffilename);
282 if (lstat(controlfile.buf, &controlstab)) {
283 if (errno == ENOENT) {
284 if ((n > 1) && c_isspace(conffilename[n - 2]))
285 warning(_("conffile filename '%s' contains trailing white spaces"),
286 conffilename);
287 ohshit(_("conffile '%.250s' does not appear in package"), conffilename);
288 } else
289 ohshite(_("conffile '%.250s' is not stattable"), conffilename);
290 } else if (!S_ISREG(controlstab.st_mode)) {
291 warning(_("conffile '%s' is not a plain file"), conffilename);
292 }
293
294 if (file_info_find_name(conffiles_head, conffilename)) {
295 warning(_("conffile name '%s' is duplicated"), conffilename);
296 } else {
297 struct file_info *conffile;
298
299 conffile = file_info_new(conffilename);
300 file_info_list_append(&conffiles_head, &conffiles_tail, conffile);
301 }
302 }
303
304 file_info_list_free(conffiles_head);
305 varbuf_destroy(&controlfile);
306
307 if (ferror(cf))
308 ohshite(_("error reading conffiles file"));
309 fclose(cf);
310}
311
312/**
313 * Check the control file.
314 *
315 * @param dir The directory from where to build the binary package.
316 * @return The pkginfo struct from the parsed control file.
317 */
318static struct pkginfo *
319check_control_file(const char *ctrldir)
320{
321 struct pkginfo *pkg;
322 char *controlfile;
323
324 controlfile = str_fmt("%s/%s", ctrldir, CONTROLFILE);
325 parsedb(controlfile, pdb_parse_binary, &pkg);
326
327 if (strspn(pkg->set->name, "abcdefghijklmnopqrstuvwxyz0123456789+-.") !=
328 strlen(pkg->set->name))
329 ohshit(_("package name has characters that aren't lowercase alphanums or '-+.'"));
330 if (pkg->available.arch->type == DPKG_ARCH_NONE ||
331 pkg->available.arch->type == DPKG_ARCH_EMPTY)
332 ohshit(_("package architecture is missing or empty"));
333 if (pkg->priority == PKG_PRIO_OTHER)
334 warning(_("'%s' contains user-defined Priority value '%s'"),
335 controlfile, pkg->otherpriority);
336
337 free(controlfile);
338
339 return pkg;
340}
341
342/**
343 * Perform some sanity checks on the to-be-built package control area.
344 *
345 * @param dir The directory from where to build the binary package.
346 * @return The pkginfo struct from the parsed control file.
347 */
348static struct pkginfo *
349check_control_area(const char *ctrldir, const char *rootdir)
350{
351 struct pkginfo *pkg;
352 int warns;
353
354 /* Start by reading in the control file so we can check its contents. */
355 pkg = check_control_file(ctrldir);
356 check_file_perms(ctrldir);
357 check_conffiles(ctrldir, rootdir);
358
359 warns = warning_get_count();
360 if (warns)
361 warning(P_("ignoring %d warning about the control file(s)",
362 "ignoring %d warnings about the control file(s)", warns),
363 warns);
364
365 return pkg;
366}
367
368/**
369 * Generate the pathname for the destination binary package.
370 *
371 * If the pathname cannot be computed, because the destination is a directory,
372 * then NULL will be returned.
373 *
374 * @param dir The directory from where to build the binary package.
375 * @param dest The destination name, either a file or directory name.
376 * @return The pathname for the package being built.
377 */
378static char *
379gen_dest_pathname(const char *dir, const char *dest)
380{
381 if (dest) {
382 struct stat dest_stab;
383
384 if (stat(dest, &dest_stab)) {
385 if (errno != ENOENT)
386 ohshite(_("unable to check for existence of archive '%.250s'"), dest);
387 } else if (S_ISDIR(dest_stab.st_mode)) {
388 /* Need to compute the destination name from the package control file. */
389 return NULL;
390 }
391
392 return m_strdup(dest);
393 } else {
394 char *pathname;
395
396 pathname = m_malloc(strlen(dir) + sizeof(DEBEXT));
397 strcpy(pathname, dir);
398 path_trim_slash_slashdot(pathname);
399 strcat(pathname, DEBEXT);
400
401 return pathname;
402 }
403}
404
405/**
406 * Generate the pathname for the destination binary package from control file.
407 *
408 * @return The pathname for the package being built.
409 */
410static char *
411gen_dest_pathname_from_pkg(const char *dir, struct pkginfo *pkg)
412{
413 return str_fmt("%s/%s_%s_%s%s", dir, pkg->set->name,
414 versiondescribe(&pkg->available.version, vdew_never),
415 pkg->available.arch->name, DEBEXT);
416}
417
418typedef void filenames_feed_func(const char *dir, int fd_out);
419
420/**
421 * Pack the contents of a directory into a tarball.
422 */
423static void
424tarball_pack(const char *dir, filenames_feed_func *tar_filenames_feeder,
425 time_t timestamp, const char *mode,
426 struct compress_params *tar_compress_params, int fd_out)
427{
428 int pipe_filenames[2], pipe_tarball[2];
429 pid_t pid_tar, pid_comp;
430
431 /* Fork off a tar. We will feed it a list of filenames on stdin later. */
432 m_pipe(pipe_filenames);
433 m_pipe(pipe_tarball);
434 pid_tar = subproc_fork();
435 if (pid_tar == 0) {
436 struct command cmd;
437 char mtime[50];
438
439 m_dup2(pipe_filenames[0], 0);
440 close(pipe_filenames[0]);
441 close(pipe_filenames[1]);
442 m_dup2(pipe_tarball[1], 1);
443 close(pipe_tarball[0]);
444 close(pipe_tarball[1]);
445
446 if (chdir(dir))
447 ohshite(_("failed to chdir to '%.255s'"), dir);
448
449 snprintf(mtime, sizeof(mtime), "@%ld", timestamp);
450
451 command_init(&cmd, TAR, "tar -cf");
452 command_add_args(&cmd, "tar", "-cf", "-", "--format=gnu",
453 "--mtime", mtime, "--clamp-mtime", NULL);
454 /* Mode might become a positional argument, pass it before -T. */
455 if (mode)
456 command_add_args(&cmd, "--mode", mode, NULL);
457 command_add_args(&cmd, "--null", "--no-unquote", "--no-recursion",
458 "-T", "-", NULL);
459 command_exec(&cmd);
460 }
461 close(pipe_filenames[0]);
462 close(pipe_tarball[1]);
463
464 /* Of course we should not forget to compress the archive as well. */
465 pid_comp = subproc_fork();
466 if (pid_comp == 0) {
467 close(pipe_filenames[1]);
468 compress_filter(tar_compress_params, pipe_tarball[0], fd_out,
469 _("compressing tar member"));
470 exit(0);
471 }
472 close(pipe_tarball[0]);
473
474 /* All the pipes are set, now lets start feeding filenames to tar. */
475 tar_filenames_feeder(dir, pipe_filenames[1]);
476
477 /* All done, clean up wait for tar and <compress> to finish their job. */
478 close(pipe_filenames[1]);
479 subproc_reap(pid_comp, _("<compress> from tar -cf"), 0);
480 subproc_reap(pid_tar, "tar -cf", 0);
481}
482
483static time_t
484parse_timestamp(const char *value)
485{
486 time_t timestamp;
487 char *end;
488
489 errno = 0;
490 timestamp = strtol(value, &end, 10);
491 if (value == end || *end || errno != 0)
492 ohshite(_("unable to parse timestamp '%.255s'"), value);
493
494 return timestamp;
495}
496
497/**
498 * Overly complex function that builds a .deb file.
499 */
500int
501do_build(const char *const *argv)
502{
503 struct compress_params control_compress_params;
504 struct dpkg_error err;
505 struct dpkg_ar *ar;
506 time_t timestamp;
507 const char *timestamp_str;
508 const char *dir, *dest;
509 char *ctrldir;
510 char *debar;
511 char *tfbuf;
512 int gzfd;
513
514 /* Decode our arguments. */
515 dir = *argv++;
516 if (!dir)
517 badusage(_("--%s needs a <directory> argument"), cipaction->olong);
518
519 dest = *argv++;
520 if (dest && *argv)
521 badusage(_("--%s takes at most two arguments"), cipaction->olong);
522
523 debar = gen_dest_pathname(dir, dest);
524 ctrldir = str_fmt("%s/%s", dir, BUILDCONTROLDIR);
525
526 /* Perform some sanity checks on the to-be-build package. */
527 if (nocheckflag) {
528 if (debar == NULL)
529 ohshit(_("target is directory - cannot skip control file check"));
530 warning(_("not checking contents of control area"));
531 info(_("building an unknown package in '%s'."), debar);
532 } else {
533 struct pkginfo *pkg;
534
535 pkg = check_control_area(ctrldir, dir);
536 if (debar == NULL)
537 debar = gen_dest_pathname_from_pkg(dest, pkg);
538 info(_("building package '%s' in '%s'."), pkg->set->name, debar);
539 }
540 m_output(stdout, _("<standard output>"));
541
542 timestamp_str = getenv("SOURCE_DATE_EPOCH");
543 if (timestamp_str)
544 timestamp = parse_timestamp(timestamp_str);
545 else
546 timestamp = time(NULL);
547
548 /* Now that we have verified everything it is time to actually
549 * build something. Let's start by making the ar-wrapper. */
550 ar = dpkg_ar_create(debar, 0644);
551
552 dpkg_ar_set_mtime(ar, timestamp);
553
554 unsetenv("TAR_OPTIONS");
555
556 /* Create a temporary file to store the control data in. Immediately
557 * unlink our temporary file so others can't mess with it. */
558 tfbuf = path_make_temp_template("dpkg-deb");
559 gzfd = mkstemp(tfbuf);
560 if (gzfd == -1)
561 ohshite(_("failed to make temporary file (%s)"), _("control member"));
562 /* Make sure it's gone, the fd will remain until we close it. */
563 if (unlink(tfbuf))
564 ohshit(_("failed to unlink temporary file (%s), %s"), _("control member"),
565 tfbuf);
566 free(tfbuf);
567
568 /* Select the compressor to use for our control archive. */
569 if (opt_uniform_compression) {
570 control_compress_params = compress_params;
571 } else {
572 control_compress_params.type = COMPRESSOR_TYPE_GZIP;
573 control_compress_params.strategy = COMPRESSOR_STRATEGY_NONE;
574 control_compress_params.level = -1;
575 if (!compressor_check_params(&control_compress_params, &err))
576 internerr("invalid control member compressor params: %s", err.str);
577 }
578
579 /* Fork a tar to package the control-section of the package. */
580 tarball_pack(ctrldir, control_treewalk_feed, timestamp, "u+rw,go=rX",
581 &control_compress_params, gzfd);
582
583 free(ctrldir);
584
585 if (lseek(gzfd, 0, SEEK_SET))
586 ohshite(_("failed to rewind temporary file (%s)"), _("control member"));
587
588 /* We have our first file for the ar-archive. Write a header for it
589 * to the package and insert it. */
590 if (deb_format.major == 0) {
591 struct stat controlstab;
592 char versionbuf[40];
593
594 if (fstat(gzfd, &controlstab))
595 ohshite(_("failed to stat temporary file (%s)"), _("control member"));
596 sprintf(versionbuf, "%-8s\n%jd\n", OLDARCHIVEVERSION,
597 (intmax_t)controlstab.st_size);
598 if (fd_write(ar->fd, versionbuf, strlen(versionbuf)) < 0)
599 ohshite(_("error writing '%s'"), debar);
600 if (fd_fd_copy(gzfd, ar->fd, -1, &err) < 0)
601 ohshit(_("cannot copy '%s' into archive '%s': %s"), _("control member"),
602 ar->name, err.str);
603 } else if (deb_format.major == 2) {
604 const char deb_magic[] = ARCHIVEVERSION "\n";
605 char adminmember[16 + 1];
606
607 sprintf(adminmember, "%s%s", ADMINMEMBER,
608 compressor_get_extension(control_compress_params.type));
609
610 dpkg_ar_put_magic(ar);
611 dpkg_ar_member_put_mem(ar, DEBMAGIC, deb_magic, strlen(deb_magic));
612 dpkg_ar_member_put_file(ar, adminmember, gzfd, -1);
613 } else {
614 internerr("unknown deb format version %d.%d", deb_format.major, deb_format.minor);
615 }
616
617 close(gzfd);
618
619 /* Control is done, now we need to archive the data. */
620 if (deb_format.major == 0) {
621 /* In old format, the data member is just concatenated after the
622 * control member, so we do not need a temporary file and can use
623 * the compression file descriptor. */
624 gzfd = ar->fd;
625 } else if (deb_format.major == 2) {
626 /* Start by creating a new temporary file. Immediately unlink the
627 * temporary file so others can't mess with it. */
628 tfbuf = path_make_temp_template("dpkg-deb");
629 gzfd = mkstemp(tfbuf);
630 if (gzfd == -1)
631 ohshite(_("failed to make temporary file (%s)"), _("data member"));
632 /* Make sure it's gone, the fd will remain until we close it. */
633 if (unlink(tfbuf))
634 ohshit(_("failed to unlink temporary file (%s), %s"), _("data member"),
635 tfbuf);
636 free(tfbuf);
637 } else {
638 internerr("unknown deb format version %d.%d", deb_format.major, deb_format.minor);
639 }
640
641 /* Pack the directory into a tarball, feeding files from the callback. */
642 tarball_pack(dir, file_treewalk_feed, timestamp, NULL, &compress_params, gzfd);
643
644 /* Okay, we have data.tar as well now, add it to the ar wrapper. */
645 if (deb_format.major == 2) {
646 char datamember[16 + 1];
647
648 sprintf(datamember, "%s%s", DATAMEMBER,
649 compressor_get_extension(compress_params.type));
650
651 if (lseek(gzfd, 0, SEEK_SET))
652 ohshite(_("failed to rewind temporary file (%s)"), _("data member"));
653
654 dpkg_ar_member_put_file(ar, datamember, gzfd, -1);
655
656 close(gzfd);
657 }
658 if (fsync(ar->fd))
659 ohshite(_("unable to sync file '%s'"), ar->name);
660
661 dpkg_ar_close(ar);
662
663 free(debar);
664
665 return 0;
666}