PageRenderTime 49ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/amanda/tags/amanda252/server-src/cmdline.c

#
C | 237 lines | 179 code | 26 blank | 32 comment | 61 complexity | 5e014df4b04441be92193fe0b95c65e5 MD5 | raw file
  1. /*
  2. * Copyright (c) 2005 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 as published by the
  6. * Free Software Foundation; either version 2 of the License, or (at your
  7. * option) any later version.
  8. *
  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
  12. * for more details.
  13. *
  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
  17. *
  18. * Contact information: Zmanda Inc, 505 N Mathlida Ave, Suite 120
  19. * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
  20. *
  21. * Author: Dustin J. Mitchell <dustin@zmanda.com>
  22. */
  23. /*
  24. * $Id$
  25. *
  26. * Utility routines for handling command lines.
  27. */
  28. #include <ctype.h>
  29. #include "amanda.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. {
  38. dumpspec_t *rv;
  39. rv = calloc(1, sizeof(*rv));
  40. if (!rv) return NULL;
  41. if (host) rv->host = stralloc(host);
  42. if (disk) rv->disk = stralloc(disk);
  43. if (datestamp) rv->datestamp = stralloc(datestamp);
  44. return rv;
  45. }
  46. void
  47. dumpspec_free(
  48. dumpspec_t *dumpspec)
  49. {
  50. if (!dumpspec) return;
  51. if (dumpspec->host) free(dumpspec->host);
  52. if (dumpspec->disk) free(dumpspec->disk);
  53. if (dumpspec->datestamp) free(dumpspec->datestamp);
  54. free(dumpspec);
  55. }
  56. void
  57. dumpspec_free_list(
  58. dumpspec_list_t *dumpspec_list)
  59. {
  60. dumpspec_t *dumpspec = (dumpspec_t *)dumpspec_list;
  61. dumpspec_t *next;
  62. while (dumpspec) {
  63. next = dumpspec->next;
  64. dumpspec_free(dumpspec);
  65. dumpspec = next;
  66. }
  67. }
  68. dumpspec_list_t *
  69. cmdline_parse_dumpspecs(
  70. int argc,
  71. char **argv)
  72. {
  73. dumpspec_t *dumpspec = NULL, *t;
  74. char *errstr;
  75. char *name;
  76. int optind = 0;
  77. enum { ARG_GET_HOST, ARG_GET_DISK, ARG_GET_DATE } arg_state = ARG_GET_HOST;
  78. while (optind < argc) {
  79. name = argv[optind++];
  80. switch (arg_state) {
  81. case ARG_GET_HOST:
  82. if (name[0] != '\0'
  83. && (errstr=validate_regexp(name)) != NULL) {
  84. fprintf(stderr, _("%s: bad hostname regex \"%s\": %s\n"),
  85. get_pname(), name, errstr);
  86. goto error;
  87. }
  88. t = dumpspec_new(name, NULL, NULL);
  89. t->next = (dumpspec_t *)dumpspec;
  90. dumpspec = t;
  91. arg_state = ARG_GET_DISK;
  92. break;
  93. case ARG_GET_DISK:
  94. if (name[0] != '\0'
  95. && (errstr=validate_regexp(name)) != NULL) {
  96. fprintf(stderr, _("%s: bad diskname regex \"%s\": %s\n"),
  97. get_pname(), name, errstr);
  98. goto error;
  99. }
  100. dumpspec->disk = stralloc(name);
  101. arg_state = ARG_GET_DATE;
  102. break;
  103. case ARG_GET_DATE:
  104. if (name[0] != '\0'
  105. && (errstr=validate_regexp(name)) != NULL) {
  106. fprintf(stderr, _("%s: bad datestamp regex \"%s\": %s\n"),
  107. get_pname(), name, errstr);
  108. goto error;
  109. }
  110. dumpspec->datestamp = stralloc(name);
  111. arg_state = ARG_GET_HOST;
  112. break;
  113. }
  114. }
  115. if (dumpspec == NULL)
  116. dumpspec = dumpspec_new("", "", "");
  117. return (dumpspec_list_t *)dumpspec;
  118. error:
  119. dumpspec_free_list((dumpspec_list_t *)dumpspec);
  120. return NULL;
  121. }
  122. char *
  123. cmdline_format_dumpspec(
  124. dumpspec_t *dumpspec)
  125. {
  126. if (!dumpspec) return NULL;
  127. return cmdline_format_dumpspec_components(
  128. dumpspec->host,
  129. dumpspec->disk,
  130. dumpspec->datestamp);
  131. }
  132. /* Quote str for shell interpretation, being conservative.
  133. * Any non-alphanumeric charcacters other than '.' and '/'
  134. * trigger surrounding single quotes, and single quotes and
  135. * backslashes within those single quotes are escaped.
  136. */
  137. static char *
  138. quote_dumpspec_string(char *str)
  139. {
  140. char *rv;
  141. char *p, *q;
  142. int len = 0;
  143. int need_single_quotes = 0;
  144. for (p = str; *p; p++) {
  145. if (!isalnum(*p) && *p != '.' && *p != '/') need_single_quotes=1;
  146. if (*p == '\'' || *p == '\\') len++; /* extra byte for '\' */
  147. len++;
  148. }
  149. if (need_single_quotes) len += 2;
  150. q = rv = malloc(len+1);
  151. if (need_single_quotes) *(q++) = '\'';
  152. for (p = str; *p; p++) {
  153. if (*p == '\'' || *p == '\\') *(q++) = '\\';
  154. *(q++) = *p;
  155. }
  156. if (need_single_quotes) *(q++) = '\'';
  157. *(q++) = '\0';
  158. return rv;
  159. }
  160. char *
  161. cmdline_format_dumpspec_components(
  162. char *host,
  163. char *disk,
  164. char *datestamp)
  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. if (host) {
  171. rv = host;
  172. if (disk) {
  173. rv = newvstralloc(rv, rv, " ", disk, NULL);
  174. amfree(disk);
  175. if (datestamp) {
  176. rv = newvstralloc(rv, rv, " ", datestamp, NULL);
  177. amfree(datestamp);
  178. }
  179. }
  180. }
  181. if (disk) amfree(disk);
  182. if (datestamp) amfree(datestamp);
  183. return rv;
  184. }
  185. sl_t *
  186. cmdline_match_holding(
  187. dumpspec_list_t *dumpspec_list)
  188. {
  189. char *host;
  190. char *disk;
  191. char *datestamp;
  192. filetype_t filetype;
  193. dumpspec_t *de;
  194. sl_t *holding_files;
  195. sle_t *he;
  196. sl_t *matching_files = new_sl();
  197. holding_set_verbosity(0);
  198. holding_files = holding_get_files(NULL, 1);
  199. for (he = holding_files->first; he != NULL; he = he->next) {
  200. filetype = holding_file_read_header(he->name, &host, &disk, NULL, &datestamp);
  201. if (filetype != F_DUMPFILE) continue;
  202. for (de = (dumpspec_t *)dumpspec_list; de != NULL; de = de->next) {
  203. if (de->host && !match_host(de->host, host)) continue;
  204. if (de->disk && !match_disk(de->disk, disk)) continue;
  205. if (de->datestamp && !match_datestamp(de->datestamp, datestamp)) continue;
  206. matching_files = insert_sort_sl(matching_files, he->name);
  207. break;
  208. }
  209. }
  210. return matching_files;
  211. }