static void import_dumpdates( amandates_t * amdp) { char *devname; char *line; char *fname; int level = 0; time_t dumpdate; FILE *dumpdf; char *s; int ch; devname = amname_to_devname(amdp->name); if((dumpdf = fopen("/etc/dumpdates", "r")) == NULL) { amfree(devname); return; } for(; (line = agets(dumpdf)) != NULL; free(line)) { if (line[0] == '\0') continue; s = line; ch = *s++; skip_whitespace(s, ch); if(ch == '\0') { continue; /* no fname field */ } fname = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; /* terminate fname */ skip_whitespace(s, ch); if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) { continue; /* no level field */ } skip_integer(s, ch); skip_whitespace(s, ch); if(ch == '\0') { continue; /* no dumpdate field */ } dumpdate = unctime(s-1); if(!g_str_equal(fname, devname) || level < 0 || level >= DUMP_LEVELS) { continue; } if(dumpdate != -1 && dumpdate > amdp->dates[level]) { if(!readonly) updated = 1; amdp->dates[level] = dumpdate; } } afclose(dumpdf); amfree(devname); }
int main() { int count; scanf("%d", &count); unsigned long nums[10]; for (int i = 0; i < count; i++) { scanf("%ld", &nums[i]); } for (int i = 0; i < count; i++) { int index = 0; int index_r = 0; long k = 1; while (1) { index_r = index; index += skip_group(k); if (index >= nums[i]) { break; } k++; } k = 1; index = index_r; while (1) { index_r = index; index += skip_integer(k); if (index >= nums[i]) { break; } k++; } int remain = nums[i] - index_r; int digits[10] = {0}; int len = 1; digits[0] = k % 10; while ((k /= 10) != 0) { digits[len++] = k % 10; } printf("%d\n", digits[len - remain]); } return 0; }
/* XXX - code assumes AVG_COUNT == 3 */ static int read_txinfofile( FILE * infof, info_t * info) { char *line = NULL; int version; int rc; perf_t *pp; char *s; int ch; int nb_history; int i; /* get version: command: lines */ while ((line = agets(infof)) != NULL) { if (line[0] != '\0') break; amfree(line); } if (line == NULL) return -1; rc = sscanf(line, _("version: %d"), &version); amfree(line); if(rc != 1) return -2; while ((line = agets(infof)) != NULL) { if (line[0] != '\0') break; amfree(line); } if (line == NULL) return -1; rc = sscanf(line, _("command: %u"), &info->command); amfree(line); if(rc != 1) return -2; /* get rate: and comp: lines for full dumps */ pp = &info->full; while ((line = agets(infof)) != NULL) { if (line[0] != '\0') break; amfree(line); } if (line == NULL) return -1; rc = sscanf(line, "full-rate: %lf %lf %lf", &pp->rate[0], &pp->rate[1], &pp->rate[2]); amfree(line); if(rc > 3) return -2; while ((line = agets(infof)) != NULL) { if (line[0] != '\0') break; amfree(line); } if (line == NULL) return -1; rc = sscanf(line, "full-comp: %lf %lf %lf", &pp->comp[0], &pp->comp[1], &pp->comp[2]); amfree(line); if(rc > 3) return -2; /* get rate: and comp: lines for incr dumps */ pp = &info->incr; while ((line = agets(infof)) != NULL) { if (line[0] != '\0') break; amfree(line); } if (line == NULL) return -1; rc = sscanf(line, "incr-rate: %lf %lf %lf", &pp->rate[0], &pp->rate[1], &pp->rate[2]); amfree(line); if(rc > 3) return -2; while ((line = agets(infof)) != NULL) { if (line[0] != '\0') break; amfree(line); } if (line == NULL) return -1; rc = sscanf(line, "incr-comp: %lf %lf %lf", &pp->comp[0], &pp->comp[1], &pp->comp[2]); amfree(line); if(rc > 3) return -2; /* get stats for dump levels */ for(rc = -2; (line = agets(infof)) != NULL; free(line)) { stats_t onestat; /* one stat record */ int level = 0; long long off_t_tmp; if (line[0] == '\0') continue; if(line[0] == '/' && line[1] == '/') { rc = 0; amfree(line); return 0; /* normal end of record */ } else if (strncmp_const(line,"last_level:") == 0) { break; /* normal */ } else if (strncmp_const(line,"history:") == 0) { break; /* normal */ } memset(&onestat, 0, sizeof(onestat)); s = line; ch = *s++; /* from here on, we had better be parsing a 'stats' line */ if(strncmp_const_skip(line, "stats:", s, ch) != 0) { amfree(line); return -1; } skip_whitespace(s, ch); if(ch == '\0' || sscanf((s - 1), "%d", &level) != 1) { amfree(line); return -1; } skip_integer(s, ch); skip_whitespace(s, ch); if(ch == '\0' || sscanf((s - 1), "%lld", &off_t_tmp) != 1) { amfree(line); return -1; } onestat.size = (off_t)off_t_tmp; skip_integer(s, ch); skip_whitespace(s, ch); if(ch == '\0' || sscanf((s - 1), "%lld", &off_t_tmp) != 1) { amfree(line); return -1; } onestat.csize = (off_t)off_t_tmp; skip_integer(s, ch); /* assume that the time fits in a long long */ skip_whitespace(s, ch); if(ch == '\0' || sscanf((s - 1), "%lld", &off_t_tmp) != 1) { amfree(line); return -1; } onestat.secs = (time_t)off_t_tmp; skip_integer(s, ch); skip_whitespace(s, ch); if(ch == '\0' || sscanf((s - 1), "%lld", &off_t_tmp) != 1) { amfree(line); return -1; } onestat.date = (time_t)off_t_tmp; skip_integer(s, ch); skip_whitespace(s, ch); if(ch != '\0') { if(sscanf((s - 1), "%lld", &off_t_tmp) != 1) { amfree(line); return -1; } onestat.filenum = (off_t)off_t_tmp; skip_integer(s, ch); skip_whitespace(s, ch); if(ch == '\0') { amfree(line); return -1; } strncpy(onestat.label, s-1, sizeof(onestat.label)-1); onestat.label[sizeof(onestat.label)-1] = '\0'; } if (level < 0 || level > DUMP_LEVELS-1) { amfree(line); return -1; } info->inf[level] = onestat; } if(line == NULL) return -1; rc = sscanf(line, "last_level: %d %d", &info->last_level, &info->consecutive_runs); amfree(line); if(rc > 2) return -2; rc = 0; nb_history = 0; for(i=0;i<=NB_HISTORY;i++) { info->history[i].level = -2; } for(rc = -2; (line = agets(infof)) != NULL; free(line)) { history_t onehistory; /* one history record */ long long off_t_tmp; if (line[0] == '\0') continue; if(line[0] == '/' && line[1] == '/') { info->history[nb_history].level = -2; rc = 0; amfree(line); return 0; /* normal end of record */ } memset(&onehistory, 0, sizeof(onehistory)); s = line; ch = *s++; if(strncmp_const_skip(line, "history:", s, ch) != 0) { amfree(line); break; } skip_whitespace(s, ch); if(ch == '\0' || sscanf((s - 1), "%d", &onehistory.level) != 1) { amfree(line); break; } skip_integer(s, ch); skip_whitespace(s, ch); if(ch == '\0' || sscanf((s - 1), "%lld", &off_t_tmp) != 1) { amfree(line); break; } onehistory.size = (off_t)off_t_tmp; skip_integer(s, ch); skip_whitespace(s, ch); if(ch == '\0' || sscanf((s - 1), "%lld", &off_t_tmp) != 1) { amfree(line); break; } onehistory.csize = (off_t)off_t_tmp; skip_integer(s, ch); skip_whitespace(s, ch); if(ch == '\0' || sscanf((s - 1), "%lld", &off_t_tmp) != 1) { amfree(line); break; } onehistory.date = (time_t)off_t_tmp; skip_integer(s, ch); onehistory.secs = (unsigned long)-1; skip_whitespace(s, ch); if(ch != '\0') { if(sscanf((s - 1), "%lld", &off_t_tmp) != 1) { amfree(line); break; } onehistory.secs = (time_t)off_t_tmp; skip_integer(s, ch); } info->history[nb_history++] = onehistory; } amfree(line); while ((line = agets(infof)) != NULL) { if (line[0] != '\0') break; amfree(line); } if (line == NULL) return -1; amfree(line); return rc; }
cmddata_t * cmdfile_parse_line ( char *line, gboolean *generic_command_restore, gboolean *specific_command_restore) { int pid; char *s, *fp, *operation; char ch; cmddata_t *cmddata; int id; s = line; if (*s == '\0') return NULL; ch = *s++; skip_whitespace(s, ch); if (ch == '\0' || sscanf((s - 1), "%d", &id) != 1) { return NULL; } skip_integer(s, ch); skip_whitespace(s, ch); operation = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; if (!g_str_equal(operation, "FLUSH") && !g_str_equal(operation, "COPY") && !g_str_equal(operation, "RESTORE")) { g_debug("BAD operation %s: %s", operation, s); return NULL; } cmddata = g_new0(cmddata_t, 1); cmddata->id = id; skip_whitespace(s, ch); fp = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; cmddata->config = unquote_string(fp); if (g_str_equal(operation, "FLUSH")) { cmddata->operation = CMD_FLUSH; skip_whitespace(s,ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->holding_file = unquote_string(fp); } else if (g_str_equal(operation, "COPY")) { char *src_labels; char *slabels; char *a; cmddata->operation = CMD_COPY; skip_whitespace(s,ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->src_storage = unquote_string(fp); skip_whitespace(s,ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->src_pool = unquote_string(fp); skip_whitespace(s,ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->src_label = unquote_string(fp); skip_whitespace(s,ch); fp = s - 1; skip_integer(s, ch); s[-1] = '\0'; cmddata->src_fileno = atoi(fp); skip_whitespace(s,ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; slabels = src_labels = unquote_string(fp); cmddata->src_labels_str = g_strdup(src_labels); a = strstr(slabels, " ;"); if (a) { slabels = a+2; while ((a = strstr(slabels, " ;"))) { *a = '\0'; cmddata->src_labels = g_slist_append(cmddata->src_labels, g_strdup(slabels)); slabels = a+2; } } g_free(src_labels); skip_whitespace(s,ch); fp = s - 1; skip_integer(s, ch); s[-1] = '\0'; cmddata->start_time = atoll(fp); } else if (g_str_equal(operation, "RESTORE")) { cmddata->operation = CMD_RESTORE; skip_whitespace(s,ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->src_storage = unquote_string(fp); skip_whitespace(s,ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->src_pool = unquote_string(fp); skip_whitespace(s,ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; if (g_str_equal(cmddata->src_pool, "HOLDING")) { cmddata->holding_file = unquote_string(fp); } else { cmddata->src_label = unquote_string(fp); } skip_whitespace(s,ch); fp = s - 1; skip_integer(s, ch); s[-1] = '\0'; cmddata->src_fileno = atoi(fp); skip_whitespace(s,ch); fp = s - 1; skip_integer(s, ch); s[-1] = '\0'; cmddata->expire = atoll(fp); } else { } skip_whitespace(s, ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->hostname = unquote_string(fp); skip_whitespace(s, ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->diskname = unquote_string(fp); skip_whitespace(s, ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->dump_timestamp = unquote_string(fp); skip_whitespace(s,ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->level = atoi(fp); skip_whitespace(s, ch); if (cmddata->operation != CMD_RESTORE) { fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->dst_storage = unquote_string(fp); skip_whitespace(s, ch); } fp = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; if (sscanf(fp, "WORKING:%d", &pid) != 1) { } cmddata->working_pid = pid; if (cmddata->operation == CMD_RESTORE) { if (cmddata->working_pid == 0) { if (generic_command_restore) *generic_command_restore = TRUE; } else { if (specific_command_restore) *specific_command_restore = TRUE; } } skip_whitespace(s, ch); fp = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; if (g_str_equal(fp, "DONE")) { cmddata->status = CMD_DONE; } else if (g_str_equal(fp, "TODO")) { cmddata->status = CMD_TODO; } else if (strncmp(fp, "PARTIAL", 7) == 0) { long long lsize; cmddata->status = CMD_PARTIAL; if (sscanf(fp, "PARTIAL:%lld", &lsize) != 1) { } else { cmddata->size = lsize; } } else { } return cmddata; }
/* WARNING: Function accesses globals find_diskqp, curlog, curlog, curstr, * dynamic_disklist */ gboolean search_logfile( find_result_t **output_find, const char *label, const char *passed_datestamp, const char *logfile, disklist_t * dynamic_disklist) { FILE *logf; char *host, *host_undo; char *disk = NULL, *qdisk, *disk_undo; char *date, *date_undo; int partnum; int totalparts; int maxparts = -1; char *number; int fileno; char *current_label; char *rest, *rest_undo; char *ck_label=NULL; int level = 0; off_t filenum; char *ck_datestamp=NULL; char *datestamp; char *s; int ch; disk_t *dp; GHashTable* valid_label; GHashTable* part_by_dle; find_result_t *part_find; find_result_t *a_part_find; gboolean right_label = FALSE; gboolean found_something = FALSE; double sec; off_t kb; off_t bytes; off_t orig_kb; int taper_part = 0; g_return_val_if_fail(output_find != NULL, 0); g_return_val_if_fail(logfile != NULL, 0); current_label = g_strdup(""); if (string_chunk == NULL) { string_chunk = g_string_chunk_new(32768); } valid_label = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); part_by_dle = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); datestamp = g_strdup(passed_datestamp); if((logf = fopen(logfile, "r")) == NULL) { error(_("could not open logfile %s: %s"), logfile, strerror(errno)); /*NOTREACHED*/ } filenum = (off_t)0; while(get_logline(logf)) { if (curlog == L_START && curprog == P_TAPER) { amfree(ck_label); ck_datestamp = NULL; if(parse_taper_datestamp_log(curstr, &ck_datestamp, &ck_label) == 0) { g_printf(_("strange log line in %s \"start taper %s\"\n"), logfile, curstr); continue; } if (datestamp != NULL) { if (!g_str_equal(datestamp, ck_datestamp)) { g_printf(_("Log file %s stamped %s, expecting %s!\n"), logfile, ck_datestamp, datestamp); amfree(ck_label); break; } } right_label = volume_matches(label, ck_label, ck_datestamp); if (right_label && ck_label) { g_hash_table_insert(valid_label, g_strdup(ck_label), GINT_TO_POINTER(1)); } if (label && datestamp && right_label) { found_something = TRUE; } amfree(current_label); current_label = ck_label; ck_label = NULL; if (datestamp == NULL) { datestamp = g_strdup(ck_datestamp); } filenum = (off_t)0; } if (!datestamp) continue; if (right_label && (curlog == L_SUCCESS || curlog == L_CHUNK || curlog == L_PART || curlog == L_PARTPARTIAL) && curprog == P_TAPER) { filenum++; } else if (right_label && curlog == L_PARTIAL && curprog == P_TAPER && taper_part == 0) { filenum++; } partnum = -1; totalparts = -1; if (curlog == L_SUCCESS || curlog == L_CHUNKSUCCESS || curlog == L_DONE || curlog == L_FAIL || curlog == L_CHUNK || curlog == L_PART || curlog == L_PARTIAL || curlog == L_PARTPARTIAL ) { s = curstr; ch = *s++; skip_whitespace(s, ch); if(ch == '\0') { g_printf(_("strange log line in %s \"%s\"\n"), logfile, curstr); continue; } if (curlog == L_PART || curlog == L_PARTPARTIAL) { char *part_label; char *qpart_label = s - 1; taper_part++; skip_quoted_string(s, ch); s[-1] = '\0'; part_label = unquote_string(qpart_label); if (!g_hash_table_lookup(valid_label, part_label)) { amfree(part_label); continue; } amfree(current_label); current_label = part_label; skip_whitespace(s, ch); if(ch == '\0') { g_printf("strange log line in %s \"%s\"\n", logfile, curstr); continue; } number = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; fileno = atoi(number); filenum = fileno; if (filenum == 0) continue; skip_whitespace(s, ch); if(ch == '\0') { g_printf("strange log line in %s \"%s\"\n", logfile, curstr); continue; } } else { taper_part = 0; } host = s - 1; skip_non_whitespace(s, ch); host_undo = s - 1; *host_undo = '\0'; skip_whitespace(s, ch); if(ch == '\0') { g_printf(_("strange log line in %s \"%s\"\n"), logfile, curstr); continue; } qdisk = s - 1; skip_quoted_string(s, ch); disk_undo = s - 1; *disk_undo = '\0'; disk = unquote_string(qdisk); skip_whitespace(s, ch); if(ch == '\0') { g_printf(_("strange log line in %s \"%s\"\n"), logfile, curstr); amfree(disk); continue; } date = s - 1; skip_non_whitespace(s, ch); date_undo = s - 1; *date_undo = '\0'; if(strlen(date) < 3) { /* old log didn't have datestamp */ level = atoi(date); date = datestamp; partnum = 1; totalparts = 1; } else { if (curprog == P_TAPER && (curlog == L_CHUNK || curlog == L_PART || curlog == L_PARTPARTIAL || curlog == L_PARTIAL || curlog == L_DONE)) { char *s1, ch1; skip_whitespace(s, ch); number = s - 1; skip_non_whitespace(s, ch); s1 = &s[-1]; ch1 = *s1; skip_whitespace(s, ch); if (*(s-1) != '[') { *s1 = ch1; sscanf(number, "%d/%d", &partnum, &totalparts); if (partnum > maxparts) maxparts = partnum; if (totalparts > maxparts) maxparts = totalparts; } else { /* nparts is not in all PARTIAL lines */ partnum = 1; totalparts = 1; s = number + 1; } } else { skip_whitespace(s, ch); } if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) { g_printf(_("Fstrange log line in %s \"%s\"\n"), logfile, s-1); amfree(disk); continue; } skip_integer(s, ch); } skip_whitespace(s, ch); if(ch == '\0') { g_printf(_("strange log line in %s \"%s\"\n"), logfile, curstr); amfree(disk); continue; } rest = s - 1; skip_non_whitespace(s, ch); rest_undo = s - 1; *rest_undo = '\0'; if (g_str_equal(rest, "[sec")) { skip_whitespace(s, ch); if(ch == '\0') { g_printf(_("strange log line in %s \"%s\"\n"), logfile, curstr); amfree(disk); continue; } sec = atof(s - 1); skip_non_whitespace(s, ch); skip_whitespace(s, ch); rest = s - 1; skip_non_whitespace(s, ch); rest_undo = s - 1; *rest_undo = '\0'; if (!g_str_equal(rest, "kb") && !g_str_equal(rest, "bytes")) { g_printf(_("Bstrange log line in %s \"%s\"\n"), logfile, curstr); amfree(disk); continue; } skip_whitespace(s, ch); if (ch == '\0') { g_printf(_("strange log line in %s \"%s\"\n"), logfile, curstr); amfree(disk); continue; } if (g_str_equal(rest, "kb")) { kb = atof(s - 1); bytes = 0; } else { bytes = atof(s - 1); kb = bytes / 1024; } skip_non_whitespace(s, ch); skip_whitespace(s, ch); rest = s - 1; skip_non_whitespace(s, ch); rest_undo = s - 1; *rest_undo = '\0'; if (!g_str_equal(rest, "kps")) { g_printf(_("Cstrange log line in %s \"%s\"\n"), logfile, curstr); amfree(disk); continue; } skip_whitespace(s, ch); if (ch == '\0') { g_printf(_("strange log line in %s \"%s\"\n"), logfile, curstr); amfree(disk); continue; } /* kps = atof(s - 1); */ skip_non_whitespace(s, ch); skip_whitespace(s, ch); rest = s - 1; skip_non_whitespace(s, ch); rest_undo = s - 1; *rest_undo = '\0'; if (!g_str_equal(rest, "orig-kb")) { orig_kb = 0; } else { skip_whitespace(s, ch); if(ch == '\0') { g_printf(_("strange log line in %s \"%s\"\n"), logfile, curstr); amfree(disk); continue; } orig_kb = atof(s - 1); } } else { sec = 0; kb = 0; bytes = 0; orig_kb = 0; *rest_undo = ' '; } if (g_str_has_prefix(rest, "error")) rest += 6; if (g_str_has_prefix(rest, "config")) rest += 7; dp = lookup_disk(host,disk); if ( dp == NULL ) { if (dynamic_disklist == NULL) { amfree(disk); continue; } dp = add_disk(dynamic_disklist, host, disk); enqueue_disk(dynamic_disklist, dp); } if (find_match(host, disk)) { if(curprog == P_TAPER) { char *key = g_strdup_printf( "HOST:%s DISK:%s: DATE:%s LEVEL:%d", host, disk, date, level); find_result_t *new_output_find = g_new0(find_result_t, 1); part_find = g_hash_table_lookup(part_by_dle, key); maxparts = partnum; if (maxparts < totalparts) maxparts = totalparts; for (a_part_find = part_find; a_part_find; a_part_find = a_part_find->next) { if (maxparts < a_part_find->partnum) maxparts = a_part_find->partnum; if (maxparts < a_part_find->totalparts) maxparts = a_part_find->totalparts; } new_output_find->timestamp = g_string_chunk_insert_const(string_chunk, date); new_output_find->write_timestamp = g_string_chunk_insert_const(string_chunk, datestamp); new_output_find->hostname=g_string_chunk_insert_const(string_chunk, host); new_output_find->diskname=g_string_chunk_insert_const(string_chunk, disk); new_output_find->level=level; new_output_find->partnum = partnum; new_output_find->totalparts = totalparts; new_output_find->label=g_string_chunk_insert_const(string_chunk, current_label); new_output_find->status=NULL; new_output_find->dump_status=NULL; new_output_find->message=""; new_output_find->filenum=filenum; new_output_find->sec=sec; new_output_find->kb=kb; new_output_find->bytes=bytes; new_output_find->orig_kb=orig_kb; new_output_find->next=NULL; if (curlog == L_SUCCESS) { new_output_find->status = "OK"; new_output_find->dump_status = "OK"; new_output_find->next = *output_find; new_output_find->partnum = 1; /* L_SUCCESS is pre-splitting */ *output_find = new_output_find; found_something = TRUE; } else if (curlog == L_CHUNKSUCCESS || curlog == L_DONE || curlog == L_PARTIAL || curlog == L_FAIL) { /* result line */ if (curlog == L_PARTIAL || curlog == L_FAIL) { /* set dump_status of each part */ for (a_part_find = part_find; a_part_find; a_part_find = a_part_find->next) { if (curlog == L_PARTIAL) a_part_find->dump_status = "PARTIAL"; else { a_part_find->dump_status = "FAIL"; a_part_find->message = g_string_chunk_insert_const(string_chunk, rest); } } } else { if (maxparts > -1) { /* format with part */ /* must check if all part are there */ int num_part = maxparts; for (a_part_find = part_find; a_part_find; a_part_find = a_part_find->next) { if (a_part_find->partnum == num_part && g_str_equal(a_part_find->status, "OK")) num_part--; } /* set dump_status of each part */ for (a_part_find = part_find; a_part_find; a_part_find = a_part_find->next) { if (num_part == 0) { a_part_find->dump_status = "OK"; } else { a_part_find->dump_status = "FAIL"; a_part_find->message = g_string_chunk_insert_const(string_chunk, "Missing part"); } } } } if (curlog == L_DONE) { for (a_part_find = part_find; a_part_find; a_part_find = a_part_find->next) { if (a_part_find->totalparts == -1) { a_part_find->totalparts = maxparts; } if (a_part_find->orig_kb == 0) { a_part_find->orig_kb = orig_kb; } } } if (part_find) { /* find last element */ for (a_part_find = part_find; a_part_find->next != NULL; a_part_find=a_part_find->next) { } /* merge part_find to *output_find */ a_part_find->next = *output_find; *output_find = part_find; part_find = NULL; maxparts = -1; found_something = TRUE; g_hash_table_remove(part_by_dle, key); } free_find_result(&new_output_find); } else { /* part line */ if (curlog == L_PART || curlog == L_CHUNK) { new_output_find->status = "OK"; new_output_find->dump_status = "OK"; } else { /* PARTPARTIAL */ new_output_find->status = "PARTIAL"; new_output_find->dump_status = "PARTIAL"; } /* Add to part_find list */ if (part_find) { new_output_find->next = part_find; part_find = new_output_find; } else { new_output_find->next = NULL; part_find = new_output_find; } g_hash_table_insert(part_by_dle, g_strdup(key), part_find); found_something = TRUE; } amfree(key); } else if(curlog == L_FAIL) { char *status_failed; /* print other failures too -- this is a hack to ensure that failures which * did not make it to tape are also listed in the output of 'amadmin x find'; * users that do not want this information (e.g., Amanda::DB::Catalog) should * filter dumps with a NULL label. */ find_result_t *new_output_find = g_new0(find_result_t, 1); new_output_find->next = *output_find; new_output_find->timestamp = g_string_chunk_insert_const(string_chunk, date); new_output_find->write_timestamp = g_strdup("00000000000000"); /* dump was not written.. */ new_output_find->hostname=g_string_chunk_insert_const(string_chunk, host); new_output_find->diskname=g_string_chunk_insert_const(string_chunk, disk); new_output_find->level=level; new_output_find->label=NULL; new_output_find->partnum=partnum; new_output_find->totalparts=totalparts; new_output_find->filenum=0; new_output_find->sec=sec; new_output_find->kb=kb; new_output_find->bytes=bytes; new_output_find->orig_kb=orig_kb; status_failed = g_strjoin(NULL, "FAILED (", program_str[(int)curprog], ") ", rest, NULL); new_output_find->status = g_string_chunk_insert_const(string_chunk, status_failed); amfree(status_failed); new_output_find->dump_status=""; new_output_find->message=""; *output_find=new_output_find; found_something = TRUE; maxparts = -1; } } amfree(disk); } } g_hash_table_destroy(valid_label); afclose(logf); amfree(datestamp); amfree(current_label); amfree(disk); return found_something; }
cmddatas_t * read_cmdfile( char *filename) { cmddatas_t *cmddatas = g_new0(cmddatas_t, 1); cmddata_t *cmddata; char *s, *fp, *operation; char ch; char **xlines; int i; int pid; pid_t pids[NB_PIDS]; pid_t new_pids[NB_PIDS]; int nb_pids = 0; int result; gboolean generic_command_restore = FALSE; gboolean specific_command_restore = FALSE; cmddatas->lock = file_lock_new(filename); cmddatas->cmdfile = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, &free_cmddata); need_rewrite = FALSE; // open while ((result = file_lock_lock(cmddatas->lock)) == 1) { sleep(1); } if (result != 0) { g_debug("read_cmdfile open failed: %s", strerror(errno)); } if (!cmddatas->lock->data) { cmddatas->version = 1; cmddatas->max_id = 0; return cmddatas; } xlines = g_strsplit(cmddatas->lock->data, "\n", 0); // read if (sscanf(xlines[0], "VERSION %d", &cmddatas->version) != 1) {}; if (sscanf(xlines[1], "ID %d", &cmddatas->max_id) != 1) {}; // read cmd for (i=2; xlines[i] != NULL; i++) { int id; s = xlines[i]; if (*s == '\0') continue; ch = *s++; skip_whitespace(s, ch); if (ch == '\0' || sscanf((s - 1), "%d", &id) != 1) { continue; } skip_integer(s, ch); skip_whitespace(s, ch); operation = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; if (!g_str_equal(operation, "FLUSH") && !g_str_equal(operation, "COPY") && !g_str_equal(operation, "RESTORE")) { g_debug("BAD operation %s: %s", operation, s); continue; } cmddata = g_new0(cmddata_t, 1); cmddata->id = id; skip_whitespace(s, ch); fp = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; cmddata->config = unquote_string(fp); if (g_str_equal(operation, "FLUSH")) { cmddata->operation = CMD_FLUSH; skip_whitespace(s,ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->holding_file = unquote_string(fp); } else if (g_str_equal(operation, "COPY")) { char *src_labels; char *slabels; char *a; cmddata->operation = CMD_COPY; skip_whitespace(s,ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->src_storage = unquote_string(fp); skip_whitespace(s,ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->src_pool = unquote_string(fp); skip_whitespace(s,ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->src_label = unquote_string(fp); skip_whitespace(s,ch); fp = s - 1; skip_integer(s, ch); s[-1] = '\0'; cmddata->src_fileno = atoi(fp); skip_whitespace(s,ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; slabels = src_labels = unquote_string(fp); cmddata->src_labels_str = g_strdup(src_labels); a = strstr(slabels, " ;"); if (a) { slabels = a+2; while ((a = strstr(slabels, " ;"))) { *a = '\0'; cmddata->src_labels = g_slist_append(cmddata->src_labels, g_strdup(slabels)); slabels = a+2; } } g_free(src_labels); skip_whitespace(s,ch); fp = s - 1; skip_integer(s, ch); s[-1] = '\0'; cmddata->start_time = atoll(fp); } else if (g_str_equal(operation, "RESTORE")) { cmddata->operation = CMD_RESTORE; skip_whitespace(s,ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->src_storage = unquote_string(fp); skip_whitespace(s,ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->src_pool = unquote_string(fp); skip_whitespace(s,ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; if (g_str_equal(cmddata->src_pool, "HOLDING")) { cmddata->holding_file = unquote_string(fp); } else { cmddata->src_label = unquote_string(fp); } skip_whitespace(s,ch); fp = s - 1; skip_integer(s, ch); s[-1] = '\0'; cmddata->src_fileno = atoi(fp); skip_whitespace(s,ch); fp = s - 1; skip_integer(s, ch); s[-1] = '\0'; cmddata->expire = atoll(fp); } else { } skip_whitespace(s, ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->hostname = unquote_string(fp); skip_whitespace(s, ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->diskname = unquote_string(fp); skip_whitespace(s, ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->dump_timestamp = unquote_string(fp); skip_whitespace(s,ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->level = atoi(fp); skip_whitespace(s, ch); if (cmddata->operation != CMD_RESTORE) { fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->dst_storage = unquote_string(fp); skip_whitespace(s, ch); } fp = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; if (sscanf(fp, "WORKING:%d", &pid) != 1) { } cmddata->working_pid = pid; if (cmddata->operation == CMD_RESTORE) { if (cmddata->working_pid == 0) generic_command_restore = TRUE; else specific_command_restore = TRUE; } skip_whitespace(s, ch); fp = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; if (g_str_equal(fp, "DONE")) { cmddata->status = CMD_DONE; } else if (g_str_equal(fp, "TODO")) { cmddata->status = CMD_TODO; } else if (strncmp(fp, "PARTIAL", 7) == 0) { long long lsize; cmddata->status = CMD_PARTIAL; if (sscanf(fp, "PARTIAL:%lld", &lsize) != 1) { } else { cmddata->size = lsize; } } else { } /* validate working_pid */ if (!checked_working_pid && cmddata->working_pid != 0) { int i; for (i = 0; i < nb_pids; i++) { if (pids[i] == cmddata->working_pid) { cmddata->working_pid = new_pids[i]; i += 100; continue; } } if (nb_pids < NB_PIDS) { pids[nb_pids] = cmddata->working_pid; if (kill(cmddata->working_pid, 0) != 0) cmddata->working_pid =0; new_pids[nb_pids] = cmddata->working_pid; nb_pids++; } } g_hash_table_insert(cmddatas->cmdfile, GINT_TO_POINTER(cmddata->id), cmddata); } if (generic_command_restore) { if (specific_command_restore) { /* set expire to NOW+24h of all genric command_restore */ g_hash_table_foreach(cmddatas->cmdfile, &cmdfile_set_expire, NULL); } else { /* check start_time of all generic command_restore and remove them */ g_hash_table_foreach(cmddatas->cmdfile, &cmdfile_set_to_DONE, NULL); } } g_strfreev(xlines); checked_working_pid = 1; if (need_rewrite) { write_cmdfile(cmddatas); return read_cmdfile(filename); } return cmddatas; }
int main( int argc, char ** argv) { int interactive = 0; int level = 0; int mesgpipe[2]; dle_t *dle = NULL; char *dumpdate, *stroptions; char *qdisk = NULL; char *qamdevice = NULL; char *line = NULL; char *err_extra = NULL; char *s; int i; int ch; GSList *errlist; FILE *mesgstream; level_t *alevel; /* initialize */ /* * Configure program for internationalization: * 1) Only set the message locale for now. * 2) Set textdomain for all amanda related programs to "amanda" * We don't want to be forced to support dozens of message catalogs. */ setlocale(LC_MESSAGES, "C"); textdomain("amanda"); safe_fd(DATA_FD_OFFSET, DATA_FD_COUNT*2); safe_cd(); set_pname("sendbackup"); /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); /* Don't die when interrupt received */ signal(SIGINT, SIG_IGN); if(argc > 1 && strcmp(argv[1],"-t") == 0) { interactive = 1; argc--; argv++; } else { interactive = 0; } erroutput_type = (ERR_INTERACTIVE|ERR_SYSLOG); dbopen(DBG_SUBDIR_CLIENT); startclock(); dbprintf(_("Version %s\n"), version()); if(argc > 2 && strcmp(argv[1], "amandad") == 0) { amandad_auth = stralloc(argv[2]); } our_features = am_init_feature_set(); our_feature_string = am_feature_to_string(our_features); config_init(CONFIG_INIT_CLIENT, NULL); /* (check for config errors comes later) */ check_running_as(RUNNING_AS_CLIENT_LOGIN); if(interactive) { /* * In interactive (debug) mode, the backup data is sent to * /dev/null and none of the network connections back to driver * programs on the tape host are set up. The index service is * run and goes to stdout. */ g_fprintf(stderr, _("%s: running in interactive test mode\n"), get_pname()); fflush(stderr); } qdisk = NULL; dumpdate = NULL; stroptions = NULL; for(; (line = agets(stdin)) != NULL; free(line)) { if (line[0] == '\0') continue; if(interactive) { g_fprintf(stderr, "%s> ", get_pname()); fflush(stderr); } if(strncmp_const(line, "OPTIONS ") == 0) { g_options = parse_g_options(line+8, 1); if(!g_options->hostname) { g_options->hostname = alloc(MAX_HOSTNAME_LENGTH+1); gethostname(g_options->hostname, MAX_HOSTNAME_LENGTH); g_options->hostname[MAX_HOSTNAME_LENGTH] = '\0'; } if (g_options->config) { /* overlay this configuration on the existing (nameless) configuration */ config_init(CONFIG_INIT_CLIENT | CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_OVERLAY, g_options->config); dbrename(get_config_name(), DBG_SUBDIR_CLIENT); } /* check for any config errors now */ if (config_errors(&errlist) >= CFGERR_ERRORS) { char *errstr = config_errors_to_error_string(errlist); g_printf("%s\n", errstr); dbclose(); return 1; } if (am_has_feature(g_options->features, fe_req_xml)) { break; } continue; } if (dle && dle->program != NULL) { err_extra = _("multiple requests"); goto err; } dbprintf(_(" sendbackup req: <%s>\n"), line); dle = alloc_dle(); s = line; ch = *s++; skip_whitespace(s, ch); /* find the program name */ if(ch == '\0') { err_extra = _("no program name"); goto err; /* no program name */ } dle->program = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; if (strcmp(dle->program, "APPLICATION")==0) { dle->program_is_application_api=1; skip_whitespace(s, ch); /* find dumper name */ if (ch == '\0') { goto err; /* no program */ } dle->program = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; } dle->program = stralloc(dle->program); skip_whitespace(s, ch); /* find the disk name */ if(ch == '\0') { err_extra = _("no disk name"); goto err; /* no disk name */ } amfree(qdisk); qdisk = s - 1; ch = *qdisk; skip_quoted_string(s, ch); s[-1] = '\0'; qdisk = stralloc(qdisk); dle->disk = unquote_string(qdisk); skip_whitespace(s, ch); /* find the device or level */ if (ch == '\0') { err_extra = _("bad level"); goto err; } if(!isdigit((int)s[-1])) { amfree(qamdevice); qamdevice = s - 1; ch = *qamdevice; skip_quoted_string(s, ch); s[-1] = '\0'; qamdevice = stralloc(qamdevice); dle->device = unquote_string(qamdevice); skip_whitespace(s, ch); /* find level number */ } else { dle->device = stralloc(dle->disk); qamdevice = stralloc(qdisk); } /* find the level number */ if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) { err_extra = _("bad level"); goto err; /* bad level */ } skip_integer(s, ch); alevel = g_new0(level_t, 1); alevel->level = level; dle->levellist = g_slist_append(dle->levellist, alevel); skip_whitespace(s, ch); /* find the dump date */ if(ch == '\0') { err_extra = _("no dumpdate"); goto err; /* no dumpdate */ } amfree(dumpdate); dumpdate = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; dumpdate = stralloc(dumpdate); skip_whitespace(s, ch); /* find the options keyword */ if(ch == '\0') { err_extra = _("no options"); goto err; /* no options */ } if(strncmp_const_skip(s - 1, "OPTIONS ", s, ch) != 0) { err_extra = _("no OPTIONS keyword"); goto err; /* no options */ } skip_whitespace(s, ch); /* find the options string */ if(ch == '\0') { err_extra = _("bad options string"); goto err; /* no options */ } amfree(stroptions); stroptions = stralloc(s - 1); } amfree(line); if (g_options == NULL) { g_printf(_("ERROR [Missing OPTIONS line in sendbackup input]\n")); error(_("Missing OPTIONS line in sendbackup input\n")); /*NOTREACHED*/ } if (am_has_feature(g_options->features, fe_req_xml)) { char *errmsg = NULL; dle = amxml_parse_node_FILE(stdin, &errmsg); if (errmsg) { err_extra = errmsg; goto err; } if (!dle) { err_extra = _("One DLE required"); goto err; } else if (dle->next) { err_extra = _("Only one DLE allowed"); goto err; } qdisk = quote_string(dle->disk); if (dle->device == NULL) dle->device = stralloc(dle->disk); qamdevice = quote_string(dle->device); dumpdate = stralloc("NODATE"); stroptions = stralloc(""); } else { parse_options(stroptions, dle, g_options->features, 0); } gdle = dle; if (dle->program == NULL || dle->disk == NULL || dle->device == NULL || dle->levellist == NULL || dumpdate == NULL) { err_extra = _("no valid sendbackup request"); goto err; } if (g_slist_length(dle->levellist) != 1) { err_extra = _("Too many level"); goto err; } alevel = (level_t *)dle->levellist->data; level = alevel->level; dbprintf(_(" Parsed request as: program `%s'\n"), dle->program); dbprintf(_(" disk `%s'\n"), qdisk); dbprintf(_(" device `%s'\n"), qamdevice); dbprintf(_(" level %d\n"), level); dbprintf(_(" since %s\n"), dumpdate); dbprintf(_(" options `%s'\n"), stroptions); if (dle->program_is_application_api==1) { /* check that the application_api exist */ } else { for(i = 0; programs[i]; i++) { if (strcmp(programs[i]->name, dle->program) == 0) { break; } } if (programs[i] == NULL) { dbprintf(_("ERROR [%s: unknown program %s]\n"), get_pname(), dle->program); error(_("ERROR [%s: unknown program %s]"), get_pname(), dle->program); /*NOTREACHED*/ } program = programs[i]; } if(!interactive) { datafd = DATA_FD_OFFSET + 0; mesgfd = DATA_FD_OFFSET + 2; indexfd = DATA_FD_OFFSET + 4; } if (!dle->create_index) indexfd = -1; if (dle->auth && amandad_auth) { if(strcasecmp(dle->auth, amandad_auth) != 0) { g_printf(_("ERROR [client configured for auth=%s while server requested '%s']\n"), amandad_auth, dle->auth); exit(-1); } } if (dle->kencrypt) { g_printf("KENCRYPT\n"); } g_printf(_("CONNECT DATA %d MESG %d INDEX %d\n"), DATA_FD_OFFSET, DATA_FD_OFFSET+1, indexfd == -1 ? -1 : DATA_FD_OFFSET+2); g_printf(_("OPTIONS ")); if(am_has_feature(g_options->features, fe_rep_options_features)) { g_printf("features=%s;", our_feature_string); } if(am_has_feature(g_options->features, fe_rep_options_hostname)) { g_printf("hostname=%s;", g_options->hostname); } g_printf("\n"); fflush(stdout); if (freopen("/dev/null", "w", stdout) == NULL) { dbprintf(_("Error redirecting stdout to /dev/null: %s\n"), strerror(errno)); exit(1); } if(interactive) { if((datafd = open("/dev/null", O_RDWR)) < 0) { error(_("ERROR [open of /dev/null for debug data stream: %s]\n"), strerror(errno)); /*NOTREACHED*/ } mesgfd = 2; indexfd = 1; } if(!interactive) { if(datafd == -1 || mesgfd == -1 || (dle->create_index && indexfd == -1)) { dbclose(); exit(1); } } mesgstream = fdopen(mesgfd,"w"); run_client_scripts(EXECUTE_ON_PRE_DLE_BACKUP, g_options, dle, mesgstream); fflush(mesgstream); if (dle->program_is_application_api==1) { guint j; char *cmd=NULL; GPtrArray *argv_ptr; char levelstr[20]; backup_support_option_t *bsu; char *compopt = NULL; char *encryptopt = skip_argument; int compout, dumpout; GSList *scriptlist; script_t *script; time_t cur_dumptime; int result; GPtrArray *errarray; int errfd[2]; FILE *dumperr; /* apply client-side encryption here */ if ( dle->encrypt == ENCRYPT_CUST ) { encpid = pipespawn(dle->clnt_encrypt, STDIN_PIPE, 0, &compout, &datafd, &mesgfd, dle->clnt_encrypt, encryptopt, NULL); dbprintf(_("encrypt: pid %ld: %s\n"), (long)encpid, dle->clnt_encrypt); } else { compout = datafd; encpid = -1; } /* now do the client-side compression */ if(dle->compress == COMP_FAST || dle->compress == COMP_BEST) { compopt = skip_argument; #if defined(COMPRESS_BEST_OPT) && defined(COMPRESS_FAST_OPT) if(dle->compress == COMP_BEST) { compopt = COMPRESS_BEST_OPT; } else { compopt = COMPRESS_FAST_OPT; } #endif comppid = pipespawn(COMPRESS_PATH, STDIN_PIPE, 0, &dumpout, &compout, &mesgfd, COMPRESS_PATH, compopt, NULL); dbprintf(_("gnutar: pid %ld: %s"), (long)comppid, COMPRESS_PATH); if(compopt != skip_argument) { dbprintf(_("pid %ld: %s %s\n"), (long)comppid, COMPRESS_PATH, compopt); } else { dbprintf(_("pid %ld: %s\n"), (long)comppid, COMPRESS_PATH); } } else if (dle->compress == COMP_CUST) { compopt = skip_argument; comppid = pipespawn(dle->compprog, STDIN_PIPE, 0, &dumpout, &compout, &mesgfd, dle->compprog, compopt, NULL); if(compopt != skip_argument) { dbprintf(_("pid %ld: %s %s\n"), (long)comppid, dle->compprog, compopt); } else { dbprintf(_("pid %ld: %s\n"), (long)comppid, dle->compprog); } } else { dumpout = compout; comppid = -1; } cur_dumptime = time(0); bsu = backup_support_option(dle->program, g_options, dle->disk, dle->device, &errarray); if (!bsu) { char *errmsg; char *qerrmsg; guint i; for (i=0; i < errarray->len; i++) { errmsg = g_ptr_array_index(errarray, i); qerrmsg = quote_string(errmsg); fdprintf(mesgfd, _("sendbackup: error [Application '%s': %s]\n"), dle->program, errmsg); dbprintf("aa: %s\n",qerrmsg); amfree(qerrmsg); } if (i == 0) { /* no errarray */ errmsg = vstrallocf(_("Can't execute application '%s'"), dle->program); qerrmsg = quote_string(errmsg); fdprintf(mesgfd, _("sendbackup: error [%s]\n"), errmsg); dbprintf(_("ERROR %s\n"), qerrmsg); amfree(qerrmsg); amfree(errmsg); } return 0; } if (pipe(errfd) < 0) { char *errmsg; char *qerrmsg; errmsg = vstrallocf(_("Application '%s': can't create pipe"), dle->program); qerrmsg = quote_string(errmsg); fdprintf(mesgfd, _("sendbackup: error [%s]\n"), errmsg); dbprintf(_("ERROR %s\n"), qerrmsg); amfree(qerrmsg); amfree(errmsg); return 0; } switch(application_api_pid=fork()) { case 0: argv_ptr = g_ptr_array_new(); cmd = vstralloc(APPLICATION_DIR, "/", dle->program, NULL); g_ptr_array_add(argv_ptr, stralloc(dle->program)); g_ptr_array_add(argv_ptr, stralloc("backup")); if (bsu->message_line == 1) { g_ptr_array_add(argv_ptr, stralloc("--message")); g_ptr_array_add(argv_ptr, stralloc("line")); } if (g_options->config && bsu->config == 1) { g_ptr_array_add(argv_ptr, stralloc("--config")); g_ptr_array_add(argv_ptr, stralloc(g_options->config)); } if (g_options->hostname && bsu->host == 1) { g_ptr_array_add(argv_ptr, stralloc("--host")); g_ptr_array_add(argv_ptr, stralloc(g_options->hostname)); } if (dle->disk && bsu->disk == 1) { g_ptr_array_add(argv_ptr, stralloc("--disk")); g_ptr_array_add(argv_ptr, stralloc(dle->disk)); } g_ptr_array_add(argv_ptr, stralloc("--device")); g_ptr_array_add(argv_ptr, stralloc(dle->device)); if (level <= bsu->max_level) { g_ptr_array_add(argv_ptr, stralloc("--level")); g_snprintf(levelstr,19,"%d",level); g_ptr_array_add(argv_ptr, stralloc(levelstr)); } if (indexfd != -1 && bsu->index_line == 1) { g_ptr_array_add(argv_ptr, stralloc("--index")); g_ptr_array_add(argv_ptr, stralloc("line")); } if (dle->record && bsu->record == 1) { g_ptr_array_add(argv_ptr, stralloc("--record")); } application_property_add_to_argv(argv_ptr, dle, bsu); for (scriptlist = dle->scriptlist; scriptlist != NULL; scriptlist = scriptlist->next) { script = (script_t *)scriptlist->data; if (script->result && script->result->proplist) { property_add_to_argv(argv_ptr, script->result->proplist); } } g_ptr_array_add(argv_ptr, NULL); dbprintf(_("%s: running \"%s\n"), get_pname(), cmd); for (j = 1; j < argv_ptr->len - 1; j++) dbprintf(" %s\n", (char *)g_ptr_array_index(argv_ptr,j)); dbprintf(_("\"\n")); if(dup2(dumpout, 1) == -1) { error(_("Can't dup2: %s"),strerror(errno)); /*NOTREACHED*/ } if (dup2(errfd[1], 2) == -1) { error(_("Can't dup2: %s"),strerror(errno)); /*NOTREACHED*/ } if(dup2(mesgfd, 3) == -1) { error(_("Can't dup2: %s"),strerror(errno)); /*NOTREACHED*/ } if(indexfd > 0) { if(dup2(indexfd, 4) == -1) { error(_("Can't dup2: %s"),strerror(errno)); /*NOTREACHED*/ } fcntl(indexfd, F_SETFD, 0); } application_api_info_tapeheader(mesgfd, dle->program, dle); if (indexfd != 0) { safe_fd(3, 2); } else { safe_fd(3, 1); } execve(cmd, (char **)argv_ptr->pdata, safe_env()); exit(1); break; default: break; case -1: error(_("%s: fork returned: %s"), get_pname(), strerror(errno)); } close(errfd[1]); dumperr = fdopen(errfd[0],"r"); if (!dumperr) { error(_("Can't fdopen: %s"), strerror(errno)); /*NOTREACHED*/ } result = 0; while ((line = agets(dumperr)) != NULL) { if (strlen(line) > 0) { fdprintf(mesgfd, "sendbackup: error [%s]\n", line); dbprintf("error: %s\n", line); result = 1; } amfree(line); } result |= check_result(mesgfd); if (result == 0) { char *amandates_file; amandates_file = getconf_str(CNF_AMANDATES); if(start_amandates(amandates_file, 1)) { amandates_updateone(dle->disk, level, cur_dumptime); finish_amandates(); free_amandates(); } else { if (GPOINTER_TO_INT(dle->estimatelist->data) == ES_CALCSIZE && bsu->calcsize) { error(_("error [opening %s for writing: %s]"), amandates_file, strerror(errno)); } else { g_debug(_("non-fatal error opening '%s' for writing: %s]"), amandates_file, strerror(errno)); } } } amfree(bsu); } else { if(!interactive) { /* redirect stderr */ if(dup2(mesgfd, 2) == -1) { dbprintf(_("Error redirecting stderr to fd %d: %s\n"), mesgfd, strerror(errno)); dbclose(); exit(1); } } if(pipe(mesgpipe) == -1) { s = strerror(errno); dbprintf(_("error [opening mesg pipe: %s]\n"), s); error(_("error [opening mesg pipe: %s]"), s); } program->start_backup(dle, g_options->hostname, datafd, mesgpipe[1], indexfd); dbprintf(_("Started backup\n")); parse_backup_messages(dle, mesgpipe[0]); dbprintf(_("Parsed backup messages\n")); } run_client_scripts(EXECUTE_ON_POST_DLE_BACKUP, g_options, dle, mesgstream); fflush(mesgstream); amfree(qdisk); amfree(qamdevice); amfree(dumpdate); amfree(stroptions); amfree(our_feature_string); am_release_feature_set(our_features); our_features = NULL; free_g_options(g_options); dbclose(); return 0; err: if (err_extra) { g_printf(_("ERROR FORMAT ERROR IN REQUEST PACKET '%s'\n"), err_extra); dbprintf(_("REQ packet is bogus: %s\n"), err_extra); } else { g_printf(_("ERROR FORMAT ERROR IN REQUEST PACKET\n")); dbprintf(_("REQ packet is bogus\n")); } amfree(qdisk); amfree(qamdevice); amfree(dumpdate); amfree(stroptions); amfree(our_feature_string); dbclose(); return 1; }
int main( int argc, char ** argv) { char *line = NULL; char *qdisk = NULL; char *qamdevice = NULL; char *optstr = NULL; char *err_extra = NULL; char *s, *fp; int ch; dle_t *dle = NULL; int level; GSList *errlist; level_t *alevel; if (argc > 1 && argv && argv[1] && g_str_equal(argv[1], "--version")) { printf("selfcheck-%s\n", VERSION); return (0); } /* initialize */ /* * Configure program for internationalization: * 1) Only set the message locale for now. * 2) Set textdomain for all amanda related programs to "amanda" * We don't want to be forced to support dozens of message catalogs. */ setlocale(LC_MESSAGES, "C"); textdomain("amanda"); safe_fd(-1, 0); openbsd_fd_inform(); safe_cd(); set_pname("selfcheck"); /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); add_amanda_log_handler(amanda_log_stderr); add_amanda_log_handler(amanda_log_syslog); dbopen(DBG_SUBDIR_CLIENT); startclock(); dbprintf(_("version %s\n"), VERSION); g_printf("OK version %s\n", VERSION); print_platform(); if(argc > 2 && g_str_equal(argv[1], "amandad")) { amandad_auth = g_strdup(argv[2]); } config_init(CONFIG_INIT_CLIENT, NULL); /* (check for config errors comes later) */ check_running_as(RUNNING_AS_CLIENT_LOGIN); our_features = am_init_feature_set(); our_feature_string = am_feature_to_string(our_features); /* handle all service requests */ /*@ignore@*/ for(; (line = agets(stdin)) != NULL; free(line)) { /*@end@*/ if (line[0] == '\0') continue; if(strncmp_const(line, "OPTIONS ") == 0) { if (g_options) { g_printf(_("ERROR [Multiple OPTIONS line in selfcheck input]\n")); error(_("Multiple OPTIONS line in selfcheck input\n")); /*NOTREACHED*/ } g_options = parse_g_options(line+8, 1); if(!g_options->hostname) { g_options->hostname = g_malloc(MAX_HOSTNAME_LENGTH+1); gethostname(g_options->hostname, MAX_HOSTNAME_LENGTH); g_options->hostname[MAX_HOSTNAME_LENGTH] = '\0'; } g_printf("OPTIONS "); if(am_has_feature(g_options->features, fe_rep_options_features)) { g_printf("features=%s;", our_feature_string); } if(am_has_feature(g_options->features, fe_rep_options_hostname)) { g_printf("hostname=%s;", g_options->hostname); } g_printf("\n"); fflush(stdout); if (g_options->config) { /* overlay this configuration on the existing (nameless) configuration */ config_init(CONFIG_INIT_CLIENT | CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_OVERLAY, g_options->config); dbrename(get_config_name(), DBG_SUBDIR_CLIENT); } /* check for any config errors now */ if (config_errors(&errlist) >= CFGERR_ERRORS) { char *errstr = config_errors_to_error_string(errlist); g_printf("%s\n", errstr); amfree(errstr); amfree(line); dbclose(); return 1; } if (am_has_feature(g_options->features, fe_req_xml)) { break; } continue; } dle = alloc_dle(); s = line; ch = *s++; skip_whitespace(s, ch); /* find program name */ if (ch == '\0') { goto err; /* no program */ } dle->program = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; /* terminate the program name */ dle->program_is_application_api = 0; if(g_str_equal(dle->program, "APPLICATION")) { dle->program_is_application_api = 1; skip_whitespace(s, ch); /* find dumper name */ if (ch == '\0') { goto err; /* no program */ } dle->program = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; /* terminate the program name */ } if(strncmp_const(dle->program, "CALCSIZE") == 0) { skip_whitespace(s, ch); /* find program name */ if (ch == '\0') { goto err; /* no program */ } dle->program = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; dle->estimatelist = g_slist_append(dle->estimatelist, GINT_TO_POINTER(ES_CALCSIZE)); } else { dle->estimatelist = g_slist_append(dle->estimatelist, GINT_TO_POINTER(ES_CLIENT)); } skip_whitespace(s, ch); /* find disk name */ if (ch == '\0') { goto err; /* no disk */ } qdisk = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; /* terminate the disk name */ dle->disk = unquote_string(qdisk); skip_whitespace(s, ch); /* find the device or level */ if (ch == '\0') { goto err; /* no device or level */ } if(!isdigit((int)s[-1])) { fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; /* terminate the device */ qamdevice = g_strdup(fp); dle->device = unquote_string(qamdevice); skip_whitespace(s, ch); /* find level number */ } else { dle->device = g_strdup(dle->disk); qamdevice = g_strdup(qdisk); } amfree(qamdevice); /* find level number */ if (ch == '\0' || sscanf(s - 1, "%d", &level) != 1) { goto err; /* bad level */ } alevel = g_new0(level_t, 1); alevel->level = level; dle->levellist = g_slist_append(dle->levellist, alevel); skip_integer(s, ch); skip_whitespace(s, ch); if (ch && strncmp_const_skip(s - 1, "OPTIONS ", s, ch) == 0) { skip_whitespace(s, ch); /* find the option string */ if(ch == '\0') { goto err; /* bad options string */ } optstr = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; /* terminate the options */ parse_options(optstr, dle, g_options->features, 1); /*@ignore@*/ check_options(dle); check_disk(dle); /*@end@*/ } else if (ch == '\0') { /* check all since no option */ need_samba=1; need_rundump=1; need_dump=1; need_restore=1; need_vdump=1; need_vrestore=1; need_xfsdump=1; need_xfsrestore=1; need_vxdump=1; need_vxrestore=1; need_runtar=1; need_gnutar=1; need_compress_path=1; need_calcsize=1; need_global_check=1; /*@ignore@*/ check_disk(dle); /*@end@*/ } else { goto err; /* bad syntax */ } free_dle(dle); dle = NULL; } if (g_options == NULL) { g_printf(_("ERROR [Missing OPTIONS line in selfcheck input]\n")); error(_("Missing OPTIONS line in selfcheck input\n")); /*NOTREACHED*/ } if (am_has_feature(g_options->features, fe_req_xml)) { char *errmsg = NULL; dle_t *dles, *dle, *dle_next; dles = amxml_parse_node_FILE(stdin, &errmsg); if (errmsg) { err_extra = errmsg; goto err; } if (merge_dles_properties(dles, 1) == 0) { goto checkoverall; } for (dle = dles; dle != NULL; dle = dle->next) { run_client_scripts(EXECUTE_ON_PRE_HOST_AMCHECK, g_options, dle, stdout); } for (dle = dles; dle != NULL; dle = dle->next) { check_options(dle); run_client_scripts(EXECUTE_ON_PRE_DLE_AMCHECK, g_options, dle, stdout); check_disk(dle); run_client_scripts(EXECUTE_ON_POST_DLE_AMCHECK, g_options, dle, stdout); } for (dle = dles; dle != NULL; dle = dle->next) { run_client_scripts(EXECUTE_ON_POST_HOST_AMCHECK, g_options, dle, stdout); } for (dle = dles; dle != NULL; dle = dle_next) { dle_next = dle->next; free_dle(dle); } } checkoverall: check_overall(); amfree(line); amfree(our_feature_string); am_release_feature_set(our_features); our_features = NULL; free_g_options(g_options); dbclose(); return 0; err: if (err_extra) { g_printf(_("ERROR [FORMAT ERROR IN REQUEST PACKET %s]\n"), err_extra); dbprintf(_("REQ packet is bogus: %s\n"), err_extra); } else { g_printf(_("ERROR [FORMAT ERROR IN REQUEST PACKET]\n")); dbprintf(_("REQ packet is bogus\n")); } amfree(err_extra); amfree(line); if (dle) free_dle(dle); dbclose(); return 1; }