diff options
Diffstat (limited to '')
49 files changed, 828 insertions, 311 deletions
diff --git a/lib/Makefile.in b/lib/Makefile.in index a1a17a6..b881bac 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -89,8 +89,8 @@ build_triplet = @build@ host_triplet = @host@ subdir = lib ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/dpkg-arch.m4 \ - $(top_srcdir)/m4/dpkg-build.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/m4/build-to-host.m4 \ + $(top_srcdir)/m4/dpkg-arch.m4 $(top_srcdir)/m4/dpkg-build.m4 \ $(top_srcdir)/m4/dpkg-compiler.m4 \ $(top_srcdir)/m4/dpkg-coverage.m4 \ $(top_srcdir)/m4/dpkg-funcs.m4 \ @@ -290,6 +290,7 @@ PACKAGE_RELEASE_DATE = @PACKAGE_RELEASE_DATE@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VCS_ID = @PACKAGE_VCS_ID@ PACKAGE_VCS_TYPE = @PACKAGE_VCS_TYPE@ PACKAGE_VCS_URL = @PACKAGE_VCS_URL@ PACKAGE_VCS_WEB = @PACKAGE_VCS_WEB@ @@ -371,6 +372,8 @@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ +localedir_c = @localedir_c@ +localedir_c_make = @localedir_c_make@ localstatedir = @localstatedir@ logdir = @logdir@ mandir = @mandir@ diff --git a/lib/compat/Makefile.in b/lib/compat/Makefile.in index 9b3c41c..3f3ccbb 100644 --- a/lib/compat/Makefile.in +++ b/lib/compat/Makefile.in @@ -105,8 +105,8 @@ host_triplet = @host@ @HAVE_UNSETENV_FALSE@am__append_15 = unsetenv.c subdir = lib/compat ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/dpkg-arch.m4 \ - $(top_srcdir)/m4/dpkg-build.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/m4/build-to-host.m4 \ + $(top_srcdir)/m4/dpkg-arch.m4 $(top_srcdir)/m4/dpkg-build.m4 \ $(top_srcdir)/m4/dpkg-compiler.m4 \ $(top_srcdir)/m4/dpkg-coverage.m4 \ $(top_srcdir)/m4/dpkg-funcs.m4 \ @@ -353,6 +353,7 @@ PACKAGE_RELEASE_DATE = @PACKAGE_RELEASE_DATE@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VCS_ID = @PACKAGE_VCS_ID@ PACKAGE_VCS_TYPE = @PACKAGE_VCS_TYPE@ PACKAGE_VCS_URL = @PACKAGE_VCS_URL@ PACKAGE_VCS_WEB = @PACKAGE_VCS_WEB@ @@ -434,6 +435,8 @@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ +localedir_c = @localedir_c@ +localedir_c_make = @localedir_c_make@ localstatedir = @localstatedir@ logdir = @logdir@ mandir = @mandir@ diff --git a/lib/compat/strnlen.c b/lib/compat/strnlen.c index d02bb4b..288a298 100644 --- a/lib/compat/strnlen.c +++ b/lib/compat/strnlen.c @@ -20,6 +20,8 @@ # include <config.h> #endif +#include <string.h> + #include "compat.h" /* Find the length of STRING, but scan at most MAXLEN characters. diff --git a/lib/compat/vasprintf.c b/lib/compat/vasprintf.c index 9d53a32..b5a2783 100644 --- a/lib/compat/vasprintf.c +++ b/lib/compat/vasprintf.c @@ -19,6 +19,8 @@ #include <config.h> +#include <errno.h> +#include <limits.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> @@ -36,7 +38,9 @@ vasprintf(char **strp, char const *fmt, va_list args) needed = vsnprintf(NULL, 0, fmt, args_copy); va_end(args_copy); - if (needed < 0) { + if (needed < 0 || needed >= INT_MAX) { + if (needed >= INT_MAX) + errno = EOVERFLOW; *strp = NULL; return -1; } diff --git a/lib/dpkg/Makefile.am b/lib/dpkg/Makefile.am index 9ef3a37..862562c 100644 --- a/lib/dpkg/Makefile.am +++ b/lib/dpkg/Makefile.am @@ -76,6 +76,7 @@ libdpkg_la_SOURCES = \ db-fsys-digest.c \ db-fsys-divert.c \ db-fsys-files.c \ + db-fsys-load.c \ db-fsys-override.c \ deb-version.c \ debug.c \ @@ -84,10 +85,11 @@ libdpkg_la_SOURCES = \ dump.c \ ehandle.c \ error.c \ + execname.c \ fdio.c \ file.c \ fields.c \ - fsys-dir.c\ + fsys-dir.c \ fsys-iter.c \ fsys-hash.c \ glob.c \ @@ -154,6 +156,7 @@ pkginclude_HEADERS = \ dpkg-db.h \ ehandle.h \ error.h \ + execname.h \ fdio.h \ file.h \ fsys.h \ diff --git a/lib/dpkg/Makefile.in b/lib/dpkg/Makefile.in index 07f9005..3c92b54 100644 --- a/lib/dpkg/Makefile.in +++ b/lib/dpkg/Makefile.in @@ -118,8 +118,8 @@ check_PROGRAMS = $(am__EXEEXT_1) t/b-fsys-hash$(EXEEXT) \ t/c-treewalk$(EXEEXT) t/c-trigdeferred$(EXEEXT) subdir = lib/dpkg ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/dpkg-arch.m4 \ - $(top_srcdir)/m4/dpkg-build.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/m4/build-to-host.m4 \ + $(top_srcdir)/m4/dpkg-arch.m4 $(top_srcdir)/m4/dpkg-build.m4 \ $(top_srcdir)/m4/dpkg-compiler.m4 \ $(top_srcdir)/m4/dpkg-coverage.m4 \ $(top_srcdir)/m4/dpkg-funcs.m4 \ @@ -196,16 +196,16 @@ am_libdpkg_la_OBJECTS = ar.lo arch.lo atomic-file.lo buffer.lo \ c-ctype.lo cleanup.lo color.lo command.lo compress.lo dbdir.lo \ dbmodify.lo db-ctrl-access.lo db-ctrl-format.lo \ db-ctrl-upgrade.lo db-fsys-digest.lo db-fsys-divert.lo \ - db-fsys-files.lo db-fsys-override.lo deb-version.lo debug.lo \ - depcon.lo dir.lo dump.lo ehandle.lo error.lo fdio.lo file.lo \ - fields.lo fsys-dir.lo fsys-iter.lo fsys-hash.lo glob.lo \ - i18n.lo log.lo meminfo.lo mustlib.lo namevalue.lo nfmalloc.lo \ - options.lo options-dirs.lo options-parsers.lo pager.lo \ - parse.lo parsehelp.lo path.lo path-remove.lo pkg.lo \ - pkg-array.lo pkg-files.lo pkg-format.lo pkg-hash.lo \ - pkg-list.lo pkg-namevalue.lo pkg-queue.lo pkg-show.lo \ - pkg-spec.lo progname.lo program.lo progress.lo report.lo \ - string.lo strhash.lo strwide.lo subproc.lo tarfn.lo \ + db-fsys-files.lo db-fsys-load.lo db-fsys-override.lo \ + deb-version.lo debug.lo depcon.lo dir.lo dump.lo ehandle.lo \ + error.lo execname.lo fdio.lo file.lo fields.lo fsys-dir.lo \ + fsys-iter.lo fsys-hash.lo glob.lo i18n.lo log.lo meminfo.lo \ + mustlib.lo namevalue.lo nfmalloc.lo options.lo options-dirs.lo \ + options-parsers.lo pager.lo parse.lo parsehelp.lo path.lo \ + path-remove.lo pkg.lo pkg-array.lo pkg-files.lo pkg-format.lo \ + pkg-hash.lo pkg-list.lo pkg-namevalue.lo pkg-queue.lo \ + pkg-show.lo pkg-spec.lo progname.lo program.lo progress.lo \ + report.lo string.lo strhash.lo strwide.lo subproc.lo tarfn.lo \ treewalk.lo trigname.lo trignote.lo triglib.lo trigdeferred.lo \ utils.lo varbuf.lo version.lo libdpkg_la_OBJECTS = $(am_libdpkg_la_OBJECTS) @@ -428,12 +428,13 @@ am__depfiles_remade = ./$(DEPDIR)/ar.Plo ./$(DEPDIR)/arch.Plo \ ./$(DEPDIR)/compress.Plo ./$(DEPDIR)/db-ctrl-access.Plo \ ./$(DEPDIR)/db-ctrl-format.Plo ./$(DEPDIR)/db-ctrl-upgrade.Plo \ ./$(DEPDIR)/db-fsys-digest.Plo ./$(DEPDIR)/db-fsys-divert.Plo \ - ./$(DEPDIR)/db-fsys-files.Plo ./$(DEPDIR)/db-fsys-override.Plo \ - ./$(DEPDIR)/dbdir.Plo ./$(DEPDIR)/dbmodify.Plo \ - ./$(DEPDIR)/deb-version.Plo ./$(DEPDIR)/debug.Plo \ - ./$(DEPDIR)/depcon.Plo ./$(DEPDIR)/dir.Plo \ - ./$(DEPDIR)/dump.Plo ./$(DEPDIR)/ehandle.Plo \ - ./$(DEPDIR)/error.Plo ./$(DEPDIR)/fdio.Plo \ + ./$(DEPDIR)/db-fsys-files.Plo ./$(DEPDIR)/db-fsys-load.Plo \ + ./$(DEPDIR)/db-fsys-override.Plo ./$(DEPDIR)/dbdir.Plo \ + ./$(DEPDIR)/dbmodify.Plo ./$(DEPDIR)/deb-version.Plo \ + ./$(DEPDIR)/debug.Plo ./$(DEPDIR)/depcon.Plo \ + ./$(DEPDIR)/dir.Plo ./$(DEPDIR)/dump.Plo \ + ./$(DEPDIR)/ehandle.Plo ./$(DEPDIR)/error.Plo \ + ./$(DEPDIR)/execname.Plo ./$(DEPDIR)/fdio.Plo \ ./$(DEPDIR)/fields.Plo ./$(DEPDIR)/file.Plo \ ./$(DEPDIR)/fsys-dir.Plo ./$(DEPDIR)/fsys-hash.Plo \ ./$(DEPDIR)/fsys-iter.Plo ./$(DEPDIR)/glob.Plo \ @@ -658,6 +659,7 @@ PACKAGE_RELEASE_DATE = @PACKAGE_RELEASE_DATE@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VCS_ID = @PACKAGE_VCS_ID@ PACKAGE_VCS_TYPE = @PACKAGE_VCS_TYPE@ PACKAGE_VCS_URL = @PACKAGE_VCS_URL@ PACKAGE_VCS_WEB = @PACKAGE_VCS_WEB@ @@ -739,6 +741,8 @@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ +localedir_c = @localedir_c@ +localedir_c_make = @localedir_c_make@ localstatedir = @localstatedir@ logdir = @logdir@ mandir = @mandir@ @@ -817,6 +821,7 @@ libdpkg_la_SOURCES = \ db-fsys-digest.c \ db-fsys-divert.c \ db-fsys-files.c \ + db-fsys-load.c \ db-fsys-override.c \ deb-version.c \ debug.c \ @@ -825,10 +830,11 @@ libdpkg_la_SOURCES = \ dump.c \ ehandle.c \ error.c \ + execname.c \ fdio.c \ file.c \ fields.c \ - fsys-dir.c\ + fsys-dir.c \ fsys-iter.c \ fsys-hash.c \ glob.c \ @@ -895,6 +901,7 @@ pkginclude_HEADERS = \ dpkg-db.h \ ehandle.h \ error.h \ + execname.h \ fdio.h \ file.h \ fsys.h \ @@ -1308,6 +1315,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/db-fsys-digest.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/db-fsys-divert.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/db-fsys-files.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/db-fsys-load.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/db-fsys-override.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbdir.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbmodify.Plo@am__quote@ # am--include-marker @@ -1318,6 +1326,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dump.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ehandle.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/execname.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fdio.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fields.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file.Plo@am__quote@ # am--include-marker @@ -1655,6 +1664,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/db-fsys-digest.Plo -rm -f ./$(DEPDIR)/db-fsys-divert.Plo -rm -f ./$(DEPDIR)/db-fsys-files.Plo + -rm -f ./$(DEPDIR)/db-fsys-load.Plo -rm -f ./$(DEPDIR)/db-fsys-override.Plo -rm -f ./$(DEPDIR)/dbdir.Plo -rm -f ./$(DEPDIR)/dbmodify.Plo @@ -1665,6 +1675,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/dump.Plo -rm -f ./$(DEPDIR)/ehandle.Plo -rm -f ./$(DEPDIR)/error.Plo + -rm -f ./$(DEPDIR)/execname.Plo -rm -f ./$(DEPDIR)/fdio.Plo -rm -f ./$(DEPDIR)/fields.Plo -rm -f ./$(DEPDIR)/file.Plo @@ -1812,6 +1823,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/db-fsys-digest.Plo -rm -f ./$(DEPDIR)/db-fsys-divert.Plo -rm -f ./$(DEPDIR)/db-fsys-files.Plo + -rm -f ./$(DEPDIR)/db-fsys-load.Plo -rm -f ./$(DEPDIR)/db-fsys-override.Plo -rm -f ./$(DEPDIR)/dbdir.Plo -rm -f ./$(DEPDIR)/dbmodify.Plo @@ -1822,6 +1834,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/dump.Plo -rm -f ./$(DEPDIR)/ehandle.Plo -rm -f ./$(DEPDIR)/error.Plo + -rm -f ./$(DEPDIR)/execname.Plo -rm -f ./$(DEPDIR)/fdio.Plo -rm -f ./$(DEPDIR)/fields.Plo -rm -f ./$(DEPDIR)/file.Plo @@ -1968,6 +1981,10 @@ tap-clean: tap-check: $(test_data) $(test_programs) $(test_scripts) [ -z "$(test_tmpdir)" ] || $(MKDIR_P) $(test_tmpdir) $(TEST_ENV_VARS) \ + TEST_PARALLEL=$(TEST_PARALLEL) \ + TEST_VERBOSE=$(TEST_VERBOSE) \ + abs_srcdir=$(abs_srcdir) \ + abs_builddir=$(abs_builddir) \ abs_top_srcdir=$(abs_top_srcdir) \ abs_top_builddir=$(abs_top_builddir) \ srcdir=$(srcdir) builddir=$(builddir) \ diff --git a/lib/dpkg/buffer.c b/lib/dpkg/buffer.c index ed05f4b..3d4ed9e 100644 --- a/lib/dpkg/buffer.c +++ b/lib/dpkg/buffer.c @@ -184,7 +184,7 @@ buffer_copy(struct buffer_data *read_data, off_t bytesread = 0, byteswritten = 0; off_t totalread = 0, totalwritten = 0; - if ((limit != -1) && (limit < bufsize)) + if ((limit >= 0) && (limit < bufsize)) bufsize = limit; if (bufsize == 0) buf = NULL; @@ -202,7 +202,7 @@ buffer_copy(struct buffer_data *read_data, totalread += bytesread; - if (limit != -1) { + if (limit >= 0) { limit -= bytesread; if (limit < bufsize) bufsize = limit; @@ -267,7 +267,7 @@ buffer_skip(struct buffer_data *input, off_t limit, struct dpkg_error *err) switch (input->type) { case BUFFER_READ_FD: - if (lseek(input->arg.i, limit, SEEK_CUR) != -1) + if (lseek(input->arg.i, limit, SEEK_CUR) >= 0) return limit; if (errno != ESPIPE) return dpkg_put_errno(err, _("failed to seek")); diff --git a/lib/dpkg/command.c b/lib/dpkg/command.c index 18c917b..4831d13 100644 --- a/lib/dpkg/command.c +++ b/lib/dpkg/command.c @@ -247,7 +247,6 @@ command_in_path(const char *cmd) if (path_len) varbuf_add_char(&filename, '/'); varbuf_add_str(&filename, cmd); - varbuf_end_str(&filename); if (file_is_exec(filename.buf)) { varbuf_destroy(&filename); diff --git a/lib/dpkg/command.h b/lib/dpkg/command.h index 768aba4..b681d65 100644 --- a/lib/dpkg/command.h +++ b/lib/dpkg/command.h @@ -24,6 +24,7 @@ #include <dpkg/macros.h> #include <stdarg.h> +#include <stdbool.h> DPKG_BEGIN_DECLS diff --git a/lib/dpkg/db-ctrl-access.c b/lib/dpkg/db-ctrl-access.c index c252336..9b788b1 100644 --- a/lib/dpkg/db-ctrl-access.c +++ b/lib/dpkg/db-ctrl-access.c @@ -73,7 +73,6 @@ pkg_infodb_foreach(struct pkginfo *pkg, struct pkgbin *pkgbin, pkgname = pkgbin_name(pkg, pkgbin, pnaw_never); varbuf_add_dir(&db_path, pkg_infodb_get_dir()); - varbuf_end_str(&db_path); varbuf_snapshot(&db_path, &db_path_state); db_dir = opendir(db_path.buf); @@ -108,7 +107,6 @@ pkg_infodb_foreach(struct pkginfo *pkg, struct pkgbin *pkgbin, varbuf_rollback(&db_path_state); varbuf_add_str(&db_path, db_de->d_name); - varbuf_end_str(&db_path); filename = db_path.buf; func(filename, filetype); diff --git a/lib/dpkg/db-ctrl-format.c b/lib/dpkg/db-ctrl-format.c index 34b5ff5..658130d 100644 --- a/lib/dpkg/db-ctrl-format.c +++ b/lib/dpkg/db-ctrl-format.c @@ -142,7 +142,6 @@ pkg_infodb_get_file(const struct pkginfo *pkg, const struct pkgbin *pkgbin, varbuf_add_archqual(&vb, pkgbin->arch); varbuf_add_char(&vb, '.'); varbuf_add_str(&vb, filetype); - varbuf_end_str(&vb); return vb.buf; } diff --git a/lib/dpkg/db-ctrl-upgrade.c b/lib/dpkg/db-ctrl-upgrade.c index 86f584b..6adffc5 100644 --- a/lib/dpkg/db-ctrl-upgrade.c +++ b/lib/dpkg/db-ctrl-upgrade.c @@ -81,7 +81,6 @@ pkg_infodb_link_multiarch_files(void) struct varbuf_state newname_state; varbuf_add_dir(&oldname, pkg_infodb_get_dir()); - varbuf_end_str(&oldname); varbuf_snapshot(&oldname, &oldname_state); varbuf_set_varbuf(&newname, &oldname); @@ -131,13 +130,11 @@ pkg_infodb_link_multiarch_files(void) varbuf_rollback(&oldname_state); varbuf_add_str(&oldname, db_de->d_name); - varbuf_end_str(&oldname); varbuf_rollback(&newname_state); varbuf_add_pkgbin_name(&newname, pkg, &pkg->installed, pnaw_always); varbuf_add_char(&newname, '.'); varbuf_add_str(&newname, filetype); - varbuf_end_str(&newname); if (link(oldname.buf, newname.buf) && errno != EEXIST) ohshite(_("error creating hard link '%.255s'"), diff --git a/lib/dpkg/db-fsys-divert.c b/lib/dpkg/db-fsys-divert.c index e0054bb..351e8ef 100644 --- a/lib/dpkg/db-fsys-divert.c +++ b/lib/dpkg/db-fsys-divert.c @@ -23,7 +23,6 @@ #include <compat.h> #include <sys/types.h> -#include <sys/stat.h> #include <errno.h> #include <string.h> @@ -40,78 +39,44 @@ #include <dpkg/db-fsys.h> static struct fsys_diversion *diversions = NULL; -static char *diversionsname; void ensure_diversions(void) { - static struct stat sb_prev; - struct stat sb_next; + static struct dpkg_db db = { + .name = DIVERSIONSFILE, + }; + enum dpkg_db_error rc; char linebuf[MAXDIVERTFILENAME]; - static FILE *file_prev; - FILE *file; struct fsys_diversion *ov, *oicontest, *oialtname; - if (diversionsname == NULL) - diversionsname = dpkg_db_get_path(DIVERSIONSFILE); - - onerr_abort++; - - file = fopen(diversionsname, "r"); - if (!file) { - if (errno != ENOENT) - ohshite(_("failed to open diversions file")); - } else { - setcloexec(fileno(file), diversionsname); - - if (fstat(fileno(file), &sb_next)) - ohshite(_("failed to fstat diversions file")); - - /* - * We need to keep the database file open so that the - * filesystem cannot reuse the inode number (f.ex. during - * multiple dpkg-divert invocations in a maintainer script), - * otherwise the following check might turn true, and we - * would skip reloading a modified database. - */ - if (file_prev && - sb_prev.st_dev == sb_next.st_dev && - sb_prev.st_ino == sb_next.st_ino) { - fclose(file); - onerr_abort--; - debug(dbg_general, "%s: same, skipping", __func__); - return; - } - sb_prev = sb_next; - } - if (file_prev) - fclose(file_prev); - file_prev = file; + rc = dpkg_db_reopen(&db); + if (rc == DPKG_DB_SAME) + return; for (ov = diversions; ov; ov = ov->next) { ov->useinstead->divert->camefrom->divert = NULL; ov->useinstead->divert = NULL; } diversions = NULL; - if (!file) { - onerr_abort--; - debug(dbg_general, "%s: none, resetting", __func__); + + if (rc == DPKG_DB_NONE) return; - } - debug(dbg_general, "%s: new, (re)loading", __func__); - while (fgets_checked(linebuf, sizeof(linebuf), file, diversionsname) >= 0) { + onerr_abort++; + + while (fgets_checked(linebuf, sizeof(linebuf), db.file, db.pathname) >= 0) { oicontest = nfmalloc(sizeof(*oicontest)); oialtname = nfmalloc(sizeof(*oialtname)); oialtname->camefrom = fsys_hash_find_node(linebuf, FHFF_NONE); oialtname->useinstead = NULL; - fgets_must(linebuf, sizeof(linebuf), file, diversionsname); + fgets_must(linebuf, sizeof(linebuf), db.file, db.pathname); oicontest->useinstead = fsys_hash_find_node(linebuf, FHFF_NONE); oicontest->camefrom = NULL; - fgets_must(linebuf, sizeof(linebuf), file, diversionsname); + fgets_must(linebuf, sizeof(linebuf), db.file, db.pathname); oicontest->pkgset = strcmp(linebuf, ":") ? pkg_hash_find_set(linebuf) : NULL; oialtname->pkgset = oicontest->pkgset; diff --git a/lib/dpkg/db-fsys-files.c b/lib/dpkg/db-fsys-files.c index 099cad3..3d7c4fc 100644 --- a/lib/dpkg/db-fsys-files.c +++ b/lib/dpkg/db-fsys-files.c @@ -70,6 +70,46 @@ enum pkg_filesdb_load_status { static enum pkg_filesdb_load_status saidread = PKG_FILESDB_LOAD_NONE; +static void +fsys_list_parse_buffer(struct varbuf *vb, struct pkginfo *pkg) +{ + struct fsys_namenode_list **files_tail; + char *loaded_list_end, *thisline; + + loaded_list_end = vb->buf + vb->used; + + files_tail = &pkg->files; + thisline = vb->buf; + + while (thisline < loaded_list_end) { + struct fsys_namenode *namenode; + char *nextline, *ptr; + + ptr = memchr(thisline, '\n', loaded_list_end - thisline); + if (ptr == NULL) + ohshit(_("files list file for package '%.250s' is missing final newline"), + pkg_name(pkg, pnaw_nonambig)); + + /* Where to start next time around. */ + nextline = ptr + 1; + + /* Strip trailing ‘/’. */ + if (ptr > thisline && ptr[-1] == '/') + ptr--; + + /* Add the file to the list. */ + if (ptr == thisline) + ohshit(_("files list file for package '%.250s' contains empty filename"), + pkg_name(pkg, pnaw_nonambig)); + *ptr = '\0'; + + namenode = fsys_hash_find_node(thisline, FHFF_NONE); + files_tail = pkg_files_add_file(pkg, namenode, files_tail); + + thisline = nextline; + } +} + /** * Load the list of files in this package into memory, or update the * list if it is there but stale. @@ -114,37 +154,8 @@ ensure_packagefiles_available(struct pkginfo *pkg) return; } - if (buf.used) { - struct fsys_namenode_list **lendp; - char *loaded_list_end, *thisline; - - loaded_list_end = buf.buf + buf.used; - - lendp = &pkg->files; - thisline = buf.buf; - while (thisline < loaded_list_end) { - struct fsys_namenode *namenode; - char *nextline, *ptr; - - ptr = memchr(thisline, '\n', loaded_list_end - thisline); - if (ptr == NULL) - ohshit(_("files list file for package '%.250s' is missing final newline"), - pkg_name(pkg, pnaw_nonambig)); - /* Where to start next time around. */ - nextline = ptr + 1; - /* Strip trailing ‘/’. */ - if (ptr > thisline && ptr[-1] == '/') ptr--; - /* Add the file to the list. */ - if (ptr == thisline) - ohshit(_("files list file for package '%.250s' contains empty filename"), - pkg_name(pkg, pnaw_nonambig)); - *ptr = '\0'; - - namenode = fsys_hash_find_node(thisline, FHFF_NONE); - lendp = pkg_files_add_file(pkg, namenode, lendp); - thisline = nextline; - } - } + if (buf.used) + fsys_list_parse_buffer(&buf, pkg); varbuf_destroy(&buf); @@ -236,7 +247,7 @@ pkg_files_optimize_load(struct pkg_array *array) listfile = pkg_infodb_get_file(pkg, &pkg->installed, LISTFILE); fd = open(listfile, O_RDONLY | O_NONBLOCK); - if (fd != -1) { + if (fd >= 0) { posix_fadvise(fd, 0, 0, POSIX_FADV_WILLNEED); close(fd); } diff --git a/lib/dpkg/db-fsys-load.c b/lib/dpkg/db-fsys-load.c new file mode 100644 index 0000000..c707f94 --- /dev/null +++ b/lib/dpkg/db-fsys-load.c @@ -0,0 +1,91 @@ +/* + * libdpkg - Debian packaging suite library routines + * db-fsys-load.c - (re)loading of database of files installed on system + * + * Copyright © 2008-2024 Guillem Jover <guillem@debian.org> + * Copyright © 2022 Simon Richter <sjr@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 <errno.h> + +#include <dpkg/dpkg.h> +#include <dpkg/dpkg-db.h> +#include <dpkg/db-fsys.h> +#include <dpkg/i18n.h> +#include <dpkg/debug.h> + +enum dpkg_db_error +dpkg_db_reopen(struct dpkg_db *db) +{ + struct stat st_next; + FILE *file_next; + + if (db->pathname == NULL) + db->pathname = dpkg_db_get_path(db->name); + + onerr_abort++; + + file_next = fopen(db->pathname, "r"); + if (!file_next) { + if (errno != ENOENT) + ohshite(_("cannot open %s file"), db->pathname); + } else { + setcloexec(fileno(file_next), db->pathname); + + if (fstat(fileno(file_next), &st_next)) + ohshite(_("cannot get %s file metadata"), db->pathname); + + /* + * We need to keep the database file open so that the + * filesystem cannot reuse the inode number (f.ex. during + * multiple dpkg-divert invocations in a maintainer script), + * otherwise the following check might turn true, and we + * would skip reloading a modified database. + */ + if (db->file && + db->st.st_dev == st_next.st_dev && + db->st.st_ino == st_next.st_ino) { + fclose(file_next); + onerr_abort--; + + debug(dbg_general, "%s: unchanged %s, skipping", + __func__, db->pathname); + return DPKG_DB_SAME; + } + db->st = st_next; + } + if (db->file) + fclose(db->file); + db->file = file_next; + + onerr_abort--; + + if (db->file) { + debug(dbg_general, "%s: new %s, (re)loading", + __func__, db->pathname); + return DPKG_DB_LOAD; + } else { + debug(dbg_general, "%s: missing %s, resetting", + __func__, db->pathname); + return DPKG_DB_NONE; + } +} diff --git a/lib/dpkg/db-fsys-override.c b/lib/dpkg/db-fsys-override.c index b74f6cb..120bc3d 100644 --- a/lib/dpkg/db-fsys-override.c +++ b/lib/dpkg/db-fsys-override.c @@ -24,7 +24,6 @@ #include <compat.h> #include <sys/types.h> -#include <sys/stat.h> #include <errno.h> #include <string.h> @@ -41,8 +40,6 @@ #include <dpkg/debug.h> #include <dpkg/db-fsys.h> -static char *statoverridename; - uid_t statdb_parse_uid(const char *str) { @@ -111,76 +108,44 @@ statdb_parse_mode(const char *str) void ensure_statoverrides(enum statdb_parse_flags flags) { - static struct stat sb_prev; - struct stat sb_next; - static FILE *file_prev; - FILE *file; + static struct dpkg_db db = { + .name = STATOVERRIDEFILE, + }; + enum dpkg_db_error rc; char *loaded_list, *loaded_list_end, *thisline, *nextline, *ptr; struct file_stat *fso; struct fsys_namenode *fnn; struct fsys_hash_iter *iter; - if (statoverridename == NULL) - statoverridename = dpkg_db_get_path(STATOVERRIDEFILE); + rc = dpkg_db_reopen(&db); + if (rc == DPKG_DB_SAME) + return; onerr_abort++; - file = fopen(statoverridename, "r"); - if (!file) { - if (errno != ENOENT) - ohshite(_("failed to open statoverride file")); - } else { - setcloexec(fileno(file), statoverridename); - - if (fstat(fileno(file), &sb_next)) - ohshite(_("failed to fstat statoverride file")); - - /* - * We need to keep the database file open so that the - * filesystem cannot reuse the inode number (f.ex. during - * multiple dpkg-statoverride invocations in a maintainer - * script), otherwise the following check might turn true, - * and we would skip reloading a modified database. - */ - if (file_prev && - sb_prev.st_dev == sb_next.st_dev && - sb_prev.st_ino == sb_next.st_ino) { - fclose(file); - onerr_abort--; - debug(dbg_general, "%s: same, skipping", __func__); - return; - } - sb_prev = sb_next; - } - if (file_prev) - fclose(file_prev); - file_prev = file; - /* Reset statoverride information. */ iter = fsys_hash_iter_new(); while ((fnn = fsys_hash_iter_next(iter))) fnn->statoverride = NULL; fsys_hash_iter_free(iter); - if (!file) { - onerr_abort--; - debug(dbg_general, "%s: none, resetting", __func__); + onerr_abort--; + + if (rc == DPKG_DB_NONE) return; - } - debug(dbg_general, "%s: new, (re)loading", __func__); /* If the statoverride list is empty we don't need to bother * reading it. */ - if (!sb_next.st_size) { - onerr_abort--; + if (!db.st.st_size) return; - } - loaded_list = m_malloc(sb_next.st_size); - loaded_list_end = loaded_list + sb_next.st_size; + onerr_abort++; + + loaded_list = m_malloc(db.st.st_size); + loaded_list_end = loaded_list + db.st.st_size; - if (fd_read(fileno(file), loaded_list, sb_next.st_size) < 0) - ohshite(_("reading statoverride file '%.250s'"), statoverridename); + if (fd_read(fileno(db.file), loaded_list, db.st.st_size) < 0) + ohshite(_("reading statoverride file '%.250s'"), db.pathname); thisline = loaded_list; while (thisline < loaded_list_end) { diff --git a/lib/dpkg/db-fsys.h b/lib/dpkg/db-fsys.h index a95b29d..2730dcd 100644 --- a/lib/dpkg/db-fsys.h +++ b/lib/dpkg/db-fsys.h @@ -22,6 +22,10 @@ #ifndef LIBDPKG_DB_FSYS_H #define LIBDPKG_DB_FSYS_H +#include <sys/stat.h> + +#include <stdio.h> + #include <dpkg/file.h> #include <dpkg/fsys.h> @@ -50,6 +54,28 @@ DPKG_BEGIN_DECLS struct pkginfo; struct pkgbin; +enum dpkg_db_error { + /** The database is new or has changed, should be loaded. */ + DPKG_DB_LOAD = 0, + /** No database file found. */ + DPKG_DB_NONE = -1, + /** The database is already loaded and has not changed. */ + DPKG_DB_SAME = -2, +}; + +struct dpkg_db { + /** Name of the database. Set by the caller. */ + const char *name; + + /* Database state members. */ + char *pathname; + FILE *file; + struct stat st; +}; + +enum dpkg_db_error +dpkg_db_reopen(struct dpkg_db *db); + void ensure_diversions(void); enum statdb_parse_flags { diff --git a/lib/dpkg/dbmodify.c b/lib/dpkg/dbmodify.c index f38bece..cefbc9d 100644 --- a/lib/dpkg/dbmodify.c +++ b/lib/dpkg/dbmodify.c @@ -70,7 +70,8 @@ static int ulist_select(const struct dirent *de) { if (l > IMPORTANTMAXLEN) ohshit(_("updates directory contains file '%.250s' whose name is too long " "(length=%d, max=%d)"), de->d_name, l, IMPORTANTMAXLEN); - if (updateslength == -1) updateslength= l; + if (updateslength < 0) + updateslength = l; else if (l != updateslength) ohshit(_("updates directory contains files with different length names " "(both %d and %d)"), l, updateslength); @@ -85,7 +86,7 @@ static void cleanupdates(void) { updateslength= -1; cdn = scandir(updatesdir, &cdlist, &ulist_select, alphasort); - if (cdn == -1) { + if (cdn < 0) { if (errno == ENOENT) { if (cstatus >= msdbrw_write && dir_make_path(updatesdir, 0755) < 0) @@ -102,7 +103,6 @@ static void cleanupdates(void) { for (i=0; i<cdn; i++) { varbuf_rollback(&updatefn_state); varbuf_add_str(&updatefn, cdlist[i]->d_name); - varbuf_end_str(&updatefn); parsedb(updatefn.buf, pdb_parse_update, NULL); } @@ -112,7 +112,6 @@ static void cleanupdates(void) { for (i=0; i<cdn; i++) { varbuf_rollback(&updatefn_state); varbuf_add_str(&updatefn, cdlist[i]->d_name); - varbuf_end_str(&updatefn); if (unlink(updatefn.buf)) ohshite(_("failed to remove incorporated update file %.255s"), updatefn.buf); @@ -193,7 +192,6 @@ modstatdb_init(void) varbuf_init(&updatefn, strlen(updatesdir) + 1 + IMPORTANTMAXLEN); varbuf_add_dir(&updatefn, updatesdir); - varbuf_end_str(&updatefn); varbuf_snapshot(&updatefn, &updatefn_state); db_initialized = true; @@ -225,9 +223,9 @@ modstatdb_is_locked(void) int lockfd; bool locked; - if (dblockfd == -1) { + if (dblockfd < 0) { lockfd = open(lockfile, O_RDONLY); - if (lockfd == -1) { + if (lockfd < 0) { if (errno == ENOENT) return false; ohshite(_("unable to check lock file for dpkg database directory %s"), @@ -241,7 +239,7 @@ modstatdb_is_locked(void) /* We only close the file if there was no lock open, otherwise we would * release the existing lock on close. */ - if (dblockfd == -1) + if (dblockfd < 0) close(lockfd); return locked; @@ -255,7 +253,7 @@ modstatdb_can_lock(void) if (getenv("DPKG_FRONTEND_LOCKED") == NULL) { frontendlockfd = open(frontendlockfile, O_RDWR | O_CREAT | O_TRUNC, 0660); - if (frontendlockfd == -1) { + if (frontendlockfd < 0) { if (errno == EACCES || errno == EPERM) return false; else @@ -267,7 +265,7 @@ modstatdb_can_lock(void) } dblockfd = open(lockfile, O_RDWR | O_CREAT | O_TRUNC, 0660); - if (dblockfd == -1) { + if (dblockfd < 0) { if (errno == EACCES || errno == EPERM) return false; else @@ -285,7 +283,7 @@ modstatdb_lock(void) ohshit(_("you do not have permission to lock the dpkg database directory %s"), dpkg_db_get_dir()); - if (frontendlockfd != -1) + if (frontendlockfd >= 0) file_lock(&frontendlockfd, FILE_LOCK_NOWAIT, frontendlockfile, _("dpkg frontend lock")); file_lock(&dblockfd, FILE_LOCK_NOWAIT, lockfile, @@ -297,7 +295,7 @@ modstatdb_unlock(void) { /* Unlock. */ pop_cleanup(ehflag_normaltidy); - if (frontendlockfd != -1) + if (frontendlockfd >= 0) pop_cleanup(ehflag_normaltidy); dblockfd = -1; diff --git a/lib/dpkg/dpkg-db.h b/lib/dpkg/dpkg-db.h index 61f2205..f223d74 100644 --- a/lib/dpkg/dpkg-db.h +++ b/lib/dpkg/dpkg-db.h @@ -77,12 +77,20 @@ struct arbitraryfield { const char *value; }; +enum DPKG_ATTR_ENUM_FLAGS conffile_flags { + /** No flags. */ + CONFFILE_NONE = 0, + /** The conffile is not shipped anymore in the new package. */ + CONFFILE_OBSOLETE = DPKG_BIT(0), + /** The conffile is marked to be removed during package upgrade. */ + CONFFILE_REMOVE_ON_UPGRADE = DPKG_BIT(1), +}; + struct conffile { struct conffile *next; const char *name; const char *hash; - bool obsolete; - bool remove_on_upgrade; + enum conffile_flags flags; }; struct archivedetails { diff --git a/lib/dpkg/dump.c b/lib/dpkg/dump.c index b27e5db..1883d3c 100644 --- a/lib/dpkg/dump.c +++ b/lib/dpkg/dump.c @@ -390,9 +390,9 @@ w_conffiles(struct varbuf *vb, varbuf_add_str(vb, i->name); varbuf_add_char(vb, ' '); varbuf_add_str(vb, i->hash); - if (i->obsolete) + if (i->flags & CONFFILE_OBSOLETE) varbuf_add_str(vb, " obsolete"); - if (i->remove_on_upgrade) + if (i->flags & CONFFILE_REMOVE_ON_UPGRADE) varbuf_add_str(vb, " remove-on-upgrade"); } if (flags&fw_printheader) @@ -484,9 +484,8 @@ write_stanza(FILE *file, const char *filename, struct varbuf vb = VARBUF_INIT; varbuf_stanza(&vb, pkg, pkgbin); - varbuf_end_str(&vb); - if (fputs(vb.buf, file) < 0) + if (fputs(varbuf_str(&vb), file) < 0) ohshite(_("failed to write details of '%.50s' to '%.250s'"), pkgbin_name_const(pkg, pkgbin, pnaw_nonambig), filename); @@ -524,8 +523,7 @@ writedb_stanzas(FILE *fp, const char *filename, enum writedb_flags flags) varbuf_stanza(&vb, pkg, pkgbin); varbuf_add_char(&vb, '\n'); - varbuf_end_str(&vb); - if (fputs(vb.buf, fp) < 0) + if (fputs(varbuf_str(&vb), fp) < 0) ohshite(_("failed to write %s database stanza about '%s' to '%s'"), which, pkgbin_name(pkg, pkgbin, pnaw_nonambig), filename); varbuf_reset(&vb); diff --git a/lib/dpkg/execname.c b/lib/dpkg/execname.c new file mode 100644 index 0000000..6529fcf --- /dev/null +++ b/lib/dpkg/execname.c @@ -0,0 +1,166 @@ +/* + * libdpkg - Debian packaging suite library routines + * execname.c - executable name handling functions + * + * Copyright © 2024 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> + +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif +#ifdef HAVE_SYS_SYSCTL_H +#include <sys/sysctl.h> +#endif +#if defined(_AIX) && defined(HAVE_SYS_PROCFS_H) +#include <sys/procfs.h> +#endif + +#include <limits.h> +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> + +#if defined(__APPLE__) && defined(__MACH__) +#include <libproc.h> +#endif + +#include <dpkg/dpkg.h> +#include <dpkg/file.h> +#include <dpkg/execname.h> + +#if defined(_AIX) && defined(HAVE_STRUCT_PSINFO) +static bool +proc_get_psinfo(pid_t pid, struct psinfo *psinfo) +{ + char filename[64]; + FILE *fp; + + sprintf(filename, "/proc/%d/psinfo", pid); + fp = fopen(filename, "r"); + if (!fp) + return false; + if (fread(psinfo, sizeof(*psinfo), 1, fp) == 0) { + fclose(fp); + return false; + } + if (ferror(fp)) { + fclose(fp); + return false; + } + + fclose(fp); + + return true; +} +#endif + +/** + * Get the executable name for a PID. + * + * Tries to obtain the executable name or process name for a specific PID, + * if the executable name cannot be obtained then it will return NULL. + * + * @return A pointer to an allocated string with the executable name, or NULL. + */ +char * +dpkg_get_pid_execname(pid_t pid) +{ + const char *execname = NULL; +#if defined(__linux__) + char lname[32]; + char lcontents[_POSIX_PATH_MAX + 1]; + int nread; + + sprintf(lname, "/proc/%d/exe", pid); + nread = readlink(lname, lcontents, sizeof(lcontents) - 1); + if (nread == -1) + return NULL; + + lcontents[nread] = '\0'; + execname = lcontents; +#elif defined(__GNU__) + struct proc_stat *ps; + + ps = get_proc_stat(pid, PSTAT_ARGS); + if (ps == NULL) + return NULL; + + /* On old Hurd systems we have to use the argv[0] value, because + * there is nothing better. */ + execname = proc_stat_args(ps); + +#ifdef PSTAT_EXE + /* On new Hurd systems we can use the correct value, as long + * as it's not NULL nor empty, as it was the case on the first + * implementation. */ + if (proc_stat_set_flags(ps, PSTAT_EXE) == 0 && + proc_stat_flags(ps) & PSTAT_EXE && + proc_stat_exe(ps) != NULL && + proc_stat_exe(ps)[0] != '\0') + execname = proc_stat_exe(ps); +#endif +#elif defined(__sun) + char filename[64]; + struct varbuf vb = VARBUF_INIT; + + sprintf(filename, "/proc/%d/execname", pid); + if (file_slurp(filename, &vb, NULL) < 0) + return NULL; + + return varbuf_detach(&vb); +#elif defined(__APPLE__) && defined(__MACH__) + char pathname[_POSIX_PATH_MAX]; + + if (proc_pidpath(pid, pathname, sizeof(pathname)) < 0) + return NULL; + + execname = pathname; +#elif defined(_AIX) && defined(HAVE_STRUCT_PSINFO) + char filename[64]; + struct psinfo psi; + + sprintf(filename, "/proc/%d/psinfo", pid); + if (!proc_get_psinfo(pid, &psi)) + return NULL; + + execname = psi.pr_fname; +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + int error, mib[4]; + size_t len; + char pathname[PATH_MAX]; + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PATHNAME; + mib[3] = pid; + len = sizeof(pathname); + + error = sysctl(mib, 4, pathname, &len, NULL, 0); + if (error != 0 && errno != ESRCH) + return NULL; + if (len == 0) + pathname[0] = '\0'; + execname = pathname; +#else + return execname; +#endif + + return m_strdup(execname); +} diff --git a/lib/dpkg/execname.h b/lib/dpkg/execname.h new file mode 100644 index 0000000..f82efc3 --- /dev/null +++ b/lib/dpkg/execname.h @@ -0,0 +1,43 @@ +/* + * libdpkg - Debian packaging suite library routines + * execname.h - executable name handling functions + * + * Copyright © 2024 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/>. + */ + +#ifndef LIBDPKG_EXECNAME_H +#define LIBDPKG_EXECNAME_H + +#include <sys/types.h> + +#include <dpkg/macros.h> + +DPKG_BEGIN_DECLS + +/** + * @defgroup execname Executable name handling + * @ingroup dpkg-public + * @{ + */ + +char * +dpkg_get_pid_execname(pid_t pid); + +/** @} */ + +DPKG_END_DECLS + +#endif diff --git a/lib/dpkg/fdio.c b/lib/dpkg/fdio.c index b50322b..075fb41 100644 --- a/lib/dpkg/fdio.c +++ b/lib/dpkg/fdio.c @@ -22,10 +22,12 @@ #include <compat.h> #include <errno.h> +#include <limits.h> #include <fcntl.h> #include <unistd.h> #include <dpkg/fdio.h> +#include <dpkg/ehandle.h> ssize_t fd_read(int fd, void *buf, size_t len) @@ -33,11 +35,14 @@ fd_read(int fd, void *buf, size_t len) ssize_t total = 0; char *ptr = buf; + if (len > SSIZE_MAX) + internerr("len=%zu exceeds SSIZE_MAX=%zd", len, SSIZE_MAX); + while (len > 0) { ssize_t n; n = read(fd, ptr + total, len); - if (n == -1) { + if (n < 0) { if (errno == EINTR || errno == EAGAIN) continue; return total ? -total : n; @@ -58,11 +63,14 @@ fd_write(int fd, const void *buf, size_t len) ssize_t total = 0; const char *ptr = buf; + if (len > SSIZE_MAX) + internerr("len=%zu exceeds SSIZE_MAX=%zd", len, SSIZE_MAX); + while (len > 0) { ssize_t n; n = write(fd, ptr + total, len); - if (n == -1) { + if (n < 0) { if (errno == EINTR || errno == EAGAIN) continue; return total ? -total : n; diff --git a/lib/dpkg/fields.c b/lib/dpkg/fields.c index e62b7b5..efcfb26 100644 --- a/lib/dpkg/fields.c +++ b/lib/dpkg/fields.c @@ -363,7 +363,7 @@ f_conffiles(struct pkginfo *pkg, struct pkgbin *pkgbin, const char *endent, *endfn, *hashstart; char *newptr; int c, namelen, hashlen; - bool obsolete, remove_on_upgrade; + int flags = CONFFILE_NONE; c= *value++; if (c == '\n') continue; @@ -375,18 +375,21 @@ f_conffiles(struct pkginfo *pkg, struct pkgbin *pkgbin, conffvalue_lastword(value, endent, endent, &hashstart, &hashlen, &endfn, ps); - remove_on_upgrade = (hashlen == sizeof(remove_on_upgrade_str) - 1 && - memcmp(hashstart, remove_on_upgrade_str, hashlen) == 0); - if (remove_on_upgrade) + if (hashlen == sizeof(remove_on_upgrade_str) - 1 && + memcmp(hashstart, remove_on_upgrade_str, hashlen) == 0) { + flags |= CONFFILE_REMOVE_ON_UPGRADE; conffvalue_lastword(value, endfn, endent, &hashstart, &hashlen, &endfn, ps); + } - obsolete= (hashlen == sizeof(obsolete_str)-1 && - memcmp(hashstart, obsolete_str, hashlen) == 0); - if (obsolete) + if (hashlen == sizeof(obsolete_str) - 1 && + memcmp(hashstart, obsolete_str, hashlen) == 0) { + flags |= CONFFILE_OBSOLETE; conffvalue_lastword(value, endfn, endent, &hashstart, &hashlen, &endfn, ps); + } + newlink = nfmalloc(sizeof(*newlink)); value = path_skip_slash_dotslash(value); namelen= (int)(endfn-value); @@ -403,8 +406,7 @@ f_conffiles(struct pkginfo *pkg, struct pkgbin *pkgbin, memcpy(newptr, hashstart, hashlen); newptr[hashlen] = '\0'; newlink->hash= newptr; - newlink->obsolete= obsolete; - newlink->remove_on_upgrade = remove_on_upgrade; + newlink->flags = flags; newlink->next =NULL; *lastp= newlink; lastp= &newlink->next; @@ -571,9 +573,9 @@ f_dependency(struct pkginfo *pkg, struct pkgbin *pkgbin, dop->verrel = DPKG_RELATION_EQ; } if ((dop->verrel != DPKG_RELATION_EQ) && (fip->integer == dep_provides)) - parse_warn(ps, - _("only exact versions may be used for '%s' field"), - fip->name); + parse_lax_problem(ps, pdb_lax_stanza_parser, + _("only exact versions may be used for '%s' field"), + fip->name); if (!c_isspace(*p) && !c_isalnum(*p)) { parse_warn(ps, diff --git a/lib/dpkg/file.c b/lib/dpkg/file.c index 0da51d6..f664feb 100644 --- a/lib/dpkg/file.c +++ b/lib/dpkg/file.c @@ -35,6 +35,21 @@ #include <dpkg/fdio.h> #include <dpkg/buffer.h> #include <dpkg/file.h> +#include <dpkg/execname.h> + +/** + * Get the current working directory. + * + */ +void +file_getcwd(struct varbuf *cwd) +{ + varbuf_reset(cwd); + varbuf_grow(cwd, 64); + while (getcwd(cwd->buf, cwd->size) == NULL) + varbuf_grow(cwd, cwd->size * 2); + varbuf_trunc(cwd, strlen(cwd->buf)); +} /** * Read the symlink content into a varbuf. @@ -49,8 +64,10 @@ file_readlink(const char *slink, struct varbuf *content, size_t content_len) varbuf_grow(content, content_len + 1); linksize = readlink(slink, content->buf, content->size); + if (linksize < 0) + return linksize; + varbuf_trunc(content, linksize); - varbuf_end_str(content); return linksize; } @@ -85,17 +102,17 @@ file_copy_perms(const char *src, const char *dst) { struct stat stab; - if (stat(src, &stab) == -1) { + if (stat(src, &stab) < 0) { if (errno == ENOENT) return; ohshite(_("unable to stat source file '%.250s'"), src); } - if (chown(dst, stab.st_uid, stab.st_gid) == -1) + if (chown(dst, stab.st_uid, stab.st_gid) < 0) ohshite(_("unable to change ownership of target file '%.250s'"), dst); - if (chmod(dst, (stab.st_mode & ~S_IFMT)) == -1) + if (chmod(dst, (stab.st_mode & ~S_IFMT)) < 0) ohshite(_("unable to set mode of target file '%.250s'"), dst); } @@ -115,10 +132,10 @@ file_slurp_fd(int fd, const char *filename, struct varbuf *vb, if (st.st_size == 0) return 0; - varbuf_init(vb, st.st_size); + varbuf_init(vb, st.st_size + 1); if (fd_read(fd, vb->buf, st.st_size) < 0) return dpkg_put_errno(err, _("cannot read %s"), filename); - vb->used = st.st_size; + varbuf_trunc(vb, st.st_size); return 0; } @@ -165,7 +182,7 @@ file_unlock(int lockfd, const char *lockfile, const char *lockdesc) file_lock_setup(&fl, F_UNLCK); - if (fcntl(lockfd, F_SETLK, &fl) == -1) + if (fcntl(lockfd, F_SETLK, &fl) < 0) ohshite(_("unable to unlock %s"), lockdesc); } @@ -192,7 +209,7 @@ file_is_locked(int lockfd, const char *filename) file_lock_setup(&fl, F_WRLCK); - if (fcntl(lockfd, F_GETLK, &fl) == -1) + if (fcntl(lockfd, F_GETLK, &fl) < 0) ohshit(_("unable to check file '%s' lock status"), filename); if (fl.l_type == F_WRLCK && fl.l_pid != getpid()) @@ -226,8 +243,9 @@ file_lock(int *lockfd, enum file_lock_flags flags, const char *filename, else lock_cmd = F_SETLK; - if (fcntl(*lockfd, lock_cmd, &fl) == -1) { + if (fcntl(*lockfd, lock_cmd, &fl) < 0) { const char *warnmsg; + char *execname; if (errno != EACCES && errno != EAGAIN) ohshite(_("unable to lock %s"), desc); @@ -238,12 +256,15 @@ file_lock(int *lockfd, enum file_lock_flags flags, const char *filename, "See <https://wiki.debian.org/Teams/Dpkg/FAQ#db-lock>."); file_lock_setup(&fl, F_WRLCK); - if (fcntl(*lockfd, F_GETLK, &fl) == -1) + if (fcntl(*lockfd, F_GETLK, &fl) < 0) ohshit(_("%s was locked by another process\n%s"), desc, warnmsg); - ohshit(_("%s was locked by another process with pid %d\n%s"), - desc, fl.l_pid, warnmsg); + execname = dpkg_get_pid_execname(fl.l_pid); + + ohshit(_("%s was locked by %s process with pid %d\n%s"), + desc, execname ? execname : C_("process", "<unknown>"), + fl.l_pid, warnmsg); } push_cleanup(file_unlock_cleanup, ~0, 3, lockfd, filename, desc); diff --git a/lib/dpkg/file.h b/lib/dpkg/file.h index c1c25fa..f5bc50d 100644 --- a/lib/dpkg/file.h +++ b/lib/dpkg/file.h @@ -48,6 +48,9 @@ struct file_stat { char *gname; }; +void +file_getcwd(struct varbuf *cwd); + ssize_t file_readlink(const char *slink, struct varbuf *content, size_t content_len); diff --git a/lib/dpkg/i18n.c b/lib/dpkg/i18n.c index 30e28bf..7313bbb 100644 --- a/lib/dpkg/i18n.c +++ b/lib/dpkg/i18n.c @@ -21,6 +21,10 @@ #include <config.h> #include <compat.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> + #include <dpkg/i18n.h> #ifdef HAVE_USELOCALE @@ -30,10 +34,27 @@ static locale_t dpkg_C_locale; #endif +static bool +dpkg_use_nls(void) +{ + const char *env; + + /* We mimic the behavior of the Dpkg::Gettext perl module. */ + env = getenv("DPKG_NLS"); + if (env == NULL) + return true; + + if (strcmp(env, "0") == 0 || env[0] == '\0') + return false; + + return true; +} + void dpkg_locales_init(const char *package) { - setlocale(LC_ALL, ""); + if (dpkg_use_nls()) + setlocale(LC_ALL, ""); bindtextdomain(package, LOCALEDIR); textdomain(package); diff --git a/lib/dpkg/libdpkg.map b/lib/dpkg/libdpkg.map index b7bedef..3b29ad4 100644 --- a/lib/dpkg/libdpkg.map +++ b/lib/dpkg/libdpkg.map @@ -30,6 +30,9 @@ global: dpkg_ar_normalize_name; dpkg_ar_member_is_illegal; + # Process information + dpkg_get_pid_execname; + local: *; }; @@ -114,6 +117,7 @@ LIBDPKG_PRIVATE { varbuf_reset; varbuf_grow; varbuf_trunc; + varbuf_str; varbuf_set_varbuf; varbuf_set_buf; varbuf_add_varbuf; @@ -122,8 +126,10 @@ LIBDPKG_PRIVATE { varbuf_map_char; varbuf_add_buf; varbuf_add_dir; - varbuf_get_str; - varbuf_end_str; + varbuf_has_prefix; + varbuf_has_suffix; + varbuf_trim_varbuf_prefix; + varbuf_trim_char_prefix; varbuf_printf; varbuf_vprintf; varbuf_detach; @@ -161,6 +167,7 @@ LIBDPKG_PRIVATE { treewalk_close; treewalk; + file_getcwd; file_readlink; file_is_exec; file_copy_perms; diff --git a/lib/dpkg/log.c b/lib/dpkg/log.c index 10a33a2..b416e22 100644 --- a/lib/dpkg/log.c +++ b/lib/dpkg/log.c @@ -74,7 +74,6 @@ log_message(const char *fmt, ...) varbuf_add_char(&log, ' '); varbuf_vprintf(&log, fmt, args); varbuf_add_char(&log, '\n'); - varbuf_end_str(&log); va_end(args); if (fd_write(logfd, log.buf, log.used) < 0) diff --git a/lib/dpkg/mustlib.c b/lib/dpkg/mustlib.c index 52d9752..df1a91a 100644 --- a/lib/dpkg/mustlib.c +++ b/lib/dpkg/mustlib.c @@ -141,8 +141,8 @@ setcloexec(int fd, const char *fn) int f; f = fcntl(fd, F_GETFD); - if (f == -1) + if (f < 0) ohshite(_("unable to read filedescriptor flags for %.250s"),fn); - if (fcntl(fd, F_SETFD, (f|FD_CLOEXEC))==-1) + if (fcntl(fd, F_SETFD, (f | FD_CLOEXEC)) < 0) ohshite(_("unable to set close-on-exec flag for %.250s"),fn); } diff --git a/lib/dpkg/parse.c b/lib/dpkg/parse.c index 96af147..da99624 100644 --- a/lib/dpkg/parse.c +++ b/lib/dpkg/parse.c @@ -555,7 +555,7 @@ parsedb_open(const char *filename, enum parsedbflags flags) return parsedb_new(filename, STDIN_FILENO, flags); fd = open(filename, O_RDONLY); - if (fd == -1 && !(errno == ENOENT && (flags & pdb_allow_empty))) + if (fd < 0 && !(errno == ENOENT && (flags & pdb_allow_empty))) ohshite(_("failed to open package info file '%.255s' for reading"), filename); @@ -577,7 +577,7 @@ parsedb_load(struct parsedb_state *ps) if (ps->fd < 0 && (ps->flags & pdb_allow_empty)) return; - if (fstat(ps->fd, &st) == -1) + if (fstat(ps->fd, &st) < 0) ohshite(_("can't stat package info file '%.255s'"), ps->filename); if (S_ISFIFO(st.st_mode)) { @@ -589,7 +589,6 @@ parsedb_load(struct parsedb_state *ps) if (size < 0) ohshit(_("reading package info file '%s': %s"), ps->filename, err.str); - varbuf_end_str(&buf); ps->dataptr = varbuf_detach(&buf); ps->endptr = ps->dataptr + size; @@ -685,14 +684,10 @@ parse_stanza(struct parsedb_state *ps, struct field_state *fs, fs->valuestart = ps->dataptr - 1; for (;;) { if (c == '\n' || c == MSDOS_EOF_CHAR) { - if (blank_line) { - if (ps->flags & pdb_lax_stanza_parser) - parse_warn(ps, _("blank line in value of field '%.*s'"), - fs->fieldlen, fs->fieldstart); - else - parse_error(ps, _("blank line in value of field '%.*s'"), - fs->fieldlen, fs->fieldstart); - } + if (blank_line) + parse_lax_problem(ps, pdb_lax_stanza_parser, + _("blank line in value of field '%.*s'"), + fs->fieldlen, fs->fieldstart); ps->lno++; if (parse_at_eof(ps)) diff --git a/lib/dpkg/parsedump.h b/lib/dpkg/parsedump.h index c43da7f..21076cc 100644 --- a/lib/dpkg/parsedump.h +++ b/lib/dpkg/parsedump.h @@ -23,6 +23,7 @@ #ifndef LIBDPKG_PARSEDUMP_H #define LIBDPKG_PARSEDUMP_H +#include <stdbool.h> #include <stdint.h> #include <dpkg/error.h> @@ -160,6 +161,10 @@ void parse_error(struct parsedb_state *ps, const char *fmt, ...) void parse_warn(struct parsedb_state *ps, const char *fmt, ...) DPKG_ATTR_PRINTF(2); void +parse_lax_problem(struct parsedb_state *ps, enum parsedbflags flags_lax, + const char *fmt, ...) + DPKG_ATTR_PRINTF(3); +void parse_problem(struct parsedb_state *ps, const char *fmt, ...) DPKG_ATTR_PRINTF(2); diff --git a/lib/dpkg/parsehelp.c b/lib/dpkg/parsehelp.c index 63a36f5..a999b5e 100644 --- a/lib/dpkg/parsehelp.c +++ b/lib/dpkg/parsehelp.c @@ -80,6 +80,23 @@ parse_warn(struct parsedb_state *ps, const char *fmt, ...) } void +parse_lax_problem(struct parsedb_state *ps, enum parsedbflags flags_lax, + const char *fmt, ...) +{ + va_list args; + const char *str; + + va_start(args, fmt); + str = parse_error_msg(ps, fmt, args); + va_end(args); + + if (ps->flags & flags_lax) + warning("%s", str); + else + ohshit("%s", str); +} + +void parse_problem(struct parsedb_state *ps, const char *fmt, ...) { va_list args; @@ -183,7 +200,6 @@ const char *versiondescribe vb= &bufs[bufnum]; bufnum++; if (bufnum == 10) bufnum= 0; varbuf_reset(vb); varbufversion(vb,version,vdew); - varbuf_end_str(vb); return vb->buf; } diff --git a/lib/dpkg/pkg-format.c b/lib/dpkg/pkg-format.c index b984012..846eb29 100644 --- a/lib/dpkg/pkg-format.c +++ b/lib/dpkg/pkg-format.c @@ -361,7 +361,6 @@ virt_source_upstream_version(struct varbuf *vb, if (version.version) varbuf_add_str(vb, version.version); - varbuf_end_str(vb); } static const struct fieldinfo virtinfos[] = { @@ -428,8 +427,7 @@ pkg_format_print(struct varbuf *vb, const struct pkg_format_node *head, if (fip) { fip->wcall(&wb, pkg, pkgbin, 0, fip); - varbuf_end_str(&wb); - pkg_format_item(&fb, node, wb.buf); + pkg_format_item(&fb, node, varbuf_str(&wb)); varbuf_reset(&wb); ok = true; } else { @@ -449,8 +447,7 @@ pkg_format_print(struct varbuf *vb, const struct pkg_format_node *head, if ((width != 0) && (len > width)) len = width; - varbuf_add_buf(vb, fb.buf, len); - varbuf_end_str(vb); + varbuf_add_buf(vb, varbuf_str(&fb), len); } varbuf_reset(&fb); diff --git a/lib/dpkg/pkg-format.h b/lib/dpkg/pkg-format.h index 40d41ff..ee4e7b1 100644 --- a/lib/dpkg/pkg-format.h +++ b/lib/dpkg/pkg-format.h @@ -21,6 +21,8 @@ #ifndef LIBDPKG_PKG_FORMAT_H #define LIBDPKG_PKG_FORMAT_H +#include <stdbool.h> + #include <dpkg/macros.h> #include <dpkg/error.h> #include <dpkg/dpkg-db.h> diff --git a/lib/dpkg/pkg-show.c b/lib/dpkg/pkg-show.c index 038343c..1782686 100644 --- a/lib/dpkg/pkg-show.c +++ b/lib/dpkg/pkg-show.c @@ -80,7 +80,6 @@ varbuf_add_pkgbin_name(struct varbuf *vb, varbuf_add_str(vb, pkg->set->name); if (pkgbin_name_needs_arch(pkgbin, pnaw)) varbuf_add_archqual(vb, pkgbin->arch); - varbuf_end_str(vb); } const char * @@ -395,7 +394,7 @@ pkg_sorter_by_nonambig_name_arch(const void *a, const void *b) * Add a string representation of the source package version to a varbuf. * * It parses the Source field (if present), and extracts the optional - * version enclosed in parenthesis. Otherwise it fallsback to use the + * version enclosed in parenthesis. Otherwise it falls back to use the * binary package version. It NUL terminates the varbuf. * * @param vb The varbuf struct to modify. @@ -410,7 +409,6 @@ varbuf_add_source_version(struct varbuf *vb, pkg_source_version(&version, pkg, pkgbin); varbufversion(vb, &version, vdew_nonambig); - varbuf_end_str(vb); } void @@ -434,11 +432,10 @@ pkg_source_version(struct dpkg_version *version, version_str++; len = strcspn(version_str, ")"); varbuf_add_buf(&vb, version_str, len); - varbuf_end_str(&vb); - if (parseversion(version, vb.buf, &err) < 0) + if (parseversion(version, varbuf_str(&vb), &err) < 0) ohshit(_("version '%s' has bad syntax: %s"), - vb.buf, err.str); + varbuf_str(&vb), err.str); varbuf_destroy(&vb); } diff --git a/lib/dpkg/subproc.c b/lib/dpkg/subproc.c index 7b3fb99..e91bb62 100644 --- a/lib/dpkg/subproc.c +++ b/lib/dpkg/subproc.c @@ -104,7 +104,7 @@ subproc_fork(void) pid_t pid; pid = fork(); - if (pid == -1) { + if (pid < 0) { onerr_abort++; ohshite(_("fork failed")); } @@ -169,7 +169,7 @@ subproc_wait(pid_t pid, const char *desc) pid_t dead_pid; int status; - while ((dead_pid = waitpid(pid, &status, 0)) == -1 && errno == EINTR) ; + while ((dead_pid = waitpid(pid, &status, 0)) < 0 && errno == EINTR) ; if (dead_pid != pid) { onerr_abort++; diff --git a/lib/dpkg/t/c-tarextract.c b/lib/dpkg/t/c-tarextract.c index 82a8dab..c68b5d2 100644 --- a/lib/dpkg/t/c-tarextract.c +++ b/lib/dpkg/t/c-tarextract.c @@ -22,10 +22,10 @@ #include <compat.h> #include <sys/types.h> -#if HAVE_SYS_SYSMACROS_H +#ifdef HAVE_SYS_SYSMACROS_H #include <sys/sysmacros.h> /* Needed on AIX for major()/minor(). */ #endif -#if HAVE_SYS_MKDEV_H +#ifdef HAVE_SYS_MKDEV_H #include <sys/mkdev.h> /* Needed on Solaris for major()/minor(). */ #endif diff --git a/lib/dpkg/t/t-arch.c b/lib/dpkg/t/t-arch.c index d0b5735..f2f7c7f 100644 --- a/lib/dpkg/t/t-arch.c +++ b/lib/dpkg/t/t-arch.c @@ -170,23 +170,19 @@ test_dpkg_arch_varbuf_archqual(void) struct varbuf vb = VARBUF_INIT; varbuf_add_archqual(&vb, dpkg_arch_get(DPKG_ARCH_NONE)); - varbuf_end_str(&vb); - test_str(vb.buf, ==, ""); + test_str(varbuf_str(&vb), ==, ""); varbuf_reset(&vb); varbuf_add_archqual(&vb, dpkg_arch_get(DPKG_ARCH_EMPTY)); - varbuf_end_str(&vb); - test_str(vb.buf, ==, ""); + test_str(varbuf_str(&vb), ==, ""); varbuf_reset(&vb); varbuf_add_archqual(&vb, dpkg_arch_get(DPKG_ARCH_ALL)); - varbuf_end_str(&vb); - test_str(vb.buf, ==, ":all"); + test_str(varbuf_str(&vb), ==, ":all"); varbuf_reset(&vb); varbuf_add_archqual(&vb, dpkg_arch_get(DPKG_ARCH_WILDCARD)); - varbuf_end_str(&vb); - test_str(vb.buf, ==, ":any"); + test_str(varbuf_str(&vb), ==, ":any"); varbuf_reset(&vb); varbuf_destroy(&vb); diff --git a/lib/dpkg/t/t-file.c b/lib/dpkg/t/t-file.c index 0004df4..16114f0 100644 --- a/lib/dpkg/t/t-file.c +++ b/lib/dpkg/t/t-file.c @@ -40,6 +40,20 @@ static const char ref_data[] = ; static void +test_file_getcwd(void) +{ + char *env; + struct varbuf cwd = VARBUF_INIT; + + env = getenv("abs_builddir"); + file_getcwd(&cwd); + + test_str(env, ==, cwd.buf); + + varbuf_destroy(&cwd); +} + +static void test_file_slurp(void) { struct varbuf vb = VARBUF_INIT; @@ -100,7 +114,8 @@ test_file_slurp(void) TEST_ENTRY(test) { - test_plan(32); + test_plan(33); + test_file_getcwd(); test_file_slurp(); } diff --git a/lib/dpkg/t/t-pkg-format.c b/lib/dpkg/t/t-pkg-format.c index 81e7ddb..c3afe1c 100644 --- a/lib/dpkg/t/t-pkg-format.c +++ b/lib/dpkg/t/t-pkg-format.c @@ -63,7 +63,7 @@ test_field(struct pkginfo *pkg, const char *fmt, const char *exp) head = pkg_format_parse(fmt, NULL); test_pass(head); pkg_format_print(&vb, head, pkg, &pkg->installed); - test_str(vb.buf, ==, exp); + test_str(varbuf_str(&vb), ==, exp); pkg_format_free(head); varbuf_destroy(&vb); } diff --git a/lib/dpkg/t/t-subproc.c b/lib/dpkg/t/t-subproc.c index 7ce610b..8846d90 100644 --- a/lib/dpkg/t/t-subproc.c +++ b/lib/dpkg/t/t-subproc.c @@ -62,13 +62,13 @@ test_subproc_fork(void) if (pid == 0) raise(SIGINT); ret = subproc_reap(pid, "subproc signal", SUBPROC_WARN); - test_pass(ret == -1); + test_pass(ret < 0); pid = subproc_fork(); if (pid == 0) raise(SIGTERM); ret = subproc_reap(pid, "subproc signal", SUBPROC_WARN); - test_pass(ret == -1); + test_pass(ret < 0); pid = subproc_fork(); if (pid == 0) @@ -81,7 +81,7 @@ test_subproc_fork(void) if (pid == 0) raise(SIGPIPE); ret = subproc_reap(pid, "subproc SIGPIPE", SUBPROC_WARN); - test_pass(ret == -1); + test_pass(ret < 0); } TEST_ENTRY(test) diff --git a/lib/dpkg/t/t-varbuf.c b/lib/dpkg/t/t-varbuf.c index 08998a5..1ab1cf2 100644 --- a/lib/dpkg/t/t-varbuf.c +++ b/lib/dpkg/t/t-varbuf.c @@ -238,19 +238,15 @@ test_varbuf_add_str(void) varbuf_init(&vb, 5); varbuf_add_str(&vb, "1234567890"); - varbuf_end_str(&vb); test_str(vb.buf, ==, "1234567890"); varbuf_add_str(&vb, "abcd"); - varbuf_end_str(&vb); test_str(vb.buf, ==, "1234567890abcd"); varbuf_add_strn(&vb, "1234567890", 5); - varbuf_end_str(&vb); test_str(vb.buf, ==, "1234567890abcd12345"); varbuf_add_strn(&vb, "abcd", 0); - varbuf_end_str(&vb); test_str(vb.buf, ==, "1234567890abcd12345"); varbuf_destroy(&vb); @@ -331,34 +327,26 @@ test_varbuf_add_dir(void) varbuf_init(&vb, 10); varbuf_add_dir(&vb, ""); - varbuf_end_str(&vb); test_str(vb.buf, ==, "/"); varbuf_add_dir(&vb, ""); - varbuf_end_str(&vb); test_str(vb.buf, ==, "/"); varbuf_add_dir(&vb, "aa"); - varbuf_end_str(&vb); test_str(vb.buf, ==, "/aa/"); varbuf_add_dir(&vb, ""); - varbuf_end_str(&vb); test_str(vb.buf, ==, "/aa/"); varbuf_reset(&vb); varbuf_add_dir(&vb, "/foo/bar"); - varbuf_end_str(&vb); test_str(vb.buf, ==, "/foo/bar/"); varbuf_reset(&vb); varbuf_add_dir(&vb, "/foo/bar/"); - varbuf_end_str(&vb); test_str(vb.buf, ==, "/foo/bar/"); varbuf_add_dir(&vb, "quux"); - varbuf_end_str(&vb); test_str(vb.buf, ==, "/foo/bar/quux/"); varbuf_add_dir(&vb, "zoo"); - varbuf_end_str(&vb); test_str(vb.buf, ==, "/foo/bar/quux/zoo/"); varbuf_destroy(&vb); @@ -378,7 +366,6 @@ test_varbuf_end_str(void) varbuf_trunc(&vb, 10); - varbuf_end_str(&vb); test_pass(vb.used == 10); test_pass(vb.size >= vb.used + 1); test_pass(vb.buf[10] == '\0'); @@ -388,7 +375,7 @@ test_varbuf_end_str(void) } static void -test_varbuf_get_str(void) +test_varbuf_str(void) { struct varbuf vb; const char *str; @@ -396,7 +383,7 @@ test_varbuf_get_str(void) varbuf_init(&vb, 10); varbuf_add_buf(&vb, "1234567890", 10); - str = varbuf_get_str(&vb); + str = varbuf_str(&vb); test_pass(vb.buf == str); test_pass(vb.used == 10); test_pass(vb.buf[vb.used] == '\0'); @@ -405,7 +392,7 @@ test_varbuf_get_str(void) test_str(str, ==, "1234567890"); varbuf_add_buf(&vb, "abcde", 5); - str = varbuf_get_str(&vb); + str = varbuf_str(&vb); test_pass(vb.buf == str); test_pass(vb.used == 15); test_pass(vb.buf[vb.used] == '\0'); @@ -417,6 +404,73 @@ test_varbuf_get_str(void) } static void +test_varbuf_has(void) +{ + struct varbuf vb = VARBUF_OBJECT; + struct varbuf vb_prefix = VARBUF_OBJECT; + struct varbuf vb_suffix = VARBUF_OBJECT; + + test_pass(varbuf_has_prefix(&vb, &vb_prefix)); + test_pass(varbuf_has_suffix(&vb, &vb_suffix)); + + varbuf_set_str(&vb_prefix, "prefix"); + varbuf_set_str(&vb_suffix, "suffix"); + + test_fail(varbuf_has_prefix(&vb, &vb_prefix)); + test_fail(varbuf_has_suffix(&vb, &vb_suffix)); + + varbuf_set_str(&vb, "prefix and some text"); + test_pass(varbuf_has_prefix(&vb, &vb_prefix)); + test_fail(varbuf_has_prefix(&vb, &vb_suffix)); + test_fail(varbuf_has_suffix(&vb, &vb_prefix)); + test_fail(varbuf_has_suffix(&vb, &vb_suffix)); + + varbuf_set_str(&vb, "some text with suffix"); + test_fail(varbuf_has_prefix(&vb, &vb_prefix)); + test_fail(varbuf_has_prefix(&vb, &vb_suffix)); + test_fail(varbuf_has_suffix(&vb, &vb_prefix)); + test_pass(varbuf_has_suffix(&vb, &vb_suffix)); + + varbuf_set_str(&vb, "prefix and some text with suffix"); + test_pass(varbuf_has_prefix(&vb, &vb_prefix)); + test_fail(varbuf_has_prefix(&vb, &vb_suffix)); + test_fail(varbuf_has_suffix(&vb, &vb_prefix)); + test_pass(varbuf_has_suffix(&vb, &vb_suffix)); + + varbuf_destroy(&vb_prefix); + varbuf_destroy(&vb_suffix); + varbuf_destroy(&vb); +} + +static void +test_varbuf_trim(void) +{ + struct varbuf vb = VARBUF_OBJECT; + struct varbuf vb_prefix = VARBUF_OBJECT; + struct varbuf vb_suffix = VARBUF_OBJECT; + + varbuf_set_str(&vb_prefix, "prefix"); + varbuf_set_str(&vb_suffix, "suffix"); + + varbuf_set_str(&vb, "some text"); + varbuf_trim_varbuf_prefix(&vb, &vb_prefix); + varbuf_trim_char_prefix(&vb, 'a'); + test_str(vb.buf, ==, "some text"); + + varbuf_set_str(&vb, "prefix and some text"); + varbuf_trim_varbuf_prefix(&vb, &vb_prefix); + test_str(vb.buf, ==, " and some text"); + + varbuf_set_str(&vb, " and some text"); + varbuf_trim_char_prefix(&vb, ' '); + test_str(vb.buf, ==, "and some text"); + + varbuf_destroy(&vb_prefix); + varbuf_destroy(&vb_suffix); + varbuf_destroy(&vb); +} + +static void test_varbuf_printf(void) { struct varbuf vb; @@ -478,18 +532,15 @@ test_varbuf_snapshot(void) test_str(varbuf_rollback_start(&vbs), ==, ""); varbuf_add_buf(&vb, "1234567890", 10); - varbuf_end_str(&vb); test_pass(vb.used == 10); test_pass(varbuf_rollback_len(&vbs) == 10); test_str(varbuf_rollback_start(&vbs), ==, "1234567890"); varbuf_rollback(&vbs); - varbuf_end_str(&vb); test_pass(vb.used == 0); test_pass(varbuf_rollback_len(&vbs) == 0); test_str(varbuf_rollback_start(&vbs), ==, ""); varbuf_add_buf(&vb, "1234567890", 10); - varbuf_end_str(&vb); test_pass(vb.used == 10); test_pass(varbuf_rollback_len(&vbs) == 10); test_str(varbuf_rollback_start(&vbs), ==, "1234567890"); @@ -499,12 +550,10 @@ test_varbuf_snapshot(void) test_str(varbuf_rollback_start(&vbs), ==, ""); varbuf_add_buf(&vb, "1234567890", 10); - varbuf_end_str(&vb); test_pass(vb.used == 20); test_pass(varbuf_rollback_len(&vbs) == 10); test_str(varbuf_rollback_start(&vbs), ==, "1234567890"); varbuf_rollback(&vbs); - varbuf_end_str(&vb); test_pass(vb.used == 10); test_pass(varbuf_rollback_len(&vbs) == 0); test_str(varbuf_rollback_start(&vbs), ==, ""); @@ -519,22 +568,41 @@ test_varbuf_detach(void) char *str; varbuf_init(&vb, 0); + test_pass(vb.used == 0); + test_pass(vb.size == 0); + test_pass(vb.buf == NULL); + str = varbuf_detach(&vb); + test_str(str, ==, ""); + test_pass(vb.used == 0); + test_pass(vb.size == 0); + test_pass(vb.buf == NULL); + free(str); - varbuf_add_buf(&vb, "1234567890", 10); - + varbuf_init(&vb, 0); + varbuf_add_buf(&vb, NULL, 0); + test_pass(vb.used == 0); + test_pass(vb.size == 0); + test_pass(vb.buf == NULL); str = varbuf_detach(&vb); + test_str(str, ==, ""); + test_pass(vb.used == 0); + test_pass(vb.size == 0); + test_pass(vb.buf == NULL); + free(str); + varbuf_init(&vb, 0); + varbuf_add_buf(&vb, "1234567890", 10); + str = varbuf_detach(&vb); test_mem(str, ==, "1234567890", 10); test_pass(vb.used == 0); test_pass(vb.size == 0); test_pass(vb.buf == NULL); - free(str); } TEST_ENTRY(test) { - test_plan(172); + test_plan(205); test_varbuf_init(); test_varbuf_prealloc(); @@ -550,7 +618,9 @@ TEST_ENTRY(test) test_varbuf_map_char(); test_varbuf_add_dir(); test_varbuf_end_str(); - test_varbuf_get_str(); + test_varbuf_str(); + test_varbuf_has(); + test_varbuf_trim(); test_varbuf_printf(); test_varbuf_reset(); test_varbuf_snapshot(); diff --git a/lib/dpkg/tarfn.c b/lib/dpkg/tarfn.c index 48e3c38..2ce07a0 100644 --- a/lib/dpkg/tarfn.c +++ b/lib/dpkg/tarfn.c @@ -22,7 +22,7 @@ #include <config.h> #include <compat.h> -#if HAVE_SYS_SYSMACROS_H +#ifdef HAVE_SYS_SYSMACROS_H #include <sys/sysmacros.h> #endif #include <sys/stat.h> @@ -209,7 +209,6 @@ tar_header_get_prefix_name(struct tar_header *h) varbuf_add_strn(&path, h->prefix, sizeof(h->prefix)); varbuf_add_char(&path, '/'); varbuf_add_strn(&path, h->name, sizeof(h->name)); - varbuf_end_str(&path); return path.buf; } diff --git a/lib/dpkg/trigdeferred.c b/lib/dpkg/trigdeferred.c index e19eca7..ae31d62 100644 --- a/lib/dpkg/trigdeferred.c +++ b/lib/dpkg/trigdeferred.c @@ -56,7 +56,6 @@ constructfn(struct varbuf *vb, const char *dir, const char *tail) varbuf_reset(vb); varbuf_add_dir(vb, dir); varbuf_add_str(vb, tail); - varbuf_end_str(vb); } /** @@ -78,9 +77,9 @@ trigdef_update_start(enum trigdef_update_flags uf) if (uf & TDUF_WRITE) { constructfn(&fn, triggersdir, TRIGGERSLOCKFILE); - if (lock_fd == -1) { + if (lock_fd < 0) { lock_fd = open(fn.buf, O_RDWR | O_CREAT | O_TRUNC, 0600); - if (lock_fd == -1) { + if (lock_fd < 0) { if (!(errno == ENOENT && (uf & TDUF_NO_LOCK_OK))) ohshite(_("unable to open/create " "triggers lock file '%.250s'"), diff --git a/lib/dpkg/triglib.c b/lib/dpkg/triglib.c index 82cb298..6cf7eba 100644 --- a/lib/dpkg/triglib.c +++ b/lib/dpkg/triglib.c @@ -291,7 +291,6 @@ trk_explicit_start(const char *trig) varbuf_reset(&trk_explicit_fn); varbuf_add_dir(&trk_explicit_fn, triggersdir); varbuf_add_str(&trk_explicit_fn, trig); - varbuf_end_str(&trk_explicit_fn); trk_explicit_f = fopen(trk_explicit_fn.buf, "r"); if (!trk_explicit_f) { diff --git a/lib/dpkg/triglib.h b/lib/dpkg/triglib.h index e4e101b..3afeb41 100644 --- a/lib/dpkg/triglib.h +++ b/lib/dpkg/triglib.h @@ -23,6 +23,8 @@ #ifndef LIBDPKG_TRIGLIB_H #define LIBDPKG_TRIGLIB_H +#include <stdbool.h> + #include <dpkg/macros.h> #include <dpkg/dpkg-db.h> #include <dpkg/fsys.h> diff --git a/lib/dpkg/varbuf.c b/lib/dpkg/varbuf.c index a5d3d31..5829a6f 100644 --- a/lib/dpkg/varbuf.c +++ b/lib/dpkg/varbuf.c @@ -46,10 +46,12 @@ varbuf_init(struct varbuf *v, size_t size) { v->used = 0; v->size = size; - if (size) + if (size) { v->buf = m_malloc(size); - else + v->buf[0] = '\0'; + } else { v->buf = NULL; + } } void @@ -83,18 +85,23 @@ varbuf_trunc(struct varbuf *v, size_t used_size) internerr("varbuf new_used(%zu) > size(%zu)", used_size, v->size); v->used = used_size; + if (v->buf) + v->buf[v->used] = '\0'; } void varbuf_reset(struct varbuf *v) { v->used = 0; + if (v->buf) + v->buf[0] = '\0'; } const char * -varbuf_get_str(struct varbuf *v) +varbuf_str(struct varbuf *v) { - varbuf_end_str(v); + if (v->buf == NULL) + return ""; return v->buf; } @@ -104,7 +111,6 @@ varbuf_set_buf(struct varbuf *v, const void *buf, size_t size) { varbuf_reset(v); varbuf_add_buf(v, buf, size); - varbuf_end_str(v); } void @@ -116,16 +122,18 @@ varbuf_set_varbuf(struct varbuf *v, struct varbuf *other) void varbuf_add_varbuf(struct varbuf *v, const struct varbuf *other) { - varbuf_grow(v, other->used); + varbuf_grow(v, other->used + 1); memcpy(v->buf + v->used, other->buf, other->used); v->used += other->used; + v->buf[v->used] = '\0'; } void varbuf_add_char(struct varbuf *v, int c) { - varbuf_grow(v, 1); + varbuf_grow(v, 2); v->buf[v->used++] = c; + v->buf[v->used] = '\0'; } void @@ -133,9 +141,10 @@ varbuf_dup_char(struct varbuf *v, int c, size_t n) { if (n == 0) return; - varbuf_grow(v, n); + varbuf_grow(v, n + 1); memset(v->buf + v->used, c, n); v->used += n; + v->buf[v->used] = '\0'; } void @@ -161,16 +170,68 @@ varbuf_add_buf(struct varbuf *v, const void *s, size_t size) { if (size == 0) return; - varbuf_grow(v, size); + varbuf_grow(v, size + 1); memcpy(v->buf + v->used, s, size); v->used += size; + v->buf[v->used] = '\0'; +} + +bool +varbuf_has_prefix(struct varbuf *v, struct varbuf *prefix) +{ + if (prefix->used > v->used) + return false; + + if (prefix->used == 0) + return true; + if (v->used == 0) + return false; + + return strncmp(v->buf, prefix->buf, prefix->used) == 0; +} + +bool +varbuf_has_suffix(struct varbuf *v, struct varbuf *suffix) +{ + const char *slice; + + if (suffix->used > v->used) + return false; + + if (suffix->used == 0) + return true; + if (v->used == 0) + return false; + + slice = v->buf + v->used - suffix->used; + + return strcmp(slice, suffix->buf) == 0; } void -varbuf_end_str(struct varbuf *v) +varbuf_trim_varbuf_prefix(struct varbuf *v, struct varbuf *prefix) { - varbuf_grow(v, 1); - v->buf[v->used] = '\0'; + if (!varbuf_has_prefix(v, prefix)) + return; + + memmove(v->buf, v->buf + prefix->used, v->used - prefix->used); + varbuf_trunc(v, v->used - prefix->used); +} + +void +varbuf_trim_char_prefix(struct varbuf *v, int prefix) +{ + const char *str = v->buf; + size_t len = v->used; + + while (str[0] == prefix && len > 0) { + str++; + len--; + } + if (str != v->buf) { + memmove(v->buf, str, len); + varbuf_trunc(v, len); + } } int @@ -239,10 +300,7 @@ varbuf_rollback_start(struct varbuf_state *vs) if (vs->used) internerr("varbuf buf(NULL) state_used(%zu) > 0", vs->used); - /* XXX: Ideally this would be handled by varbuf always having - * a valid buf or switching all users to the getter, but for - * now this will do. */ - return ""; + return varbuf_str(vs->v); } return vs->v->buf + vs->used; } @@ -256,6 +314,9 @@ varbuf_detach(struct varbuf *v) v->size = 0; v->used = 0; + if (buf == NULL) + buf = m_strdup(""); + return buf; } diff --git a/lib/dpkg/varbuf.h b/lib/dpkg/varbuf.h index e58dac5..2a4da2b 100644 --- a/lib/dpkg/varbuf.h +++ b/lib/dpkg/varbuf.h @@ -24,6 +24,7 @@ #include <stddef.h> #include <stdarg.h> +#include <stdbool.h> #include <string.h> #include <dpkg/macros.h> @@ -83,6 +84,8 @@ void varbuf_reset(struct varbuf *v); void varbuf_destroy(struct varbuf *v); void varbuf_free(struct varbuf *v); +const char *varbuf_str(struct varbuf *v); + void varbuf_set_varbuf(struct varbuf *v, struct varbuf *other); void varbuf_set_buf(struct varbuf *v, const void *buf, size_t size); #define varbuf_set_str(v, s) varbuf_set_buf(v, s, strlen(s)) @@ -96,8 +99,11 @@ void varbuf_map_char(struct varbuf *v, int c_src, int c_dst); #define varbuf_add_strn(v, s, n) varbuf_add_buf(v, s, strnlen(s, n)) void varbuf_add_dir(struct varbuf *v, const char *dirname); void varbuf_add_buf(struct varbuf *v, const void *s, size_t size); -void varbuf_end_str(struct varbuf *v); -const char *varbuf_get_str(struct varbuf *v); + +bool varbuf_has_prefix(struct varbuf *v, struct varbuf *prefix); +bool varbuf_has_suffix(struct varbuf *v, struct varbuf *suffix); +void varbuf_trim_varbuf_prefix(struct varbuf *v, struct varbuf *prefix); +void varbuf_trim_char_prefix(struct varbuf *v, int prefix); int varbuf_printf(struct varbuf *v, const char *fmt, ...) DPKG_ATTR_PRINTF(2); int varbuf_vprintf(struct varbuf *v, const char *fmt, va_list va) @@ -182,7 +188,7 @@ varbuf::operator()(const char *s) inline const char * varbuf::string() { - return varbuf_get_str(this); + return varbuf_str(this); } #endif |