summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-08-07 13:30:11 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-08-07 13:30:11 +0000
commitb4f7d8b1566e3220d0e9004499ef9c257e079c57 (patch)
treece0468ca8cf21380bef3d2aaacc9fcb30116e757 /lib
parentReleasing progress-linux version 1.22.6-0.0~progress7.99u1. (diff)
downloaddpkg-b4f7d8b1566e3220d0e9004499ef9c257e079c57.tar.xz
dpkg-b4f7d8b1566e3220d0e9004499ef9c257e079c57.zip
Merging upstream version 1.22.7.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.in7
-rw-r--r--lib/compat/Makefile.in7
-rw-r--r--lib/compat/strnlen.c2
-rw-r--r--lib/compat/vasprintf.c6
-rw-r--r--lib/dpkg/Makefile.am5
-rw-r--r--lib/dpkg/Makefile.in55
-rw-r--r--lib/dpkg/buffer.c6
-rw-r--r--lib/dpkg/command.c1
-rw-r--r--lib/dpkg/command.h1
-rw-r--r--lib/dpkg/db-ctrl-access.c2
-rw-r--r--lib/dpkg/db-ctrl-format.c1
-rw-r--r--lib/dpkg/db-ctrl-upgrade.c3
-rw-r--r--lib/dpkg/db-fsys-divert.c63
-rw-r--r--lib/dpkg/db-fsys-files.c75
-rw-r--r--lib/dpkg/db-fsys-load.c91
-rw-r--r--lib/dpkg/db-fsys-override.c69
-rw-r--r--lib/dpkg/db-fsys.h26
-rw-r--r--lib/dpkg/dbmodify.c22
-rw-r--r--lib/dpkg/dpkg-db.h12
-rw-r--r--lib/dpkg/dump.c10
-rw-r--r--lib/dpkg/execname.c166
-rw-r--r--lib/dpkg/execname.h43
-rw-r--r--lib/dpkg/fdio.c12
-rw-r--r--lib/dpkg/fields.c26
-rw-r--r--lib/dpkg/file.c45
-rw-r--r--lib/dpkg/file.h3
-rw-r--r--lib/dpkg/i18n.c23
-rw-r--r--lib/dpkg/libdpkg.map11
-rw-r--r--lib/dpkg/log.c1
-rw-r--r--lib/dpkg/mustlib.c4
-rw-r--r--lib/dpkg/parse.c17
-rw-r--r--lib/dpkg/parsedump.h5
-rw-r--r--lib/dpkg/parsehelp.c18
-rw-r--r--lib/dpkg/pkg-format.c7
-rw-r--r--lib/dpkg/pkg-format.h2
-rw-r--r--lib/dpkg/pkg-show.c9
-rw-r--r--lib/dpkg/subproc.c4
-rw-r--r--lib/dpkg/t/c-tarextract.c4
-rw-r--r--lib/dpkg/t/t-arch.c12
-rw-r--r--lib/dpkg/t/t-file.c17
-rw-r--r--lib/dpkg/t/t-pkg-format.c2
-rw-r--r--lib/dpkg/t/t-subproc.c6
-rw-r--r--lib/dpkg/t/t-varbuf.c122
-rw-r--r--lib/dpkg/tarfn.c3
-rw-r--r--lib/dpkg/trigdeferred.c5
-rw-r--r--lib/dpkg/triglib.c1
-rw-r--r--lib/dpkg/triglib.h2
-rw-r--r--lib/dpkg/varbuf.c93
-rw-r--r--lib/dpkg/varbuf.h12
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