Exemple #1
0
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);
}
Exemple #2
0
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;
}
Exemple #3
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;
}
Exemple #4
0
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;
}
Exemple #5
0
/* 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;
}
Exemple #6
0
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;
}
Exemple #7
0
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;
}
Exemple #8
0
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;
}