2 * Copyright (c) 2007-2012 Zmanda, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * Contact information: Zmanda Inc, 465 S. Mathilda Ave., Suite 300
19 * Sunnyvale, CA 94086, USA, or: http://www.zmanda.com
21 * Author: Dustin J. Mitchell <dustin@zmanda.com>
26 * Utility routines for handling command lines.
41 char *write_timestamp)
45 rv = g_new0(dumpspec_t, 1);
46 if (host) rv->host = stralloc(host);
47 if (disk) rv->disk = stralloc(disk);
48 if (datestamp) rv->datestamp = stralloc(datestamp);
49 if (level) rv->level = stralloc(level);
50 if (write_timestamp) rv->write_timestamp = stralloc(write_timestamp);
59 if (!dumpspec) return;
60 if (dumpspec->host) free(dumpspec->host);
61 if (dumpspec->disk) free(dumpspec->disk);
62 if (dumpspec->datestamp) free(dumpspec->datestamp);
63 if (dumpspec->level) free(dumpspec->level);
64 if (dumpspec->write_timestamp) free(dumpspec->write_timestamp);
70 GSList *dumpspec_list)
72 /* first free all of the individual dumpspecs */
73 g_slist_foreach_nodata(dumpspec_list, dumpspec_free);
75 /* then free the list itself */
76 g_slist_free(dumpspec_list);
80 cmdline_parse_dumpspecs(
85 dumpspec_t *dumpspec = NULL;
90 enum { ARG_GET_HOST, ARG_GET_DISK, ARG_GET_DATESTAMP, ARG_GET_LEVEL } arg_state = ARG_GET_HOST;
92 while (optind < argc) {
93 char *new_name = NULL;
95 if (flags & CMDLINE_EXACT_MATCH && *name != '=') {
96 new_name = g_strconcat("=", name, NULL);
101 arg_state = ARG_GET_DISK;
102 dumpspec = dumpspec_new(name, NULL, NULL, NULL, NULL);
103 list = g_slist_append(list, (gpointer)dumpspec);
107 arg_state = ARG_GET_DATESTAMP;
108 dumpspec->disk = stralloc(name);
111 case ARG_GET_DATESTAMP:
112 arg_state = ARG_GET_LEVEL;
113 if (!(flags & CMDLINE_PARSE_DATESTAMP)) continue;
114 dumpspec->datestamp = stralloc(name);
118 arg_state = ARG_GET_HOST;
119 if (!(flags & CMDLINE_PARSE_LEVEL)) continue;
121 && !(flags & CMDLINE_EXACT_MATCH)
122 && (errstr=validate_regexp(name)) != NULL) {
123 error(_("bad level regex \"%s\": %s\n"), name, errstr);
125 dumpspec->level = stralloc(name);
133 /* if nothing was processed and the caller has requested it,
134 * then add an "empty" element */
135 if (list == NULL && (flags & CMDLINE_EMPTY_TO_WILDCARD)) {
136 dumpspec = dumpspec_new("", "",
137 (flags & CMDLINE_PARSE_DATESTAMP)?"":NULL,
138 (flags & CMDLINE_PARSE_LEVEL)?"":NULL, "");
139 list = g_slist_append(list, (gpointer)dumpspec);
146 cmdline_format_dumpspec(
147 dumpspec_t *dumpspec)
149 if (!dumpspec) return NULL;
150 return cmdline_format_dumpspec_components(
157 /* Quote str for shell interpretation, being conservative.
158 * Any non-alphanumeric charcacters other than '.' and '/'
159 * trigger surrounding single quotes, and single quotes and
160 * backslashes within those single quotes are escaped.
163 quote_dumpspec_string(char *str)
168 int need_single_quotes = 0;
171 return stralloc("''"); /* special-case the empty string */
173 for (p = str; *p; p++) {
174 if (!isalnum((int)*p) && *p != '.' && *p != '/') need_single_quotes=1;
175 if (*p == '\'' || *p == '\\') len++; /* extra byte for '\' */
178 if (need_single_quotes) len += 2;
180 q = rv = malloc(len+1);
181 if (need_single_quotes) *(q++) = '\'';
182 for (p = str; *p; p++) {
183 if (*p == '\'' || *p == '\\') *(q++) = '\\';
186 if (need_single_quotes) *(q++) = '\'';
193 cmdline_format_dumpspec_components(
201 host = host? quote_dumpspec_string(host):NULL;
202 disk = disk? quote_dumpspec_string(disk):NULL;
203 datestamp = datestamp? quote_dumpspec_string(datestamp):NULL;
204 level = level? quote_dumpspec_string(level):NULL;
210 rv = newvstralloc(rv, rv, " ", disk, NULL);
212 rv = newvstralloc(rv, rv, " ", datestamp, NULL);
214 rv = newvstralloc(rv, rv, " ", level, NULL);
220 if (host) amfree(host);
221 if (disk) amfree(disk);
222 if (datestamp) amfree(datestamp);
223 if (level) amfree(level);
229 cmdline_match_holding(
230 GSList *dumpspec_list)
234 GSList *holding_files;
235 GSList *matching_files = NULL;
238 holding_files = holding_get_files(NULL, 1);
240 for (hi = holding_files; hi != NULL; hi = hi->next) {
242 if (!holding_file_get_dumpfile((char *)hi->data, &file)) continue;
243 if (file.type != F_DUMPFILE) {
244 dumpfile_free_data(&file);
247 for (li = dumpspec_list; li != NULL; li = li->next) {
248 de = (dumpspec_t *)(li->data);
249 if (de->host && de->host[0] && !match_host(de->host, file.name)) continue;
250 if (de->disk && de->disk[0] && !match_disk(de->disk, file.disk)) continue;
251 if (de->datestamp && de->datestamp[0] && !match_datestamp(de->datestamp, file.datestamp)) continue;
252 matching_files = g_slist_append(matching_files, g_strdup((char *)hi->data));
255 dumpfile_free_data(&file);
258 slist_free_full(holding_files, g_free);
260 return matching_files;