⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 changer.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
字号:
/* * Amanda, The Advanced Maryland Automatic Network Disk Archiver * Copyright (c) 1991-1998 University of Maryland at College Park * All Rights Reserved. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of U.M. not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission.  U.M. makes no representations about the * suitability of this software for any purpose.  It is provided "as is" * without express or implied warranty. * * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Authors: the Amanda Development Team.  Its members are listed in a * file named AUTHORS, in the root directory of this distribution. *//* * $Id: changer.c,v 1.36 2006/08/24 01:57:16 paddy_s Exp $ * * interface routines for tape changers */#include "amanda.h"#include "util.h"#include "conffile.h"#include "version.h"#include "changer.h"/* * If we don't have the new-style wait access functions, use our own, * compatible with old-style BSD systems at least.  Note that we don't * care about the case w_stopval == WSTOPPED since we don't ask to see * stopped processes, so should never get them from wait. */#ifndef WEXITSTATUS#   define WEXITSTATUS(r)       (((union wait *) &(r))->w_retcode)#   define WTERMSIG(r)          (((union wait *) &(r))->w_termsig)#   undef  WIFSIGNALED#   define WIFSIGNALED(r)       (((union wait *) &(r))->w_termsig != 0)#endifint changer_debug = 0;char *changer_resultstr = NULL;static char *tapechanger = NULL;/* local functions */static int changer_command(char *cmd, char *arg);static int report_bad_resultstr(char *cmd);static int run_changer_command(char *cmd, char *arg, char **slotstr, char **rest);intchanger_init(void){    if (tapechanger == NULL)	tapechanger = getconf_str(CNF_TPCHANGER);    if (*tapechanger != '\0' && *tapechanger != '/') {	tapechanger = vstralloc(amlibexecdir, "/", tapechanger, versionsuffix(),			        NULL);    }    return strcmp(tapechanger, "") != 0;}static intreport_bad_resultstr(char *cmd){    char *s;    s = vstrallocf(_("badly formed result from changer command %s: \"%s\""),		  cmd, changer_resultstr);    amfree(changer_resultstr);    changer_resultstr = s;    return 2;}static intrun_changer_command(    char *	cmd,    char *	arg,    char **	slotstr,    char **	rest){    int exitcode;    char *result_copy;    char *slot;    char *s;    int ch;    if (slotstr) {        *slotstr = NULL;    }    if (rest) {        *rest = NULL;    }    exitcode = changer_command(cmd, arg);    s = changer_resultstr;    ch = *s++;    skip_whitespace(s, ch);    if(ch == '\0') return report_bad_resultstr(cmd);    slot = s - 1;    skip_non_whitespace(s, ch);    s[-1] = '\0';    if (slotstr) {        *slotstr = newstralloc(*slotstr, slot);    }    s[-1] = (char)ch;    skip_whitespace(s, ch);    if (rest) {        *rest = s - 1;    }    if(exitcode) {	if(ch == '\0') return report_bad_resultstr(cmd);	result_copy = stralloc(s - 1);	amfree(changer_resultstr);	changer_resultstr = result_copy;	return exitcode;    }    return 0;}intchanger_reset(    char **	slotstr){    char *rest;    return run_changer_command("-reset", (char *) NULL, slotstr, &rest);}intchanger_clean(    char **	slotstr){    char *rest;    return run_changer_command("-clean", (char *) NULL, slotstr, &rest);}intchanger_eject(    char **	slotstr){    char *rest;    return run_changer_command("-eject", (char *) NULL, slotstr, &rest);}intchanger_loadslot(    char *inslotstr,    char **outslotstr,    char **devicename){    char *rest;    int rc;    rc = run_changer_command("-slot", inslotstr, outslotstr, &rest);    if(rc) return rc;    if(*rest == '\0') return report_bad_resultstr("-slot");    *devicename = newstralloc(*devicename, rest);    return 0;}/* * This function is somewhat equal to changer_info with one additional * parameter, to get information, if the changer is able to search for * tapelabels himself. E.g. Barcodereader * The changer_script answers with an additional parameter, if it is able * to search. This one should be 1, if it is able to search, and 0 if it * knows about the extension. If the additional answer is omitted, the * changer is not able to search for a tape.  */intchanger_query(    int *	nslotsp,    char **	curslotstr,    int *	backwardsp,    int *	searchable){    char *rest;    int rc;    rc = run_changer_command("-info", (char *) NULL, curslotstr, &rest);    if(rc) return rc;    dbprintf(_("changer_query: changer return was %s\n"),rest);    if (sscanf(rest, "%d %d %d", nslotsp, backwardsp, searchable) != 3) {      if (sscanf(rest, "%d %d", nslotsp, backwardsp) != 2) {        return report_bad_resultstr("-info");      } else {        *searchable = 0;      }    }    dbprintf(_("changer_query: searchable = %d\n"),*searchable);    return 0;}intchanger_info(    int *	nslotsp,    char **	curslotstr,    int *	backwardsp){    char *rest;    int rc;    rc = run_changer_command("-info", (char *) NULL, curslotstr, &rest);    if(rc) return rc;    if (sscanf(rest, "%d %d", nslotsp, backwardsp) != 2) {	return report_bad_resultstr("-info");    }    return 0;}/* ---------------------------- *//* * This function first uses searchlabel and changer_search, if * the library is able to find a tape itself. If it is not, or if  * the tape could not be found, then the normal scan is done. * * See interface documentation in changer.h. */voidchanger_find(     void *	user_data,     int	(*user_init)(void *, int, int, int, int),     int	(*user_slot)(void *, int, char *, char *),     char *	searchlabel){    char *slotstr, *device = NULL, *curslotstr = NULL;    int nslots, checked, backwards, rc, done, searchable;    rc = changer_query(&nslots, &curslotstr, &backwards, &searchable);    if (rc != 0) {        /* Problem with the changer script. Bail. */        g_fprintf(stderr, _("Changer problem: %s\n"), changer_resultstr);        return;    }    done = user_init(user_data, rc, nslots, backwards, searchable);    amfree(curslotstr);       if (searchlabel != NULL)    {      dbprintf(_("changer_find: looking for %s changer is searchable = %d\n"),		searchlabel, searchable);    } else {      dbprintf(_("changer_find: looking for NULL changer is searchable = %d\n"),		searchable);    }    if ((searchlabel!=NULL) && searchable && !done){      rc=changer_search(searchlabel, &curslotstr, &device);      if(rc == 0)        done = user_slot(user_data, rc, curslotstr, device);    }     slotstr = "current";    checked = 0;    while(!done && checked < nslots) {	rc = changer_loadslot(slotstr, &curslotstr, &device);	if(rc > 0)	    done = user_slot(user_data, rc, curslotstr, device);	else if(!done)	    done = user_slot(user_data, 0,  curslotstr, device);	amfree(curslotstr);	amfree(device);	checked += 1;	slotstr = "next";    }}/* ---------------------------- */voidchanger_current(    void *	user_data,    int		(*user_init)(void *, int, int, int, int),    int		(*user_slot)(void *, int, char *, char *)){    char *device = NULL, *curslotstr = NULL;    int nslots, backwards, rc, done, searchable;    rc = changer_query(&nslots, &curslotstr, &backwards, &searchable);    done = user_init(user_data, rc, nslots, backwards, searchable);    amfree(curslotstr);    rc = changer_loadslot("current", &curslotstr, &device);    if(rc > 0) {	done = user_slot(user_data, rc, curslotstr, device);    } else if(!done) {	done = user_slot(user_data, 0,  curslotstr, device);    }    amfree(curslotstr);    amfree(device);}/* ---------------------------- */static intchanger_command(     char *cmd,     char *arg){    int fd[2];    amwait_t wait_exitcode = 1;    int exitcode;    char *cmdstr;    pid_t pid, changer_pid = 0;    int fd_to_close[4], *pfd_to_close = fd_to_close;    cmdstr = vstralloc(tapechanger, " ",		       cmd, arg ? " " : "", 		       arg ? arg : "",		       NULL);    if(changer_debug) {	g_fprintf(stderr, _("changer: opening pipe to: %s\n"), cmdstr);	fflush(stderr);    }    amfree(changer_resultstr);    if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd) == -1) {	changer_resultstr = vstrallocf(				_("<error> could not create pipe for \"%s\": %s"),				cmdstr, strerror(errno));	exitcode = 2;	goto failed;    }    /* make sure fd[0] > 2  && fd[1] > 2 */    pfd_to_close = fd_to_close;    while(fd[0] <= 2) {	int a = dup(fd[0]);	*pfd_to_close++ = fd[0];	fd[0] = a;    }    while(fd[1] <= 2) {	int a = dup(fd[1]);	*pfd_to_close++ = fd[1];	fd[1] = a;    }    while (pfd_to_close > fd_to_close) {	close(*--pfd_to_close);    }    if(fd[0] < 0 || fd[0] >= (int)FD_SETSIZE) {	changer_resultstr = vstrallocf(			_("<error> could not create pipe for \"%s\":"			"socketpair 0: descriptor %d out of range ( 0 .. %d)"),			cmdstr, fd[0], (int)FD_SETSIZE-1);	exitcode = 2;	goto done;    }    if(fd[1] < 0 || fd[1] >= (int)FD_SETSIZE) {	changer_resultstr = vstrallocf(			_("<error> could not create pipe for \"%s\":"			"socketpair 1: descriptor %d out of range ( 0 .. %d)"),			cmdstr, fd[1], (int)FD_SETSIZE-1);	exitcode = 2;	goto done;    }    switch(changer_pid = fork()) {    case -1:	changer_resultstr = vstrallocf(			_("<error> could not fork for \"%s\": %s"),			cmdstr, strerror(errno));	exitcode = 2;	goto done;    case 0:	debug_dup_stderr_to_debug();	if(dup2(fd[1], 1) == -1) {	    changer_resultstr = vstrallocf(			_("<error> could not open pipe to \"%s\": %s"),			cmdstr, strerror(errno));	    (void)fullwrite(fd[1], changer_resultstr, strlen(changer_resultstr));	    exit(1);	}	aclose(fd[0]);	aclose(fd[1]);	if(config_dir && chdir(config_dir) == -1) {	    changer_resultstr = vstrallocf(			_("<error> could not cd to \"%s\": %s"),			config_dir, strerror(errno));	    (void)fullwrite(STDOUT_FILENO, changer_resultstr, strlen(changer_resultstr));	    exit(1);	}	safe_fd(-1, 0);	if(arg) {	    execle(tapechanger, tapechanger, cmd, arg, (char *)NULL,		   safe_env());	} else {	    execle(tapechanger, tapechanger, cmd, (char *)NULL, safe_env());	}	changer_resultstr = vstrallocf(			_("<error> could not exec \"%s\": %s"),			tapechanger, strerror(errno));	(void)fullwrite(STDOUT_FILENO, changer_resultstr, strlen(changer_resultstr));	exit(1);    default:	aclose(fd[1]);    }    if((changer_resultstr = areads(fd[0])) == NULL) {	if (errno == 0) {	    changer_resultstr = vstrallocf(			_("<error> could not read result from \"%s\": Premature end of file, see %s"),			tapechanger, dbfn());	} else {	    changer_resultstr = vstrallocf(			_("<error> could not read result from \"%s\": %s"),			tapechanger, strerror(errno));	}    }    while(1) {	if ((pid = wait(&wait_exitcode)) == -1) {	    if(errno == EINTR) {		continue;	    } else {		changer_resultstr = vstrallocf(			_("<error> wait for \"%s\" failed: %s"),			tapechanger, strerror(errno));		exitcode = 2;		goto done;	    }	} else if (pid != changer_pid) {	    changer_resultstr = vstrallocf(			_("<error> wait for \"%s\" returned unexpected pid %ld"),			tapechanger, (long)pid);	    exitcode = 2;	    goto done;	} else {	    break;	}    }    /* mark out-of-control changers as fatal error */    if(WIFSIGNALED(wait_exitcode)) {	changer_resultstr = newvstrallocf(changer_resultstr,			_("<error> %s (got signal %d)"),			changer_resultstr, WTERMSIG(wait_exitcode));	exitcode = 2;    } else {	exitcode = WEXITSTATUS(wait_exitcode);    }done:    aclose(fd[0]);    aclose(fd[1]);failed:    if (exitcode != 0) {        dbprintf(_("changer: got exit: %d str: %s\n"), exitcode, changer_resultstr);     }    amfree(cmdstr);    return exitcode;}/* * This function commands the changerscript to look for a tape named * searchlabel. If is found, the changerscript answers with the device, * in which the tape can be accessed. */intchanger_search(    char *	searchlabel,    char **	outslotstr,    char **	devicename){    char *rest;    int rc;    dbprintf("changer_search: %s\n",searchlabel);    rc = run_changer_command("-search", searchlabel, outslotstr, &rest);    if(rc) return rc;    if(*rest == '\0') return report_bad_resultstr("-search");    *devicename = newstralloc(*devicename, rest);    return 0;}/* * Because barcodelabel are short, and may not be the same as the  * amandalabels, the changerscript should be informed, which tapelabel * is associated with a tape. This function should be called after  * giving a label for a tape. (Maybe also, when the label and the associated * slot is known. e.g. during library scan. */intchanger_label(    char *	slotsp,     char *	labelstr){    int rc;    char *rest=NULL;    char *slotstr;    char *curslotstr = NULL;    int nslots, backwards, searchable;    dbprintf(_("changer_label: %s for slot %s\n"),labelstr,slotsp);    rc = changer_query(&nslots, &curslotstr, &backwards,&searchable);    amfree(curslotstr);    if ((rc == 0) && (searchable == 1)){	dbprintf(_("changer_label: calling changer -label %s\n"),labelstr);	rc = run_changer_command("-label", labelstr, &slotstr, &rest);	amfree(slotstr);    }    if(rc) return rc;    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -