static int vss_opts_changed(struct sdirs *sdirs, struct conf **cconfs, const char *incexc) { int ret=-1; struct conf **oldconfs; struct conf **newconfs; if(!(oldconfs=confs_alloc()) || !(newconfs=confs_alloc())) goto end; confs_init(oldconfs); confs_init(newconfs); // Figure out the old config, which is in the incexc file left // in the current backup directory on the server. if(conf_parse_incexcs_path(oldconfs, sdirs->cincexc)) { // Assume that the file did not exist, and therefore // the old split_vss setting is 0. set_int(oldconfs[OPT_SPLIT_VSS], 0); set_int(oldconfs[OPT_STRIP_VSS], 0); } // Figure out the new config, which is either in the incexc file from // the client, or in the cconf on the server. if(incexc) { if(conf_parse_incexcs_buf(newconfs, incexc)) { // Should probably not got here. set_int(newconfs[OPT_SPLIT_VSS], 0); set_int(newconfs[OPT_STRIP_VSS], 0); } } else { set_int(newconfs[OPT_SPLIT_VSS], get_int(cconfs[OPT_SPLIT_VSS])); set_int(newconfs[OPT_STRIP_VSS], get_int(cconfs[OPT_STRIP_VSS])); } if(get_int(newconfs[OPT_SPLIT_VSS])!=get_int(oldconfs[OPT_SPLIT_VSS])) { logp("split_vss=%d (changed since last backup)\n", get_int(newconfs[OPT_SPLIT_VSS])); ret=1; goto end; } if(get_int(newconfs[OPT_STRIP_VSS])!=get_int(oldconfs[OPT_STRIP_VSS])) { logp("strip_vss=%d (changed since last backup)\n", get_int(newconfs[OPT_STRIP_VSS])); ret=1; goto end; } ret=0; end: if(ret==1) logp("All files will be treated as new\n"); confs_free(&oldconfs); confs_free(&newconfs); return ret; }
// The return code of this is the return code of the standalone process. int champ_chooser_server_standalone(struct conf **globalcs) { int ret=1; struct sdirs *sdirs=NULL; struct conf **cconfs=NULL; const char *orig_client=get_string(globalcs[OPT_ORIG_CLIENT]); if(!(cconfs=confs_alloc())) goto end; confs_init(cconfs); // We need to be given a client name and load the relevant server side // clientconfdir file, because various settings may be overridden // there. if(set_string(cconfs[OPT_CNAME], orig_client) || conf_load_clientconfdir(globalcs, cconfs) || !(sdirs=sdirs_alloc()) || sdirs_init_from_confs(sdirs, cconfs) || champ_chooser_server(sdirs, cconfs, 0 /* resume */)) goto end; ret=0; end: confs_free(&cconfs); sdirs_free(&sdirs); return ret; }
static void tear_down(struct fdirs **fdirs, struct sdirs **sdirs, struct conf ***confs) { fdirs_free(fdirs); sdirs_free(sdirs); confs_free(confs); alloc_check(); }
static void test_cstat_remove_teardown(struct conf ***globalcs, struct cstat **clist) { confs_free(globalcs); cstat_list_free_sdirs(*clist); cstat_list_free(clist); clean(); alloc_check(); }
static void tear_down( struct sdirs **sdirs, struct fdirs **fdirs, struct conf ***confs) { sdirs_free(sdirs); fdirs_free(fdirs); confs_free(confs); fail_unless(!recursive_delete(BASE)); alloc_check(); }
static void tear_down(FF_PKT **ff, struct conf ***confs) { fail_unless(e==NULL); find_files_free(ff); confs_free(confs); strlists_free(&expected); fail_unless(recursive_delete(BASE)==0); alloc_check(); }
static void tear_down(struct asfd **asfd, struct conf ***confs) { asfd_free(asfd); confs_free(confs); asfd_mock_teardown(&reads, &writes); //printf("%d %d\n", alloc_count, free_count); alloc_check(); fail_unless(recursive_delete(BASE)==0); }
static void tear_down(struct async **as, struct sdirs **sdirs, struct conf ***confs) { async_free(as); sdirs_free(sdirs); confs_free(confs); fail_unless(!recursive_delete(BASE)); //printf("%d %d\n", alloc_count, free_count); alloc_check(); }
static void tear_down(struct async **as, struct asfd **asfd, struct sdirs **sdirs, struct conf ***confs) { async_free(as); asfd_free(asfd); sdirs_free(sdirs); asfd_mock_teardown(&reads, &writes); confs_free(confs); //printf("%d %d\n", alloc_count, free_count); alloc_check(); }
static void tear_down(struct sbuf **sb, struct cntr **cntr, struct conf ***confs, struct asfd **asfd) { clean(); sbuf_free(sb); cntr_free(cntr); confs_free(confs); asfd_free(asfd); asfd_mock_teardown(&areads, &awrites); alloc_check(); }
// FIX THIS: need to unit test this. static int do_conf_switch_to_orig_client(struct conf **globalcs, struct conf **cconfs, const char *orig_client, const char *buf) { int ret=-1; int loadrc; struct conf **sconfs=NULL; if(!(sconfs=confs_alloc()) || confs_init(sconfs)) goto end; if(set_string(sconfs[OPT_CNAME], orig_client)) goto end; logp("Client wants to switch to client: %s\n", get_string(sconfs[OPT_CNAME])); // Allow unit testing using a buffer. #ifdef UTEST if(buf) loadrc=conf_load_overrides_buf(globalcs, sconfs, buf); else #endif loadrc=conf_load_clientconfdir(globalcs, sconfs); if(loadrc) { logp("Could not load alternate config: %s", get_string(sconfs[OPT_CNAME])); goto end; } set_int(sconfs[OPT_SEND_CLIENT_CNTR], get_int(cconfs[OPT_SEND_CLIENT_CNTR])); if(!restore_client_allowed(cconfs, sconfs)) goto end; if(set_string(sconfs[OPT_RESTORE_PATH], get_string(cconfs[OPT_RESTORE_PATH]))) goto end; if(set_string(cconfs[OPT_RESTORE_PATH], NULL)) goto end; set_cntr(sconfs[OPT_CNTR], get_cntr(cconfs[OPT_CNTR])); set_cntr(cconfs[OPT_CNTR], NULL); confs_free_content(cconfs); confs_init(cconfs); confs_memcpy(cconfs, sconfs); confs_null(sconfs); if(set_string(cconfs[OPT_RESTORE_CLIENT], get_string(cconfs[OPT_CNAME]))) goto end; if(set_string(cconfs[OPT_ORIG_CLIENT], get_string(cconfs[OPT_CNAME]))) goto end; logp("Switched to client %s\n", get_string(cconfs[OPT_CNAME])); ret=0; end: confs_free(&sconfs); return ret; }
END_TEST START_TEST(test_cstat_load_data_from_disk) { struct cstat *clist=NULL; struct conf **globalcs; struct conf **cconfs; clist=test_cstat_remove_setup(&globalcs, cnames1234); fail_unless((cconfs=confs_alloc())!=NULL); cstat_load_data_from_disk(&clist, globalcs, cconfs); confs_free(&cconfs); test_cstat_remove_teardown(&globalcs, &clist); }
END_TEST static void check_restore_clients(struct cstat *cstat, struct conf **parentconf, const char *restore_clients, int permitted) { struct conf **cconfs=NULL; fail_unless((cconfs=confs_alloc())!=NULL); fail_unless(!confs_init(cconfs)); fail_unless(!set_string(cconfs[OPT_CNAME], "cli1")); build_clientconfdir_file("cli1", restore_clients); fail_unless(!conf_load_clientconfdir(parentconf, cconfs)); fail_unless(!set_string(parentconf[OPT_CNAME], "cli2")); fail_unless(cstat_permitted(cstat, parentconf, cconfs)==permitted); confs_free(&cconfs); }
// FIX THIS: need to unit test this. int conf_switch_to_orig_client(struct conf **globalcs, struct conf **cconfs, const char *orig_client) { int ret=-1; struct conf **sconfs=NULL; if(!(sconfs=confs_alloc()) || confs_init(sconfs)) goto end; if(set_string(sconfs[OPT_CNAME], orig_client)) goto end; logp("Client wants to switch to client: %s\n", get_string(sconfs[OPT_CNAME])); if(conf_load_clientconfdir(globalcs, sconfs)) { logp("Could not load alternate config: %s", get_string(sconfs[OPT_CNAME])); goto end; } set_int(sconfs[OPT_SEND_CLIENT_CNTR], get_int(cconfs[OPT_SEND_CLIENT_CNTR])); if(!restore_client_allowed(cconfs, sconfs)) goto end; if(set_string(sconfs[OPT_RESTORE_PATH], get_string(cconfs[OPT_RESTORE_PATH]))) goto end; if(set_string(cconfs[OPT_RESTORE_PATH], NULL)) goto end; set_cntr(sconfs[OPT_CNTR], get_cntr(cconfs)); set_cntr(cconfs[OPT_CNTR], NULL); confs_free_content(cconfs); confs_init(cconfs); confs_memcpy(cconfs, sconfs); confs_null(sconfs); if(set_string(cconfs[OPT_RESTORE_CLIENT], get_string(cconfs[OPT_CNAME]))) goto end; if(set_string(cconfs[OPT_ORIG_CLIENT], get_string(cconfs[OPT_CNAME]))) goto end; logp("Switched to client %s\n", get_string(cconfs[OPT_CNAME])); ret=0; end: confs_free(&sconfs); return ret; }
static int run_test_confs(struct conf **confs, const char *client) { int ret=-1; struct conf **cconfs=NULL; if(!client) { confs_dump(confs, 0); ret=0; goto end; } if(!(cconfs=confs_alloc())) goto end; confs_init(cconfs); if(set_string(cconfs[OPT_CNAME], client) || set_string(cconfs[OPT_PEER_VERSION], VERSION) || conf_load_clientconfdir(confs, cconfs)) goto end; confs_dump(cconfs, CONF_FLAG_CC_OVERRIDE|CONF_FLAG_INCEXC); end: confs_free(&cconfs); return ret; }
static int run_child(int *cfd, SSL_CTX *ctx, struct sockaddr_storage *addr, int status_wfd, int status_rfd, const char *conffile, int forking) { int ret=-1; int ca_ret=0; SSL *ssl=NULL; BIO *sbio=NULL; struct conf **confs=NULL; struct conf **cconfs=NULL; struct cntr *cntr=NULL; struct async *as=NULL; const char *cname=NULL; struct asfd *asfd=NULL; int is_status_server=0; if(!(confs=confs_alloc()) || !(cconfs=confs_alloc())) goto end; set_peer_env_vars(addr); // Reload global config, in case things have changed. This means that // the server does not need to be restarted for most conf changes. confs_init(confs); confs_init(cconfs); if(conf_load_global_only(conffile, confs)) goto end; // Hack to keep forking turned off if it was specified as off on the // command line. if(!forking) set_int(confs[OPT_FORK], 0); if(!(sbio=BIO_new_socket(*cfd, BIO_NOCLOSE)) || !(ssl=SSL_new(ctx))) { logp("There was a problem joining ssl to the socket\n"); goto end; } SSL_set_bio(ssl, sbio, sbio); /* Do not try to check peer certificate straight away. Clients can send a certificate signing request when they have no certificate. */ SSL_set_verify(ssl, SSL_VERIFY_PEER /* | SSL_VERIFY_FAIL_IF_NO_PEER_CERT */, 0); if(ssl_do_accept(ssl)) goto end; if(!(as=async_alloc()) || as->init(as, 0) || !(asfd=setup_asfd_ssl(as, "main socket", cfd, ssl))) goto end; asfd->set_timeout(asfd, get_int(confs[OPT_NETWORK_TIMEOUT])); asfd->ratelimit=get_float(confs[OPT_RATELIMIT]); if(authorise_server(as->asfd, confs, cconfs) || !(cname=get_string(cconfs[OPT_CNAME])) || !*cname) { // Add an annoying delay in case they are tempted to // try repeatedly. log_and_send(as->asfd, "unable to authorise on server"); sleep(1); goto end; } if(!get_int(cconfs[OPT_ENABLED])) { log_and_send(as->asfd, "client not enabled on server"); sleep(1); goto end; } // Set up counters. Have to wait until here to get cname. if(!(cntr=cntr_alloc()) || cntr_init(cntr, cname)) goto end; set_cntr(confs[OPT_CNTR], cntr); set_cntr(cconfs[OPT_CNTR], cntr); /* At this point, the client might want to get a new certificate signed. Clients on 1.3.2 or newer can do this. */ if((ca_ret=ca_server_maybe_sign_client_cert(as->asfd, confs, cconfs))<0) { logp("Error signing client certificate request for %s\n", cname); goto end; } else if(ca_ret>0) { // Certificate signed and sent back. // Everything is OK, but we will close this instance // so that the client can start again with a new // connection and its new certificates. logp("Signed and returned client certificate request for %s\n", cname); ret=0; goto end; } /* Now it is time to check the certificate. */ if(ssl_check_cert(ssl, confs, cconfs)) { log_and_send(as->asfd, "check cert failed on server"); goto end; } if(status_rfd>=0) { is_status_server=1; if(!setup_asfd(as, "status server parent socket", &status_rfd)) goto end; } ret=child(as, is_status_server, status_wfd, confs, cconfs); end: *cfd=-1; if(as && asfd_flush_asio(as->asfd)) ret=-1; async_asfd_free_all(&as); // This closes cfd for us. logp("exit child\n"); if(cntr) cntr_free(&cntr); if(confs) { set_cntr(confs[OPT_CNTR], NULL); confs_free(&confs); } if(cconfs) { set_cntr(cconfs[OPT_CNTR], NULL); confs_free(&cconfs); } return ret; }
static #endif int real_main(int argc, char *argv[]) { int ret=1; int option=0; int daemon=1; int forking=1; int strip=0; int randomise=0; struct lock *lock=NULL; struct conf **confs=NULL; int forceoverwrite=0; enum action act=ACTION_LIST; const char *backup=NULL; const char *backup2=NULL; char *restoreprefix=NULL; char *stripfrompath=NULL; const char *regex=NULL; const char *browsefile=NULL; char *browsedir=NULL; const char *conffile=get_conf_path(); const char *orig_client=NULL; const char *logfile=NULL; // The orig_client is the original client that the normal client // would like to restore from. #ifndef HAVE_WIN32 int generate_ca_only=0; #endif int vss_restore=1; int test_confs=0; enum burp_mode mode; log_init(argv[0]); #ifndef HAVE_WIN32 if(!strcmp(prog, "bedup")) return run_bedup(argc, argv); if(!strcmp(prog, "bsigs")) return run_bsigs(argc, argv); #endif while((option=getopt(argc, argv, "a:b:c:C:d:fFghil:nq:Qr:s:tvxjz:?"))!=-1) { switch(option) { case 'a': if(parse_action(&act, optarg)) goto end; break; case 'b': // The diff command may have two backups // specified. if(!backup2 && backup) backup2=optarg; if(!backup) backup=optarg; break; case 'c': conffile=optarg; break; case 'C': orig_client=optarg; break; case 'd': restoreprefix=optarg; // for restores browsedir=optarg; // for lists break; case 'f': forceoverwrite=1; break; case 'F': daemon=0; break; case 'g': #ifndef HAVE_WIN32 generate_ca_only=1; #endif break; case 'i': cmd_print_all(); ret=0; goto end; case 'l': logfile=optarg; break; case 'n': forking=0; break; case 'q': randomise=atoi(optarg); break; case 'Q': log_force_quiet(); break; case 'r': regex=optarg; break; case 's': strip=atoi(optarg); break; case 'v': printf("%s-%s\n", progname(), VERSION); ret=0; goto end; case 'x': vss_restore=0; break; case 't': test_confs=1; break; case 'z': browsefile=optarg; break; case 'h': case '?': default: usage(); goto end; } } if(optind<argc) { usage(); goto end; } if(act==ACTION_MONITOR) { // Try to output everything in JSON. log_set_json(1); #ifndef HAVE_WIN32 // Need to do this so that processes reading stdout get the // result of the printfs of logp straight away. setlinebuf(stdout); #endif } if(!(confs=confs_alloc())) goto end; if(reload(confs, conffile, 1)) goto end; // Dry run to test config file syntax. if(test_confs) { ret=run_test_confs(confs, orig_client); goto end; } if(!backup) switch(act) { case ACTION_DELETE: logp("No backup specified for deletion.\n"); goto end; case ACTION_RESTORE: case ACTION_VERIFY: case ACTION_DIFF: case ACTION_DIFF_LONG: logp("No backup specified. Using the most recent.\n"); backup="0"; default: break; } if(!backup2) switch(act) { case ACTION_DIFF: case ACTION_DIFF_LONG: logp("No second backup specified. Using file system scan.\n"); backup2="n"; // For 'next'. default: break; } // The logfile option is only used for the status client stuff. if(logfile && (act!=ACTION_STATUS && act!=ACTION_STATUS_SNAPSHOT)) logp("-l <logfile> option obsoleted\n"); if(orig_client && *orig_client && set_string(confs[OPT_ORIG_CLIENT], orig_client)) goto end; // The random delay needs to happen before the lock is got, otherwise // you would never be able to use burp by hand. if(randomise) set_int(confs[OPT_RANDOMISE], randomise); mode=get_e_burp_mode(confs[OPT_BURP_MODE]); if(mode==BURP_MODE_CLIENT && (act==ACTION_BACKUP_TIMED || act==ACTION_TIMER_CHECK)) random_delay(confs); if(mode==BURP_MODE_SERVER && act==ACTION_CHAMP_CHOOSER) { // These server modes need to run without getting the lock. } else if(mode==BURP_MODE_CLIENT && (act==ACTION_LIST || act==ACTION_LIST_LONG || act==ACTION_DIFF || act==ACTION_DIFF_LONG || act==ACTION_STATUS || act==ACTION_STATUS_SNAPSHOT || act==ACTION_MONITOR)) { // These client modes need to run without getting the lock. } else { const char *lockfile=confs_get_lockfile(confs); if(!(lock=lock_alloc_and_init(lockfile))) goto end; lock_get(lock); switch(lock->status) { case GET_LOCK_GOT: break; case GET_LOCK_NOT_GOT: logp("Could not get lockfile.\n"); logp("Another process is probably running,\n"); goto end; case GET_LOCK_ERROR: default: logp("Could not get lockfile.\n"); logp("Maybe you do not have permissions to write to %s.\n", lockfile); goto end; } } set_int(confs[OPT_OVERWRITE], forceoverwrite); set_int(confs[OPT_STRIP], strip); set_int(confs[OPT_FORK], forking); set_int(confs[OPT_DAEMON], daemon); strip_trailing_slashes(&restoreprefix); strip_trailing_slashes(&browsedir); if(replace_conf_str(confs[OPT_BACKUP], backup) || replace_conf_str(confs[OPT_BACKUP2], backup2) || replace_conf_str(confs[OPT_RESTOREPREFIX], restoreprefix) || replace_conf_str(confs[OPT_STRIP_FROM_PATH], stripfrompath) || replace_conf_str(confs[OPT_REGEX], regex) || replace_conf_str(confs[OPT_BROWSEFILE], browsefile) || replace_conf_str(confs[OPT_BROWSEDIR], browsedir) || replace_conf_str(confs[OPT_MONITOR_LOGFILE], logfile)) goto end; base64_init(); hexmap_init(); if(mode==BURP_MODE_SERVER) { #ifdef HAVE_WIN32 logp("Sorry, server mode is not implemented for Windows.\n"); #else ret=server_modes(act, conffile, lock, generate_ca_only, confs); #endif } else { ret=client(confs, act, vss_restore); } end: lock_release(lock); lock_free(&lock); confs_free(&confs); return ret; }
int run_bedup(int argc, char *argv[]) { int i=1; int ret=0; int option=0; int nonburp=0; unsigned int maxlinks=DEF_MAX_LINKS; char *groups=NULL; char ext[16]=""; int givenconfigfile=0; const char *configfile=NULL; configfile=get_config_path(); snprintf(ext, sizeof(ext), ".bedup.%d", getpid()); while((option=getopt(argc, argv, "c:dg:hlm:nvV?"))!=-1) { switch(option) { case 'c': configfile=optarg; givenconfigfile=1; break; case 'd': deletedups=1; break; case 'g': groups=optarg; break; case 'l': makelinks=1; break; case 'm': maxlinks=atoi(optarg); break; case 'n': nonburp=1; break; case 'V': printf("%s-%s\n", prog, VERSION); return 0; case 'v': verbose=1; break; case 'h': case '?': return usage(); } } if(nonburp && givenconfigfile) { logp("-n and -c options are mutually exclusive\n"); return 1; } if(nonburp && groups) { logp("-n and -g options are mutually exclusive\n"); return 1; } if(!nonburp && maxlinks!=DEF_MAX_LINKS) { logp("-m option is specified via the configuration file in burp mode (max_hardlinks=)\n"); return 1; } if(deletedups && makelinks) { logp("-d and -l options are mutually exclusive\n"); return 1; } if(deletedups && !nonburp) { logp("-d option requires -n option\n"); return 1; } if(optind>=argc) { if(nonburp) { logp("No directories found after options\n"); return 1; } } else { if(!nonburp) { logp("Do not specify extra arguments.\n"); return 1; } } if(maxlinks<2) { logp("The argument to -m needs to be greater than 1.\n"); return 1; } if(nonburp) { // Read directories from command line. for(i=optind; i<argc; i++) { // Strip trailing slashes, for tidiness. if(argv[i][strlen(argv[i])-1]=='/') argv[i][strlen(argv[i])-1]='\0'; if(process_dir("", argv[i], ext, maxlinks, 0 /* not burp mode */, 0 /* level */)) { ret=1; break; } } } else { struct conf **globalcs=NULL; struct strlist *grouplist=NULL; struct lock *globallock=NULL; if(groups) { char *tok=NULL; if((tok=strtok(groups, ",\n"))) { do { if(strlist_add(&grouplist, tok, 1)) { log_out_of_memory(__func__); return -1; } } while((tok=strtok(NULL, ",\n"))); } if(!grouplist) { logp("unable to read list of groups\n"); return -1; } } // Read directories from config files, and get locks. if(!(globalcs=confs_alloc())) return -1; if(confs_init(globalcs)) return -1; if(conf_load_global_only(configfile, globalcs)) return 1; if(get_e_burp_mode(globalcs[OPT_BURP_MODE])!=BURP_MODE_SERVER) { logp("%s is not a server config file\n", configfile); confs_free(&globalcs); return 1; } logp("Dedup clients from %s\n", get_string(globalcs[OPT_CLIENTCONFDIR])); maxlinks=get_int(globalcs[OPT_MAX_HARDLINKS]); if(grouplist) { struct strlist *g=NULL; logp("in dedup groups:\n"); for(g=grouplist; g; g=g->next) logp("%s\n", g->path); } else { char *lockpath=NULL; // Only get the global lock when doing a global run. // If you are doing individual groups, you are likely // to want to do many different dedup jobs and a // global lock would get in the way. if(!(lockpath=prepend( get_string(globalcs[OPT_LOCKFILE]), ".bedup", "")) || !(globallock=lock_alloc_and_init(lockpath))) return 1; lock_get(globallock); if(globallock->status!=GET_LOCK_GOT) { logp("Could not get lock %s (%d)\n", lockpath, globallock->status); free_w(&lockpath); return 1; } logp("Got %s\n", lockpath); } ret=iterate_over_clients(globalcs, grouplist, ext, maxlinks); confs_free(&globalcs); lock_release(globallock); lock_free(&globallock); strlists_free(&grouplist); } if(!nonburp) { logp("%d client storages scanned\n", ccount); } logp("%llu duplicate %s found\n", count, count==1?"file":"files"); logp("%llu bytes %s%s\n", savedbytes, (makelinks || deletedups)?"saved":"saveable", bytes_to_human(savedbytes)); return ret; }
static int iterate_over_clients(struct conf **globalcs, struct strlist *grouplist, const char *ext, unsigned int maxlinks) { int ret=0; DIR *dirp=NULL; struct conf **cconfs=NULL; struct dirent *dirinfo=NULL; const char *globalclientconfdir=get_string(globalcs[OPT_CLIENTCONFDIR]); signal(SIGABRT, &sighandler); signal(SIGTERM, &sighandler); signal(SIGINT, &sighandler); if(!(cconfs=confs_alloc())) return -1; if(confs_init(cconfs)) return -1; if(!(dirp=opendir(globalclientconfdir))) { logp("Could not opendir '%s': %s\n", globalclientconfdir, strerror(errno)); return 0; } while((dirinfo=readdir(dirp))) { char *lockfile=NULL; char *lockfilebase=NULL; char *client_lockdir=NULL; struct lock *lock=NULL; if(dirinfo->d_ino==0 // looks_like...() also avoids '.' and '..'. || looks_like_tmp_or_hidden_file(dirinfo->d_name) || !is_regular_file(globalclientconfdir, dirinfo->d_name)) continue; confs_free_content(cconfs); if(confs_init(cconfs)) return -1; if(set_string(cconfs[OPT_CNAME], dirinfo->d_name)) return -1; if(conf_load_clientconfdir(globalcs, cconfs)) { logp("could not load config for client %s\n", dirinfo->d_name); return 0; } if(grouplist) { const char *dedup_group= get_string(cconfs[OPT_DEDUP_GROUP]); if(!dedup_group || !in_group(grouplist, dedup_group)) continue; } if(!(client_lockdir=get_string(cconfs[OPT_CLIENT_LOCKDIR]))) client_lockdir=get_string(cconfs[OPT_DIRECTORY]); if(!(lockfilebase=prepend(client_lockdir, dirinfo->d_name, "/")) || !(lockfile=prepend(lockfilebase, BEDUP_LOCKFILE_NAME, "/"))) { free_w(&lockfilebase); free_w(&lockfile); ret=-1; break; } free_w(&lockfilebase); if(!(lock=lock_alloc_and_init(lockfile))) { ret=-1; break; } lock_get(lock); free_w(&lockfile); if(lock->status!=GET_LOCK_GOT) { logp("Could not get %s\n", lock->path); continue; } logp("Got %s\n", lock->path); // Remember that we got that lock. lock_add_to_list(&locklist, lock); if(process_dir(get_string(cconfs[OPT_DIRECTORY]), dirinfo->d_name, ext, maxlinks, 1 /* burp mode */, 0 /* level */)) { ret=-1; break; } ccount++; } closedir(dirp); locks_release_and_free(&locklist); confs_free(&cconfs); return ret; }
static void tear_down(struct conf ***globalcs, struct conf ***confs) { confs_free(confs); confs_free(globalcs); fail_unless(free_count==alloc_count); }