summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorSean Finney <seanius@seanius.net>2009-09-28 23:34:28 +0200
committerGuillem Jover <guillem@debian.org>2009-10-05 03:57:01 +0200
commit37e32a9c2c3fa05c1bb7d16b1552c8cb63ad08e2 (patch)
treed53880d2d6d6aa44117ddf1b6b01aa4bc98dd525 /lib
parent5e435949d6379f7dc930f042db5241af1e2ffb46 (diff)
downloaddpkg-37e32a9c2c3fa05c1bb7d16b1552c8cb63ad08e2.tar.gz
libdpkg: Move quote_filename to the path module as path_quote_filename
This function will be useful for other parts of dpkg, so the function has been moved to a more sensible location, the static qualifier removed, and its name appropriately prefixed. Signed-off-by: Guillem Jover <guillem@debian.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/dpkg/path.c61
-rw-r--r--lib/dpkg/path.h1
2 files changed, 62 insertions, 0 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