summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2008-06-21 19:06:37 +0000
committerkientzle <kientzle@FreeBSD.org>2008-06-21 19:06:37 +0000
commit9469ce2c389848f3213f79ad5552baebf458f981 (patch)
treedb379594305665ff78e5a8dbe44ce465cae18996
parentda7e9647feb7605b759c392628c2fc004df6a58c (diff)
downloadFreeBSD-src-9469ce2c389848f3213f79ad5552baebf458f981.zip
FreeBSD-src-9469ce2c389848f3213f79ad5552baebf458f981.tar.gz
MfP4: Joerg Sonnenberg's extensions to the mtree support for more
complete quoting. In particular, this handles escaped newlines and common C-style escapes.
-rw-r--r--lib/libarchive/archive_read_support_format_mtree.c91
1 files changed, 79 insertions, 12 deletions
diff --git a/lib/libarchive/archive_read_support_format_mtree.c b/lib/libarchive/archive_read_support_format_mtree.c
index 8126f95..3b82752 100644
--- a/lib/libarchive/archive_read_support_format_mtree.c
+++ b/lib/libarchive/archive_read_support_format_mtree.c
@@ -1020,7 +1020,7 @@ skip(struct archive_read *a)
}
/*
- * Since parsing octal escapes always makes strings shorter,
+ * Since parsing backslash sequences always makes strings shorter,
* we can always do this conversion in-place.
*/
static void
@@ -1041,13 +1041,57 @@ parse_escapes(char *src, struct mtree_entry *mentry)
if (c == '/' && mentry != NULL)
mentry->full = 1;
if (c == '\\') {
- if (src[0] >= '0' && src[0] <= '3'
- && src[1] >= '0' && src[1] <= '7'
- && src[2] >= '0' && src[2] <= '7') {
- c = (src[0] - '0') << 6;
- c |= (src[1] - '0') << 3;
- c |= (src[2] - '0');
- src += 3;
+ switch (src[0]) {
+ case '0':
+ if (src[1] < '0' || src[1] > '7') {
+ c = 0;
+ ++src;
+ break;
+ }
+ /* FALLTHROUGH */
+ case '1':
+ case '2':
+ case '3':
+ if (src[1] >= '0' && src[1] <= '7' &&
+ src[2] >= '0' && src[2] <= '7') {
+ c = (src[0] - '0') << 6;
+ c |= (src[1] - '0') << 3;
+ c |= (src[2] - '0');
+ src += 3;
+ }
+ break;
+ case 'a':
+ c = '\a';
+ ++src;
+ break;
+ case 'b':
+ c = '\b';
+ ++src;
+ break;
+ case 'f':
+ c = '\f';
+ ++src;
+ break;
+ case 'n':
+ c = '\n';
+ ++src;
+ break;
+ case 'r':
+ c = '\r';
+ ++src;
+ break;
+ case 's':
+ c = ' ';
+ ++src;
+ break;
+ case 't':
+ c = '\t';
+ ++src;
+ break;
+ case 'v':
+ c = '\v';
+ ++src;
+ break;
}
}
*dest++ = c;
@@ -1190,6 +1234,7 @@ readline(struct archive_read *a, struct mtree *mtree, char **start, ssize_t limi
const void *t;
const char *s;
void *p;
+ char *u;
/* Accumulate line in a line buffer. */
for (;;) {
@@ -1222,10 +1267,32 @@ readline(struct archive_read *a, struct mtree *mtree, char **start, ssize_t limi
total_size += bytes_read;
/* Null terminate. */
mtree->line.s[total_size] = '\0';
- /* If we found '\n', clean up and return. */
- if (p != NULL) {
- *start = mtree->line.s;
- return (total_size);
+ /* If we found an unescaped '\n', clean up and return. */
+ if (p == NULL)
+ continue;
+ for (u = mtree->line.s; *u; ++u) {
+ if (u[0] == '\n') {
+ *start = mtree->line.s;
+ return total_size;
+ }
+ if (u[0] == '#') {
+ if (p == NULL)
+ break;
+ *start = mtree->line.s;
+ return total_size;
+ }
+ if (u[0] != '\\')
+ continue;
+ if (u[1] == '\\') {
+ ++u;
+ continue;
+ }
+ if (u[1] == '\n') {
+ memmove(u, u + 1,
+ total_size - (u - mtree->line.s) + 1);
+ --total_size;
+ continue;
+ }
}
}
}
OpenPOWER on IntegriCloud