summaryrefslogtreecommitdiffstats
path: root/lib/libarchive/archive_util.c
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2009-03-06 05:58:56 +0000
committerkientzle <kientzle@FreeBSD.org>2009-03-06 05:58:56 +0000
commita6d71699e11ca2aa4e0f92a369ac8071b9eb85c0 (patch)
tree5d87f6f3a950ec9ead6d49f3895b6b060a82f0b7 /lib/libarchive/archive_util.c
parent1c1c217183280235637a950efa5a836ddab91b71 (diff)
downloadFreeBSD-src-a6d71699e11ca2aa4e0f92a369ac8071b9eb85c0.zip
FreeBSD-src-a6d71699e11ca2aa4e0f92a369ac8071b9eb85c0.tar.gz
Merge r491,493,500,507,510,530,543 from libarchive.googlecode.com:
This implements the new generic options framework that provides a way to override format- and compression-specific parameters.
Diffstat (limited to 'lib/libarchive/archive_util.c')
-rw-r--r--lib/libarchive/archive_util.c193
1 files changed, 193 insertions, 0 deletions
diff --git a/lib/libarchive/archive_util.c b/lib/libarchive/archive_util.c
index bc39a4d..1c171b9 100644
--- a/lib/libarchive/archive_util.c
+++ b/lib/libarchive/archive_util.c
@@ -1,4 +1,5 @@
/*-
+ * Copyright (c) 2009 Michihiro NAKAJIMA
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
@@ -186,3 +187,195 @@ __archive_errx(int retvalue, const char *msg)
write(2, "\n", 1);
exit(retvalue);
}
+
+/*
+ * Parse option strings
+ * Detail of option format.
+ * - The option can accept:
+ * "opt-name", "!opt-name", "opt-name=value".
+ *
+ * - The option entries are separated by comma.
+ * e.g "compression=9,opt=XXX,opt-b=ZZZ"
+ *
+ * - The name of option string consist of '-' and alphabet
+ * but character '-' cannot be used for the first character.
+ * (Regular expression is [a-z][-a-z]+)
+ *
+ * - For a specfic format/filter, using the format name with ':'.
+ * e.g "zip:compression=9"
+ * (This "compression=9" option entry is for "zip" format only)
+ *
+ * If another entries follow it, those are not for
+ * the specfic format/filter.
+ * e.g handle "zip:compression=9,opt=XXX,opt-b=ZZZ"
+ * "zip" format/filter handler will get "compression=9"
+ * all format/filter handler will get "opt=XXX"
+ * all format/filter handler will get "opt-b=ZZZ"
+ *
+ * - Whitespace and tab are bypassed.
+ *
+ */
+int
+__archive_parse_options(const char *p, const char *fn, int keysize, char *key,
+ int valsize, char *val)
+{
+ const char *p_org;
+ int apply;
+ int kidx, vidx;
+ int negative;
+ enum {
+ /* Requested for initialization. */
+ INIT,
+ /* Finding format/filter-name and option-name. */
+ F_BOTH,
+ /* Finding option-name only.
+ * (already detected format/filter-name) */
+ F_NAME,
+ /* Getting option-value. */
+ G_VALUE,
+ } state;
+
+ p_org = p;
+ state = INIT;
+ kidx = vidx = negative = 0;
+ apply = 1;
+ while (*p) {
+ switch (state) {
+ case INIT:
+ kidx = vidx = 0;
+ negative = 0;
+ apply = 1;
+ state = F_BOTH;
+ break;
+ case F_BOTH:
+ case F_NAME:
+ if ((*p >= 'a' && *p <= 'z') ||
+ (*p >= '0' && *p <= '9') || *p == '-') {
+ if (kidx == 0 && !(*p >= 'a' && *p <= 'z'))
+ /* Illegal sequence. */
+ return (-1);
+ if (kidx >= keysize -1)
+ /* Too many characters. */
+ return (-1);
+ key[kidx++] = *p++;
+ } else if (*p == '!') {
+ if (kidx != 0)
+ /* Illegal sequence. */
+ return (-1);
+ negative = 1;
+ ++p;
+ } else if (*p == ',') {
+ if (kidx == 0)
+ /* Illegal sequence. */
+ return (-1);
+ if (!negative)
+ val[vidx++] = '1';
+ /* We have got boolean option data. */
+ ++p;
+ if (apply)
+ goto complete;
+ else
+ /* This option does not apply to the
+ * format which the fn variable
+ * indicate. */
+ state = INIT;
+ } else if (*p == ':') {
+ /* obuf data is format name */
+ if (state == F_NAME)
+ /* We already found it. */
+ return (-1);
+ if (kidx == 0)
+ /* Illegal sequence. */
+ return (-1);
+ if (negative)
+ /* We cannot accept "!format-name:". */
+ return (-1);
+ key[kidx] = '\0';
+ if (strcmp(fn, key) != 0)
+ /* This option does not apply to the
+ * format which the fn variable
+ * indicate. */
+ apply = 0;
+ kidx = 0;
+ ++p;
+ state = F_NAME;
+ } else if (*p == '=') {
+ if (kidx == 0)
+ /* Illegal sequence. */
+ return (-1);
+ if (negative)
+ /* We cannot accept "!opt-name=value". */
+ return (-1);
+ ++p;
+ state = G_VALUE;
+ } else if (*p == ' ') {
+ /* Pass the space character */
+ ++p;
+ } else {
+ /* Illegal character. */
+ return (-1);
+ }
+ break;
+ case G_VALUE:
+ if (*p == ',') {
+ if (vidx == 0)
+ /* Illegal sequence. */
+ return (-1);
+ /* We have got option data. */
+ ++p;
+ if (apply)
+ goto complete;
+ else
+ /* This option does not apply to the
+ * format which the fn variable
+ * indicate. */
+ state = INIT;
+ } else if (*p == ' ') {
+ /* Pass the space character */
+ ++p;
+ } else {
+ if (vidx >= valsize -1)
+ /* Too many characters. */
+ return (-1);
+ val[vidx++] = *p++;
+ }
+ break;
+ }
+ }
+
+ switch (state) {
+ case F_BOTH:
+ case F_NAME:
+ if (kidx != 0) {
+ if (!negative)
+ val[vidx++] = '1';
+ /* We have got boolean option. */
+ if (apply)
+ /* This option apply to the format which the
+ * fn variable indicate. */
+ goto complete;
+ }
+ break;
+ case G_VALUE:
+ if (vidx == 0)
+ /* Illegal sequence. */
+ return (-1);
+ /* We have got option value. */
+ if (apply)
+ /* This option apply to the format which the fn
+ * variable indicate. */
+ goto complete;
+ break;
+ case INIT:/* nothing */
+ break;
+ }
+
+ /* End of Option string. */
+ return (0);
+
+complete:
+ key[kidx] = '\0';
+ val[vidx] = '\0';
+ /* Return a size which we've consumed for detecting option */
+ return ((int)(p - p_org));
+}
OpenPOWER on IntegriCloud