Пример #1
0
static int
delete_txinfofile(
    char *	host,
    char *	disk)
{
    char *fn = NULL, *fn_new = NULL;
    int rc;
    char *myhost;
    char *mydisk;

    myhost = sanitise_filename(host);
    mydisk = sanitise_filename(disk);
    fn = vstralloc(infodir,
		   "/", myhost,
		   "/", mydisk,
		   "/info",
		   NULL);
    fn_new = stralloc2(fn, ".new");

    amfree(myhost);
    amfree(mydisk);

    unlink(fn_new);
    amfree(fn_new);

    rc = rmpdir(fn, infodir);
    amfree(fn);

    return rc;
}
Пример #2
0
/* sets a date, mapping given date into standard form if needed */
int
set_date(
    char *	date)
{
    char *cmd = NULL;

    clear_dir_list();

    cmd = stralloc2("DATE ", date);
    if (converse(cmd) == -1)
	exit(1);

    /* if a host/disk/directory is set, then check if that directory
       is still valid at the new date, and if not set directory to
       mount_point */
    if (disk_path != NULL) {
	cmd = newstralloc2(cmd, "OISD ", disk_path);
	if (exchange(cmd) == -1)
	    exit(1);
	if (server_happy())
	{
	    suck_dir_list_from_server();
	}
	else
	{
	    g_printf(_("No index records for cwd on new date\n"));
	    g_printf(_("Setting cwd to mount point\n"));
	    disk_path = newstralloc(disk_path, "/");	/* fake it */
	    clear_dir_list();
	}
    }
    amfree(cmd);
    return 0;
}
Пример #3
0
/* A GHFunc (callback for g_hash_table_foreach) */
void proplist_add_to_argv(
    gpointer key_p,
    gpointer value_p,
    gpointer user_data_p)
{
    char         *property_s = key_p;
    property_t   *value_s = value_p;
    GPtrArray    *argv_ptr = user_data_p;
    GSList       *value;
    char         *q, *w, *qprop;

    q = stralloc(property_s);
    /* convert to lower case */
    for (w=q; *w != '\0'; w++) {
	*w = tolower(*w);
	if (*w == '_')
	    *w = '-';
    }
    qprop = stralloc2("--", q);
    amfree(q);
    for(value=value_s->values; value != NULL; value = value->next) {
	g_ptr_array_add(argv_ptr, stralloc(qprop));
	g_ptr_array_add(argv_ptr, stralloc((char *)value->data));
    }
    amfree(qprop);
}
Пример #4
0
int
cd_glob(
    char *	glob,
    int		verbose)
{
    char *regex;
    char *regex_path;
    char *s;
    char *uqglob;
    int   result;

    char *path_on_disk = NULL;

    if (disk_name == NULL) {
	g_printf(_("Must select disk before changing directory\n"));
	return 0;
    }

    uqglob = unquote_string(glob);
    regex = glob_to_regex(uqglob);
    dbprintf(_("cd_glob (%s) -> %s\n"), uqglob, regex);
    if ((s = validate_regexp(regex)) != NULL) {
        g_printf(_("\"%s\" is not a valid shell wildcard pattern: "), glob);
        puts(s);
	amfree(regex);
	amfree(uqglob);
        return 0;
    }
    /*
     * glob_to_regex() anchors the beginning of the pattern with ^,
     * but we will be tacking it onto the end of the current directory
     * in add_file, so strip that off.  Also, it anchors the end with
     * $, but we need to match a trailing /, add it if it is not there
     */
    regex_path = stralloc(regex + 1);
    amfree(regex);
    if(regex_path[strlen(regex_path) - 2] != '/' ) {
	regex_path[strlen(regex_path) - 1] = '\0';
	strappend(regex_path, "/$");
    }

    /* convert path (assumed in cwd) to one on disk */
    if (strcmp(disk_path, "/") == 0)
        path_on_disk = stralloc2("/", regex_path);
    else {
        char *clean_disk_path = clean_regex(disk_path, 0);
        path_on_disk = vstralloc(clean_disk_path, "/", regex_path, NULL);
        amfree(clean_disk_path);
    }

    result = cd_dir(path_on_disk, uqglob, verbose);

    amfree(regex_path);
    amfree(path_on_disk);
    amfree(uqglob);

    return result;
}
Пример #5
0
int
cd_regex(
    char *	regex,
    int		verbose)
{
    char *s;
    char *uq_orig_regex;
    char *uqregex;
    int  len_uqregex;
    int  result;

    char *path_on_disk = NULL;

    if (disk_name == NULL) {
	g_printf(_("Must select disk before changing directory\n"));
	return 0;
    }

    uq_orig_regex = unquote_string(regex);
    uqregex = stralloc(uq_orig_regex);

    /* Add a terminating '/' if it is not there, maybe before a '$' */
    len_uqregex = strlen(uqregex);
    if (uqregex[len_uqregex-1] == '$') {
	if (uqregex[len_uqregex-2] != '/') {
	    uqregex[len_uqregex-1] = '\0';
	    strappend(uqregex, "/$");
	}
    } else if (uqregex[len_uqregex-1] != '/') {
	//uqregex[len_uqregex-1] = '\0';
	strappend(uqregex, "/");
    }
    if ((s = validate_regexp(uqregex)) != NULL) {
	g_printf(_("\"%s\" is not a valid regular expression: "), uq_orig_regex);
	amfree(uqregex);
	amfree(uq_orig_regex);
	puts(s);
	return 0;
    }

    /* convert path (assumed in cwd) to one on disk */
    if (strcmp(disk_path, "/") == 0)
        path_on_disk = stralloc2("/", uqregex);
    else {
        char *clean_disk_path = clean_regex(disk_path, 0);
        path_on_disk = vstralloc(clean_disk_path, "/", regex, NULL);
        amfree(clean_disk_path);
    }

    result = cd_dir(path_on_disk, uq_orig_regex, verbose);

    amfree(path_on_disk);
    amfree(uqregex);
    amfree(uq_orig_regex);

    return result;
}
Пример #6
0
void
cd_dir(
    char *	path_on_disk,
    char *	default_dir)
{
    char *path_on_disk_slash = NULL;
    char *dir = NULL;

    int nb_found;
    size_t i;

    DIR_ITEM *ditem;

    path_on_disk_slash = stralloc2(path_on_disk, "/");

    nb_found = 0;

    for (ditem=get_dir_list(); ditem!=NULL && nb_found <= 1; 
			       ditem=get_next_dir_item(ditem))
    {
	if (match(path_on_disk, ditem->path)
	    || match(path_on_disk_slash, ditem->path))
	{
	    i = strlen(ditem->path);
	    if((i > 0 && ditem->path[i-1] == '/')
               || (i > 1 && ditem->path[i-2] == '/' && ditem->path[i-1] == '.'))
            {   /* It is a directory */
		char *dir1, *dir2;
		nb_found++;
		dir = newstralloc(dir,ditem->path);
		if(dir[strlen(dir)-1] == '/')
		    dir[strlen(dir)-1] = '\0'; /* remove last / */
		/* remove everything before the last / */
		dir1 = strrchr(dir,'/');
		if (dir1) {
		    dir1++;
		    dir2 = stralloc(dir1);
		    amfree(dir);
		    dir = dir2;
		}
	    }
	}
    }
    amfree(path_on_disk_slash);

    if(nb_found==0) {
	set_directory(default_dir);
    }
    else if(nb_found==1) {
	set_directory(dir);
    }
    else {
	g_printf(_("Too many directory\n"));
    }
    amfree(dir);
}
Пример #7
0
static FILE *
open_txinfofile(
    char *	host,
    char *	disk,
    char *	mode)
{
    FILE *infof;
    char *myhost;
    char *mydisk;

    assert(infofile == (char *)0);

    writing = (*mode == 'w');

    myhost = sanitise_filename(host);
    mydisk = sanitise_filename(disk);

    infofile = vstralloc(infodir,
			 "/", myhost,
			 "/", mydisk,
			 "/info",
			 NULL);

    amfree(myhost);
    amfree(mydisk);

    /* create the directory structure if in write mode */
    if (writing) {
        if (mkpdir(infofile, 0755, (uid_t)-1, (gid_t)-1) == -1) {
	    amfree(infofile);
	    return NULL;
	}
    }

    newinfofile = stralloc2(infofile, ".new");

    if(writing) {
	infof = fopen(newinfofile, mode);
	if(infof != NULL)
	    amflock(fileno(infof), "info");
    }
    else {
	infof = fopen(infofile, mode);
	/* no need to lock readers */
    }

    if(infof == (FILE *)0) {
	amfree(infofile);
	amfree(newinfofile);
	return NULL;
    }

    return infof;
}
Пример #8
0
char *
get_security(void)
{
    struct passwd *pwptr;

    if((pwptr = getpwuid(getuid())) == NULL) {
	error(_("can't get login name for my uid %ld"), (long)getuid());
	/*NOTREACHED*/
    }
    return stralloc2("SECURITY USER ", pwptr->pw_name);
}
Пример #9
0
static int
ln_lock(
    char *	res, /* name of resource to lock */
    int		op)  /* true to lock; false to unlock */
{
    long mypid;
    char *lockfile = NULL;
    char *tlockfile = NULL;
    char *mres = NULL;
    int rc;
    char pid_str[NUM_STR_SIZE];

    mypid = (long)getpid();

    lockfile = g_strjoin(NULL, _lnlock_dir, "/am", res, ".lock", NULL);

    if (!op) {
        /* unlock the resource */
        assert(read_lock(lockfile) == mypid);

        (void)delete_lock(lockfile);
        amfree(lockfile);
        return 0;
    }

    /* lock the resource */

    g_snprintf(pid_str, sizeof(pid_str), "%ld", mypid);
    tlockfile = g_strjoin(NULL, _lnlock_dir, "/am", res, ".", pid_str, NULL);

    (void)create_lock(tlockfile, mypid);

    mres = stralloc2(res, ".");

    while(1) {
        rc = link_lock(lockfile, tlockfile);
        if (rc == -1) break;
        if (rc == 0) break;

        rc = steal_lock(lockfile, mypid, mres);
        if (rc == -1) break;
        if (rc == 0) continue;
        sleep(1);
    }

    (void) delete_lock(tlockfile);

    amfree(mres);
    amfree(tlockfile);
    amfree(lockfile);

    return rc;
}
Пример #10
0
void
startup_dump_processes(
    char *dumper_program,
    int inparallel,
    char *timestamp)
{
    int i;
    dumper_t *dumper;
    char number[NUM_STR_SIZE];

    for(dumper = dmptable, i = 0; i < inparallel; dumper++, i++) {
	g_snprintf(number, SIZEOF(number), "%d", i);
	dumper->name = stralloc2("dumper", number);
	dumper->chunker = &chktable[i];
	chktable[i].name = stralloc2("chunker", number);
	chktable[i].dumper = dumper;
	chktable[i].fd = -1;

	startup_dump_process(dumper, dumper_program);
	dumper_cmd(dumper, START, NULL, (void *)timestamp);
    }
}
Пример #11
0
static void
update_tapelist(
    taper_state_t *state)
{
    char *tapelist_name = NULL;
    char *tapelist_name_old = NULL;
    tape_t *tp;
    char *comment = NULL;

    tapelist_name = config_dir_relative(getconf_str(CNF_TAPELIST));
    if (state->cur_tape == 0) {
	tapelist_name_old = stralloc2(tapelist_name, ".yesterday");
    } else {
	char cur_str[NUM_STR_SIZE];
	g_snprintf(cur_str, SIZEOF(cur_str), "%d", state->cur_tape - 1);
	tapelist_name_old = vstralloc(tapelist_name,
				      ".today.", cur_str, NULL);
    }

   if (read_tapelist(tapelist_name) != 0) {
        log_add(L_INFO, "pid-done %ld", (long)getpid());
        error("could not load tapelist \"%s\"", tapelist_name);
        /*NOTREACHED*/
    }

    /* make a copy of the tapelist file */
    if (write_tapelist(tapelist_name_old)) {
        log_add(L_INFO, "pid-done %ld", (long)getpid());
	error("could not write tapelist: %s", strerror(errno));
	/*NOTREACHED*/
    }
    amfree(tapelist_name_old);

    /* get a copy of the comment, before freeing the old record */
    tp = lookup_tapelabel(state->device->volume_label);
    if (tp && tp->comment)
	comment = stralloc(tp->comment);

    /* edit the tapelist and rewrite it */
    remove_tapelabel(state->device->volume_label);
    add_tapelabel(state->driver_start_time,
                  state->device->volume_label,
		  comment);
    if (write_tapelist(tapelist_name)) {
	error("could not write tapelist: %s", strerror(errno));
	/*NOTREACHED*/
    }
    amfree(tapelist_name);
    amfree(comment);
}
Пример #12
0
void
list_disk(
    char *	amdevice)
{
    char *cmd = NULL;
    char *uqamdevice;

    if(amdevice) {
	uqamdevice = unquote_string(amdevice);
	cmd = stralloc2("LISTDISK ", uqamdevice);
	amfree(uqamdevice);
	if (converse(cmd) == -1)
	    exit(1);
	amfree(cmd);
    }
    else {
	cmd = stralloc("LISTDISK");
	if (converse(cmd) == -1)
	    exit(1);
	amfree(cmd);
    }
}
Пример #13
0
void
cd_regex(
    char *	regex)
{
    char *s;
    char *uqregex;

    char *path_on_disk = NULL;

    if (disk_name == NULL) {
	g_printf(_("Must select disk before changing directory\n"));
	return;
    }

    uqregex = unquote_string(regex);
    if ((s = validate_regexp(uqregex)) != NULL) {
	g_printf(_("\"%s\" is not a valid regular expression: "), uqregex);
	amfree(uqregex);
	puts(s);
	return;
    }

    /* convert path (assumed in cwd) to one on disk */
    if (strcmp(disk_path, "/") == 0)
        path_on_disk = stralloc2("/", regex);
    else {
        char *clean_disk_path = clean_regex(disk_path);
        path_on_disk = vstralloc(clean_disk_path, "/", regex, NULL);
        amfree(clean_disk_path);
    }

    cd_dir(path_on_disk, uqregex);

    amfree(path_on_disk);
    amfree(uqregex);
}
Пример #14
0
/*
 *  doing similar to $ gtar | compression | encryption 
 */
static void
start_backup(
    dle_t      *dle,
    char       *host,
    int		dataf,
    int		mesgf,
    int		indexf)
{
    char tmppath[PATH_MAX];
    int dumpin, dumpout, compout;
    char *cmd = NULL;
    char *indexcmd = NULL;
    char *dirname = NULL;
    int l;
    char dumptimestr[80] = "UNUSED";
    struct tm *gmtm;
    amandates_t *amdates = NULL;
    time_t prev_dumptime = 0;
    char *error_pn = NULL;
    char *compopt  = NULL;
    char *encryptopt = skip_argument;
    char *tquoted;
    char *fquoted;
    char *qdisk;
    int infd, outfd;
    ssize_t nb;
    char buf[32768];
    char *amandates_file = NULL;
    level_t *alevel = (level_t *)dle->levellist->data;
    int      level  = alevel->level;

    error_pn = stralloc2(get_pname(), "-smbclient");

    qdisk = quote_string(dle->disk);
    dbprintf(_("start: %s:%s lev %d\n"), host, qdisk, level);

    g_fprintf(stderr, _("%s: start [%s:%s level %d]\n"),
	    get_pname(), host, qdisk, level);

     /*  apply client-side encryption here */
     if ( dle->encrypt == ENCRYPT_CUST ) {
         encpid = pipespawn(dle->clnt_encrypt, STDIN_PIPE, 0, 
			&compout, &dataf, &mesgf, 
			dle->clnt_encrypt, encryptopt, NULL);
         dbprintf(_("gnutar: pid %ld: %s\n"), (long)encpid, dle->clnt_encrypt);
    } else {
       compout = dataf;
       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, &mesgf,
			    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, &mesgf,
			    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;
    }

    gnutar_list_dir = getconf_str(CNF_GNUTAR_LIST_DIR);
    if (strlen(gnutar_list_dir) == 0)
	gnutar_list_dir = NULL;

#ifdef SAMBA_CLIENT							/* { */
    if (dle->device[0] == '/' && dle->device[1]=='/')
	amfree(incrname);
    else
#endif									/* } */
    if (gnutar_list_dir) {
	char *basename = NULL;
	char number[NUM_STR_SIZE];
	char *inputname = NULL;
	int baselevel;
	char *sdisk = sanitise_filename(dle->disk);

	basename = g_strjoin(NULL, gnutar_list_dir,
			     "/",
			     host,
			     sdisk,
			     NULL);
	amfree(sdisk);

	g_snprintf(number, sizeof(number), "%d", level);
	incrname = g_strjoin(NULL, basename, "_", number, ".new", NULL);
	unlink(incrname);

	/*
	 * Open the listed incremental file from the previous level.  Search
	 * backward until one is found.  If none are found (which will also
	 * be true for a level 0), arrange to read from /dev/null.
	 */
	baselevel = level;
	infd = -1;
	while (infd == -1) {
	    if (--baselevel >= 0) {
		g_snprintf(number, sizeof(number), "%d", baselevel);
		inputname = newvstralloc(inputname,
					 basename, "_", number, NULL);
	    } else {
		inputname = newstralloc(inputname, "/dev/null");
	    }
	    if ((infd = open(inputname, O_RDONLY)) == -1) {
		int save_errno = errno;
		char *qname = quote_string(inputname);

		dbprintf(_("gnutar: error opening '%s': %s\n"),
			  qname,
			  strerror(save_errno));
		if (baselevel < 0) {
		    error(_("error [opening '%s': %s]"), qname, strerror(save_errno));
		    /*NOTREACHED*/
		}
		amfree(qname);
	    }
	}

	/*
	 * Copy the previous listed incremental file to the new one.
	 */
	if ((outfd = open(incrname, O_WRONLY|O_CREAT, 0600)) == -1) {
	    error(_("error [opening '%s': %s]"), incrname, strerror(errno));
	    /*NOTREACHED*/
	}

	while ((nb = read(infd, &buf, sizeof(buf))) > 0) {
	    if (full_write(outfd, &buf, (size_t)nb) < (size_t)nb) {
		error(_("error [writing to '%s': %s]"), incrname,
		       strerror(errno));
		/*NOTREACHED*/
	    }
	}

	if (nb < 0) {
	    error(_("error [reading from '%s': %s]"), inputname, strerror(errno));
	    /*NOTREACHED*/
	}

	if (close(infd) != 0) {
	    error(_("error [closing '%s': %s]"), inputname, strerror(errno));
	    /*NOTREACHED*/
	}
	if (close(outfd) != 0) {
	    error(_("error [closing '%s': %s]"), incrname, strerror(errno));
	    /*NOTREACHED*/
	}

	tquoted = quote_string(incrname);
	if(baselevel >= 0) {
	    fquoted = quote_string(inputname);
	    dbprintf(_("doing level %d dump as listed-incremental from '%s' to '%s'\n"),
		     level, fquoted, tquoted);
	    amfree(fquoted);
	} else {
	    dbprintf(_("doing level %d dump as listed-incremental to '%s'\n"),
		     level, tquoted);
	}
	amfree(tquoted);
	amfree(inputname);
	amfree(basename);
    } else {
	/* no gnutar-listdir, so we're using amandates */

	/* find previous dump time, failing completely if there's a problem */
	amandates_file = getconf_str(CNF_AMANDATES);
	if(!start_amandates(amandates_file, 0)) {
	    error(_("error [opening %s: %s]"), amandates_file, strerror(errno));
	    /*NOTREACHED*/
	}

	amdates = amandates_lookup(dle->disk);

	prev_dumptime = EPOCH;
	for(l = 0; l < level; l++) {
	    if(amdates->dates[l] > prev_dumptime)
		prev_dumptime = amdates->dates[l];
	}

	finish_amandates();
	free_amandates();

	gmtm = gmtime(&prev_dumptime);
	g_snprintf(dumptimestr, sizeof(dumptimestr),
		    "%04d-%02d-%02d %2d:%02d:%02d GMT",
		    gmtm->tm_year + 1900, gmtm->tm_mon+1, gmtm->tm_mday,
		    gmtm->tm_hour, gmtm->tm_min, gmtm->tm_sec);

	dbprintf(_("gnutar: doing level %d dump from amandates-derived date: %s\n"),
		  level, dumptimestr);
    }

    dirname = amname_to_dirname(dle->device);

    cur_dumptime = time(0);
    cur_level = level;
    cur_disk = g_strdup(dle->disk);
#ifdef GNUTAR
#  define PROGRAM_GNUTAR GNUTAR
#else
#  define PROGRAM_GNUTAR "tar"
#endif
    indexcmd = g_strjoin(NULL, 
			 PROGRAM_GNUTAR,
			 " -tf", " -",
			 " 2>/dev/null",
			 " | sed", " -e",
			 " \'s/^\\.//\'",
			 NULL);

#ifdef SAMBA_CLIENT							/* { */
    /* Use sambatar if the disk to back up is a PC disk */
    if (dle->device[0] == '/' && dle->device[1]=='/') {
	char *sharename = NULL, *user_and_password = NULL, *domain = NULL;
	char *share = NULL, *subdir = NULL;
	char *pwtext = NULL;
	char *taropt;
	int passwdf = -1;
	size_t lpass;
	size_t pwtext_len;
	char *pw_fd_env;

	parsesharename(dle->device, &share, &subdir);
	if (!share) {
	    amfree(share);
	    amfree(subdir);
	    set_pname(error_pn);
	    amfree(error_pn);
	    error(_("cannot parse disk entry %s for share/subdir"), qdisk);
	    /*NOTREACHED*/
	}
	if ((subdir) && (SAMBA_VERSION < 2)) {
	    amfree(share);
	    amfree(subdir);
	    set_pname(error_pn);
	    amfree(error_pn);
	    error(_("subdirectory specified for share %s but samba not v2 or better"), qdisk);
	    /*NOTREACHED*/
	}
	if ((user_and_password = findpass(share, &domain)) == NULL) {
	    if(domain) {
		memset(domain, '\0', strlen(domain));
		amfree(domain);
	    }
	    set_pname(error_pn);
	    amfree(error_pn);
	    error(_("error [invalid samba host or password not found?]"));
	    /*NOTREACHED*/
	}
	lpass = strlen(user_and_password);
	if ((pwtext = strchr(user_and_password, '%')) == NULL) {
	    memset(user_and_password, '\0', lpass);
	    amfree(user_and_password);
	    if(domain) {
		memset(domain, '\0', strlen(domain));
		amfree(domain);
	    }
	    set_pname(error_pn);
	    amfree(error_pn);
	    error(_("password field not \'user%%pass\' for %s"), qdisk);
	    /*NOTREACHED*/
	}
	*pwtext++ = '\0';
	pwtext_len = strlen(pwtext);
	if ((sharename = makesharename(share, 0)) == 0) {
	    memset(user_and_password, '\0', lpass);
	    amfree(user_and_password);
	    if(domain) {
		memset(domain, '\0', strlen(domain));
		amfree(domain);
	    }
	    set_pname(error_pn);
	    amfree(error_pn);
	    error(_("error [can't make share name of %s]"), share);
	    /*NOTREACHED*/
	}

	taropt = g_strdup("-T");
	if(dle->exclude_file && dle->exclude_file->nb_element == 1) {
	    strappend(taropt, "X");
	}
#if SAMBA_VERSION >= 2
	strappend(taropt, "q");
#endif
	strappend(taropt, "c");
	if (level != 0) {
	    strappend(taropt, "g");
	} else if (dle->record) {
	    strappend(taropt, "a");
	}

	if (subdir) {
	    dbprintf(_("gnutar: backup of %s/%s\n"), sharename, subdir);
	} else {
	    dbprintf(_("gnutar: backup of %s\n"), sharename);
	}

	program->backup_name = program->restore_name = SAMBA_CLIENT;
	cmd = g_strdup(program->backup_name);
	info_tapeheader(dle);

	start_index(dle->create_index, dumpout, mesgf, indexf, indexcmd);

	if (pwtext_len > 0) {
	    pw_fd_env = "PASSWD_FD";
	} else {
	    pw_fd_env = "dummy_PASSWD_FD";
	}
	dumppid = pipespawn(cmd, STDIN_PIPE|PASSWD_PIPE, 0,
			    &dumpin, &dumpout, &mesgf,
			    pw_fd_env, &passwdf,
			    "smbclient",
			    sharename,
			    *user_and_password ? "-U" : skip_argument,
			    *user_and_password ? user_and_password : skip_argument,
			    "-E",
			    domain ? "-W" : skip_argument,
			    domain ? domain : skip_argument,
#if SAMBA_VERSION >= 2
			    subdir ? "-D" : skip_argument,
			    subdir ? subdir : skip_argument,
#endif
			    "-d0",
			    taropt,
			    "-",
			    dle->exclude_file && dle->exclude_file->nb_element == 1 ? dle->exclude_file->first->name : skip_argument,
			    NULL);
	if(domain) {
	    memset(domain, '\0', strlen(domain));
	    amfree(domain);
	}
	if(pwtext_len > 0 && full_write(passwdf, pwtext, pwtext_len) < pwtext_len) {
	    int save_errno = errno;

	    aclose(passwdf);
	    memset(user_and_password, '\0', lpass);
	    amfree(user_and_password);
	    set_pname(error_pn);
	    amfree(error_pn);
	    error(_("error [password write failed: %s]"), strerror(save_errno));
	    /*NOTREACHED*/
	}
	memset(user_and_password, '\0', lpass);
	amfree(user_and_password);
	aclose(passwdf);
	amfree(sharename);
	amfree(share);
	amfree(subdir);
	amfree(taropt);
	tarpid = dumppid;
    } else
#endif			/*end of samba */
    {

	int nb_exclude = 0;
	int nb_include = 0;
	GPtrArray *argv_ptr = g_ptr_array_new();
	char *file_exclude = NULL;
	char *file_include = NULL;

	if (dle->exclude_file) nb_exclude+=dle->exclude_file->nb_element;
	if (dle->exclude_list) nb_exclude+=dle->exclude_list->nb_element;
	if (dle->include_file) nb_include+=dle->include_file->nb_element;
	if (dle->include_list) nb_include+=dle->include_list->nb_element;

	if (nb_exclude > 0) file_exclude = build_exclude(dle, 0);
	if (nb_include > 0) file_include = build_include(dle, 0);

	cmd = g_strjoin(NULL, amlibexecdir, "/", "runtar", NULL);
	info_tapeheader(dle);

	start_index(dle->create_index, dumpout, mesgf, indexf, indexcmd);

	g_ptr_array_add(argv_ptr, g_strdup("runtar"));
	if (g_options->config)
	    g_ptr_array_add(argv_ptr, g_strdup(g_options->config));
	else
	    g_ptr_array_add(argv_ptr, g_strdup("NOCONFIG"));
#ifdef GNUTAR
	g_ptr_array_add(argv_ptr, g_strdup(GNUTAR));
#else
	g_ptr_array_add(argv_ptr, g_strdup("tar"));
#endif
	g_ptr_array_add(argv_ptr, g_strdup("--create"));
	g_ptr_array_add(argv_ptr, g_strdup("--file"));
	g_ptr_array_add(argv_ptr, g_strdup("-"));
	g_ptr_array_add(argv_ptr, g_strdup("--directory"));
	canonicalize_pathname(dirname, tmppath);
	g_ptr_array_add(argv_ptr, g_strdup(tmppath));
	g_ptr_array_add(argv_ptr, g_strdup("--one-file-system"));
	if (gnutar_list_dir && incrname) {
	    g_ptr_array_add(argv_ptr, g_strdup("--listed-incremental"));
	    g_ptr_array_add(argv_ptr, g_strdup(incrname));
	} else {
	    g_ptr_array_add(argv_ptr, g_strdup("--incremental"));
	    g_ptr_array_add(argv_ptr, g_strdup("--newer"));
	    g_ptr_array_add(argv_ptr, g_strdup(dumptimestr));
	}
#ifdef ENABLE_GNUTAR_ATIME_PRESERVE
	/* --atime-preserve causes gnutar to call
	 * utime() after reading files in order to
	 * adjust their atime.  However, utime()
	 * updates the file's ctime, so incremental
	 * dumps will think the file has changed. */
	g_ptr_array_add(argv_ptr, g_strdup("--atime-preserve"));
#endif
	g_ptr_array_add(argv_ptr, g_strdup("--sparse"));
	g_ptr_array_add(argv_ptr, g_strdup("--ignore-failed-read"));
	g_ptr_array_add(argv_ptr, g_strdup("--totals"));

	if(file_exclude) {
	    g_ptr_array_add(argv_ptr, g_strdup("--exclude-from"));
	    g_ptr_array_add(argv_ptr, g_strdup(file_exclude));
	}

	if(file_include) {
	    g_ptr_array_add(argv_ptr, g_strdup("--files-from"));
	    g_ptr_array_add(argv_ptr, g_strdup(file_include));
	}
	else {
	    g_ptr_array_add(argv_ptr, g_strdup("."));
	}
	    g_ptr_array_add(argv_ptr, NULL);
	dumppid = pipespawnv(cmd, STDIN_PIPE, 0,
			     &dumpin, &dumpout, &mesgf,
			     (char **)argv_ptr->pdata);
	tarpid = dumppid;
	amfree(file_exclude);
	amfree(file_include);
	g_ptr_array_free_full(argv_ptr);
    }
    dbprintf(_("gnutar: %s: pid %ld\n"), cmd, (long)dumppid);

    amfree(qdisk);
    amfree(dirname);
    amfree(cmd);
    amfree(indexcmd);
    amfree(error_pn);

    /* close the write ends of the pipes */

    aclose(dumpin);
    aclose(dumpout);
    aclose(compout);
    aclose(dataf);
    aclose(mesgf);
    if (dle->create_index)
	aclose(indexf);
}
Пример #15
0
static void
amstar_restore(
    application_argument_t *argument)
{
    char       *cmd;
    GPtrArray  *argv_ptr = g_ptr_array_new();
    char      **env;
    int         j;
    char       *e;

    if (!star_path) {
	error(_("STAR-PATH not defined"));
    }

    cmd = stralloc(star_path);

    g_ptr_array_add(argv_ptr, stralloc(star_path));
    if (star_directory) {
	struct stat stat_buf;
	if(stat(star_directory, &stat_buf) != 0) {
	    fprintf(stderr,"can not stat directory %s: %s\n", star_directory, strerror(errno));
	    exit(1);
	}
	if (!S_ISDIR(stat_buf.st_mode)) {
	    fprintf(stderr,"%s is not a directory\n", star_directory);
	    exit(1);
	}
	if (access(star_directory, W_OK) != 0 ) {
	    fprintf(stderr, "Can't write to %s: %s\n", star_directory, strerror(errno));
	    exit(1);
	}

	g_ptr_array_add(argv_ptr, stralloc("-C"));
	g_ptr_array_add(argv_ptr, stralloc(star_directory));
    }
    g_ptr_array_add(argv_ptr, stralloc("-x"));
    g_ptr_array_add(argv_ptr, stralloc("-v"));
    g_ptr_array_add(argv_ptr, stralloc("-xattr"));
    g_ptr_array_add(argv_ptr, stralloc("-acl"));
    g_ptr_array_add(argv_ptr, stralloc("errctl=WARN|SAMEFILE|SETTIME|DIFF|SETACL|SETXATTR|SETMODE|BADACL *"));
    g_ptr_array_add(argv_ptr, stralloc("-no-fifo"));
    g_ptr_array_add(argv_ptr, stralloc("-f"));
    g_ptr_array_add(argv_ptr, stralloc("-"));

    if (argument->dle.exclude_list &&
	argument->dle.exclude_list->nb_element == 1) {
	g_ptr_array_add(argv_ptr, stralloc("-exclude-from"));
	g_ptr_array_add(argv_ptr,
			stralloc(argument->dle.exclude_list->first->name));
    }

    if (argument->dle.include_list &&
	argument->dle.include_list->nb_element == 1) {
	g_ptr_array_add(argv_ptr,
			stralloc2("list=",
				  argument->dle.include_list->first->name));
    }
    for (j=1; j< argument->argc; j++)
	g_ptr_array_add(argv_ptr, stralloc(argument->argv[j]+2));/*remove ./ */
    g_ptr_array_add(argv_ptr, NULL);

    debug_executing(argv_ptr);
    env = safe_env();
    become_root();
    execve(cmd, (char **)argv_ptr->pdata, env);
    e = strerror(errno);
    error(_("error [exec %s: %s]"), cmd, e);

}
Пример #16
0
int
main(
    int		argc,
    char **	argv)
{
    disk_t *diskp;
    disklist_t diskl;
    size_t i;
    char *conf_diskfile;
    char *conf_tapelist;
    char *conf_indexdir;
    find_result_t *output_find;
    time_t tmp_time;
    int amtrmidx_debug = 0;
    config_overrides_t *cfg_ovr = NULL;

    /*
     * 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);
    safe_cd();

    set_pname("amtrmidx");

    /* Don't die when child closes pipe */
    signal(SIGPIPE, SIG_IGN);

    dbopen(DBG_SUBDIR_SERVER);
    dbprintf(_("%s: version %s\n"), argv[0], VERSION);

    cfg_ovr = extract_commandline_config_overrides(&argc, &argv);

    if (argc > 1 && strcmp(argv[1], "-t") == 0) {
	amtrmidx_debug = 1;
	argc--;
	argv++;
    }

    if (argc < 2) {
	g_fprintf(stderr, _("Usage: %s [-t] <config> [-o configoption]*\n"), argv[0]);
	return 1;
    }

    set_config_overrides(cfg_ovr);
    config_init(CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_USE_CWD, argv[1]);

    conf_diskfile = config_dir_relative(getconf_str(CNF_DISKFILE));
    read_diskfile(conf_diskfile, &diskl);
    amfree(conf_diskfile);

    if (config_errors(NULL) >= CFGERR_WARNINGS) {
	config_print_errors();
	if (config_errors(NULL) >= CFGERR_ERRORS) {
	    g_critical(_("errors processing config file"));
	}
    }

    check_running_as(RUNNING_AS_DUMPUSER);

    dbrename(get_config_name(), DBG_SUBDIR_SERVER);

    conf_tapelist = config_dir_relative(getconf_str(CNF_TAPELIST));
    if(read_tapelist(conf_tapelist)) {
	error(_("could not load tapelist \"%s\""), conf_tapelist);
	/*NOTREACHED*/
    }
    amfree(conf_tapelist);

    output_find = find_dump(&diskl);

    conf_indexdir = config_dir_relative(getconf_str(CNF_INDEXDIR));

    /* now go through the list of disks and find which have indexes */
    time(&tmp_time);
    tmp_time -= 7*24*60*60;			/* back one week */
    for (diskp = diskl.head; diskp != NULL; diskp = diskp->next)
    {
	if (diskp->index)
	{
	    char *indexdir, *qindexdir;
	    DIR *d;
	    struct dirent *f;
	    char **names;
	    size_t name_length;
	    size_t name_count;
	    char *host;
	    char *disk, *qdisk;
	    size_t len_date;
	    disk_t *dp;
	    GSList *matching_dp = NULL;

	    /* get listing of indices, newest first */
	    host = sanitise_filename(diskp->host->hostname);
	    disk = sanitise_filename(diskp->name);
	    qdisk = quote_string(diskp->name);
	    indexdir = g_strjoin(NULL, conf_indexdir, "/",
				 host, "/",
				 disk, "/",
				 NULL);
	    qindexdir = quote_string(indexdir);

	    /* find all dles that use the same indexdir */
	    for (dp = diskl.head; dp != NULL; dp = dp->next) {
		char *dp_host, *dp_disk;

		dp_host = sanitise_filename(dp->host->hostname);
		dp_disk = sanitise_filename(dp->name);
		if (strcmp(host, dp_host) == 0 &&
		    strcmp(disk, dp_disk) == 0) {
		    matching_dp = g_slist_append(matching_dp, dp);
		}
		amfree(dp_host);
		amfree(dp_disk);
	    }

	    dbprintf("%s %s -> %s\n", diskp->host->hostname,
			qdisk, qindexdir);
	    amfree(host);
	    amfree(qdisk);
	    amfree(disk);
	    if ((d = opendir(indexdir)) == NULL) {
		dbprintf(_("could not open index directory %s\n"), qindexdir);
		amfree(indexdir);
	        amfree(qindexdir);
		g_slist_free(matching_dp);
		continue;
	    }
	    name_length = 100;
	    names = (char **)g_malloc(name_length * sizeof(char *));
	    name_count = 0;
	    while ((f = readdir(d)) != NULL) {
		size_t l;

		if(is_dot_or_dotdot(f->d_name)) {
		    continue;
		}
		for(i = 0; i < sizeof("YYYYMMDDHHMMSS")-1; i++) {
		    if(! isdigit((int)(f->d_name[i]))) {
			break;
		    }
		}
		len_date = i;
		/* len_date=8  for YYYYMMDD       */
		/* len_date=14 for YYYYMMDDHHMMSS */
		if((len_date != 8 && len_date != 14)
		    || f->d_name[len_date] != '_'
		    || ! isdigit((int)(f->d_name[len_date+1]))) {
		    continue;			/* not an index file */
		}
		/*
		 * Clear out old index temp files.
		 */
		l = strlen(f->d_name) - (sizeof(".tmp")-1);
		if ((l > (len_date + 1))
			&& (strcmp(f->d_name + l, ".tmp")==0)) {
		    struct stat sbuf;
		    char *path, *qpath;

		    path = stralloc2(indexdir, f->d_name);
		    qpath = quote_string(path);
		    if(lstat(path, &sbuf) != -1
			&& ((sbuf.st_mode & S_IFMT) == S_IFREG)
			&& ((time_t)sbuf.st_mtime < tmp_time)) {
			dbprintf("rm %s\n", qpath);
		        if(amtrmidx_debug == 0 && unlink(path) == -1) {
			    dbprintf(_("Error removing %s: %s\n"),
				      qpath, strerror(errno));
		        }
		    }
		    amfree(qpath);
		    amfree(path);
		    continue;
		}
		if(name_count >= name_length) {
		    char **new_names;

		    new_names = g_malloc((name_length * 2) * sizeof(char *));
		    memcpy(new_names, names, name_length * sizeof(char *));
		    amfree(names);
		    names = new_names;
		    name_length *= 2;
		}
		names[name_count++] = g_strdup(f->d_name);
	    }
	    closedir(d);
	    qsort(names, name_count, sizeof(char *), sort_by_name_reversed);

	    /*
	     * Search for the first full dump past the minimum number
	     * of index files to keep.
	     */
	    for(i = 0; i < name_count; i++) {
		char *datestamp;
		int level;
		size_t len_date;
		int matching = 0;
		GSList *mdp;

		for(len_date = 0; len_date < sizeof("YYYYMMDDHHMMSS")-1; len_date++) {
                    if(! isdigit((int)(names[i][len_date]))) {
                        break;
                    }
                }

		datestamp = g_strdup(names[i]);
		datestamp[len_date] = '\0';
		if (sscanf(&names[i][len_date+1], "%d", &level) != 1)
		    level = 0;
		for (mdp = matching_dp; mdp != NULL; mdp = mdp->next) {
		    dp = mdp->data;
		    if (dump_exist(output_find, dp->host->hostname,
				   dp->name, datestamp, level)) {
			matching = 1;
		    }
		}
		if (!matching) {
		    char *path, *qpath;
		    path = stralloc2(indexdir, names[i]);
		    qpath = quote_string(path);
		    dbprintf("rm %s\n", qpath);
		    if(amtrmidx_debug == 0 && unlink(path) == -1) {
			dbprintf(_("Error removing %s: %s\n"),
				  qpath, strerror(errno));
		    }
		    amfree(qpath);
		    amfree(path);
		}
		amfree(datestamp);
		amfree(names[i]);
	    }
	    g_slist_free(matching_dp);
	    amfree(names);
	    amfree(indexdir);
	    amfree(qindexdir);
	}
    }

    amfree(conf_indexdir);
    free_find_result(&output_find);
    clear_tapelist();
    free_disklist(&diskl);

    dbclose();

    return 0;
}
Пример #17
0
void
set_host(
    const char *	host)
{
    char *cmd = NULL;
    struct hostent *hp;
    char **hostp;
    int found_host = 0;
    char *uqhost = unquote_string(host);

    if (is_extract_list_nonempty())
    {
	g_printf(_("Must clear extract list before changing host\n"));
	return;
    }

    cmd = stralloc2("HOST ", uqhost);
    if (converse(cmd) == -1)
	exit(1);
    if (server_happy())
    {
	found_host = 1;
    }
    else
    {
	/*
	 * Try converting the given host to a fully qualified name
	 * and then try each of the aliases.
	 */
	if ((hp = gethostbyname(uqhost)) != NULL) {
	    host = hp->h_name;
	    g_printf(_("Trying host %s ...\n"), host);
	    cmd = newstralloc2(cmd, "HOST ", host);
	    if (converse(cmd) == -1)
		exit(1);
	    if(server_happy())
	    {
		found_host = 1;
	    }
	    else
	    {
	        for (hostp = hp->h_aliases; (host = *hostp) != NULL; hostp++)
	        {
		    g_printf(_("Trying host %s ...\n"), host);
		    cmd = newstralloc2(cmd, "HOST ", host);
		    if (converse(cmd) == -1)
		        exit(1);
		    if(server_happy())
		    {
		        found_host = 1;
		        break;
		    }
		}
	    }
	}
    }
    if(found_host)
    {
	dump_hostname = newstralloc(dump_hostname, host);
	amfree(disk_name);
	amfree(mount_point);
	amfree(disk_path);
	clear_dir_list();
    }
    amfree(cmd);
    amfree(uqhost);
}
Пример #18
0
int
chunker_cmd(
    chunker_t *chunker,
    cmd_t cmd,
    disk_t *dp,
    char   *mesg)
{
    char *cmdline = NULL;
    char number[NUM_STR_SIZE];
    char chunksize[NUM_STR_SIZE];
    char use[NUM_STR_SIZE];
    char *o;
    int activehd=0;
    assignedhd_t **h=NULL;
    char *features;
    char *qname;
    char *qdest;

    switch(cmd) {
    case START:
	cmdline = vstralloc(cmdstr[cmd], " ", mesg, "\n", NULL);
	break;
    case PORT_WRITE:
	if(dp && sched(dp) && sched(dp)->holdp) {
	    h = sched(dp)->holdp;
	    activehd = sched(dp)->activehd;
	}

	if (dp && h) {
	    qname = quote_string(dp->name);
	    qdest = quote_string(sched(dp)->destname);
	    h[activehd]->disk->allocated_dumpers++;
	    g_snprintf(number, SIZEOF(number), "%d", sched(dp)->level);
	    g_snprintf(chunksize, SIZEOF(chunksize), "%lld",
		    (long long)holdingdisk_get_chunksize(h[0]->disk->hdisk));
	    g_snprintf(use, SIZEOF(use), "%lld",
		    (long long)h[0]->reserved);
	    features = am_feature_to_string(dp->host->features);
	    o = optionstr(dp, dp->host->features, NULL);
	    if ( o == NULL ) {
	      error(_("problem with option string, check the dumptype definition.\n"));
	    }
	    cmdline = vstralloc(cmdstr[cmd],
			    " ", disk2serial(dp),
			    " ", qdest,
			    " ", dp->host->hostname,
			    " ", features,
			    " ", qname,
			    " ", number,
			    " ", sched(dp)->dumpdate,
			    " ", chunksize,
			    " ", dp->program,
			    " ", use,
			    " |", o,
			    "\n", NULL);
	    amfree(features);
	    amfree(o);
	    amfree(qdest);
	    amfree(qname);
	} else {
		error(_("%s command without disk and holding disk.\n"),
		      cmdstr[cmd]);
		/*NOTREACHED*/
	}
	break;
    case CONTINUE:
	if(dp && sched(dp) && sched(dp)->holdp) {
	    h = sched(dp)->holdp;
	    activehd = sched(dp)->activehd;
	}

	if(dp && h) {
	    qname = quote_string(dp->name);
	    qdest = quote_string(h[activehd]->destname);
	    h[activehd]->disk->allocated_dumpers++;
	    g_snprintf(chunksize, SIZEOF(chunksize), "%lld", 
		     (long long)holdingdisk_get_chunksize(h[activehd]->disk->hdisk));
	    g_snprintf(use, SIZEOF(use), "%lld", 
		     (long long)(h[activehd]->reserved - h[activehd]->used));
	    cmdline = vstralloc(cmdstr[cmd],
				" ", disk2serial(dp),
				" ", qdest,
				" ", chunksize,
				" ", use,
				"\n", NULL );
	    amfree(qdest);
	    amfree(qname);
	} else {
	    cmdline = stralloc2(cmdstr[cmd], "\n");
	}
	break;
    case QUIT:
    case ABORT:
	{
	    char *q = quote_string(mesg);
	    cmdline = vstralloc(cmdstr[cmd], " ", q, "\n", NULL);
	    amfree(q);
	}
	break;
    case DONE:
    case FAILED:
	if( dp ) {
	    cmdline = vstralloc(cmdstr[cmd],
				" ", disk2serial(dp),
				"\n",  NULL);
	} else {
	    cmdline = vstralloc(cmdstr[cmd], "\n");
	}
	break;
    default:
	error(_("Don't know how to send %s command to chunker"), cmdstr[cmd]);
	/*NOTREACHED*/
    }

    /*
     * Note: cmdline already has a '\n'.
     */
    g_printf(_("driver: send-cmd time %s to %s: %s"),
	   walltime_str(curclock()), chunker->name, cmdline);
    fflush(stdout);
    if (full_write(chunker->fd, cmdline, strlen(cmdline)) < strlen(cmdline)) {
	g_printf(_("writing %s command: %s\n"), chunker->name, strerror(errno));
	fflush(stdout);
	amfree(cmdline);
	return 0;
    }
    if (cmd == QUIT) aclose(chunker->fd);
    amfree(cmdline);
    return 1;
}
Пример #19
0
int
main(
    int		argc,
    char **	argv)
{
    in_port_t my_port;
    struct servent *sp;
    int i;
    time_t timer;
    char *lineread = NULL;
    struct sigaction act, oact;
    extern char *optarg;
    extern int optind;
    char cwd[STR_SIZE], *dn_guess = NULL, *mpt_guess = NULL;
    char *service_name;
    char *line = NULL;
    struct tm *tm;

    /*
     * 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);

    set_pname("amoldrecover");

    /* Don't die when child closes pipe */
    signal(SIGPIPE, SIG_IGN);

    dbopen(DBG_SUBDIR_CLIENT);

    localhost = alloc(MAX_HOSTNAME_LENGTH+1);
    if (gethostname(localhost, MAX_HOSTNAME_LENGTH) != 0) {
	error(_("cannot determine local host name\n"));
	/*NOTREACHED*/
    }
    localhost[MAX_HOSTNAME_LENGTH] = '\0';

    config = newstralloc(config, DEFAULT_CONFIG);

    dbrename(config, DBG_SUBDIR_CLIENT);

    check_running_as(RUNNING_AS_ROOT);

    amfree(server_name);
    server_name = getenv("AMANDA_SERVER");
    if(!server_name) server_name = DEFAULT_SERVER;
    server_name = stralloc(server_name);

    amfree(tape_server_name);
    tape_server_name = getenv("AMANDA_TAPESERVER");
    if(!tape_server_name) tape_server_name = DEFAULT_TAPE_SERVER;
    tape_server_name = stralloc(tape_server_name);

    config_init(CONFIG_INIT_CLIENT, NULL);

    if (config_errors(NULL) >= CFGERR_WARNINGS) {
	config_print_errors();
	if (config_errors(NULL) >= CFGERR_ERRORS) {
	    g_critical(_("errors processing config file"));
	}
    }

    if (argc > 1 && argv[1][0] != '-')
    {
	/*
	 * If the first argument is not an option flag, then we assume
	 * it is a configuration name to match the syntax of the other
	 * Amanda utilities.
	 */
	char **new_argv;

	new_argv = (char **) alloc((size_t)((argc + 1 + 1) * sizeof(*new_argv)));
	new_argv[0] = argv[0];
	new_argv[1] = "-C";
	for (i = 1; i < argc; i++)
	{
	    new_argv[i + 1] = argv[i];
	}
	new_argv[i + 1] = NULL;
	argc++;
	argv = new_argv;
    }
    while ((i = getopt(argc, argv, "C:s:t:d:U")) != EOF)
    {
	switch (i)
	{
	    case 'C':
		config = newstralloc(config, optarg);
		break;

	    case 's':
		server_name = newstralloc(server_name, optarg);
		break;

	    case 't':
		tape_server_name = newstralloc(tape_server_name, optarg);
		break;

	    case 'd':
		tape_device_name = newstralloc(tape_device_name, optarg);
		break;

	    case 'U':
	    case '?':
		(void)g_printf(USAGE);
		return 0;
	}
    }
    if (optind != argc)
    {
	(void)g_fprintf(stderr, USAGE);
	exit(1);
    }

    amfree(disk_name);
    amfree(mount_point);
    amfree(disk_path);
    dump_date[0] = '\0';

    /* Don't die when child closes pipe */
    signal(SIGPIPE, SIG_IGN);

    /* set up signal handler */
    act.sa_handler = sigint_handler;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    if (sigaction(SIGINT, &act, &oact) != 0) {
	error(_("error setting signal handler: %s"), strerror(errno));
	/*NOTREACHED*/
    }

    service_name = stralloc2("amandaidx", SERVICE_SUFFIX);

    g_printf(_("AMRECOVER Version %s. Contacting server on %s ...\n"),
	   version(), server_name);  
    if ((sp = getservbyname(service_name, "tcp")) == NULL) {
	error(_("%s/tcp unknown protocol"), service_name);
	/*NOTREACHED*/
    }
    amfree(service_name);
    server_socket = stream_client_privileged(server_name,
					     (in_port_t)ntohs((in_port_t)sp->s_port),
					     0,
					     0,
					     &my_port,
					     0);
    if (server_socket < 0) {
	error(_("cannot connect to %s: %s"), server_name, strerror(errno));
	/*NOTREACHED*/
    }
    if (my_port >= IPPORT_RESERVED) {
        aclose(server_socket);
	error(_("did not get a reserved port: %d"), my_port);
	/*NOTREACHED*/
    }

    /* get server's banner */
    if (grab_reply(1) == -1) {
        aclose(server_socket);
	exit(1);
    }
    if (!server_happy())
    {
	dbclose();
	aclose(server_socket);
	exit(1);
    }

    /* do the security thing */
    line = get_security();
    if (converse(line) == -1) {
        aclose(server_socket);
	exit(1);
    }
    if (!server_happy()) {
        aclose(server_socket);
	exit(1);
    }
    memset(line, '\0', strlen(line));
    amfree(line);

    /* try to get the features from the server */
    {
	char *our_feature_string = NULL;
	char *their_feature_string = NULL;

	our_features = am_init_feature_set();
	our_feature_string = am_feature_to_string(our_features);
	line = stralloc2("FEATURES ", our_feature_string);
	if(exchange(line) == 0) {
	    their_feature_string = stralloc(server_line+13);
	    indexsrv_features = am_string_to_feature(their_feature_string);
	}
	else {
	    indexsrv_features = am_set_default_feature_set();
        }
	amfree(our_feature_string);
	amfree(their_feature_string);
	amfree(line);
    }

    /* set the date of extraction to be today */
    (void)time(&timer);
    tm = localtime(&timer);
    if (tm)
	strftime(dump_date, sizeof(dump_date), "%Y-%m-%d", tm);
    else
	error(_("BAD DATE"));

    g_printf(_("Setting restore date to today (%s)\n"), dump_date);
    line = stralloc2("DATE ", dump_date);
    if (converse(line) == -1) {
        aclose(server_socket);
	exit(1);
    }
    amfree(line);

    line = stralloc2("SCNF ", config);
    if (converse(line) == -1) {
        aclose(server_socket);
	exit(1);
    }
    amfree(line);

    if (server_happy())
    {
	/* set host we are restoring to this host by default */
	amfree(dump_hostname);
	set_host(localhost);
	if (dump_hostname)
	{
            /* get a starting disk and directory based on where
	       we currently are */
	    switch (guess_disk(cwd, sizeof(cwd), &dn_guess, &mpt_guess))
	    {
		case 1:
		    /* okay, got a guess. Set disk accordingly */
		    g_printf(_("$CWD '%s' is on disk '%s' mounted at '%s'.\n"),
			   cwd, dn_guess, mpt_guess);
		    set_disk(dn_guess, mpt_guess);
		    set_directory(cwd);
		    if (server_happy() && strcmp(cwd, mpt_guess) != 0)
		        g_printf(_("WARNING: not on root of selected filesystem, check man-page!\n"));
		    amfree(dn_guess);
		    amfree(mpt_guess);
		    break;

		case 0:
		    g_printf(_("$CWD '%s' is on a network mounted disk\n"),
			   cwd);
		    g_printf(_("so you must 'sethost' to the server\n"));
		    /* fake an unhappy server */
		    server_line[0] = '5';
		    break;

		case 2:
		case -1:
		default:
		    g_printf(_("Use the setdisk command to choose dump disk to recover\n"));
		    /* fake an unhappy server */
		    server_line[0] = '5';
		    break;
	    }
	}
    }

    quit_prog = 0;
    do
    {
	if ((lineread = readline("amrecover> ")) == NULL) {
	    clearerr(stdin);
	    putchar('\n');
	    break;
	}
	if (lineread[0] != '\0') 
	{
	    add_history(lineread);
	    process_line(lineread);	/* act on line's content */
	}
	amfree(lineread);
    } while (!quit_prog);

    dbclose();

    aclose(server_socket);
    return 0;
}
Пример #20
0
void
set_host(
    const char *host)
{
    char *cmd = NULL;
    struct hostent *hp = NULL;
    char **hostp;
    int found_host = 0;
    char *uqhost = unquote_string(host);

    if (is_extract_list_nonempty())
    {
	g_printf(_("Must clear extract list before changing host\n"));
	amfree(uqhost);
	return;
    }

    /*
     * The idea here is to try as many permutations of the hostname
     * as we can imagine.  The server will reject anything it doesn't
     * recognize.
     */

    cmd = stralloc2("HOST ", uqhost);
    if (converse(cmd) == -1)
	exit(1);
    if (server_happy())
	found_host = 1;

    /*
     * Try converting the given host to a fully qualified, canonical
     * name.
     */
    if (!found_host) {
	if ((hp = gethostbyname(uqhost)) != NULL) {
	    host = hp->h_name;
	    g_printf(_("Trying host %s ...\n"), host);
	    cmd = newstralloc2(cmd, "HOST ", host);
	    if (converse(cmd) == -1)
		exit(1);
	    if(server_happy())
		found_host = 1;
	}
    }

    /*
     * Since we have them, try any CNAMEs that were traversed from uqhost
     * to the canonical name (this assumes gethostbyname was called above)
     */
    if (!found_host) {
	if (hp) {
	    for (hostp = hp->h_aliases; (host = *hostp) != NULL; hostp++)
	    {
		g_printf(_("Trying host %s ...\n"), host);
		cmd = newstralloc2(cmd, "HOST ", host);
		if (converse(cmd) == -1)
		    exit(1);
		if(server_happy())
		{
		    found_host = 1;
		    break;
		}
	    }
	}
    }

    /* Try looking up the canonical name of the host */
    if (!found_host) {
	char *canonname;
	int result;

	result = resolve_hostname(uqhost, 0, NULL, &canonname);
	if (result == 0 && canonname) {
	    host = canonname;
	    g_printf(_("Trying host %s ...\n"), host);
	    cmd = newstralloc2(cmd, "HOST ", host);
	    if (converse(cmd) == -1)
		exit(1);
	    if(server_happy())
		found_host = 1;
	}
    }

    if(found_host) {
	dump_hostname = newstralloc(dump_hostname, host);
	amfree(disk_name);
	amfree(mount_point);
	amfree(disk_path);
	clear_dir_list();
    }
    amfree(cmd);
    amfree(uqhost);
}
Пример #21
0
void
set_disk(
    char *	dsk,
    char *	mtpt)
{
    char *cmd = NULL;
    char *qdsk;
    char *uqdsk;
    char *uqmtpt = NULL;

    if (is_extract_list_nonempty())
    {
	g_printf(_("Must clear extract list before changing disk\n"));
	return;
    }

    /* if mount point specified, check it is valid */
    if (mtpt != NULL) {
	uqmtpt = unquote_string(mtpt);
	if (*mtpt != '/') {
	    g_printf(_("Mount point \"%s\" invalid - must start with /\n"), uqmtpt);
	    amfree(uqmtpt);
	    return;
	}
    }

    clear_dir_list();
    uqdsk = unquote_string(dsk);
    qdsk = quote_string(uqdsk);
    cmd = stralloc2("DISK ", qdsk);
    amfree(qdsk);
    if (converse(cmd) == -1)
	exit(1);
    amfree(cmd);

    if (!server_happy()) {
	amfree(uqmtpt);
	amfree(uqdsk);
	return;
    }

    disk_name = newstralloc(disk_name, uqdsk);
    if (mtpt == NULL)
    {
	/* mount point not specified */
	if (*uqdsk == '/')
	{
	    /* disk specified by mount point, hence use it */
	    mount_point = newstralloc(mount_point, uqdsk);
	}
	else
	{
	    /* device name given, use '/' because nothing better */
	    mount_point = newstralloc(mount_point, "/");
	}
    }
    else
    {
	/* mount point specified */
	mount_point = newstralloc(mount_point, uqmtpt);
    }

    /* set the working directory to the mount point */
    /* there is the possibility that there are no index records for the
       disk for the given date, hence setting the directory to the
       mount point will fail. Preempt this by checking first so we can write
       a more informative message. */
    if (exchange("OISD /") == -1)
	exit(1);
    if (server_happy())
    {
	disk_path = newstralloc(disk_path, "/");
	suck_dir_list_from_server();	/* get list of directory contents */
    }
    else
    {
	g_printf(_("No index records for disk for specified date\n"));
	g_printf(_("If date correct, notify system administrator\n"));
	disk_path = newstralloc(disk_path, "/");	/* fake it */
	clear_dir_list();
    }
    amfree(uqmtpt);
    amfree(uqdsk);

    if (am_has_feature(indexsrv_features, fe_amindexd_DLE)) {
	char *dle_str;
	char *errmsg = NULL;

	cmd = stralloc("DLE");
	if (exchange(cmd) == -1)
	    exit(1);
	amfree(cmd);

	if (!server_happy())
	    return;

	dle_str = reply_line();
	if (BSTRNCMP(dle_str+4, "NODLE") == 0) {
	    dump_dle = NULL;
	} else {
	    dle_str = unquote_string(dle_str+4);
	    dump_dle = amxml_parse_node_CHAR(dle_str, &errmsg);
	    amfree(dle_str);
	}
    }
}
Пример #22
0
void
set_directory(
    char *	dir,
    int		verbose)
{
    char *cmd = NULL;
    char *new_dir = NULL;
    char *qnew_dir;
    char *dp, *de;
    char *ldir = NULL;

    /* do nothing if "." */
    if(strcmp(dir,".")==0) {
	show_directory();		/* say where we are */
	return;
	/*NOTREACHED*/
    }

    if (disk_name == NULL) {
	g_printf(_("Must select disk before setting directory\n"));
	return;
	/*NOTREACHED*/
    }

    ldir = stralloc(dir);
    clean_pathname(ldir);

    /* convert directory into absolute path relative to disk mount point */
    if (ldir[0] == '/')
    {
	/* absolute path specified, must start with mount point */
	if (strcmp(mount_point, "/") == 0)
	{
	    new_dir = stralloc(ldir);
	}
	else
	{
	    if (strncmp(mount_point, ldir, strlen(mount_point)) != 0)
	    {
		g_printf(_("Invalid directory - Can't cd outside mount point \"%s\"\n"),
		       mount_point);
		amfree(ldir);
		return;
		/*NOTREACHED*/
	    }
	    new_dir = stralloc(ldir+strlen(mount_point));
	    if (strlen(new_dir) == 0) {
		new_dir = newstralloc(new_dir, "/");
					/* i.e. ldir == mount_point */
	    }
	}
    }
    else
    {
	new_dir = stralloc(disk_path);
	dp = ldir;
	/* strip any leading ..s */
	while (strncmp(dp, "../", 3) == 0)
	{
	    de = strrchr(new_dir, '/');	/* always at least 1 */
	    if (de == new_dir)
	    {
		/* at top of disk */
		*(de + 1) = '\0';
		dp = dp + 3;
	    }
	    else
	    {
		*de = '\0';
		dp = dp + 3;
	    }
	}
	if (strcmp(dp, "..") == 0) {
	    if (strcmp(new_dir, "/") == 0) {
		/* at top of disk */
		g_printf(_("Invalid directory - Can't cd outside mount point \"%s\"\n"),
		       mount_point);
		/*@ignore@*/
		amfree(new_dir);
		/*@end@*/
		amfree(ldir);
		return;
		/*NOTREACHED*/
	    }
	    de = strrchr(new_dir, '/');	/* always at least 1 */
	    if (de == new_dir)
	    {
		/* at top of disk */
		*(de+1) = '\0';
	    }
	    else
	    {
		*de = '\0';
 	    }
	} else {
	    /*@ignore@*/
	    if (strcmp(new_dir, "/") != 0) {
		strappend(new_dir, "/");
	    }
	    strappend(new_dir, ldir);
	    /*@end@*/
	}
    }

    qnew_dir = quote_string(new_dir);
    cmd = stralloc2("OISD ", qnew_dir);
    amfree(qnew_dir);
    if (exchange(cmd) == -1) {
	exit(1);
	/*NOTREACHED*/
    }
    amfree(cmd);

    if (server_happy())
    {
	disk_path = newstralloc(disk_path, new_dir);
	suck_dir_list_from_server();	/* get list of directory contents */
	if (verbose)
	    show_directory();		/* say where we moved to */
    }
    else
    {
	g_printf(_("Invalid directory - %s\n"), dir);
    }

    /*@ignore@*/
    amfree(new_dir);
    amfree(ldir);
    /*@end@*/
}
Пример #23
0
int
taper_cmd(
    cmd_t cmd,
    void *ptr,
    char *destname,
    int level,
    char *datestamp)
{
    char *cmdline = NULL;
    char number[NUM_STR_SIZE];
    char splitsize[NUM_STR_SIZE];
    char fallback_splitsize[NUM_STR_SIZE];
    char *diskbuffer = NULL;
    disk_t *dp;
    char *qname;
    char *qdest;
    char *q;

    switch(cmd) {
    case START_TAPER:
	cmdline = vstralloc(cmdstr[cmd], " ", (char *)ptr, "\n", NULL);
	break;
    case FILE_WRITE:
	dp = (disk_t *) ptr;
        qname = quote_string(dp->name);
	qdest = quote_string(destname);
	g_snprintf(number, SIZEOF(number), "%d", level);
	g_snprintf(splitsize, SIZEOF(splitsize), "%lld",
		 (long long)dp->tape_splitsize * 1024);
	cmdline = vstralloc(cmdstr[cmd],
			    " ", disk2serial(dp),
			    " ", qdest,
			    " ", dp->host->hostname,
			    " ", qname,
			    " ", number,
			    " ", datestamp,
			    " ", splitsize,
			    "\n", NULL);
	amfree(qdest);
	amfree(qname);
	break;
    case PORT_WRITE:
	dp = (disk_t *) ptr;
        qname = quote_string(dp->name);
	g_snprintf(number, SIZEOF(number), "%d", level);

	/*
          If we haven't been given a place to buffer split dumps to disk,
          make the argument something besides and empty string so's taper
          won't get confused
	*/
	if(!dp->split_diskbuffer || dp->split_diskbuffer[0] == '\0'){
	    diskbuffer = "NULL";
	} else {
	    diskbuffer = dp->split_diskbuffer;
	}
	g_snprintf(splitsize, SIZEOF(splitsize), "%lld",
		 (long long)dp->tape_splitsize * 1024);
	g_snprintf(fallback_splitsize, SIZEOF(fallback_splitsize), "%lld",
		 (long long)dp->fallback_splitsize * 1024);
	cmdline = vstralloc(cmdstr[cmd],
			    " ", disk2serial(dp),
			    " ", dp->host->hostname,
			    " ", qname,
			    " ", number,
			    " ", datestamp,
			    " ", splitsize,
			    " ", diskbuffer,
			    " ", fallback_splitsize,
			    " ", data_path_to_string(dp->data_path),
			    "\n", NULL);
	amfree(qname);
	break;
    case DONE: /* handle */
    case FAILED: /* handle */
	dp = (disk_t *) ptr;
	cmdline = vstralloc(cmdstr[cmd],
			    " ", disk2serial(dp),
			    "\n", NULL);
	break;
    case NO_NEW_TAPE:
	q = quote_string((char *)ptr);
	cmdline = vstralloc(cmdstr[cmd],
			    " ", q,
			    "\n", NULL);
	amfree(q);
	break;
    case NEW_TAPE:
    case QUIT:
	cmdline = stralloc2(cmdstr[cmd], "\n");
	break;
    default:
	error(_("Don't know how to send %s command to taper"), cmdstr[cmd]);
	/*NOTREACHED*/
    }

    /*
     * Note: cmdline already has a '\n'.
     */
    g_printf(_("driver: send-cmd time %s to taper: %s"),
	   walltime_str(curclock()), cmdline);
    fflush(stdout);
    if ((full_write(taper, cmdline, strlen(cmdline))) < strlen(cmdline)) {
	g_printf(_("writing taper command '%s' failed: %s\n"),
		cmdline, strerror(errno));
	fflush(stdout);
	amfree(cmdline);
	return 0;
    }
    if(cmd == QUIT) aclose(taper);
    amfree(cmdline);
    return 1;
}
Пример #24
0
/*
 * check ~/.k5amandahosts to see if this principal is allowed in.  If it's
 * hardcoded, then we don't check the realm
 */
static char *
krb5_checkuser( char *	host,
    char *	name,
    char *	realm)
{
#ifdef AMANDA_PRINCIPAL
    if(strcmp(name, AMANDA_PRINCIPAL) == 0) {
	return(NULL);
    } else {
	return(vstrallocf(_("does not match compiled in default")));
    }
#else
    struct passwd *pwd;
    char *ptmp;
    char *result = _("generic error");	/* default is to not permit */
    FILE *fp = NULL;
    struct stat sbuf;
    uid_t localuid;
    char *line = NULL;
    char *filehost = NULL, *fileuser = NULL, *filerealm = NULL;

    assert( host != NULL);
    assert( name != NULL);

    if((pwd = getpwnam(CLIENT_LOGIN)) == NULL) {
	result = vstrallocf(_("can not find user %s"), CLIENT_LOGIN);
    }
    localuid = pwd->pw_uid;

#ifdef USE_AMANDAHOSTS
    ptmp = stralloc2(pwd->pw_dir, "/.k5amandahosts");
#else
    ptmp = stralloc2(pwd->pw_dir, "/.k5login");
#endif

    if(!ptmp) {
	result = vstrallocf(_("could not find home directory for %s"), CLIENT_LOGIN);
	goto common_exit;
   }

   /*
    * check to see if the ptmp file does nto exist.
    */
   if(access(ptmp, R_OK) == -1 && errno == ENOENT) {
	/*
	 * in this case we check to see if the principal matches
	 * the destination user mimicing the .k5login functionality.
	 */
	 if(strcmp(name, CLIENT_LOGIN) != 0) {
		result = vstrallocf(_("%s does not match %s"),
			name, CLIENT_LOGIN);
		return result;
	}
	result = NULL;
	goto common_exit;
    }

    auth_debug(1, _("opening ptmp: %s\n"), (ptmp)?ptmp: "NULL!");
    if((fp = fopen(ptmp, "r")) == NULL) {
	result = vstrallocf(_("can not open %s"), ptmp);
	return result;
    }
    auth_debug(1, _("opened ptmp\n"));

    if (fstat(fileno(fp), &sbuf) != 0) {
	result = vstrallocf(_("cannot fstat %s: %s"), ptmp, strerror(errno));
	goto common_exit;
    }

    if (sbuf.st_uid != localuid) {
	result = vstrallocf(_("%s is owned by %ld, should be %ld"),
		ptmp, (long)sbuf.st_uid, (long)localuid);
	goto common_exit;
    }
    if ((sbuf.st_mode & 077) != 0) {
	result = vstrallocf(
	    _("%s: incorrect permissions; file must be accessible only by its owner"), ptmp);
	goto common_exit;
    }

    while ((line = agets(fp)) != NULL) {
	if (line[0] == '\0') {
	    amfree(line);
	    continue;
	}

	/* if there's more than one column, then it's the host */
	if( (filehost = strtok(line, " \t")) == NULL) {
	    amfree(line);
	    continue;
	}

	/*
	 * if there's only one entry, then it's a username and we have
	 * no hostname.  (so the principal is allowed from anywhere.
	 */
	if((fileuser = strtok(NULL, " \t")) == NULL) {
	    fileuser = filehost;
	    filehost = NULL;
	}

	if(filehost && strcmp(filehost, host) != 0) {
	    amfree(line);
	    continue;
	} else {
		auth_debug(1, _("found a host match\n"));
	}

	if( (filerealm = strchr(fileuser, '@')) != NULL) {
	    *filerealm++ = '\0';
	}

	/*
	 * we have a match.  We're going to be a little bit insecure
	 * and indicate that the principal is correct but the realm is
	 * not if that's the case.  Technically we should say nothing
	 * and let the user figure it out, but it's helpful for debugging.
	 * You likely only get this far if you've turned on cross-realm auth
	 * anyway...
	 */
	auth_debug(1, _("comparing %s %s\n"), fileuser, name);
	if(strcmp(fileuser, name) == 0) {
		auth_debug(1, _("found a match!\n"));
		if(realm && filerealm && (strcmp(realm, filerealm)!=0)) {
			amfree(line);
			continue;
		}
		result = NULL;
		amfree(line);
		goto common_exit;
	}
	amfree(line);
    }
    result = vstrallocf(_("no match in %s"), ptmp);

common_exit:
    afclose(fp);
    return(result);
#endif /* AMANDA_PRINCIPAL */
}
Пример #25
0
/* do this by looking for the longest mount point which matches the
   current directory */
int
guess_disk (
    char *	cwd,
    size_t	cwd_len,
    char **	dn_guess,
    char **	mpt_guess)
{
    size_t longest_match = 0;
    size_t current_length;
    size_t cwd_length;
    int local_disk = 0;
    generic_fsent_t fsent;
    char *fsname = NULL;
    char *disk_try = NULL;

    *dn_guess = NULL;
    *mpt_guess = NULL;

    if (getcwd(cwd, cwd_len) == NULL) {
	return -1;
	/*NOTREACHED*/
    }
    cwd_length = strlen(cwd);
    dbprintf(_("guess_disk: %zu: \"%s\"\n"), cwd_length, cwd);

    if (open_fstab() == 0) {
	return -1;
	/*NOTREACHED*/
    }

    while (get_fstab_nextentry(&fsent))
    {
	current_length = fsent.mntdir ? strlen(fsent.mntdir) : (size_t)0;
	dbprintf(_("guess_disk: %zu: %zu: \"%s\": \"%s\"\n"),
		  longest_match,
		  current_length,
		  fsent.mntdir ? fsent.mntdir : _("(mntdir null)"),
		  fsent.fsname ? fsent.fsname : _("(fsname null)"));
	if ((current_length > longest_match)
	    && (current_length <= cwd_length)
	    && (strncmp(fsent.mntdir, cwd, current_length) == 0))
	{
	    longest_match = current_length;
	    *mpt_guess = newstralloc(*mpt_guess, fsent.mntdir);
	    if(strncmp(fsent.fsname,DEV_PREFIX,(strlen(DEV_PREFIX))))
	    {
	        fsname = newstralloc(fsname, fsent.fsname);
            }
	    else
	    {
	        fsname = newstralloc(fsname,fsent.fsname+strlen(DEV_PREFIX));
	    }
	    local_disk = is_local_fstype(&fsent);
	    dbprintf(_("guess_disk: local_disk = %d, fsname = \"%s\"\n"),
		      local_disk,
		      fsname);
	}
    }
    close_fstab();

    if (longest_match == 0) {
	amfree(*mpt_guess);
	amfree(fsname);
	return -1;			/* ? at least / should match */
    }

    if (!local_disk) {
	amfree(*mpt_guess);
	amfree(fsname);
	return 0;
    }

    /* have mount point now */
    /* disk name may be specified by mount point (logical name) or
       device name, have to determine */
    g_printf(_("Trying disk %s ...\n"), *mpt_guess);
    disk_try = stralloc2("DISK ", *mpt_guess);		/* try logical name */
    if (exchange(disk_try) == -1)
	exit(1);
    amfree(disk_try);
    if (server_happy())
    {
	*dn_guess = stralloc(*mpt_guess);		/* logical is okay */
	amfree(fsname);
	return 1;
    }
    g_printf(_("Trying disk %s ...\n"), fsname);
    disk_try = stralloc2("DISK ", fsname);		/* try device name */
    if (exchange(disk_try) == -1)
	exit(1);
    amfree(disk_try);
    if (server_happy())
    {
	*dn_guess = stralloc(fsname);			/* dev name is okay */
	amfree(fsname);
	return 1;
    }

    /* neither is okay */
    amfree(*mpt_guess);
    amfree(fsname);
    return 2;
}