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 = g_strjoin(NULL, infodir, "/", myhost, "/", mydisk, "/info", NULL); fn_new = g_strconcat(fn, ".new", NULL); amfree(myhost); amfree(mydisk); unlink(fn_new); amfree(fn_new); rc = rmpdir(fn, infodir); amfree(fn); return rc; }
int check_infofile( char *infodir, disklist_t *dl, char **errmsg) { disk_t *dp, *diskp; char *hostinfodir, *old_hostinfodir, *Xhostinfodir; char *diskdir, *old_diskdir, *Xdiskdir; char *infofile, *old_infofile, *Xinfofile; struct stat statbuf; int other_dle_match; if (stat(infodir, &statbuf) != 0) { return 0; } for (dp = dl->head; dp != NULL; dp = dp->next) { hostinfodir = sanitise_filename(dp->host->hostname); diskdir = sanitise_filename(dp->name); infofile = vstralloc(infodir, "/", hostinfodir, "/", diskdir, "/info", NULL); if (stat(infofile, &statbuf) == -1 && errno == ENOENT) { old_hostinfodir = old_sanitise_filename(dp->host->hostname); old_diskdir = old_sanitise_filename(dp->name); old_infofile = vstralloc(infodir, old_hostinfodir, "/", old_diskdir, "/info", NULL); if (stat(old_infofile, &statbuf) == 0) { other_dle_match = 0; diskp = dl->head; while (diskp != NULL) { Xhostinfodir = sanitise_filename(diskp->host->hostname); Xdiskdir = sanitise_filename(diskp->name); Xinfofile = vstralloc(infodir, "/", Xhostinfodir, "/", Xdiskdir, "/info", NULL); if (strcmp(old_infofile, Xinfofile) == 0) { other_dle_match = 1; diskp = NULL; } else { diskp = diskp->next; } } if (other_dle_match == 0) { if(mkpdir(infofile, (mode_t)0755, (uid_t)-1, (gid_t)-1) == -1) { *errmsg = vstralloc("Can't create directory for ", infofile, NULL); return -1; } if(copy_file(infofile, old_infofile, errmsg) == -1) return -1; } } } amfree(diskdir); amfree(hostinfodir); amfree(infofile); } return 0; }
char * getindexfname( char * host, char * disk, char * date, int level) { char *conf_indexdir; char *buf; char level_str[NUM_STR_SIZE]; char datebuf[14 + 1]; char *dc = NULL; char *pc; int ch; if (date != NULL) { dc = date; pc = datebuf; while (pc < datebuf + sizeof(datebuf)) { ch = *dc++; *pc++ = (char)ch; if (ch == '\0') { break; } else if (! isdigit (ch)) { pc--; } } datebuf[sizeof(datebuf)-1] = '\0'; dc = datebuf; g_snprintf(level_str, sizeof(level_str), "%d", level); } host = sanitise_filename(host); if (disk != NULL) { disk = sanitise_filename(disk); } conf_indexdir = config_dir_relative(getconf_str(CNF_INDEXDIR)); /* * Note: g_strjoin(NULL, ) will stop at the first NULL, which might be * "disk" or "dc" (datebuf) rather than the full file name. */ buf = g_strjoin(NULL, conf_indexdir, "/", host, "/", disk, "/", dc, "_", level_str, COMPRESS_SUFFIX, NULL); amfree(conf_indexdir); amfree(host); amfree(disk); return buf; }
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 = g_strjoin(NULL, 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 = g_strconcat(infofile, ".new", NULL); 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; }
/* * 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; am_level_t *alevel = (am_level_t *)dle->levellist->data; int level = alevel->level; int native_pipe[2]; int client_pipe[2]; int data_out; have_filter = FALSE; crc32_init(&native_crc.crc); crc32_init(&client_crc.crc); /* create pipes to compute the native CRC */ if (pipe(native_pipe) < 0) { char *errmsg; char *qerrmsg; errmsg = g_strdup_printf(_("Program '%s': can't create pipe"), dle->program); qerrmsg = quote_string(errmsg); fdprintf(mesgf, _("sendbackup: error [%s]\n"), errmsg); dbprintf(_("ERROR %s\n"), qerrmsg); amfree(qerrmsg); amfree(errmsg); return; } if (dle->encrypt == ENCRYPT_CUST || dle->compress == COMP_FAST || dle->compress == COMP_BEST || dle->compress == COMP_CUST) { have_filter = TRUE; /* create pipes to compute the client CRC */ if (pipe(client_pipe) < 0) { char *errmsg; char *qerrmsg; errmsg = g_strdup_printf(_("Application '%s': can't create pipe"), dle->program); qerrmsg = quote_string(errmsg); fdprintf(mesgf, _("sendbackup: error [%s]\n"), errmsg); dbprintf(_("ERROR %s\n"), qerrmsg); amfree(qerrmsg); amfree(errmsg); return; } data_out = client_pipe[1]; client_pipe[1] = -1; } else { data_out = dataf; dataf = -1; } error_pn = g_strconcat(get_pname(), "-smbclient", NULL); 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, &data_out, &mesgf, dle->clnt_encrypt, encryptopt, NULL); dbprintf(_("gnutar: pid %ld: %s\n"), (long)encpid, dle->clnt_encrypt); aclose(data_out); } else { compout = data_out; data_out = -1; 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); } aclose(compout); } 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); } aclose(compout); } else { dumpout = compout; compout = -1; 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); g_free(inputname); inputname = g_strconcat(basename, "_", number, NULL); } else { g_free(inputname); inputname = g_strdup("/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, native_pipe[1], 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, &native_pipe[1], &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; messagelist_t mlist = 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, &mlist); if (nb_include > 0) file_include = build_include(dle, dirname, &mlist); g_slist_free(mlist); // MUST also free the message cmd = g_strjoin(NULL, amlibexecdir, "/", "runtar", NULL); info_tapeheader(dle); start_index(dle->create_index, native_pipe[1], 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, &native_pipe[1], &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(native_pipe[1]); aclose(mesgf); if (dle->create_index) aclose(indexf); if (shm_control_name) { shm_ring = shm_ring_link(shm_control_name); shm_ring_producer_set_size(shm_ring, NETWORK_BLOCK_BYTES*16, NETWORK_BLOCK_BYTES*4); native_crc.in = native_pipe[0]; if (!have_filter) { native_crc.out = dumpout; native_crc.shm_ring = shm_ring; native_crc.thread = g_thread_create(handle_crc_to_shm_ring_thread, (gpointer)&native_crc, TRUE, NULL); } else { native_crc.out = dumpout; native_crc.thread = g_thread_create(handle_crc_thread, (gpointer)&native_crc, TRUE, NULL); client_crc.in = client_pipe[0]; client_crc.out = dataf; client_crc.shm_ring = shm_ring; client_crc.thread = g_thread_create(handle_crc_to_shm_ring_thread, (gpointer)&client_crc, TRUE, NULL); } } else { native_crc.in = native_pipe[0]; native_crc.out = dumpout; native_crc.thread = g_thread_create(handle_crc_thread, (gpointer)&native_crc, TRUE, NULL); if (have_filter) { client_crc.in = client_pipe[0]; client_crc.out = dataf; client_crc.thread = g_thread_create(handle_crc_thread, (gpointer)&client_crc, TRUE, NULL); } } }
int main( int argc, char ** argv) { GList *dlist; GList *dlist1; 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; gboolean compress_index; gboolean sort_index; char *lock_file; file_lock *lock_index; if (argc > 1 && argv[1] && g_str_equal(argv[1], "--version")) { printf("amtrmidx-%s\n", VERSION); return (0); } /* * 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 && g_str_equal(argv[1], "-t")) { 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_with_global(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); compress_index = getconf_boolean(CNF_COMPRESS_INDEX); sort_index = getconf_boolean(CNF_SORT_INDEX); output_find = find_dump(&diskl); conf_indexdir = config_dir_relative(getconf_str(CNF_INDEXDIR)); /* take a lock file to prevent concurent trim */ lock_file = g_strdup_printf("%s/%s", conf_indexdir, "lock"); lock_index = file_lock_new(lock_file); if (file_lock_lock_wr(lock_index) != 0) goto lock_failed; /* 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 (dlist = diskl.head; dlist != NULL; dlist = dlist->next) { diskp = dlist->data; 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 (dlist1 = diskl.head; dlist1 != NULL; dlist1 = dlist1->next) { char *dp_host, *dp_disk; dp = dlist1->data; dp_host = sanitise_filename(dp->host->hostname); dp_disk = sanitise_filename(dp->name); if (g_str_equal(host, dp_host) && g_str_equal(disk, dp_disk)) { 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(qdisk); if ((d = opendir(indexdir)) == NULL) { dbprintf(_("could not open index directory %s\n"), qindexdir); amfree(host); amfree(disk); 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)) && (g_str_equal(f->d_name + l, ".tmp"))) { struct stat sbuf; char *path, *qpath; path = g_strconcat(indexdir, f->d_name, NULL); 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) { struct stat sbuf; char *path, *qpath; path = g_strconcat(indexdir, names[i], NULL); 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); } /* Did it require un/compression and/or sorting */ { char *orig_name = getindexfname(host, disk, datestamp, level); char *sorted_name = getindex_sorted_fname(host, disk, datestamp, level); char *sorted_gz_name = getindex_sorted_gz_fname(host, disk, datestamp, level); char *unsorted_name = getindex_unsorted_fname(host, disk, datestamp, level); char *unsorted_gz_name = getindex_unsorted_gz_fname(host, disk, datestamp, level); gboolean orig_exist = FALSE; gboolean sorted_exist = FALSE; gboolean sorted_gz_exist = FALSE; gboolean unsorted_exist = FALSE; gboolean unsorted_gz_exist = FALSE; int fd; int uncompress_err_fd = -1; int sort_err_fd = -1; int compress_err_fd = -1; pid_t uncompress_pid = -1; pid_t sort_pid = -1; pid_t compress_pid = -1; orig_exist = file_exists(orig_name); sorted_exist = file_exists(sorted_name); sorted_gz_exist = file_exists(sorted_gz_name); unsorted_exist = file_exists(unsorted_name); unsorted_gz_exist = file_exists(unsorted_gz_name); if (sort_index && compress_index) { if (!sorted_gz_exist) { if (sorted_exist) { // COMPRESS compress_pid = run_compress(-1, NULL, &compress_err_fd, sorted_name, sorted_gz_name); unlink(sorted_name); } else if (unsorted_exist) { // SORT AND COMPRESS sort_pid = run_sort(-1, &fd, &sort_err_fd, unsorted_name, NULL); compress_pid = run_compress(fd, NULL, &compress_err_fd, NULL, sorted_gz_name); unlink(unsorted_name); } else if (unsorted_gz_exist) { // UNCOMPRESS SORT AND COMPRESS uncompress_pid = run_uncompress(-1, &fd, &uncompress_err_fd, unsorted_gz_name, NULL); sort_pid = run_sort(fd, &fd, &sort_err_fd, NULL, NULL); compress_pid = run_compress(fd, NULL, &compress_err_fd, NULL, sorted_gz_name); unlink(unsorted_gz_name); } else if (orig_exist) { // UNCOMPRESS SORT AND COMPRESS uncompress_pid = run_uncompress(-1, &fd, &uncompress_err_fd, orig_name, NULL); sort_pid = run_sort(fd, &fd, &sort_err_fd, NULL, NULL); compress_pid = run_compress(fd, NULL, &compress_err_fd, NULL, sorted_gz_name); unlink(orig_name); } } else { if (sorted_exist) { unlink(sorted_name); } if (unsorted_exist) { unlink(unsorted_name); } if (unsorted_gz_exist) { unlink(unsorted_gz_name); } } } else if (sort_index && !compress_index) { if (!sorted_exist) { if (sorted_gz_exist) { // UNCOMPRESS uncompress_pid = run_uncompress(-1, NULL, &uncompress_err_fd, sorted_gz_name, sorted_name); unlink(sorted_gz_name); } else if (unsorted_exist) { // SORT sort_pid = run_sort(-1, NULL, &sort_err_fd, unsorted_name, sorted_name); unlink(unsorted_name); } else if (unsorted_gz_exist) { // UNCOMPRESS AND SORT uncompress_pid = run_uncompress(-1, &fd, &uncompress_err_fd, unsorted_gz_name, NULL); sort_pid = run_sort(fd, NULL, &sort_err_fd, NULL, sorted_name); unlink(unsorted_gz_name); } else if (orig_exist) { // UNCOMPRESS AND SORT uncompress_pid = run_uncompress(-1, &fd, &uncompress_err_fd, orig_name, NULL); sort_pid = run_sort(fd, NULL, &sort_err_fd, NULL, sorted_name); unlink(orig_name); } } else { if (sorted_gz_exist) { unlink(sorted_gz_name); } if (unsorted_exist) { unlink(unsorted_name); } if (unsorted_gz_exist) { unlink(unsorted_gz_name); } } } else if (!sort_index && compress_index) { if (!sorted_gz_exist && !unsorted_gz_exist) { if (sorted_exist) { // COMPRESS sorted compress_pid = run_compress(-1, NULL, &compress_err_fd, sorted_name, sorted_gz_name); unlink(sorted_name); } else if (unsorted_exist) { // COMPRESS unsorted compress_pid = run_compress(-1, NULL, &compress_err_fd, unsorted_name, unsorted_gz_name); unlink(unsorted_name); } else if (orig_exist) { // RENAME orig rename(orig_name, unsorted_gz_name); } } else { if (sorted_exist) { unlink(sorted_name); } if (unsorted_exist) { unlink(unsorted_name); } if (sorted_gz_exist && unsorted_gz_exist) { unlink(unsorted_gz_name); } } } else if (!sort_index && !compress_index) { if (!sorted_exist && !unsorted_exist) { if (sorted_gz_exist) { // UNCOMPRESS sorted uncompress_pid = run_uncompress(-1, NULL, &uncompress_err_fd, sorted_gz_name, sorted_name); unlink(sorted_gz_name); } else if (unsorted_gz_exist) { // UNCOMPRESS unsorted uncompress_pid = run_uncompress(-1, NULL, &uncompress_err_fd, unsorted_gz_name, unsorted_name); unlink(unsorted_gz_name); } else if (orig_exist) { // UNCOMPRESS orig uncompress_pid = run_uncompress(-1, NULL, &uncompress_err_fd, orig_name, unsorted_name); unlink(orig_name); } } else { if (sorted_gz_exist) { unlink(sorted_gz_name); } if (unsorted_gz_exist) { unlink(unsorted_gz_name); } if (sorted_exist && unsorted_exist) { unlink(unsorted_name); } } } if (uncompress_pid != -1) wait_process(uncompress_pid, uncompress_err_fd, "uncompress"); if (sort_pid != -1) wait_process(sort_pid, sort_err_fd, "sort"); if (compress_pid != -1) wait_process(compress_pid, compress_err_fd, "compress"); g_free(orig_name); g_free(sorted_name); g_free(sorted_gz_name); g_free(unsorted_name); g_free(unsorted_gz_name); } amfree(datestamp); amfree(names[i]); } g_slist_free(matching_dp); amfree(names); amfree(host); amfree(disk); amfree(indexdir); amfree(qindexdir); } } file_lock_unlock(lock_index); lock_failed: file_lock_free(lock_index); amfree(conf_indexdir); amfree(lock_file); free_find_result(&output_find); clear_tapelist(); free_disklist(&diskl); unload_disklist(); dbclose(); return 0; }
static void amgtar_restore( application_argument_t *argument) { char *cmd; GPtrArray *argv_ptr = g_ptr_array_new(); char **env; int j; char *e; char *include_filename = NULL; char *exclude_filename = NULL; int tarpid; if (!gnutar_path) { error(_("GNUTAR-PATH not defined")); } cmd = g_strdup(gnutar_path); g_ptr_array_add(argv_ptr, g_strdup(gnutar_path)); g_ptr_array_add(argv_ptr, g_strdup("--numeric-owner")); if (gnutar_no_unquote) g_ptr_array_add(argv_ptr, g_strdup("--no-unquote")); if (gnutar_acls) g_ptr_array_add(argv_ptr, g_strdup("--acls")); if (gnutar_selinux) g_ptr_array_add(argv_ptr, g_strdup("--selinux")); if (gnutar_xattrs) g_ptr_array_add(argv_ptr, g_strdup("--xattrs")); /* ignore trailing zero blocks on input (this was the default until tar-1.21) */ if (argument->ignore_zeros) { g_ptr_array_add(argv_ptr, g_strdup("--ignore-zeros")); } if (argument->tar_blocksize) { g_ptr_array_add(argv_ptr, g_strdup("--blocking-factor")); g_ptr_array_add(argv_ptr, g_strdup(argument->tar_blocksize)); } g_ptr_array_add(argv_ptr, g_strdup("-xpGvf")); g_ptr_array_add(argv_ptr, g_strdup("-")); if (gnutar_directory) { struct stat stat_buf; if(stat(gnutar_directory, &stat_buf) != 0) { fprintf(stderr,"can not stat directory %s: %s\n", gnutar_directory, strerror(errno)); exit(1); } if (!S_ISDIR(stat_buf.st_mode)) { fprintf(stderr,"%s is not a directory\n", gnutar_directory); exit(1); } if (access(gnutar_directory, W_OK) != 0) { fprintf(stderr, "Can't write to %s: %s\n", gnutar_directory, strerror(errno)); exit(1); } g_ptr_array_add(argv_ptr, g_strdup("--directory")); g_ptr_array_add(argv_ptr, g_strdup(gnutar_directory)); } g_ptr_array_add(argv_ptr, g_strdup("--wildcards")); if (argument->dle.exclude_list && argument->dle.exclude_list->nb_element == 1) { FILE *exclude; char *sdisk; int in_argv; int entry_in_exclude = 0; char line[2*PATH_MAX]; FILE *exclude_list; if (argument->dle.disk) { sdisk = sanitise_filename(argument->dle.disk); } else { sdisk = g_strdup_printf("no_dle-%d", (int)getpid()); } exclude_filename= g_strjoin(NULL, AMANDA_TMPDIR, "/", "exclude-", sdisk, NULL); exclude_list = fopen(argument->dle.exclude_list->first->name, "r"); if (!exclude_list) { fprintf(stderr, "Cannot open exclude file '%s': %s\n", argument->dle.exclude_list->first->name, strerror(errno)); error("Cannot open exclude file '%s': %s\n", argument->dle.exclude_list->first->name, strerror(errno)); /*NOTREACHED*/ } exclude = fopen(exclude_filename, "w"); if (!exclude) { fprintf(stderr, "Cannot open exclude file '%s': %s\n", exclude_filename, strerror(errno)); fclose(exclude_list); error("Cannot open exclude file '%s': %s\n", exclude_filename, strerror(errno)); /*NOTREACHED*/ } while (fgets(line, 2*PATH_MAX, exclude_list)) { char *escaped; line[strlen(line)-1] = '\0'; /* remove '\n' */ escaped = escape_tar_glob(line, &in_argv); if (in_argv) { g_ptr_array_add(argv_ptr, "--exclude"); g_ptr_array_add(argv_ptr, escaped); } else { fprintf(exclude,"%s\n", escaped); entry_in_exclude++; amfree(escaped); } } fclose(exclude_list); fclose(exclude); g_ptr_array_add(argv_ptr, g_strdup("--exclude-from")); g_ptr_array_add(argv_ptr, exclude_filename); } if (argument->exclude_list_glob) { g_ptr_array_add(argv_ptr, g_strdup("--exclude-from")); g_ptr_array_add(argv_ptr, g_strdup(argument->exclude_list_glob)); } { GPtrArray *argv_include = g_ptr_array_new(); FILE *include; char *sdisk; int in_argv; guint i; int entry_in_include = 0; if (argument->dle.disk) { sdisk = sanitise_filename(argument->dle.disk); } else { sdisk = g_strdup_printf("no_dle-%d", (int)getpid()); } include_filename = g_strjoin(NULL, AMANDA_TMPDIR, "/", "include-", sdisk, NULL); include = fopen(include_filename, "w"); if (!include) { fprintf(stderr, "Cannot open include file '%s': %s\n", include_filename, strerror(errno)); error("Cannot open include file '%s': %s\n", include_filename, strerror(errno)); /*NOTREACHED*/ } if (argument->dle.include_list && argument->dle.include_list->nb_element == 1) { char line[2*PATH_MAX]; FILE *include_list = fopen(argument->dle.include_list->first->name, "r"); if (!include_list) { fclose(include); fprintf(stderr, "Cannot open include file '%s': %s\n", argument->dle.include_list->first->name, strerror(errno)); error("Cannot open include file '%s': %s\n", argument->dle.include_list->first->name, strerror(errno)); /*NOTREACHED*/ } while (fgets(line, 2*PATH_MAX, include_list)) { char *escaped; line[strlen(line)-1] = '\0'; /* remove '\n' */ escaped = escape_tar_glob(line, &in_argv); if (in_argv) { g_ptr_array_add(argv_include, escaped); } else { fprintf(include,"%s\n", escaped); entry_in_include++; amfree(escaped); } } fclose(include_list); } for (j=1; j< argument->argc; j++) { char *escaped = escape_tar_glob(argument->argv[j], &in_argv); if (in_argv) { g_ptr_array_add(argv_include, escaped); } else { fprintf(include,"%s\n", escaped); entry_in_include++; amfree(escaped); } } fclose(include); if (entry_in_include) { g_ptr_array_add(argv_ptr, g_strdup("--files-from")); g_ptr_array_add(argv_ptr, include_filename); } if (argument->include_list_glob) { g_ptr_array_add(argv_ptr, g_strdup("--files-from")); g_ptr_array_add(argv_ptr, g_strdup(argument->include_list_glob)); } for (i = 0; i < argv_include->len; i++) { g_ptr_array_add(argv_ptr, (char *)g_ptr_array_index(argv_include,i)); } amfree(sdisk); } g_ptr_array_add(argv_ptr, NULL); debug_executing(argv_ptr); tarpid = fork(); switch (tarpid) { case -1: error(_("%s: fork returned: %s"), get_pname(), strerror(errno)); case 0: env = safe_env(); become_root(); execve(cmd, (char **)argv_ptr->pdata, env); e = strerror(errno); error(_("error [exec %s: %s]"), cmd, e); break; default: break; } waitpid(tarpid, NULL, 0); if (argument->verbose == 0) { if (exclude_filename) unlink(exclude_filename); unlink(include_filename); } amfree(cmd); amfree(include_filename); amfree(exclude_filename); }
int check_infofile( char *infodir, disklist_t *dl, char **errmsg) { GList *dlist, *dlist1; disk_t *dp, *diskp; char *hostinfodir, *old_hostinfodir; char *diskdir, *old_diskdir; char *infofile, *old_infofile; struct stat statbuf; int other_dle_match; if (stat(infodir, &statbuf) != 0) { return 0; } // for (dp = dl->head; dp != NULL; dp = dp->next) { for (dlist = dl->head; dlist != NULL; dlist = dlist->next) { dp = dlist->data; hostinfodir = sanitise_filename(dp->host->hostname); diskdir = sanitise_filename(dp->name); infofile = g_strjoin(NULL, infodir, "/", hostinfodir, "/", diskdir, "/info", NULL); if (stat(infofile, &statbuf) == -1 && errno == ENOENT) { old_hostinfodir = old_sanitise_filename(dp->host->hostname); old_diskdir = old_sanitise_filename(dp->name); old_infofile = g_strjoin(NULL, infodir, old_hostinfodir, "/", old_diskdir, "/info", NULL); if (stat(old_infofile, &statbuf) == 0) { other_dle_match = 0; dlist1 = dl->head; while (dlist1 != NULL) { char *Xhostinfodir; char *Xdiskdir; char *Xinfofile; diskp = dlist1->data; Xhostinfodir = sanitise_filename(diskp->host->hostname); Xdiskdir = sanitise_filename(diskp->name); Xinfofile = g_strjoin(NULL, infodir, "/", Xhostinfodir, "/", Xdiskdir, "/info", NULL); if (g_str_equal(old_infofile, Xinfofile)) { other_dle_match = 1; dlist1 = NULL; } else { dlist1 = dlist1->next; } amfree(Xhostinfodir); amfree(Xdiskdir); amfree(Xinfofile); } if (other_dle_match == 0) { if(mkpdir(infofile, (mode_t)0755, (uid_t)-1, (gid_t)-1) == -1) { *errmsg = g_strjoin(NULL, "Can't create directory for ", infofile, NULL); amfree(hostinfodir); amfree(diskdir); amfree(infofile); amfree(old_hostinfodir); amfree(old_diskdir); amfree(old_infofile); return -1; } if(copy_file(infofile, old_infofile, errmsg) == -1) { amfree(hostinfodir); amfree(diskdir); amfree(infofile); amfree(old_hostinfodir); amfree(old_diskdir); amfree(old_infofile); return -1; } } } amfree(old_hostinfodir); amfree(old_diskdir); amfree(old_infofile); } amfree(diskdir); amfree(hostinfodir); amfree(infofile); } return 0; }