PageRenderTime 45ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

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

#
C | 1089 lines | 875 code | 125 blank | 89 comment | 284 complexity | ed7f83f74c1fd825b2f24cfcff613742 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. new_output_find->status=stralloc("OK");
  212. *output_find=new_output_find;
  213. }
  214. dumpfile_free_data(&file);
  215. }
  216. g_slist_free_full(holding_file_list);
  217. }
  218. static char *
  219. get_write_timestamp(char *tapelabel)
  220. {
  221. tape_t *tp;
  222. if (!tapelabel || !(tp = lookup_tapelabel(tapelabel)))
  223. return "0";
  224. return tp->datestamp;
  225. }
  226. static int
  227. find_compare(
  228. const void *i1,
  229. const void *j1)
  230. {
  231. int compare=0;
  232. find_result_t *i, *j;
  233. size_t nb_compare=strlen(find_sort_order);
  234. size_t k;
  235. for(k=0;k<nb_compare;k++) {
  236. char sort_key = find_sort_order[k];
  237. if (isupper((int)sort_key)) {
  238. /* swap */
  239. sort_key = tolower(sort_key);
  240. j = *(find_result_t **)i1;
  241. i = *(find_result_t **)j1;
  242. } else {
  243. i = *(find_result_t **)i1;
  244. j = *(find_result_t **)j1;
  245. }
  246. switch (sort_key) {
  247. case 'h' : compare=strcmp(i->hostname,j->hostname);
  248. break;
  249. case 'k' : compare=strcmp(i->diskname,j->diskname);
  250. break;
  251. case 'd' : compare=strcmp(i->timestamp,j->timestamp);
  252. break;
  253. case 'l' : compare=j->level - i->level;
  254. break;
  255. case 'f' : compare=(i->filenum == j->filenum) ? 0 :
  256. ((i->filenum < j->filenum) ? -1 : 1);
  257. break;
  258. case 'b' : compare=compare_possibly_null_strings(i->label,
  259. j->label);
  260. break;
  261. case 'w': compare=strcmp(get_write_timestamp(i->label),
  262. get_write_timestamp(j->label));
  263. break;
  264. case 'p' :
  265. if(strcmp(i->partnum, "--") != 0 &&
  266. strcmp(j->partnum, "--") != 0){
  267. compare = atoi(i->partnum) - atoi(j->partnum);
  268. }
  269. else compare=strcmp(i->partnum,j->partnum);
  270. break;
  271. }
  272. if(compare != 0)
  273. return compare;
  274. }
  275. return 0;
  276. }
  277. void
  278. sort_find_result(
  279. char *sort_order,
  280. find_result_t **output_find)
  281. {
  282. find_result_t *output_find_result;
  283. find_result_t **array_find_result = NULL;
  284. size_t nb_result=0;
  285. size_t no_result;
  286. find_sort_order = sort_order;
  287. /* qsort core dump if nothing to sort */
  288. if(*output_find==NULL)
  289. return;
  290. /* How many result */
  291. for(output_find_result=*output_find;
  292. output_find_result;
  293. output_find_result=output_find_result->next) {
  294. nb_result++;
  295. }
  296. /* put the list in an array */
  297. array_find_result=alloc(nb_result * SIZEOF(find_result_t *));
  298. for(output_find_result=*output_find,no_result=0;
  299. output_find_result;
  300. output_find_result=output_find_result->next,no_result++) {
  301. array_find_result[no_result]=output_find_result;
  302. }
  303. /* sort the array */
  304. qsort(array_find_result,nb_result,SIZEOF(find_result_t *),
  305. find_compare);
  306. /* put the sorted result in the list */
  307. for(no_result=0;
  308. no_result<nb_result-1; no_result++) {
  309. array_find_result[no_result]->next = array_find_result[no_result+1];
  310. }
  311. array_find_result[nb_result-1]->next=NULL;
  312. *output_find=array_find_result[0];
  313. amfree(array_find_result);
  314. }
  315. void
  316. print_find_result(
  317. find_result_t *output_find)
  318. {
  319. find_result_t *output_find_result;
  320. int max_len_datestamp = 4;
  321. int max_len_hostname = 4;
  322. int max_len_diskname = 4;
  323. int max_len_level = 2;
  324. int max_len_label =12;
  325. int max_len_filenum = 4;
  326. int max_len_part = 4;
  327. int max_len_status = 6;
  328. size_t len;
  329. for(output_find_result=output_find;
  330. output_find_result;
  331. output_find_result=output_find_result->next) {
  332. char *qdiskname;
  333. len=strlen(find_nicedate(output_find_result->timestamp));
  334. if((int)len > max_len_datestamp)
  335. max_len_datestamp=(int)len;
  336. len=strlen(output_find_result->hostname);
  337. if((int)len > max_len_hostname)
  338. max_len_hostname = (int)len;
  339. qdiskname=quote_string(output_find_result->diskname);
  340. len=strlen(qdiskname);
  341. amfree(qdiskname);
  342. if((int)len > max_len_diskname)
  343. max_len_diskname = (int)len;
  344. if (output_find_result->label != NULL) {
  345. len=strlen(output_find_result->label);
  346. if((int)len > max_len_label)
  347. max_len_label = (int)len;
  348. }
  349. len=strlen(output_find_result->status);
  350. if((int)len > max_len_status)
  351. max_len_status = (int)len;
  352. len=strlen(output_find_result->partnum);
  353. if((int)len > max_len_part)
  354. max_len_part = (int)len;
  355. }
  356. /*
  357. * Since status is the rightmost field, we zap the maximum length
  358. * because it is not needed. The code is left in place in case
  359. * another column is added later.
  360. */
  361. max_len_status = 1;
  362. if(output_find==NULL) {
  363. g_printf(_("\nNo dump to list\n"));
  364. }
  365. else {
  366. g_printf(_("\ndate%*s host%*s disk%*s lv%*s tape or file%*s file%*s part%*s status\n"),
  367. max_len_datestamp-4,"",
  368. max_len_hostname-4 ,"",
  369. max_len_diskname-4 ,"",
  370. max_len_level-2 ,"",
  371. max_len_label-12 ,"",
  372. max_len_filenum-4 ,"",
  373. max_len_part-4 ,"");
  374. for(output_find_result=output_find;
  375. output_find_result;
  376. output_find_result=output_find_result->next) {
  377. char *qdiskname;
  378. char * formatted_label;
  379. qdiskname = quote_string(output_find_result->diskname);
  380. formatted_label = output_find_result->label;
  381. if (formatted_label == NULL)
  382. formatted_label = "";
  383. /*@ignore@*/
  384. /* sec and kb are omitted here, for compatibility with the existing
  385. * output from 'amadmin' */
  386. g_printf("%-*s %-*s %-*s %*d %-*s %*lld %*s %-*s\n",
  387. max_len_datestamp,
  388. find_nicedate(output_find_result->timestamp),
  389. max_len_hostname, output_find_result->hostname,
  390. max_len_diskname, qdiskname,
  391. max_len_level, output_find_result->level,
  392. max_len_label, formatted_label,
  393. max_len_filenum, (long long)output_find_result->filenum,
  394. max_len_part, output_find_result->partnum,
  395. max_len_status, output_find_result->status
  396. );
  397. /*@end@*/
  398. amfree(qdiskname);
  399. }
  400. }
  401. }
  402. void
  403. free_find_result(
  404. find_result_t **output_find)
  405. {
  406. find_result_t *output_find_result, *prev;
  407. prev=NULL;
  408. for(output_find_result=*output_find;
  409. output_find_result;
  410. output_find_result=output_find_result->next) {
  411. amfree(prev);
  412. amfree(output_find_result->timestamp);
  413. amfree(output_find_result->hostname);
  414. amfree(output_find_result->diskname);
  415. amfree(output_find_result->label);
  416. amfree(output_find_result->partnum);
  417. amfree(output_find_result->status);
  418. prev = output_find_result;
  419. }
  420. amfree(prev);
  421. *output_find = NULL;
  422. }
  423. int
  424. find_match(
  425. char *host,
  426. char *disk)
  427. {
  428. disk_t *dp = lookup_disk(host,disk);
  429. return (dp && dp->todo);
  430. }
  431. char *
  432. find_nicedate(
  433. char *datestamp)
  434. {
  435. static char nice[20];
  436. int year, month, day;
  437. int hours, minutes, seconds;
  438. char date[9], atime[7];
  439. int numdate, numtime;
  440. strncpy(date, datestamp, 8);
  441. date[8] = '\0';
  442. numdate = atoi(date);
  443. year = numdate / 10000;
  444. month = (numdate / 100) % 100;
  445. day = numdate % 100;
  446. if(strlen(datestamp) <= 8) {
  447. g_snprintf(nice, SIZEOF(nice), "%4d-%02d-%02d",
  448. year, month, day);
  449. }
  450. else {
  451. strncpy(atime, &(datestamp[8]), 6);
  452. atime[6] = '\0';
  453. numtime = atoi(atime);
  454. hours = numtime / 10000;
  455. minutes = (numtime / 100) % 100;
  456. seconds = numtime % 100;
  457. g_snprintf(nice, SIZEOF(nice), "%4d-%02d-%02d %02d:%02d:%02d",
  458. year, month, day, hours, minutes, seconds);
  459. }
  460. return nice;
  461. }
  462. static int
  463. parse_taper_datestamp_log(
  464. char *logline,
  465. char **datestamp,
  466. char **label)
  467. {
  468. char *s;
  469. int ch;
  470. s = logline;
  471. ch = *s++;
  472. skip_whitespace(s, ch);
  473. if(ch == '\0') {
  474. return 0;
  475. }
  476. if(strncmp_const_skip(s - 1, "datestamp", s, ch) != 0) {
  477. return 0;
  478. }
  479. skip_whitespace(s, ch);
  480. if(ch == '\0') {
  481. return 0;
  482. }
  483. *datestamp = s - 1;
  484. skip_non_whitespace(s, ch);
  485. s[-1] = '\0';
  486. skip_whitespace(s, ch);
  487. if(ch == '\0') {
  488. return 0;
  489. }
  490. if(strncmp_const_skip(s - 1, "label", s, ch) != 0) {
  491. return 0;
  492. }
  493. skip_whitespace(s, ch);
  494. if(ch == '\0') {
  495. return 0;
  496. }
  497. *label = s - 1;
  498. skip_non_whitespace(s, ch);
  499. s[-1] = '\0';
  500. return 1;
  501. }
  502. /* Returns TRUE if the given logfile mentions the given tape. */
  503. static gboolean logfile_has_tape(char * label, char * datestamp,
  504. char * logfile) {
  505. FILE * logf;
  506. char * ck_datestamp, *ck_label;
  507. if((logf = fopen(logfile, "r")) == NULL) {
  508. error(_("could not open logfile %s: %s"), logfile, strerror(errno));
  509. /*NOTREACHED*/
  510. }
  511. while(get_logline(logf)) {
  512. if(curlog == L_START && curprog == P_TAPER) {
  513. if(parse_taper_datestamp_log(curstr,
  514. &ck_datestamp, &ck_label) == 0) {
  515. g_printf(_("strange log line \"start taper %s\" curstr='%s'\n"),
  516. logfile, curstr);
  517. } else if(strcmp(ck_datestamp, datestamp) == 0
  518. && strcmp(ck_label, label) == 0) {
  519. afclose(logf);
  520. return TRUE;
  521. }
  522. }
  523. }
  524. afclose(logf);
  525. return FALSE;
  526. }
  527. /* Like (strcmp(label1, label2) == 0), except that NULL values force TRUE. */
  528. static gboolean volume_matches(const char * label1, const char * label2) {
  529. return (label1 == NULL || label2 == NULL || strcmp(label1, label2) == 0);
  530. }
  531. /* WARNING: Function accesses globals find_diskqp, curlog, curlog, curstr,
  532. * dynamic_disklist */
  533. gboolean
  534. search_logfile(
  535. find_result_t **output_find,
  536. const char *label,
  537. const char *passed_datestamp,
  538. const char *logfile,
  539. disklist_t * dynamic_disklist)
  540. {
  541. FILE *logf;
  542. char *host, *host_undo;
  543. char *disk, *qdisk, *disk_undo;
  544. char *date, *date_undo;
  545. char *partnum=NULL, *partnum_undo;
  546. char *number;
  547. int fileno;
  548. char *current_label = NULL;
  549. char *rest;
  550. char *ck_label=NULL;
  551. int level = 0;
  552. off_t filenum;
  553. char *ck_datestamp, *datestamp;
  554. char *s;
  555. int ch;
  556. disk_t *dp;
  557. find_result_t *part_find = NULL; /* List for all part of a DLE */
  558. find_result_t *a_part_find;
  559. gboolean right_label = FALSE;
  560. gboolean found_something = FALSE;
  561. regex_t regex;
  562. int reg_result;
  563. regmatch_t pmatch[3];
  564. double sec;
  565. size_t kb;
  566. g_return_val_if_fail(output_find != NULL, 0);
  567. g_return_val_if_fail(logfile != NULL, 0);
  568. datestamp = g_strdup(passed_datestamp);
  569. if((logf = fopen(logfile, "r")) == NULL) {
  570. error(_("could not open logfile %s: %s"), logfile, strerror(errno));
  571. /*NOTREACHED*/
  572. }
  573. filenum = (off_t)0;
  574. while(get_logline(logf)) {
  575. if (curlog == L_START && curprog == P_TAPER) {
  576. if(parse_taper_datestamp_log(curstr, &ck_datestamp,
  577. &ck_label) == 0) {
  578. g_printf(_("strange log line in %s \"start taper %s\"\n"),
  579. logfile, curstr);
  580. continue;
  581. }
  582. if (datestamp != NULL) {
  583. if (strcmp(datestamp, ck_datestamp) != 0) {
  584. g_printf(_("Log file %s stamped %s, expecting %s!\n"),
  585. logfile, ck_datestamp, datestamp);
  586. break;
  587. }
  588. }
  589. right_label = volume_matches(label, ck_label);
  590. if (label && datestamp && right_label) {
  591. found_something = TRUE;
  592. }
  593. amfree(current_label);
  594. current_label = g_strdup(ck_label);
  595. if (datestamp == NULL) {
  596. datestamp = g_strdup(ck_datestamp);
  597. }
  598. }
  599. if (!right_label) {
  600. continue;
  601. }
  602. if ((curlog == L_SUCCESS ||
  603. curlog == L_CHUNK || curlog == L_PART || curlog == L_PARTPARTIAL) &&
  604. curprog == P_TAPER) {
  605. filenum++;
  606. }
  607. partnum = "--";
  608. if (curlog == L_SUCCESS || curlog == L_CHUNKSUCCESS ||
  609. curlog == L_DONE || curlog == L_FAIL ||
  610. curlog == L_CHUNK || curlog == L_PART || curlog == L_PARTIAL ||
  611. curlog == L_PARTPARTIAL ) {
  612. s = curstr;
  613. ch = *s++;
  614. skip_whitespace(s, ch);
  615. if(ch == '\0') {
  616. g_printf(_("strange log line in %s \"%s\"\n"),
  617. logfile, curstr);
  618. continue;
  619. }
  620. if (curlog == L_PART || curlog == L_PARTPARTIAL) {
  621. char * part_label = s - 1;
  622. skip_non_whitespace(s, ch);
  623. s[-1] = '\0';
  624. if (strcmp(current_label, part_label) != 0) {
  625. g_printf("PART label %s doesn't match START label %s\n",
  626. part_label, current_label);
  627. continue;
  628. }
  629. skip_whitespace(s, ch);
  630. if(ch == '\0') {
  631. g_printf("strange log line in %s \"%s\"\n",
  632. logfile, curstr);
  633. continue;
  634. }
  635. number = s - 1;
  636. skip_non_whitespace(s, ch);
  637. s[-1] = '\0';
  638. fileno = atoi(number);
  639. filenum = fileno;
  640. skip_whitespace(s, ch);
  641. if(ch == '\0') {
  642. g_printf("strange log line in %s \"%s\"\n",
  643. logfile, curstr);
  644. continue;
  645. }
  646. }
  647. host = s - 1;
  648. skip_non_whitespace(s, ch);
  649. host_undo = s - 1;
  650. *host_undo = '\0';
  651. skip_whitespace(s, ch);
  652. if(ch == '\0') {
  653. g_printf(_("strange log line in %s \"%s\"\n"),
  654. logfile, curstr);
  655. continue;
  656. }
  657. qdisk = s - 1;
  658. skip_quoted_string(s, ch);
  659. disk_undo = s - 1;
  660. *disk_undo = '\0';
  661. disk = unquote_string(qdisk);
  662. skip_whitespace(s, ch);
  663. if(ch == '\0') {
  664. g_printf(_("strange log line in %s \"%s\"\n"),
  665. logfile, curstr);
  666. continue;
  667. }
  668. date = s - 1;
  669. skip_non_whitespace(s, ch);
  670. date_undo = s - 1;
  671. *date_undo = '\0';
  672. if(strlen(date) < 3) { /* old log didn't have datestamp */
  673. level = atoi(date);
  674. date = stralloc(datestamp);
  675. } else {
  676. if (curlog == L_CHUNK || curlog == L_PART ||
  677. curlog == L_PARTPARTIAL || curlog == L_DONE){
  678. skip_whitespace(s, ch);
  679. partnum = s - 1;
  680. skip_non_whitespace(s, ch);
  681. partnum_undo = s - 1;
  682. *partnum_undo = '\0';
  683. }
  684. skip_whitespace(s, ch);
  685. if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
  686. g_printf(_("strange log line in %s \"%s\"\n"),
  687. logfile, curstr);
  688. continue;
  689. }
  690. skip_integer(s, ch);
  691. }
  692. skip_whitespace(s, ch);
  693. if(ch == '\0') {
  694. g_printf(_("strange log line in %s \"%s\"\n"),
  695. logfile, curstr);
  696. continue;
  697. }
  698. rest = s - 1;
  699. if((s = strchr(s, '\n')) != NULL) {
  700. *s = '\0';
  701. }
  702. /* extract sec, kb, kps from 'rest', if present. This isn't the stone age
  703. * anymore, so we'll just do it the easy way (a regex) */
  704. bzero(&regex, sizeof(regex));
  705. reg_result = regcomp(&regex,
  706. "\\[sec ([0-9.]+) kb ([0-9]+) kps [0-9.]+\\]", REG_EXTENDED);
  707. if (reg_result != 0) {
  708. error("Error compiling regular expression for parsing log lines");
  709. /* NOTREACHED */
  710. }
  711. /* an error here just means the line wasn't found -- not fatal. */
  712. reg_result = regexec(&regex, rest, sizeof(pmatch)/sizeof(*pmatch), pmatch, 0);
  713. if (reg_result == 0) {
  714. char *str;
  715. str = find_regex_substring(rest, pmatch[1]);
  716. sec = atof(str);
  717. amfree(str);
  718. str = find_regex_substring(rest, pmatch[2]);
  719. kb = OFF_T_ATOI(str);
  720. amfree(str);
  721. } else {
  722. sec = 0;
  723. kb = 0;
  724. }
  725. regfree(&regex);
  726. dp = lookup_disk(host,disk);
  727. if ( dp == NULL ) {
  728. if (dynamic_disklist == NULL) {
  729. continue;
  730. }
  731. dp = add_disk(dynamic_disklist, host, disk);
  732. enqueue_disk(dynamic_disklist, dp);
  733. }
  734. if (find_match(host, disk)) {
  735. if(curprog == P_TAPER) {
  736. find_result_t *new_output_find = g_new0(find_result_t, 1);
  737. new_output_find->timestamp = stralloc(date);
  738. new_output_find->hostname=stralloc(host);
  739. new_output_find->diskname=stralloc(disk);
  740. new_output_find->level=level;
  741. new_output_find->partnum = stralloc(partnum);
  742. new_output_find->label=stralloc(current_label);
  743. new_output_find->status=NULL;
  744. new_output_find->filenum=filenum;
  745. new_output_find->sec=sec;
  746. new_output_find->kb=kb;
  747. new_output_find->next=NULL;
  748. if (curlog == L_SUCCESS) {
  749. new_output_find->status = stralloc("OK");
  750. new_output_find->next = *output_find;
  751. *output_find = new_output_find;
  752. found_something = TRUE;
  753. } else if (curlog == L_CHUNKSUCCESS || curlog == L_DONE ||
  754. curlog == L_PARTIAL || curlog == L_FAIL) {
  755. /* result line */
  756. if (curlog == L_PARTIAL || curlog == L_FAIL) {
  757. /* change status of each part */
  758. for (a_part_find = part_find; a_part_find;
  759. a_part_find = a_part_find->next) {
  760. if (curlog == L_PARTIAL)
  761. a_part_find->status = stralloc("PARTIAL");
  762. else
  763. a_part_find->status = stralloc(rest);
  764. }
  765. }
  766. if (part_find) { /* find last element */
  767. for (a_part_find = part_find;
  768. a_part_find->next != NULL;
  769. a_part_find=a_part_find->next) {
  770. }
  771. /* merge part_find to *output_find */
  772. a_part_find->next = *output_find;
  773. *output_find = part_find;
  774. part_find = NULL;
  775. found_something = TRUE;
  776. }
  777. free_find_result(&new_output_find);
  778. } else { /* part line */
  779. if (curlog == L_PART || curlog == L_CHUNK)
  780. new_output_find->status=stralloc("OK");
  781. else /* PARTPARTIAL */
  782. new_output_find->status=stralloc("PARTIAL");
  783. /* Add to part_find list */
  784. new_output_find->next = part_find;
  785. part_find = new_output_find;
  786. found_something = TRUE;
  787. }
  788. }
  789. else if(curlog == L_FAIL) {
  790. /* print other failures too -- this is a hack to ensure that failures which
  791. * did not make it to tape are also listed in the output of 'amadmin x find';
  792. * users that do not want this information (e.g., Amanda::DB::Catalog) should
  793. * filter dumps with a NULL label. */
  794. find_result_t *new_output_find = g_new0(find_result_t, 1);
  795. new_output_find->next=*output_find;
  796. new_output_find->timestamp = stralloc(date);
  797. new_output_find->hostname=stralloc(host);
  798. new_output_find->diskname=stralloc(disk);
  799. new_output_find->level=level;
  800. new_output_find->label=NULL;
  801. new_output_find->partnum=stralloc(partnum);
  802. new_output_find->filenum=0;
  803. new_output_find->sec=sec;
  804. new_output_find->kb=kb;
  805. new_output_find->status=vstralloc(
  806. "FAILED (",
  807. program_str[(int)curprog],
  808. ") ",
  809. rest,
  810. NULL);
  811. *output_find=new_output_find;
  812. found_something = TRUE;
  813. }
  814. }
  815. amfree(disk);
  816. }
  817. }
  818. if (part_find != NULL) {
  819. if (label) {
  820. /* parse log file until PARTIAL/DONE/SUCCESS/FAIL from taper */
  821. while(get_logline(logf)) {
  822. if (curprog == P_TAPER &&
  823. (curlog == L_DONE || curlog == L_SUCCESS ||
  824. curlog == L_PARTIAL || curlog == L_FAIL)) {
  825. break;
  826. }
  827. }
  828. }
  829. for (a_part_find = part_find; a_part_find;
  830. a_part_find = a_part_find->next) {
  831. if (curlog == L_PARTIAL)
  832. a_part_find->status = stralloc("PARTIAL");
  833. else if (curlog == L_FAIL)
  834. a_part_find->status = stralloc("FAIL");
  835. }
  836. for (a_part_find = part_find;
  837. a_part_find->next != NULL;
  838. a_part_find=a_part_find->next) {
  839. }
  840. /* merge part_find to *output_find */
  841. a_part_find->next = *output_find;
  842. *output_find = part_find;
  843. part_find = NULL;
  844. }
  845. afclose(logf);
  846. amfree(datestamp);
  847. amfree(current_label);
  848. return found_something;
  849. }
  850. /*
  851. * Return the set of dumps that match *all* of the given patterns (we consider
  852. * an empty pattern to match .*, though). If 'ok' is true, will only match
  853. * dumps with SUCCESS status.
  854. *
  855. * Returns a newly allocated list of results, where all strings are also newly
  856. * allocated. Apparently some part of Amanda leaks under this condition.
  857. */
  858. find_result_t *
  859. dumps_match(
  860. find_result_t *output_find,
  861. char *hostname,
  862. char *diskname,
  863. char *datestamp,
  864. char *level,
  865. int ok)
  866. {
  867. find_result_t *cur_result;
  868. find_result_t *matches = NULL;
  869. for(cur_result=output_find;
  870. cur_result;
  871. cur_result=cur_result->next) {
  872. char level_str[NUM_STR_SIZE];
  873. g_snprintf(level_str, SIZEOF(level_str), "%d", cur_result->level);
  874. if((!hostname || *hostname == '\0' || match_host(hostname, cur_result->hostname)) &&
  875. (!diskname || *diskname == '\0' || match_disk(diskname, cur_result->diskname)) &&
  876. (!datestamp || *datestamp== '\0' || match_datestamp(datestamp, cur_result->timestamp)) &&
  877. (!level || *level== '\0' || match_level(level, level_str)) &&
  878. (!ok || !strcmp(cur_result->status, "OK"))){
  879. find_result_t *curmatch = g_new0(find_result_t, 1);
  880. memcpy(curmatch, cur_result, SIZEOF(find_result_t));
  881. curmatch->timestamp = stralloc(cur_result->timestamp);
  882. curmatch->hostname = stralloc(cur_result->hostname);
  883. curmatch->diskname = stralloc(cur_result->diskname);
  884. curmatch->level = cur_result->level;
  885. curmatch->label = cur_result->label? stralloc(cur_result->label) : NULL;
  886. curmatch->filenum = cur_result->filenum;
  887. curmatch->sec = cur_result->sec;
  888. curmatch->kb = cur_result->kb;
  889. curmatch->status = stralloc(cur_result->status);
  890. curmatch->partnum = stralloc(cur_result->partnum);
  891. curmatch->next = matches;
  892. matches = curmatch;
  893. }
  894. }
  895. return(matches);
  896. }
  897. /*
  898. * Return the set of dumps that match one or more of the given dumpspecs,
  899. * If 'ok' is true, only dumps with a SUCCESS status will be matched.
  900. *
  901. * Returns a newly allocated list of results, where all strings are also newly
  902. * allocated. Apparently some part of Amanda leaks under this condition.
  903. */
  904. find_result_t *
  905. dumps_match_dumpspecs(
  906. find_result_t *output_find,
  907. GSList *dumpspecs,
  908. int ok)
  909. {
  910. find_result_t *cur_result;
  911. find_result_t *matches = NULL;
  912. GSList *dumpspec;
  913. dumpspec_t *ds;
  914. for(cur_result=output_find;
  915. cur_result;
  916. cur_result=cur_result->next) {
  917. char level_str[NUM_STR_SIZE];
  918. g_snprintf(level_str, SIZEOF(level_str), "%d", cur_result->level);
  919. for (dumpspec = dumpspecs; dumpspec; dumpspec = dumpspec->next) {
  920. ds = (dumpspec_t *)dumpspec->data;
  921. if((!ds->host || *ds->host == '\0' || match_host(ds->host, cur_result->hostname)) &&
  922. (!ds->disk || *ds->disk == '\0' || match_disk(ds->disk, cur_result->diskname)) &&
  923. (!ds->datestamp || *ds->datestamp== '\0' || match_datestamp(ds->datestamp, cur_result->timestamp)) &&
  924. (!ds->level || *ds->level== '\0' || match_level(ds->level, level_str)) &&
  925. (!ok || !strcmp(cur_result->status, "OK"))){
  926. find_result_t *curmatch = alloc(SIZEOF(find_result_t));
  927. memcpy(curmatch, cur_result, SIZEOF(find_result_t));
  928. curmatch->timestamp = stralloc(cur_result->timestamp);
  929. curmatch->hostname = stralloc(cur_result->hostname);
  930. curmatch->diskname = stralloc(cur_result->diskname);
  931. curmatch->level = cur_result->level;
  932. curmatch->label = cur_result->label? stralloc(cur_result->label) : NULL;
  933. curmatch->filenum = cur_result->filenum;
  934. curmatch->status = stralloc(cur_result->status);
  935. curmatch->partnum = stralloc(cur_result->partnum);
  936. curmatch->next = matches;
  937. matches = curmatch;
  938. break;
  939. }
  940. }
  941. }
  942. return(matches);
  943. }
  944. find_result_t *
  945. dump_exist(
  946. find_result_t *output_find,
  947. char *hostname,
  948. char *diskname,
  949. char *datestamp,
  950. int level)
  951. {
  952. find_result_t *output_find_result;
  953. for(output_find_result=output_find;
  954. output_find_result;
  955. output_find_result=output_find_result->next) {
  956. if( !strcmp(output_find_result->hostname, hostname) &&
  957. !strcmp(output_find_result->diskname, diskname) &&
  958. !strcmp(output_find_result->timestamp, datestamp) &&
  959. output_find_result->level == level) {
  960. return output_find_result;
  961. }
  962. }
  963. return(NULL);
  964. }