PageRenderTime 38ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/amanda/tags/3_1_0_mac01/server-src/cmdline.c

#
C | 250 lines | 183 code | 31 blank | 36 comment | 64 complexity | bd34f46cab8d0e7a66e312004fbe6384 MD5 | raw file
  1. /*
  2. * Copyright (c) 2007, 2008, 2009, 2010 Zmanda, Inc. All Rights Reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms of the GNU General Public License version 2 as published
  6. * by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful, but
  9. * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  11. * for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License along
  14. * with this program; if not, write to the Free Software Foundation, Inc.,
  15. * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  16. *
  17. * Contact information: Zmanda Inc, 465 S. Mathilda Ave., Suite 300
  18. * Sunnyvale, CA 94086, USA, or: http://www.zmanda.com
  19. *
  20. * Author: Dustin J. Mitchell <dustin@zmanda.com>
  21. */
  22. /*
  23. * $Id$
  24. *
  25. * Utility routines for handling command lines.
  26. */
  27. #include <ctype.h>
  28. #include "amanda.h"
  29. #include "match.h"
  30. #include "cmdline.h"
  31. #include "holding.h"
  32. dumpspec_t *
  33. dumpspec_new(
  34. char *host,
  35. char *disk,
  36. char *datestamp,
  37. char *level)
  38. {
  39. dumpspec_t *rv;
  40. rv = g_new0(dumpspec_t, 1);
  41. if (host) rv->host = stralloc(host);
  42. if (disk) rv->disk = stralloc(disk);
  43. if (datestamp) rv->datestamp = stralloc(datestamp);
  44. if (level) rv->level = stralloc(level);
  45. return rv;
  46. }
  47. void
  48. dumpspec_free(
  49. dumpspec_t *dumpspec)
  50. {
  51. if (!dumpspec) return;
  52. if (dumpspec->host) free(dumpspec->host);
  53. if (dumpspec->disk) free(dumpspec->disk);
  54. if (dumpspec->datestamp) free(dumpspec->datestamp);
  55. if (dumpspec->level) free(dumpspec->level);
  56. free(dumpspec);
  57. }
  58. void
  59. dumpspec_list_free(
  60. GSList *dumpspec_list)
  61. {
  62. /* first free all of the individual dumpspecs */
  63. g_slist_foreach_nodata(dumpspec_list, dumpspec_free);
  64. /* then free the list itself */
  65. g_slist_free(dumpspec_list);
  66. }
  67. GSList *
  68. cmdline_parse_dumpspecs(
  69. int argc,
  70. char **argv,
  71. int flags)
  72. {
  73. dumpspec_t *dumpspec = NULL;
  74. GSList *list = NULL;
  75. char *errstr;
  76. char *name;
  77. int optind = 0;
  78. enum { ARG_GET_HOST, ARG_GET_DISK, ARG_GET_DATESTAMP, ARG_GET_LEVEL } arg_state = ARG_GET_HOST;
  79. while (optind < argc) {
  80. name = argv[optind];
  81. switch (arg_state) {
  82. case ARG_GET_HOST:
  83. arg_state = ARG_GET_DISK;
  84. dumpspec = dumpspec_new(name, NULL, NULL, NULL);
  85. list = g_slist_append(list, (gpointer)dumpspec);
  86. break;
  87. case ARG_GET_DISK:
  88. arg_state = ARG_GET_DATESTAMP;
  89. dumpspec->disk = stralloc(name);
  90. break;
  91. case ARG_GET_DATESTAMP:
  92. arg_state = ARG_GET_LEVEL;
  93. if (!(flags & CMDLINE_PARSE_DATESTAMP)) continue;
  94. dumpspec->datestamp = stralloc(name);
  95. break;
  96. case ARG_GET_LEVEL:
  97. arg_state = ARG_GET_HOST;
  98. if (!(flags & CMDLINE_PARSE_LEVEL)) continue;
  99. if (name[0] != '\0'
  100. && (errstr=validate_regexp(name)) != NULL) {
  101. error(_("bad level regex \"%s\": %s\n"), name, errstr);
  102. }
  103. dumpspec->level = stralloc(name);
  104. break;
  105. }
  106. optind++;
  107. }
  108. /* if nothing was processed and the caller has requested it,
  109. * then add an "empty" element */
  110. if (list == NULL && (flags & CMDLINE_EMPTY_TO_WILDCARD)) {
  111. dumpspec = dumpspec_new("", "",
  112. (flags & CMDLINE_PARSE_DATESTAMP)?"":NULL,
  113. (flags & CMDLINE_PARSE_LEVEL)?"":NULL);
  114. list = g_slist_append(list, (gpointer)dumpspec);
  115. }
  116. return list;
  117. }
  118. char *
  119. cmdline_format_dumpspec(
  120. dumpspec_t *dumpspec)
  121. {
  122. if (!dumpspec) return NULL;
  123. return cmdline_format_dumpspec_components(
  124. dumpspec->host,
  125. dumpspec->disk,
  126. dumpspec->datestamp,
  127. dumpspec->level);
  128. }
  129. /* Quote str for shell interpretation, being conservative.
  130. * Any non-alphanumeric charcacters other than '.' and '/'
  131. * trigger surrounding single quotes, and single quotes and
  132. * backslashes within those single quotes are escaped.
  133. */
  134. static char *
  135. quote_dumpspec_string(char *str)
  136. {
  137. char *rv;
  138. char *p, *q;
  139. int len = 0;
  140. int need_single_quotes = 0;
  141. if (!str[0])
  142. return stralloc("''"); /* special-case the empty string */
  143. for (p = str; *p; p++) {
  144. if (!isalnum((int)*p) && *p != '.' && *p != '/') need_single_quotes=1;
  145. if (*p == '\'' || *p == '\\') len++; /* extra byte for '\' */
  146. len++;
  147. }
  148. if (need_single_quotes) len += 2;
  149. q = rv = malloc(len+1);
  150. if (need_single_quotes) *(q++) = '\'';
  151. for (p = str; *p; p++) {
  152. if (*p == '\'' || *p == '\\') *(q++) = '\\';
  153. *(q++) = *p;
  154. }
  155. if (need_single_quotes) *(q++) = '\'';
  156. *(q++) = '\0';
  157. return rv;
  158. }
  159. char *
  160. cmdline_format_dumpspec_components(
  161. char *host,
  162. char *disk,
  163. char *datestamp,
  164. char *level)
  165. {
  166. char *rv = NULL;
  167. host = host? quote_dumpspec_string(host):NULL;
  168. disk = disk? quote_dumpspec_string(disk):NULL;
  169. datestamp = datestamp? quote_dumpspec_string(datestamp):NULL;
  170. level = level? quote_dumpspec_string(level):NULL;
  171. if (host) {
  172. rv = host;
  173. host = NULL;
  174. if (disk) {
  175. rv = newvstralloc(rv, rv, " ", disk, NULL);
  176. if (datestamp) {
  177. rv = newvstralloc(rv, rv, " ", datestamp, NULL);
  178. if (level) {
  179. rv = newvstralloc(rv, rv, " ", level, NULL);
  180. }
  181. }
  182. }
  183. }
  184. if (host) amfree(host);
  185. if (disk) amfree(disk);
  186. if (datestamp) amfree(datestamp);
  187. if (level) amfree(level);
  188. return rv;
  189. }
  190. GSList *
  191. cmdline_match_holding(
  192. GSList *dumpspec_list)
  193. {
  194. dumpspec_t *de;
  195. GSList *li, *hi;
  196. GSList *holding_files;
  197. GSList *matching_files = NULL;
  198. dumpfile_t file;
  199. holding_files = holding_get_files(NULL, 1);
  200. for (hi = holding_files; hi != NULL; hi = hi->next) {
  201. /* TODO add level */
  202. if (!holding_file_get_dumpfile((char *)hi->data, &file)) continue;
  203. if (file.type != F_DUMPFILE) {
  204. dumpfile_free_data(&file);
  205. continue;
  206. }
  207. for (li = dumpspec_list; li != NULL; li = li->next) {
  208. de = (dumpspec_t *)(li->data);
  209. if (de->host && de->host[0] && !match_host(de->host, file.name)) continue;
  210. if (de->disk && de->disk[0] && !match_disk(de->disk, file.disk)) continue;
  211. if (de->datestamp && de->datestamp[0] && !match_datestamp(de->datestamp, file.datestamp)) continue;
  212. matching_files = g_slist_append(matching_files, g_strdup((char *)hi->data));
  213. break;
  214. }
  215. dumpfile_free_data(&file);
  216. }
  217. g_slist_free_full(holding_files);
  218. return matching_files;
  219. }