PageRenderTime 56ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/amanda/tags/amanda261p2/server-src/find.c

#
C | 1092 lines | 878 code | 125 blank | 89 comment | 285 complexity | dcddf9387e6461bc504cbd360cb06610 MD5 | raw file
  1. /*
  2. * Amanda, The Advanced Maryland Automatic Network Disk Archiver
  3. * Copyright (c) 1991-1998 University of Maryland at College Park
  4. * All Rights Reserved.
  5. *
  6. * Permission to use, copy, modify, distribute, and sell this software and its
  7. * documentation for any purpose is hereby granted without fee, provided that
  8. * the above copyright notice appear in all copies and that both that
  9. * copyright notice and this permission notice appear in supporting
  10. * documentation, and that the name of U.M. not be used in advertising or
  11. * publicity pertaining to distribution of the software without specific,
  12. * written prior permission. U.M. makes no representations about the
  13. * suitability of this software for any purpose. It is provided "as is"
  14. * without express or implied warranty.
  15. *
  16. * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
  18. * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  20. * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  21. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22. *
  23. * Author: James da Silva, Systems Design and Analysis Group
  24. * Computer Science Department
  25. * University of Maryland at College Park
  26. */
  27. /*
  28. * $Id: find.c,v 1.33 2006/07/06 13:13:15 martinea Exp $
  29. *
  30. * controlling process for the Amanda backup system
  31. */
  32. #include "amanda.h"
  33. #include "conffile.h"
  34. #include "tapefile.h"
  35. #include "logfile.h"
  36. #include "holding.h"
  37. #include "find.h"
  38. #include <regex.h>
  39. #include "cmdline.h"
  40. int find_match(char *host, char *disk);
  41. void search_holding_disk(find_result_t **output_find);
  42. char *find_nicedate(char *datestamp);
  43. static int find_compare(const void *, const void *);
  44. static int parse_taper_datestamp_log(char *logline, char **datestamp, char **level);
  45. static gboolean logfile_has_tape(char * label, char * datestamp,
  46. char * logfile);
  47. static char *find_sort_order = NULL;
  48. find_result_t * find_dump(disklist_t* diskqp) {
  49. char *conf_logdir, *logfile = NULL;
  50. int tape, maxtape, logs;
  51. unsigned seq;
  52. tape_t *tp;
  53. find_result_t *output_find = NULL;
  54. conf_logdir = config_dir_relative(getconf_str(CNF_LOGDIR));
  55. maxtape = lookup_nb_tape();
  56. for(tape = 1; tape <= maxtape; tape++) {
  57. tp = lookup_tapepos(tape);
  58. if(tp == NULL) continue;
  59. /* search log files */
  60. logs = 0;
  61. /* new-style log.<date>.<seq> */
  62. for(seq = 0; 1; seq++) {
  63. char seq_str[NUM_STR_SIZE];
  64. g_snprintf(seq_str, SIZEOF(seq_str), "%u", seq);
  65. logfile = newvstralloc(logfile,
  66. conf_logdir, "/log.", tp->datestamp, ".", seq_str, NULL);
  67. if(access(logfile, R_OK) != 0) break;
  68. if (search_logfile(&output_find, tp->label, tp->datestamp,
  69. logfile, diskqp)) {
  70. logs ++;
  71. }
  72. }
  73. /* search old-style amflush log, if any */
  74. logfile = newvstralloc(logfile, conf_logdir, "/log.",
  75. tp->datestamp, ".amflush", NULL);
  76. if(access(logfile,R_OK) == 0) {
  77. if (search_logfile(&output_find, tp->label, tp->datestamp,
  78. logfile, diskqp)) {
  79. logs ++;
  80. }
  81. }
  82. /* search old-style main log, if any */
  83. logfile = newvstralloc(logfile, conf_logdir, "/log.", tp->datestamp,
  84. NULL);
  85. if(access(logfile,R_OK) == 0) {
  86. if (search_logfile(&output_find, tp->label, tp->datestamp,
  87. logfile, diskqp)) {
  88. logs ++;
  89. }
  90. }
  91. if(logs == 0 && strcmp(tp->datestamp,"0") != 0)
  92. g_fprintf(stderr,
  93. _("Warning: no log files found for tape %s written %s\n"),
  94. tp->label, find_nicedate(tp->datestamp));
  95. }
  96. amfree(logfile);
  97. amfree(conf_logdir);
  98. search_holding_disk(&output_find);
  99. return(output_find);
  100. }
  101. char **
  102. find_log(void)
  103. {
  104. char *conf_logdir, *logfile = NULL;
  105. char *pathlogfile = NULL;
  106. int tape, maxtape, logs;
  107. unsigned seq;
  108. tape_t *tp;
  109. char **output_find_log = NULL;
  110. char **current_log;
  111. conf_logdir = config_dir_relative(getconf_str(CNF_LOGDIR));
  112. maxtape = lookup_nb_tape();
  113. output_find_log = alloc((maxtape*5+10) * SIZEOF(char *));
  114. current_log = output_find_log;
  115. for(tape = 1; tape <= maxtape; tape++) {
  116. tp = lookup_tapepos(tape);
  117. if(tp == NULL) continue;
  118. /* search log files */
  119. logs = 0;
  120. /* new-style log.<date>.<seq> */
  121. for(seq = 0; 1; seq++) {
  122. char seq_str[NUM_STR_SIZE];
  123. g_snprintf(seq_str, SIZEOF(seq_str), "%u", seq);
  124. logfile = newvstralloc(logfile, "log.", tp->datestamp, ".", seq_str, NULL);
  125. pathlogfile = newvstralloc(pathlogfile, conf_logdir, "/", logfile, NULL);
  126. if (access(pathlogfile, R_OK) != 0) break;
  127. if (logfile_has_tape(tp->label, tp->datestamp, pathlogfile)) {
  128. if (current_log == output_find_log || strcmp(*(current_log-1), logfile)) {
  129. *current_log = stralloc(logfile);
  130. current_log++;
  131. }
  132. logs++;
  133. break;
  134. }
  135. }
  136. /* search old-style amflush log, if any */
  137. logfile = newvstralloc(logfile, "log.", tp->datestamp, ".amflush", NULL);
  138. pathlogfile = newvstralloc(pathlogfile, conf_logdir, "/", logfile, NULL);
  139. if (access(pathlogfile, R_OK) == 0) {
  140. if (logfile_has_tape(tp->label, tp->datestamp, pathlogfile)) {
  141. if (current_log == output_find_log || strcmp(*(current_log-1), logfile)) {
  142. *current_log = stralloc(logfile);
  143. current_log++;
  144. }
  145. logs++;
  146. }
  147. }
  148. /* search old-style main log, if any */
  149. logfile = newvstralloc(logfile, "log.", tp->datestamp, NULL);
  150. pathlogfile = newvstralloc(pathlogfile, conf_logdir, "/", logfile, NULL);
  151. if (access(pathlogfile, R_OK) == 0) {
  152. if (logfile_has_tape(tp->label, tp->datestamp, pathlogfile)) {
  153. if (current_log == output_find_log || strcmp(*(current_log-1), logfile)) {
  154. *current_log = stralloc(logfile);
  155. current_log++;
  156. }
  157. logs++;
  158. }
  159. }
  160. if(logs == 0 && strcmp(tp->datestamp,"0") != 0)
  161. g_fprintf(stderr, _("Warning: no log files found for tape %s written %s\n"),
  162. tp->label, find_nicedate(tp->datestamp));
  163. }
  164. amfree(logfile);
  165. amfree(pathlogfile);
  166. amfree(conf_logdir);
  167. *current_log = NULL;
  168. return(output_find_log);
  169. }
  170. void
  171. search_holding_disk(
  172. find_result_t **output_find)
  173. {
  174. GSList *holding_file_list;
  175. GSList *e;
  176. char *holding_file;
  177. disk_t *dp;
  178. holding_file_list = holding_get_files(NULL, 1);
  179. for(e = holding_file_list; e != NULL; e = e->next) {
  180. dumpfile_t file;
  181. holding_file = (char *)e->data;
  182. if (!holding_file_get_dumpfile(holding_file, &file))
  183. continue;
  184. if (file.dumplevel < 0 || file.dumplevel > 9) {
  185. dumpfile_free_data(&file);
  186. continue;
  187. }
  188. dp = NULL;
  189. for(;;) {
  190. char *s;
  191. if((dp = lookup_disk(file.name, file.disk)))
  192. break;
  193. if((s = strrchr(file.name,'.')) == NULL)
  194. break;
  195. *s = '\0';
  196. }
  197. if ( dp == NULL ) {
  198. dumpfile_free_data(&file);
  199. continue;
  200. }
  201. if(find_match(file.name,file.disk)) {
  202. find_result_t *new_output_find = g_new0(find_result_t, 1);
  203. new_output_find->next=*output_find;
  204. new_output_find->timestamp = stralloc(file.datestamp);
  205. new_output_find->hostname = stralloc(file.name);
  206. new_output_find->diskname = stralloc(file.disk);
  207. new_output_find->level=file.dumplevel;
  208. new_output_find->label=stralloc(holding_file);
  209. new_output_find->partnum=stralloc("--");
  210. new_output_find->filenum=0;
  211. if (file.is_partial)
  212. new_output_find->status=stralloc("PARTIAL");
  213. else
  214. new_output_find->status=stralloc("OK");
  215. *output_find=new_output_find;
  216. }
  217. dumpfile_free_data(&file);
  218. }
  219. g_slist_free_full(holding_file_list);
  220. }
  221. static char *
  222. get_write_timestamp(char *tapelabel)
  223. {
  224. tape_t *tp;
  225. if (!tapelabel || !(tp = lookup_tapelabel(tapelabel)))
  226. return "0";
  227. return tp->datestamp;
  228. }
  229. static int
  230. find_compare(
  231. const void *i1,
  232. const void *j1)
  233. {
  234. int compare=0;
  235. find_result_t *i, *j;
  236. size_t nb_compare=strlen(find_sort_order);
  237. size_t k;
  238. for(k=0;k<nb_compare;k++) {
  239. char sort_key = find_sort_order[k];
  240. if (isupper((int)sort_key)) {
  241. /* swap */
  242. sort_key = tolower(sort_key);
  243. j = *(find_result_t **)i1;
  244. i = *(find_result_t **)j1;
  245. } else {
  246. i = *(find_result_t **)i1;
  247. j = *(find_result_t **)j1;
  248. }
  249. switch (sort_key) {
  250. case 'h' : compare=strcmp(i->hostname,j->hostname);
  251. break;
  252. case 'k' : compare=strcmp(i->diskname,j->diskname);
  253. break;
  254. case 'd' : compare=strcmp(i->timestamp,j->timestamp);
  255. break;
  256. case 'l' : compare=j->level - i->level;
  257. break;
  258. case 'f' : compare=(i->filenum == j->filenum) ? 0 :
  259. ((i->filenum < j->filenum) ? -1 : 1);
  260. break;
  261. case 'b' : compare=compare_possibly_null_strings(i->label,
  262. j->label);
  263. break;
  264. case 'w': compare=strcmp(get_write_timestamp(i->label),
  265. get_write_timestamp(j->label));
  266. break;
  267. case 'p' :
  268. if(strcmp(i->partnum, "--") != 0 &&
  269. strcmp(j->partnum, "--") != 0){
  270. compare = atoi(i->partnum) - atoi(j->partnum);
  271. }
  272. else compare=strcmp(i->partnum,j->partnum);
  273. break;
  274. }
  275. if(compare != 0)
  276. return compare;
  277. }
  278. return 0;
  279. }
  280. void
  281. sort_find_result(
  282. char *sort_order,
  283. find_result_t **output_find)
  284. {
  285. find_result_t *output_find_result;
  286. find_result_t **array_find_result = NULL;
  287. size_t nb_result=0;
  288. size_t no_result;
  289. find_sort_order = sort_order;
  290. /* qsort core dump if nothing to sort */
  291. if(*output_find==NULL)
  292. return;
  293. /* How many result */
  294. for(output_find_result=*output_find;
  295. output_find_result;
  296. output_find_result=output_find_result->next) {
  297. nb_result++;
  298. }
  299. /* put the list in an array */
  300. array_find_result=alloc(nb_result * SIZEOF(find_result_t *));
  301. for(output_find_result=*output_find,no_result=0;
  302. output_find_result;
  303. output_find_result=output_find_result->next,no_result++) {
  304. array_find_result[no_result]=output_find_result;
  305. }
  306. /* sort the array */
  307. qsort(array_find_result,nb_result,SIZEOF(find_result_t *),
  308. find_compare);
  309. /* put the sorted result in the list */
  310. for(no_result=0;
  311. no_result<nb_result-1; no_result++) {
  312. array_find_result[no_result]->next = array_find_result[no_result+1];
  313. }
  314. array_find_result[nb_result-1]->next=NULL;
  315. *output_find=array_find_result[0];
  316. amfree(array_find_result);
  317. }
  318. void
  319. print_find_result(
  320. find_result_t *output_find)
  321. {
  322. find_result_t *output_find_result;
  323. int max_len_datestamp = 4;
  324. int max_len_hostname = 4;
  325. int max_len_diskname = 4;
  326. int max_len_level = 2;
  327. int max_len_label =12;
  328. int max_len_filenum = 4;
  329. int max_len_part = 4;
  330. int max_len_status = 6;
  331. size_t len;
  332. for(output_find_result=output_find;
  333. output_find_result;
  334. output_find_result=output_find_result->next) {
  335. char *qdiskname;
  336. len=strlen(find_nicedate(output_find_result->timestamp));
  337. if((int)len > max_len_datestamp)
  338. max_len_datestamp=(int)len;
  339. len=strlen(output_find_result->hostname);
  340. if((int)len > max_len_hostname)
  341. max_len_hostname = (int)len;
  342. qdiskname=quote_string(output_find_result->diskname);
  343. len=strlen(qdiskname);
  344. amfree(qdiskname);
  345. if((int)len > max_len_diskname)
  346. max_len_diskname = (int)len;
  347. if (output_find_result->label != NULL) {
  348. len=strlen(output_find_result->label);
  349. if((int)len > max_len_label)
  350. max_len_label = (int)len;
  351. }
  352. len=strlen(output_find_result->status);
  353. if((int)len > max_len_status)
  354. max_len_status = (int)len;
  355. len=strlen(output_find_result->partnum);
  356. if((int)len > max_len_part)
  357. max_len_part = (int)len;
  358. }
  359. /*
  360. * Since status is the rightmost field, we zap the maximum length
  361. * because it is not needed. The code is left in place in case
  362. * another column is added later.
  363. */
  364. max_len_status = 1;
  365. if(output_find==NULL) {
  366. g_printf(_("\nNo dump to list\n"));
  367. }
  368. else {
  369. g_printf(_("\ndate%*s host%*s disk%*s lv%*s tape or file%*s file%*s part%*s status\n"),
  370. max_len_datestamp-4,"",
  371. max_len_hostname-4 ,"",
  372. max_len_diskname-4 ,"",
  373. max_len_level-2 ,"",
  374. max_len_label-12 ,"",
  375. max_len_filenum-4 ,"",
  376. max_len_part-4 ,"");
  377. for(output_find_result=output_find;
  378. output_find_result;
  379. output_find_result=output_find_result->next) {
  380. char *qdiskname;
  381. char * formatted_label;
  382. qdiskname = quote_string(output_find_result->diskname);
  383. formatted_label = output_find_result->label;
  384. if (formatted_label == NULL)
  385. formatted_label = "";
  386. /*@ignore@*/
  387. /* sec and kb are omitted here, for compatibility with the existing
  388. * output from 'amadmin' */
  389. g_printf("%-*s %-*s %-*s %*d %-*s %*lld %*s %-*s\n",
  390. max_len_datestamp,
  391. find_nicedate(output_find_result->timestamp),
  392. max_len_hostname, output_find_result->hostname,
  393. max_len_diskname, qdiskname,
  394. max_len_level, output_find_result->level,
  395. max_len_label, formatted_label,
  396. max_len_filenum, (long long)output_find_result->filenum,
  397. max_len_part, output_find_result->partnum,
  398. max_len_status, output_find_result->status
  399. );
  400. /*@end@*/
  401. amfree(qdiskname);
  402. }
  403. }
  404. }
  405. void
  406. free_find_result(
  407. find_result_t **output_find)
  408. {
  409. find_result_t *output_find_result, *prev;
  410. prev=NULL;
  411. for(output_find_result=*output_find;
  412. output_find_result;
  413. output_find_result=output_find_result->next) {
  414. amfree(prev);
  415. amfree(output_find_result->timestamp);
  416. amfree(output_find_result->hostname);
  417. amfree(output_find_result->diskname);
  418. amfree(output_find_result->label);
  419. amfree(output_find_result->partnum);
  420. amfree(output_find_result->status);
  421. prev = output_find_result;
  422. }
  423. amfree(prev);
  424. *output_find = NULL;
  425. }
  426. int
  427. find_match(
  428. char *host,
  429. char *disk)
  430. {
  431. disk_t *dp = lookup_disk(host,disk);
  432. return (dp && dp->todo);
  433. }
  434. char *
  435. find_nicedate(
  436. char *datestamp)
  437. {
  438. static char nice[20];
  439. int year, month, day;
  440. int hours, minutes, seconds;
  441. char date[9], atime[7];
  442. int numdate, numtime;
  443. strncpy(date, datestamp, 8);
  444. date[8] = '\0';
  445. numdate = atoi(date);
  446. year = numdate / 10000;
  447. month = (numdate / 100) % 100;
  448. day = numdate % 100;
  449. if(strlen(datestamp) <= 8) {
  450. g_snprintf(nice, SIZEOF(nice), "%4d-%02d-%02d",
  451. year, month, day);
  452. }
  453. else {
  454. strncpy(atime, &(datestamp[8]), 6);
  455. atime[6] = '\0';
  456. numtime = atoi(atime);
  457. hours = numtime / 10000;
  458. minutes = (numtime / 100) % 100;
  459. seconds = numtime % 100;
  460. g_snprintf(nice, SIZEOF(nice), "%4d-%02d-%02d %02d:%02d:%02d",
  461. year, month, day, hours, minutes, seconds);
  462. }
  463. return nice;
  464. }
  465. static int
  466. parse_taper_datestamp_log(
  467. char *logline,
  468. char **datestamp,
  469. char **label)
  470. {
  471. char *s;
  472. int ch;
  473. s = logline;
  474. ch = *s++;
  475. skip_whitespace(s, ch);
  476. if(ch == '\0') {
  477. return 0;
  478. }
  479. if(strncmp_const_skip(s - 1, "datestamp", s, ch) != 0) {
  480. return 0;
  481. }
  482. skip_whitespace(s, ch);
  483. if(ch == '\0') {
  484. return 0;
  485. }
  486. *datestamp = s - 1;
  487. skip_non_whitespace(s, ch);
  488. s[-1] = '\0';
  489. skip_whitespace(s, ch);
  490. if(ch == '\0') {
  491. return 0;
  492. }
  493. if(strncmp_const_skip(s - 1, "label", s, ch) != 0) {
  494. return 0;
  495. }
  496. skip_whitespace(s, ch);
  497. if(ch == '\0') {
  498. return 0;
  499. }
  500. *label = s - 1;
  501. skip_non_whitespace(s, ch);
  502. s[-1] = '\0';
  503. return 1;
  504. }
  505. /* Returns TRUE if the given logfile mentions the given tape. */
  506. static gboolean logfile_has_tape(char * label, char * datestamp,
  507. char * logfile) {
  508. FILE * logf;
  509. char * ck_datestamp, *ck_label;
  510. if((logf = fopen(logfile, "r")) == NULL) {
  511. error(_("could not open logfile %s: %s"), logfile, strerror(errno));
  512. /*NOTREACHED*/
  513. }
  514. while(get_logline(logf)) {
  515. if(curlog == L_START && curprog == P_TAPER) {
  516. if(parse_taper_datestamp_log(curstr,
  517. &ck_datestamp, &ck_label) == 0) {
  518. g_printf(_("strange log line \"start taper %s\" curstr='%s'\n"),
  519. logfile, curstr);
  520. } else if(strcmp(ck_datestamp, datestamp) == 0
  521. && strcmp(ck_label, label) == 0) {
  522. afclose(logf);
  523. return TRUE;
  524. }
  525. }
  526. }
  527. afclose(logf);
  528. return FALSE;
  529. }
  530. /* Like (strcmp(label1, label2) == 0), except that NULL values force TRUE. */
  531. static gboolean volume_matches(const char * label1, const char * label2) {
  532. return (label1 == NULL || label2 == NULL || strcmp(label1, label2) == 0);
  533. }
  534. /* WARNING: Function accesses globals find_diskqp, curlog, curlog, curstr,
  535. * dynamic_disklist */
  536. gboolean
  537. search_logfile(
  538. find_result_t **output_find,
  539. const char *label,
  540. const char *passed_datestamp,
  541. const char *logfile,
  542. disklist_t * dynamic_disklist)
  543. {
  544. FILE *logf;
  545. char *host, *host_undo;
  546. char *disk, *qdisk, *disk_undo;
  547. char *date, *date_undo;
  548. char *partnum=NULL, *partnum_undo;
  549. char *number;
  550. int fileno;
  551. char *current_label = NULL;
  552. char *rest;
  553. char *ck_label=NULL;
  554. int level = 0;
  555. off_t filenum;
  556. char *ck_datestamp, *datestamp;
  557. char *s;
  558. int ch;
  559. disk_t *dp;
  560. find_result_t *part_find = NULL; /* List for all part of a DLE */
  561. find_result_t *a_part_find;
  562. gboolean right_label = FALSE;
  563. gboolean found_something = FALSE;
  564. regex_t regex;
  565. int reg_result;
  566. regmatch_t pmatch[3];
  567. double sec;
  568. size_t kb;
  569. g_return_val_if_fail(output_find != NULL, 0);
  570. g_return_val_if_fail(logfile != NULL, 0);
  571. datestamp = g_strdup(passed_datestamp);
  572. if((logf = fopen(logfile, "r")) == NULL) {
  573. error(_("could not open logfile %s: %s"), logfile, strerror(errno));
  574. /*NOTREACHED*/
  575. }
  576. filenum = (off_t)0;
  577. while(get_logline(logf)) {
  578. if (curlog == L_START && curprog == P_TAPER) {
  579. if(parse_taper_datestamp_log(curstr, &ck_datestamp,
  580. &ck_label) == 0) {
  581. g_printf(_("strange log line in %s \"start taper %s\"\n"),
  582. logfile, curstr);
  583. continue;
  584. }
  585. if (datestamp != NULL) {
  586. if (strcmp(datestamp, ck_datestamp) != 0) {
  587. g_printf(_("Log file %s stamped %s, expecting %s!\n"),
  588. logfile, ck_datestamp, datestamp);
  589. break;
  590. }
  591. }
  592. right_label = volume_matches(label, ck_label);
  593. if (label && datestamp && right_label) {
  594. found_something = TRUE;
  595. }
  596. amfree(current_label);
  597. current_label = g_strdup(ck_label);
  598. if (datestamp == NULL) {
  599. datestamp = g_strdup(ck_datestamp);
  600. }
  601. }
  602. if (!right_label) {
  603. continue;
  604. }
  605. if ((curlog == L_SUCCESS ||
  606. curlog == L_CHUNK || curlog == L_PART || curlog == L_PARTPARTIAL) &&
  607. curprog == P_TAPER) {
  608. filenum++;
  609. }
  610. partnum = "--";
  611. if (curlog == L_SUCCESS || curlog == L_CHUNKSUCCESS ||
  612. curlog == L_DONE || curlog == L_FAIL ||
  613. curlog == L_CHUNK || curlog == L_PART || curlog == L_PARTIAL ||
  614. curlog == L_PARTPARTIAL ) {
  615. s = curstr;
  616. ch = *s++;
  617. skip_whitespace(s, ch);
  618. if(ch == '\0') {
  619. g_printf(_("strange log line in %s \"%s\"\n"),
  620. logfile, curstr);
  621. continue;
  622. }
  623. if (curlog == L_PART || curlog == L_PARTPARTIAL) {
  624. char * part_label = s - 1;
  625. skip_non_whitespace(s, ch);
  626. s[-1] = '\0';
  627. if (strcmp(current_label, part_label) != 0) {
  628. g_printf("PART label %s doesn't match START label %s\n",
  629. part_label, current_label);
  630. continue;
  631. }
  632. skip_whitespace(s, ch);
  633. if(ch == '\0') {
  634. g_printf("strange log line in %s \"%s\"\n",
  635. logfile, curstr);
  636. continue;
  637. }
  638. number = s - 1;
  639. skip_non_whitespace(s, ch);
  640. s[-1] = '\0';
  641. fileno = atoi(number);
  642. filenum = fileno;
  643. skip_whitespace(s, ch);
  644. if(ch == '\0') {
  645. g_printf("strange log line in %s \"%s\"\n",
  646. logfile, curstr);
  647. continue;
  648. }
  649. }
  650. host = s - 1;
  651. skip_non_whitespace(s, ch);
  652. host_undo = s - 1;
  653. *host_undo = '\0';
  654. skip_whitespace(s, ch);
  655. if(ch == '\0') {
  656. g_printf(_("strange log line in %s \"%s\"\n"),
  657. logfile, curstr);
  658. continue;
  659. }
  660. qdisk = s - 1;
  661. skip_quoted_string(s, ch);
  662. disk_undo = s - 1;
  663. *disk_undo = '\0';
  664. disk = unquote_string(qdisk);
  665. skip_whitespace(s, ch);
  666. if(ch == '\0') {
  667. g_printf(_("strange log line in %s \"%s\"\n"),
  668. logfile, curstr);
  669. continue;
  670. }
  671. date = s - 1;
  672. skip_non_whitespace(s, ch);
  673. date_undo = s - 1;
  674. *date_undo = '\0';
  675. if(strlen(date) < 3) { /* old log didn't have datestamp */
  676. level = atoi(date);
  677. date = stralloc(datestamp);
  678. } else {
  679. if (curlog == L_CHUNK || curlog == L_PART ||
  680. curlog == L_PARTPARTIAL || curlog == L_DONE){
  681. skip_whitespace(s, ch);
  682. partnum = s - 1;
  683. skip_non_whitespace(s, ch);
  684. partnum_undo = s - 1;
  685. *partnum_undo = '\0';
  686. }
  687. skip_whitespace(s, ch);
  688. if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
  689. g_printf(_("strange log line in %s \"%s\"\n"),
  690. logfile, curstr);
  691. continue;
  692. }
  693. skip_integer(s, ch);
  694. }
  695. skip_whitespace(s, ch);
  696. if(ch == '\0') {
  697. g_printf(_("strange log line in %s \"%s\"\n"),
  698. logfile, curstr);
  699. continue;
  700. }
  701. rest = s - 1;
  702. if((s = strchr(s, '\n')) != NULL) {
  703. *s = '\0';
  704. }
  705. /* extract sec, kb, kps from 'rest', if present. This isn't the stone age
  706. * anymore, so we'll just do it the easy way (a regex) */
  707. bzero(&regex, sizeof(regex));
  708. reg_result = regcomp(&regex,
  709. "\\[sec ([0-9.]+) kb ([0-9]+) kps [0-9.]+\\]", REG_EXTENDED);
  710. if (reg_result != 0) {
  711. error("Error compiling regular expression for parsing log lines");
  712. /* NOTREACHED */
  713. }
  714. /* an error here just means the line wasn't found -- not fatal. */
  715. reg_result = regexec(&regex, rest, sizeof(pmatch)/sizeof(*pmatch), pmatch, 0);
  716. if (reg_result == 0) {
  717. char *str;
  718. str = find_regex_substring(rest, pmatch[1]);
  719. sec = atof(str);
  720. amfree(str);
  721. str = find_regex_substring(rest, pmatch[2]);
  722. kb = OFF_T_ATOI(str);
  723. amfree(str);
  724. } else {
  725. sec = 0;
  726. kb = 0;
  727. }
  728. regfree(&regex);
  729. dp = lookup_disk(host,disk);
  730. if ( dp == NULL ) {
  731. if (dynamic_disklist == NULL) {
  732. continue;
  733. }
  734. dp = add_disk(dynamic_disklist, host, disk);
  735. enqueue_disk(dynamic_disklist, dp);
  736. }
  737. if (find_match(host, disk)) {
  738. if(curprog == P_TAPER) {
  739. find_result_t *new_output_find = g_new0(find_result_t, 1);
  740. new_output_find->timestamp = stralloc(date);
  741. new_output_find->hostname=stralloc(host);
  742. new_output_find->diskname=stralloc(disk);
  743. new_output_find->level=level;
  744. new_output_find->partnum = stralloc(partnum);
  745. new_output_find->label=stralloc(current_label);
  746. new_output_find->status=NULL;
  747. new_output_find->filenum=filenum;
  748. new_output_find->sec=sec;
  749. new_output_find->kb=kb;
  750. new_output_find->next=NULL;
  751. if (curlog == L_SUCCESS) {
  752. new_output_find->status = stralloc("OK");
  753. new_output_find->next = *output_find;
  754. *output_find = new_output_find;
  755. found_something = TRUE;
  756. } else if (curlog == L_CHUNKSUCCESS || curlog == L_DONE ||
  757. curlog == L_PARTIAL || curlog == L_FAIL) {
  758. /* result line */
  759. if (curlog == L_PARTIAL || curlog == L_FAIL) {
  760. /* change status of each part */
  761. for (a_part_find = part_find; a_part_find;
  762. a_part_find = a_part_find->next) {
  763. if (curlog == L_PARTIAL)
  764. a_part_find->status = stralloc("PARTIAL");
  765. else
  766. a_part_find->status = stralloc(rest);
  767. }
  768. }
  769. if (part_find) { /* find last element */
  770. for (a_part_find = part_find;
  771. a_part_find->next != NULL;
  772. a_part_find=a_part_find->next) {
  773. }
  774. /* merge part_find to *output_find */
  775. a_part_find->next = *output_find;
  776. *output_find = part_find;
  777. part_find = NULL;
  778. found_something = TRUE;
  779. }
  780. free_find_result(&new_output_find);
  781. } else { /* part line */
  782. if (curlog == L_PART || curlog == L_CHUNK)
  783. new_output_find->status=stralloc("OK");
  784. else /* PARTPARTIAL */
  785. new_output_find->status=stralloc("PARTIAL");
  786. /* Add to part_find list */
  787. new_output_find->next = part_find;
  788. part_find = new_output_find;
  789. found_something = TRUE;
  790. }
  791. }
  792. else if(curlog == L_FAIL) {
  793. /* print other failures too -- this is a hack to ensure that failures which
  794. * did not make it to tape are also listed in the output of 'amadmin x find';
  795. * users that do not want this information (e.g., Amanda::DB::Catalog) should
  796. * filter dumps with a NULL label. */
  797. find_result_t *new_output_find = g_new0(find_result_t, 1);
  798. new_output_find->next=*output_find;
  799. new_output_find->timestamp = stralloc(date);
  800. new_output_find->hostname=stralloc(host);
  801. new_output_find->diskname=stralloc(disk);
  802. new_output_find->level=level;
  803. new_output_find->label=NULL;
  804. new_output_find->partnum=stralloc(partnum);
  805. new_output_find->filenum=0;
  806. new_output_find->sec=sec;
  807. new_output_find->kb=kb;
  808. new_output_find->status=vstralloc(
  809. "FAILED (",
  810. program_str[(int)curprog],
  811. ") ",
  812. rest,
  813. NULL);
  814. *output_find=new_output_find;
  815. found_something = TRUE;
  816. }
  817. }
  818. amfree(disk);
  819. }
  820. }
  821. if (part_find != NULL) {
  822. if (label) {
  823. /* parse log file until PARTIAL/DONE/SUCCESS/FAIL from taper */
  824. while(get_logline(logf)) {
  825. if (curprog == P_TAPER &&
  826. (curlog == L_DONE || curlog == L_SUCCESS ||
  827. curlog == L_PARTIAL || curlog == L_FAIL)) {
  828. break;
  829. }
  830. }
  831. }
  832. for (a_part_find = part_find; a_part_find;
  833. a_part_find = a_part_find->next) {
  834. if (curlog == L_PARTIAL)
  835. a_part_find->status = stralloc("PARTIAL");
  836. else if (curlog == L_FAIL)
  837. a_part_find->status = stralloc("FAIL");
  838. }
  839. for (a_part_find = part_find;
  840. a_part_find->next != NULL;
  841. a_part_find=a_part_find->next) {
  842. }
  843. /* merge part_find to *output_find */
  844. a_part_find->next = *output_find;
  845. *output_find = part_find;
  846. part_find = NULL;
  847. }
  848. afclose(logf);
  849. amfree(datestamp);
  850. amfree(current_label);
  851. return found_something;
  852. }
  853. /*
  854. * Return the set of dumps that match *all* of the given patterns (we consider
  855. * an empty pattern to match .*, though). If 'ok' is true, will only match
  856. * dumps with SUCCESS status.
  857. *
  858. * Returns a newly allocated list of results, where all strings are also newly
  859. * allocated. Apparently some part of Amanda leaks under this condition.
  860. */
  861. find_result_t *
  862. dumps_match(
  863. find_result_t *output_find,
  864. char *hostname,
  865. char *diskname,
  866. char *datestamp,
  867. char *level,
  868. int ok)
  869. {
  870. find_result_t *cur_result;
  871. find_result_t *matches = NULL;
  872. for(cur_result=output_find;
  873. cur_result;
  874. cur_result=cur_result->next) {
  875. char level_str[NUM_STR_SIZE];
  876. g_snprintf(level_str, SIZEOF(level_str), "%d", cur_result->level);
  877. if((!hostname || *hostname == '\0' || match_host(hostname, cur_result->hostname)) &&
  878. (!diskname || *diskname == '\0' || match_disk(diskname, cur_result->diskname)) &&
  879. (!datestamp || *datestamp== '\0' || match_datestamp(datestamp, cur_result->timestamp)) &&
  880. (!level || *level== '\0' || match_level(level, level_str)) &&
  881. (!ok || !strcmp(cur_result->status, "OK"))){
  882. find_result_t *curmatch = g_new0(find_result_t, 1);
  883. memcpy(curmatch, cur_result, SIZEOF(find_result_t));
  884. curmatch->timestamp = stralloc(cur_result->timestamp);
  885. curmatch->hostname = stralloc(cur_result->hostname);
  886. curmatch->diskname = stralloc(cur_result->diskname);
  887. curmatch->level = cur_result->level;
  888. curmatch->label = cur_result->label? stralloc(cur_result->label) : NULL;
  889. curmatch->filenum = cur_result->filenum;
  890. curmatch->sec = cur_result->sec;
  891. curmatch->kb = cur_result->kb;
  892. curmatch->status = stralloc(cur_result->status);
  893. curmatch->partnum = stralloc(cur_result->partnum);
  894. curmatch->next = matches;
  895. matches = curmatch;
  896. }
  897. }
  898. return(matches);
  899. }
  900. /*
  901. * Return the set of dumps that match one or more of the given dumpspecs,
  902. * If 'ok' is true, only dumps with a SUCCESS status will be matched.
  903. *
  904. * Returns a newly allocated list of results, where all strings are also newly
  905. * allocated. Apparently some part of Amanda leaks under this condition.
  906. */
  907. find_result_t *
  908. dumps_match_dumpspecs(
  909. find_result_t *output_find,
  910. GSList *dumpspecs,
  911. int ok)
  912. {
  913. find_result_t *cur_result;
  914. find_result_t *matches = NULL;
  915. GSList *dumpspec;
  916. dumpspec_t *ds;
  917. for(cur_result=output_find;
  918. cur_result;
  919. cur_result=cur_result->next) {
  920. char level_str[NUM_STR_SIZE];
  921. g_snprintf(level_str, SIZEOF(level_str), "%d", cur_result->level);
  922. for (dumpspec = dumpspecs; dumpspec; dumpspec = dumpspec->next) {
  923. ds = (dumpspec_t *)dumpspec->data;
  924. if((!ds->host || *ds->host == '\0' || match_host(ds->host, cur_result->hostname)) &&
  925. (!ds->disk || *ds->disk == '\0' || match_disk(ds->disk, cur_result->diskname)) &&
  926. (!ds->datestamp || *ds->datestamp== '\0' || match_datestamp(ds->datestamp, cur_result->timestamp)) &&
  927. (!ds->level || *ds->level== '\0' || match_level(ds->level, level_str)) &&
  928. (!ok || !strcmp(cur_result->status, "OK"))){
  929. find_result_t *curmatch = alloc(SIZEOF(find_result_t));
  930. memcpy(curmatch, cur_result, SIZEOF(find_result_t));
  931. curmatch->timestamp = stralloc(cur_result->timestamp);
  932. curmatch->hostname = stralloc(cur_result->hostname);
  933. curmatch->diskname = stralloc(cur_result->diskname);
  934. curmatch->level = cur_result->level;
  935. curmatch->label = cur_result->label? stralloc(cur_result->label) : NULL;
  936. curmatch->filenum = cur_result->filenum;
  937. curmatch->status = stralloc(cur_result->status);
  938. curmatch->partnum = stralloc(cur_result->partnum);
  939. curmatch->next = matches;
  940. matches = curmatch;
  941. break;
  942. }
  943. }
  944. }
  945. return(matches);
  946. }
  947. find_result_t *
  948. dump_exist(
  949. find_result_t *output_find,
  950. char *hostname,
  951. char *diskname,
  952. char *datestamp,
  953. int level)
  954. {
  955. find_result_t *output_find_result;
  956. for(output_find_result=output_find;
  957. output_find_result;
  958. output_find_result=output_find_result->next) {
  959. if( !strcmp(output_find_result->hostname, hostname) &&
  960. !strcmp(output_find_result->diskname, diskname) &&
  961. !strcmp(output_find_result->timestamp, datestamp) &&
  962. output_find_result->level == level) {
  963. return output_find_result;
  964. }
  965. }
  966. return(NULL);
  967. }