Path: blob/master/Utilities/cmlibarchive/libarchive/archive_cmdline.c
3153 views
/*-1* Copyright (c) 2012 Michihiro NAKAJIMA2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12*13* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR14* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES15* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.16* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,17* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT18* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,19* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY20* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT21* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF22* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.23*/2425#include "archive_platform.h"2627#ifdef HAVE_STRING_H28# include <string.h>29#endif30#ifdef HAVE_STDLIB_H31# include <stdlib.h>32#endif3334#include "archive.h"35#include "archive_cmdline_private.h"36#include "archive_string.h"3738static int cmdline_set_path(struct archive_cmdline *, const char *);39static int cmdline_add_arg(struct archive_cmdline *, const char *);4041static ssize_t42extract_quotation(struct archive_string *as, const char *p)43{44const char *s;4546for (s = p + 1; *s;) {47if (*s == '\\') {48if (s[1] != '\0') {49archive_strappend_char(as, s[1]);50s += 2;51} else52s++;53} else if (*s == '"')54break;55else {56archive_strappend_char(as, s[0]);57s++;58}59}60if (*s != '"')61return (ARCHIVE_FAILED);/* Invalid sequence. */62return ((ssize_t)(s + 1 - p));63}6465static ssize_t66get_argument(struct archive_string *as, const char *p)67{68const char *s = p;6970archive_string_empty(as);7172/* Skip beginning space characters. */73while (*s != '\0' && *s == ' ')74s++;75/* Copy non-space characters. */76while (*s != '\0' && *s != ' ') {77if (*s == '\\') {78if (s[1] != '\0') {79archive_strappend_char(as, s[1]);80s += 2;81} else {82s++;/* Ignore this character.*/83break;84}85} else if (*s == '"') {86ssize_t q = extract_quotation(as, s);87if (q < 0)88return (ARCHIVE_FAILED);/* Invalid sequence. */89s += q;90} else {91archive_strappend_char(as, s[0]);92s++;93}94}95return ((ssize_t)(s - p));96}9798/*99* Set up command line arguments.100* Returns ARCHIVE_OK if everything okey.101* Returns ARCHIVE_FAILED if there is a lack of the `"' terminator or an102* empty command line.103* Returns ARCHIVE_FATAL if no memory.104*/105int106__archive_cmdline_parse(struct archive_cmdline *data, const char *cmd)107{108struct archive_string as;109const char *p;110ssize_t al;111int r;112113archive_string_init(&as);114115/* Get first argument as a command path. */116al = get_argument(&as, cmd);117if (al < 0) {118r = ARCHIVE_FAILED;/* Invalid sequence. */119goto exit_function;120}121if (archive_strlen(&as) == 0) {122r = ARCHIVE_FAILED;/* An empty command path. */123goto exit_function;124}125r = cmdline_set_path(data, as.s);126if (r != ARCHIVE_OK)127goto exit_function;128p = strrchr(as.s, '/');129if (p == NULL)130p = as.s;131else132p++;133r = cmdline_add_arg(data, p);134if (r != ARCHIVE_OK)135goto exit_function;136cmd += al;137138for (;;) {139al = get_argument(&as, cmd);140if (al < 0) {141r = ARCHIVE_FAILED;/* Invalid sequence. */142goto exit_function;143}144if (al == 0)145break;146cmd += al;147if (archive_strlen(&as) == 0 && *cmd == '\0')148break;149r = cmdline_add_arg(data, as.s);150if (r != ARCHIVE_OK)151goto exit_function;152}153r = ARCHIVE_OK;154exit_function:155archive_string_free(&as);156return (r);157}158159/*160* Set the program path.161*/162static int163cmdline_set_path(struct archive_cmdline *data, const char *path)164{165char *newptr;166167newptr = realloc(data->path, strlen(path) + 1);168if (newptr == NULL)169return (ARCHIVE_FATAL);170data->path = newptr;171strcpy(data->path, path);172return (ARCHIVE_OK);173}174175/*176* Add a argument for the program.177*/178static int179cmdline_add_arg(struct archive_cmdline *data, const char *arg)180{181char **newargv;182183if (data->path == NULL)184return (ARCHIVE_FAILED);185186newargv = realloc(data->argv, (data->argc + 2) * sizeof(char *));187if (newargv == NULL)188return (ARCHIVE_FATAL);189data->argv = newargv;190data->argv[data->argc] = strdup(arg);191if (data->argv[data->argc] == NULL)192return (ARCHIVE_FATAL);193/* Set the terminator of argv. */194data->argv[++data->argc] = NULL;195return (ARCHIVE_OK);196}197198struct archive_cmdline *199__archive_cmdline_allocate(void)200{201return (struct archive_cmdline *)202calloc(1, sizeof(struct archive_cmdline));203}204205/*206* Release the resources.207*/208int209__archive_cmdline_free(struct archive_cmdline *data)210{211212if (data) {213free(data->path);214if (data->argv != NULL) {215int i;216for (i = 0; data->argv[i] != NULL; i++)217free(data->argv[i]);218free(data->argv);219}220free(data);221}222return (ARCHIVE_OK);223}224225226227