summaryrefslogtreecommitdiffstats
path: root/src/deb/info.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 18:35:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 18:35:28 +0000
commitea314d2f45c40a006c0104157013ab4b857f665f (patch)
tree3ef2971cb3675c318b8d9effd987854ad3f6d3e8 /src/deb/info.c
parentInitial commit. (diff)
downloaddpkg-ea314d2f45c40a006c0104157013ab4b857f665f.tar.xz
dpkg-ea314d2f45c40a006c0104157013ab4b857f665f.zip
Adding upstream version 1.22.4.upstream/1.22.4
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/deb/info.c')
-rw-r--r--src/deb/info.c341
1 files changed, 341 insertions, 0 deletions
diff --git a/src/deb/info.c b/src/deb/info.c
new file mode 100644
index 0000000..6598663
--- /dev/null
+++ b/src/deb/info.c
@@ -0,0 +1,341 @@
+/*
+ * dpkg-deb - construction and deconstruction of *.deb archives
+ * info.c - providing information
+ *
+ * Copyright © 1994,1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
+ * Copyright © 2001 Wichert Akkerman
+ * Copyright © 2007-2015 Guillem Jover <guillem@debian.org>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <compat.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <dpkg/i18n.h>
+#include <dpkg/c-ctype.h>
+#include <dpkg/dpkg.h>
+#include <dpkg/dpkg-db.h>
+#include <dpkg/parsedump.h>
+#include <dpkg/pkg-format.h>
+#include <dpkg/buffer.h>
+#include <dpkg/path.h>
+#include <dpkg/options.h>
+
+#include "dpkg-deb.h"
+
+static void cu_info_prepare(int argc, void **argv) {
+ char *dir;
+
+ dir = argv[0];
+ path_remove_tree(dir);
+ free(dir);
+}
+
+static void info_prepare(const char *const **argvp,
+ const char **debarp,
+ const char **dirp,
+ int admininfo) {
+ char *dbuf;
+
+ *debarp= *(*argvp)++;
+ if (!*debarp) badusage(_("--%s needs a .deb filename argument"),cipaction->olong);
+
+ dbuf = mkdtemp(path_make_temp_template("dpkg-deb"));
+ if (!dbuf)
+ ohshite(_("unable to create temporary directory"));
+ *dirp = dbuf;
+
+ push_cleanup(cu_info_prepare, -1, 1, (void *)dbuf);
+ extracthalf(*debarp, dbuf, DPKG_TAR_EXTRACT | DPKG_TAR_NOMTIME, admininfo);
+}
+
+static int ilist_select(const struct dirent *de) {
+ return strcmp(de->d_name,".") && strcmp(de->d_name,"..");
+}
+
+static void
+info_spew(const char *debar, const char *dir, const char *const *argv)
+{
+ struct dpkg_error err;
+ const char *component;
+ struct varbuf controlfile = VARBUF_INIT;
+ int re= 0;
+
+ while ((component = *argv++) != NULL) {
+ int fd;
+
+ varbuf_reset(&controlfile);
+ varbuf_printf(&controlfile, "%s/%s", dir, component);
+
+ fd = open(controlfile.buf, O_RDONLY);
+ if (fd >= 0) {
+ if (fd_fd_copy(fd, 1, -1, &err) < 0)
+ ohshit(_("cannot extract control file '%s' from '%s': %s"),
+ controlfile.buf, debar, err.str);
+ close(fd);
+ } else if (errno == ENOENT) {
+ notice(_("'%.255s' contains no control component '%.255s'"),
+ debar, component);
+ re++;
+ } else {
+ ohshite(_("open component '%.255s' (in %.255s) failed in an unexpected way"),
+ component, dir);
+ }
+ }
+ varbuf_destroy(&controlfile);
+
+ if (re > 0)
+ ohshit(P_("%d requested control component is missing",
+ "%d requested control components are missing", re), re);
+}
+
+static char *
+info_interpreter(FILE *cc, int *lines)
+{
+ char interpreter[INTERPRETER_MAX + 1];
+ int c;
+
+ *lines = 0;
+ interpreter[0] = '\0';
+ if (getc(cc) == '#' && getc(cc) == '!') {
+ char *p;
+ int il;
+
+ while ((c = getc(cc)) == ' ')
+ ;
+ p = interpreter;
+ *p++ = '#';
+ *p++ = '!';
+ il = 2;
+ while (il < INTERPRETER_MAX && !c_isspace(c) && c != EOF) {
+ *p++ = c;
+ il++;
+ c = getc(cc);
+ }
+ *p = '\0';
+ if (c == '\n')
+ (*lines)++;
+ }
+ while ((c = getc(cc)) != EOF) {
+ if (c == '\n')
+ (*lines)++;
+ }
+
+ return m_strdup(interpreter);
+}
+
+static void
+info_list(const char *debar, const char *dir)
+{
+ struct varbuf controlfile = VARBUF_INIT;
+ struct dirent **cdlist;
+ int cdn, n;
+ FILE *cc;
+
+ cdn = scandir(dir, &cdlist, &ilist_select, alphasort);
+ if (cdn == -1)
+ ohshite(_("cannot scan directory '%.255s'"), dir);
+
+ for (n = 0; n < cdn; n++) {
+ struct dirent *cdep;
+ struct stat stab;
+
+ cdep = cdlist[n];
+
+ varbuf_reset(&controlfile);
+ varbuf_printf(&controlfile, "%s/%s", dir, cdep->d_name);
+
+ if (stat(controlfile.buf, &stab))
+ ohshite(_("cannot stat '%.255s' (in '%.255s')"), cdep->d_name, dir);
+ if (S_ISREG(stab.st_mode)) {
+ int exec_mark = (S_IXUSR & stab.st_mode) ? '*' : ' ';
+ char *interpreter;
+ int lines;
+
+ cc = fopen(controlfile.buf, "r");
+ if (!cc)
+ ohshite(_("cannot open '%.255s' (in '%.255s')"), cdep->d_name, dir);
+
+ interpreter = info_interpreter(cc, &lines);
+
+ if (ferror(cc))
+ ohshite(_("failed to read '%.255s' (in '%.255s')"), cdep->d_name, dir);
+ fclose(cc);
+ if (str_is_set(interpreter))
+ printf(_(" %7jd bytes, %5d lines %c %-20.127s %.127s\n"),
+ (intmax_t)stab.st_size, lines, exec_mark, cdep->d_name,
+ interpreter);
+ else
+ printf(_(" %7jd bytes, %5d lines %c %.127s\n"),
+ (intmax_t)stab.st_size, lines, exec_mark, cdep->d_name);
+
+ free(interpreter);
+ } else {
+ printf(_(" not a plain file %.255s\n"), cdep->d_name);
+ }
+ free(cdep);
+ }
+ free(cdlist);
+
+ varbuf_reset(&controlfile);
+ varbuf_printf(&controlfile, "%s/%s", dir, CONTROLFILE);
+ cc = fopen(controlfile.buf, "r");
+ if (!cc) {
+ if (errno != ENOENT)
+ ohshite(_("failed to read '%.255s' (in '%.255s')"), CONTROLFILE, dir);
+ warning(_("no 'control' file in control archive!"));
+ } else {
+ int lines, c;
+
+ lines= 1;
+ while ((c= getc(cc))!= EOF) {
+ if (lines)
+ putc(' ', stdout);
+ putc(c, stdout);
+ lines= c=='\n';
+ }
+ if (!lines)
+ putc('\n', stdout);
+
+ if (ferror(cc))
+ ohshite(_("failed to read '%.255s' (in '%.255s')"), CONTROLFILE, dir);
+ fclose(cc);
+ }
+
+ m_output(stdout, _("<standard output>"));
+ varbuf_destroy(&controlfile);
+}
+
+static void
+info_field(const char *debar, const char *dir, const char *const *fields,
+ enum fwriteflags fieldflags)
+{
+ char *controlfile;
+ struct varbuf str = VARBUF_INIT;
+ struct pkginfo *pkg;
+ int i;
+
+ controlfile = str_fmt("%s/%s", dir, CONTROLFILE);
+ parsedb(controlfile, pdb_parse_binary | pdb_ignore_archives, &pkg);
+ free(controlfile);
+
+ for (i = 0; fields[i]; i++) {
+ const struct fieldinfo *field;
+
+ varbuf_reset(&str);
+ field = find_field_info(fieldinfos, fields[i]);
+ if (field) {
+ field->wcall(&str, pkg, &pkg->available, fieldflags, field);
+ } else {
+ const struct arbitraryfield *arbfield;
+
+ arbfield = find_arbfield_info(pkg->available.arbs, fields[i]);
+ if (arbfield)
+ varbuf_add_arbfield(&str, arbfield, fieldflags);
+ }
+ varbuf_end_str(&str);
+
+ if (fieldflags & fw_printheader)
+ printf("%s", str.buf);
+ else
+ printf("%s\n", str.buf);
+ }
+
+ m_output(stdout, _("<standard output>"));
+
+ varbuf_destroy(&str);
+}
+
+int
+do_showinfo(const char *const *argv)
+{
+ const char *debar, *dir;
+ char *controlfile;
+ struct dpkg_error err;
+ struct pkginfo *pkg;
+ struct pkg_format_node *fmt;
+
+ fmt = pkg_format_parse(opt_showformat, &err);
+ if (!fmt)
+ ohshit(_("error in show format: %s"), err.str);
+
+ info_prepare(&argv, &debar, &dir, 1);
+
+ controlfile = str_fmt("%s/%s", dir, CONTROLFILE);
+ parsedb(controlfile, pdb_parse_binary | pdb_ignore_archives, &pkg);
+ pkg_format_show(fmt, pkg, &pkg->available);
+ pkg_format_free(fmt);
+ free(controlfile);
+
+ return 0;
+}
+
+int
+do_info(const char *const *argv)
+{
+ const char *debar, *dir;
+
+ if (*argv && argv[1]) {
+ info_prepare(&argv, &debar, &dir, 1);
+ info_spew(debar, dir, argv);
+ } else {
+ info_prepare(&argv, &debar, &dir, 2);
+ info_list(debar, dir);
+ }
+
+ return 0;
+}
+
+int
+do_field(const char *const *argv)
+{
+ const char *debar, *dir;
+
+ info_prepare(&argv, &debar, &dir, 1);
+ if (*argv) {
+ info_field(debar, dir, argv, argv[1] != NULL ? fw_printheader : 0);
+ } else {
+ static const char *const controlonly[] = { CONTROLFILE, NULL };
+ info_spew(debar, dir, controlonly);
+ }
+
+ return 0;
+}
+
+int
+do_contents(const char *const *argv)
+{
+ const char *debar = *argv++;
+
+ if (debar == NULL || *argv)
+ badusage(_("--%s takes exactly one argument"), cipaction->olong);
+ extracthalf(debar, NULL, DPKG_TAR_LIST, 0);
+
+ return 0;
+}