diff options
author | kientzle <kientzle@FreeBSD.org> | 2009-03-06 05:58:56 +0000 |
---|---|---|
committer | kientzle <kientzle@FreeBSD.org> | 2009-03-06 05:58:56 +0000 |
commit | a6d71699e11ca2aa4e0f92a369ac8071b9eb85c0 (patch) | |
tree | 5d87f6f3a950ec9ead6d49f3895b6b060a82f0b7 /lib/libarchive/archive_util.c | |
parent | 1c1c217183280235637a950efa5a836ddab91b71 (diff) | |
download | FreeBSD-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.c | 193 |
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)); +} |