summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/dpkg/path.c61
-rw-r--r--lib/dpkg/path.h1
-rw-r--r--src/archives.c65
3 files changed, 67 insertions, 60 deletions
diff --git a/lib/dpkg/path.c b/lib/dpkg/path.c
index 8ea891eb4..240bdce4d 100644
--- a/lib/dpkg/path.c
+++ b/lib/dpkg/path.c
@@ -23,6 +23,7 @@
#include <config.h>
#include <compat.h>
+#include <stdio.h>
#include <string.h>
#include <dpkg/path.h>
@@ -54,3 +55,63 @@ path_skip_slash_dotslash(const char *path)
return path;
}
+/*
+ * snprintf(3) doesn't work if format contains %.<nnn>s and an argument has
+ * invalid char for locale, then it returns -1.
+ * ohshite() is ok, but fd_fd_copy(), which is used in tarobject() in this
+ * file, is not ok, because
+ * - fd_fd_copy() == buffer_copy_setup() [include/dpkg.h]
+ * - buffer_copy_setup() uses varbufvprintf(&v, desc, al); [lib/mlib.c]
+ * - varbufvprintf() fails and memory exausted, because it call
+ * fmt = "backend dpkg-deb during `%.255s'
+ * arg may contain some invalid char, for example,
+ * /usr/share/doc/console-tools/examples/unicode/\342\231\252\342\231\254
+ * in console-tools.
+ * In this case, if user uses some locale which doesn't support \342\231...,
+ * vsnprintf() always returns -1 and varbufextend() get called again
+ * and again until memory is exausted and it aborts.
+ *
+ * So, we need to escape invalid char, probably as in
+ * tar-1.13.19/lib/quotearg.c: quotearg_buffer_restyled()
+ * but here I escape all 8bit chars, in order to be simple.
+ * - ukai@debian.or.jp
+ */
+char *
+path_quote_filename(char *buf, int size, char *s)
+{
+ char *r = buf;
+
+ while (size > 0) {
+ switch (*s) {
+ case '\0':
+ *buf = '\0';
+ return r;
+ case '\\':
+ *buf++ = '\\';
+ *buf++ = '\\';
+ size -= 2;
+ break;
+ default:
+ if (((*s) & 0x80) == '\0') {
+ *buf++ = *s++;
+ --size;
+ } else {
+ if (size > 4) {
+ sprintf(buf, "\\%03o",
+ *(unsigned char *)s);
+ size -= 4;
+ buf += 4;
+ s++;
+ } else {
+ /* Buffer full. */
+ *buf = '\0'; /* XXX */
+ return r;
+ }
+ }
+ }
+ }
+ *buf = '\0'; /* XXX */
+
+ return r;
+}
+
diff --git a/lib/dpkg/path.h b/lib/dpkg/path.h
index 701eb8e87..ae65f063e 100644
--- a/lib/dpkg/path.h
+++ b/lib/dpkg/path.h
@@ -32,6 +32,7 @@ DPKG_BEGIN_DECLS
size_t path_rtrim_slash_slashdot(char *path);
const char *path_skip_slash_dotslash(const char *path);
+char *path_quote_filename(char *buf, int size, char *s);
DPKG_END_DECLS
diff --git a/src/archives.c b/src/archives.c
index 17ae9a288..41d3f0744 100644
--- a/src/archives.c
+++ b/src/archives.c
@@ -43,6 +43,7 @@
#include <dpkg/dpkg.h>
#include <dpkg/dpkg-db.h>
+#include <dpkg/path.h>
#include <dpkg/buffer.h>
#include <dpkg/subproc.h>
#include <dpkg/tarfn.h>
@@ -63,64 +64,6 @@ static security_context_t scontext = NULL;
struct pkginfo *conflictor[MAXCONFLICTORS];
int cflict_index = 0;
-/* snprintf(3) doesn't work if format contains %.<nnn>s and an argument has
- * invalid char for locale, then it returns -1.
- * ohshite() is ok, but fd_fd_copy(), which is used in tarobject() in this
- * file, is not ok, because
- * - fd_fd_copy() == buffer_copy_setup() [include/dpkg.h]
- * - buffer_copy_setup() uses varbufvprintf(&v, desc, al); [lib/mlib.c]
- * - varbufvprintf() fails and memory exausted, because it call
- * fmt = "backend dpkg-deb during `%.255s'
- * arg may contain some invalid char, for example,
- * /usr/share/doc/console-tools/examples/unicode/\342\231\252\342\231\254
- * in console-tools.
- * In this case, if user uses some locale which doesn't support \342\231...,
- * vsnprintf() always returns -1 and varbufextend() get called again
- * and again until memory is exausted and it aborts.
- *
- * So, we need to escape invalid char, probably as in
- * tar-1.13.19/lib/quotearg.c: quotearg_buffer_restyled()
- * but here I escape all 8bit chars, in order to be simple.
- * - ukai@debian.or.jp
- */
-static char *
-quote_filename(char *buf, int size, char *s)
-{
- char *r = buf;
-
- while (size > 0) {
- switch (*s) {
- case '\0':
- *buf = '\0';
- return r;
- case '\\':
- *buf++ = '\\';
- *buf++ = '\\';
- size -= 2;
- break;
- default:
- if (((*s) & 0x80) == '\0') {
- *buf++ = *s++;
- --size;
- } else {
- if (size > 4) {
- sprintf(buf, "\\%03o", *(unsigned char *)s);
- size -= 4;
- buf += 4;
- s++;
- } else {
- /* buffer full */
- *buf = '\0'; /* XXX */
- return r;
- }
- }
- }
- }
- *buf = '\0'; /* XXX */
-
- return r;
-}
-
/* special routine to handle partial reads from the tarfile */
static int safe_read(int fd, void *buf, int len)
{
@@ -258,7 +201,7 @@ tarfile_skip_one_forward(struct TarInfo *ti,
fd_null_copy(tc->backendpipe, ti->Size,
_("skipped unpacking file '%.255s' (replaced or excluded?)"),
- quote_filename(fnamebuf, 256, ti->Name));
+ path_quote_filename(fnamebuf, 256, ti->Name));
r = ti->Size % TARBLKSZ;
if (r > 0)
r = safe_read(tc->backendpipe, databuf, TARBLKSZ - r);
@@ -694,7 +637,9 @@ int tarobject(struct TarInfo *ti) {
debug(dbg_eachfiledetail,"tarobject NormalFile[01] open size=%lu",
(unsigned long)ti->Size);
{ char fnamebuf[256];
- fd_fd_copy(tc->backendpipe, fd, ti->Size, _("backend dpkg-deb during `%.255s'"),quote_filename(fnamebuf,256,ti->Name));
+ fd_fd_copy(tc->backendpipe, fd, ti->Size,
+ _("backend dpkg-deb during `%.255s'"),
+ path_quote_filename(fnamebuf, 256, ti->Name));
}
r= ti->Size % TARBLKSZ;
if (r > 0) r= safe_read(tc->backendpipe,databuf,TARBLKSZ - r);