static int do_lock_dirs(struct sdirs *sdirs, struct conf *conf) { int ret=-1; char *lockbase=NULL; char *lockfile=NULL; if(conf->client_lockdir) { if(!(sdirs->lockdir=strdup_w(conf->client_lockdir, __func__)) || !(lockbase=prepend_s(sdirs->lockdir, conf->cname))) goto end; } else { if(!(sdirs->lockdir=strdup_w(sdirs->client, __func__)) || !(lockbase=strdup_w(sdirs->client, __func__))) goto end; } if(!(lockfile=prepend_s(lockbase, "lockfile")) || !(sdirs->lock=lock_alloc_and_init(lockfile))) goto end; ret=0; end: free_w(&lockbase); free_w(&lockfile); return ret; }
static struct sbuf *setup_sbuf(const char *path, const char *datapth, const char *endfile, int compression) { struct sbuf *sb; fail_unless((sb=sbuf_alloc(PROTO_1))!=NULL); if(path) { fail_unless((path=strdup_w(path, __func__))!=NULL); iobuf_from_str(&sb->path, CMD_FILE, (char *)path); } if(datapth) { fail_unless((datapth=strdup_w("/datapth", __func__))!=NULL); iobuf_from_str(&sb->protocol1->datapth, CMD_FILE, (char *)datapth); } if(endfile) { fail_unless((endfile=strdup_w(endfile, __func__))!=NULL); iobuf_from_str(&sb->endfile, CMD_END_FILE, (char *)endfile); } sb->compression=compression; return sb; }
static void run_test(int expected_ret, void setup_asfds_callback(struct asfd *sfd, struct asfd *in, struct asfd *out)) { struct async *as; struct asfd *sfd; struct asfd *in; struct asfd *out; as=setup(); sfd=asfd_mock_setup(&areads, &awrites); in=asfd_mock_setup(&ireads, &iwrites); out=asfd_mock_setup(&oreads, &owrites); fail_unless((sfd->desc=strdup_w("main_socket", __func__))!=NULL); fail_unless((in->desc=strdup_w("stdin", __func__))!=NULL); fail_unless((out->desc=strdup_w("stdout", __func__))!=NULL); as->asfd_add(as, sfd); as->asfd_add(as, in); as->asfd_add(as, out); as->read_write=async_rw_both; setup_asfds_callback(sfd, in, out); fail_unless(monitor_client_main_loop(as)==expected_ret); asfd_free(&in); asfd_free(&out); asfd_free(&sfd); asfd_mock_teardown(&areads, &awrites); asfd_mock_teardown(&ireads, &iwrites); asfd_mock_teardown(&oreads, &owrites); tear_down(&as); }
static struct manio *do_manio_open(const char *manifest, const char *mode, enum protocol protocol, int phase) { struct manio *manio=NULL; if(!(manio=manio_alloc()) || !(manio->manifest=strdup_w(manifest, __func__)) || !(manio->mode=strdup_w(mode, __func__)) || !(manio->offset=man_off_t_alloc())) goto error; manio->protocol=protocol; manio->phase=phase; if(!strcmp(manio->mode, MANIO_MODE_APPEND)) { if(manio->phase!=2) { logp("manio append mode only works for phase 2.\n"); logp("%s has phase: %s\n", manio->manifest, manio->phase); goto error; } if(manio_open_last_fpath(manio)) goto error; } else { if(manio_open_next_fpath(manio)) goto error; } return manio; error: manio_close(&manio); return NULL; }
static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **prefix, smb_ucs2_t **extension, bool allow_wildcards) { size_t ext_len; smb_ucs2_t *p; *extension = 0; *prefix = strdup_w(ucs2_string); if (!*prefix) { return NT_STATUS_NO_MEMORY; } if ((p = strrchr_w(*prefix, UCS2_CHAR('.')))) { ext_len = strlen_w(p+1); if ((ext_len > 0) && (ext_len < 4) && (p != *prefix) && (NT_STATUS_IS_OK(has_valid_83_chars(p+1,allow_wildcards)))) /* check extension */ { *p = 0; *extension = strdup_w(p+1); if (!*extension) { SAFE_FREE(*prefix); return NT_STATUS_NO_MEMORY; } } } return NT_STATUS_OK; }
int check_browsedir(const char *browsedir, struct sbuf *mb, size_t bdlen, char **last_bd_match) { char *cp=mb->path.buf; char *copy=NULL; if(bdlen>0) { if(strncmp(browsedir, cp, bdlen)) return 0; cp+=bdlen; if(browsedir[bdlen-1]!='/') { if(*cp!='\0') { if(*cp!='/') return 0; cp++; } } } if(*cp=='\0') cp=(char *)"."; if(!(copy=strdup_w(cp, __func__))) goto error; if((cp=strchr(copy, '/'))) { if(bdlen==0) cp++; *cp='\0'; maybe_fake_directory(mb); } else if(!strcmp(mb->path.buf, "/") && !strcmp(browsedir, "/")) maybe_fake_directory(mb); else if(mb->path.cmd==CMD_DIRECTORY) maybe_fake_directory(mb); // Strip off possible trailing slash. if((cp=strrchr(copy, '/')) && cp>copy) *cp='\0'; if(*last_bd_match && !strcmp(*last_bd_match, copy)) { // Got a duplicate match. free_w(©); return 0; } free_w(&mb->path.buf); mb->path.buf=copy; free_w(last_bd_match); if(!(*last_bd_match=strdup_w(copy, __func__))) goto error; return 1; error: free_w(©); log_out_of_memory(__func__); return -1; }
static int run_list(struct asfd *asfd, struct sdirs *sdirs, struct conf **cconfs) { int ret=-1; char *cp=NULL; char *backupno=NULL; char *browsedir=NULL; char *listregex=NULL; struct iobuf *rbuf=asfd->rbuf; if(!client_can_generic(cconfs, OPT_CLIENT_CAN_LIST)) { logp("Not allowing list of %s\n", get_string(cconfs[OPT_CNAME])); asfd->write_str(asfd, CMD_GEN, "Client list is not allowed"); goto end; } if(!strncmp_w(rbuf->buf, "list ")) { if((cp=strchr(rbuf->buf, ':'))) { *cp='\0'; if(!(listregex=strdup_w(cp+1, __func__))) goto end; } if(!(backupno=strdup_w(rbuf->buf+strlen("list "), __func__))) goto end; } else if(!strncmp_w(rbuf->buf, "listb ")) { if((cp=strchr(rbuf->buf, ':'))) { *cp='\0'; if(!(browsedir=strdup_w(cp+1, __func__))) goto end; } strip_trailing_slashes(&browsedir); if(!(backupno=strdup_w(rbuf->buf+strlen("listb "), __func__))) goto end; } if(asfd->write_str(asfd, CMD_GEN, "ok")) goto end; iobuf_free_content(asfd->rbuf); if(list_server_init(asfd, sdirs, get_cntr(cconfs), get_protocol(cconfs), backupno, listregex, browsedir)) goto end; ret=do_list_server(); end: free_w(&backupno); free_w(&browsedir); free_w(&listregex); list_server_free(); return ret; }
int check_browsedir(const char *browsedir, char **path, size_t bdlen, char **last_bd_match) { char *cp=NULL; char *copy=NULL; if(strncmp(browsedir, *path, bdlen)) return 0; if((*path)[bdlen+1]=='\0' || (bdlen>1 && (*path)[bdlen]!='/')) return 0; /* Lots of messing around related to whether browsedir was '', '/', or something else. */ if(*browsedir) { if(!strcmp(browsedir, "/")) { if(!(copy=strdup_w((*path)+bdlen, __func__))) goto error; if((cp=strchr(copy+1, '/'))) *cp='\0'; } else { if(!(copy=strdup_w((*path)+bdlen+1, __func__))) goto error; if((cp=strchr(copy, '/'))) *cp='\0'; } } else { if(!(copy=strdup_w((*path)+bdlen, __func__))) goto error; if(*copy=='/') *(copy+1)='\0'; // Messing around for Windows. else if(strlen(copy)>2 && copy[1]==':' && copy[2]=='/') copy[2]='\0'; } if(last_bd_match && *last_bd_match) { if(!strcmp(*last_bd_match, copy)) { // Got a duplicate match. free(copy); return 0; } free(*last_bd_match); } free(*path); *path=copy; if(!(*last_bd_match=strdup_w(copy, __func__))) goto error; return 1; error: if(copy) free(copy); log_out_of_memory(__func__); return -1; }
static int init_write_hooks(struct manio *manio, const char *hook_dir, const char *rmanifest) { if(!(manio->hook_dir=strdup_w(hook_dir, __func__)) || !(manio->rmanifest=strdup_w(rmanifest, __func__)) || !(manio->hook_sort=(uint64_t *)calloc_w(MANIFEST_SIG_MAX, sizeof(uint64_t), __func__))) return -1; return 0; }
static void do_snapshot_test( const char *orig_client, int expected_ret, void setup_callback( struct asfd *csin, struct asfd *csout, struct asfd *so_asfd ) ) { struct asfd *csin; struct asfd *csout; struct asfd *so_asfd; struct async *as; struct sel *sel; as=setup_async(); csin=asfd_mock_setup(&reads_csin, &writes_csin); csout=asfd_mock_setup(&reads_csout, &writes_csout); so_asfd=asfd_mock_setup(&reads_so, &writes_so); fail_unless((csin->desc=strdup_w("csin", __func__))!=NULL); fail_unless((csout->desc=strdup_w("csout", __func__))!=NULL); fail_unless((so_asfd->desc=strdup_w("so_asfd", __func__))!=NULL); as->asfd_add(as, csin); as->asfd_add(as, csout); as->asfd_add(as, so_asfd); as->read_write=async_rw_simple; as->write=async_write_simple; setup_callback(csin, csout, so_asfd); fail_unless((sel=sel_alloc())!=NULL); fail_unless(!status_client_ncurses_init(ACTION_STATUS_SNAPSHOT)); fail_unless(status_client_ncurses_main_loop( as, so_asfd, sel, orig_client )==expected_ret); sel_free(&sel); asfd_free(&csin); asfd_free(&csout); asfd_free(&so_asfd); asfd_mock_teardown(&reads_csin, &writes_csin); asfd_mock_teardown(&reads_csout, &writes_csout); asfd_mock_teardown(&reads_so, &writes_so); async_free(&as); alloc_check(); }
static void run_test(int expected_ret, int manio_entries, int async_read_write_callback(struct async *as), void setup_asfds_callback(struct asfd *asfd, struct asfd *chfd, struct slist *slist)) { struct asfd *asfd; struct asfd *chfd; struct async *as; struct sdirs *sdirs; struct conf **confs; struct slist *slist=NULL; prng_init(0); base64_init(); hexmap_init(); setup(&as, &sdirs, &confs); asfd=asfd_mock_setup(&areads, &awrites); chfd=asfd_mock_setup(&creads, &cwrites); fail_unless((asfd->desc=strdup_w("a", __func__))!=NULL); fail_unless((chfd->desc=strdup_w("c", __func__))!=NULL); as->asfd_add(as, asfd); as->asfd_add(as, chfd); as->read_write=async_read_write_callback; if(manio_entries) slist=build_manifest(sdirs->phase1data, PROTO_2, manio_entries, 1 /*phase*/); setup_asfds_callback(asfd, chfd, slist); fail_unless(do_backup_phase2_server_protocol2( as, chfd, sdirs, 0, // resume confs )==expected_ret); if(!expected_ret) { // FIX THIS: Should check for the presence and correctness of // changed and unchanged manios. } asfd_free(&asfd); asfd_free(&chfd); asfd_mock_teardown(&areads, &awrites); asfd_mock_teardown(&creads, &cwrites); slist_free(&slist); tear_down(&as, &sdirs, &confs); }
int manio_init_write_hooks(struct manio *manio, const char *base_dir, const char *dir) { int i=0; if(!(manio->base_dir=strdup_w(base_dir, __func__)) || !(manio->hook_dir=strdup_w(dir, __func__)) || !(manio->hook_sort= (char **)calloc_w(MANIFEST_SIG_MAX, sizeof(char*), __func__))) return -1; for(i=0; i<MANIFEST_SIG_MAX; i++) if(!(manio->hook_sort[i]= (char *)calloc_w(1, WEAK_STR_LEN, __func__))) return -1; return 0; }
static #endif int conf_load_lines_from_buf(const char *buf, struct conf **c) { int ret=0; int line=0; char *tok=NULL; char *copy=NULL; if(!buf) return 0; if(!(copy=strdup_w(buf, __func__))) return -1; if(!(tok=strtok(copy, "\n"))) { logp("unable to parse conf buffer\n"); free_w(©); return -1; } do { line++; if(conf_parse_line(c, "", tok, line)) { ret=-1; break; } } while((tok=strtok(NULL, "\n"))); free_w(©); return ret; }
// When a backup is ongoing, use this to add newly complete candidates. int candidate_add_fresh(const char *path, const char *directory, struct scores *scores) { const char *cp=NULL; struct candidate *candidate=NULL; if(!(candidate=candidates_add_new())) goto error; cp=path+strlen(directory); while(cp && *cp=='/') cp++; if(!(candidate->path=strdup_w(cp, __func__))) goto error; switch(candidate_load(candidate, path, scores)) { case CAND_RET_PERM: goto error; case CAND_RET_TEMP: // Had an error - try to carry on. Errors can happen // when loading a fresh candidate because the backup // process can move to the next phase and rename the // candidates. logp("Removing candidate.\n"); candidates_len--; sparse_delete_fresh_candidate(candidate); candidate_free(&candidate); // Fall through. case CAND_RET_OK: return 0; } error: candidate_free(&candidate); return -1; }
static int conf_parse_line(struct conf **confs, const char *conf_path, char buf[], int line) { int ret=-1; char *f=NULL; // field char *v=NULL; // value char *extrafile=NULL; if(!strncmp(buf, ". ", 2)) { // The conf file specifies another file to include. char *np=NULL; if(!(extrafile=strdup_w(buf+2, __func__))) goto end; if((np=strrchr(extrafile, '\n'))) *np='\0'; if(!*extrafile) goto end; ret=deal_with_dot_inclusion(conf_path, &extrafile, confs); goto end; } if(conf_get_pair(buf, &f, &v)) goto end; if(f && v && load_conf_field_and_value(confs, f, v, conf_path, line)) goto end; ret=0; end: free_w(&extrafile); return ret; }
static char *set_new_datapth(struct asfd *asfd, struct sdirs *sdirs, struct conf **cconfs, struct sbuf *sb, struct dpth *dpth, int *istreedata) { char *tmp=NULL; char *rpath=NULL; if(get_int(cconfs[OPT_DIRECTORY_TREE])) *istreedata=treedata(sb, cconfs); if(*istreedata) { // We want to place this file in a directory structure like // the directory structure on the original client. if(!(tmp=prepend_s(TREE_DIR, sb->path.buf))) { log_and_send_oom(asfd, __func__); return NULL; } } else { if(!(tmp=strdup_w(dpth_protocol1_mk(dpth, get_int(cconfs[OPT_COMPRESSION]), sb->path.cmd), __func__))) return NULL; } iobuf_from_str(&sb->protocol1->datapth, CMD_DATAPTH, tmp); if(build_path(sdirs->datadirtmp, sb->protocol1->datapth.buf, &rpath, sdirs->datadirtmp)) { log_and_send(asfd, "build path failed"); return NULL; } return rpath; }
// Return 1 for ok, -1 for error, 0 for too many components stripped. static int strip_path_components(struct asfd *asfd, struct sbuf *sb, int strip, struct cntr *cntr, enum protocol protocol) { int s=0; char *tmp=NULL; char *cp=sb->path.buf; char *dp=NULL; for(s=0; cp && *cp && s<strip; s++) { if(!(dp=strchr(cp, '/'))) { char msg[256]=""; snprintf(msg, sizeof(msg), "Stripped too many components: %s", sb->path.buf); if(restore_interrupt(asfd, sb, msg, cntr, protocol)) return -1; return 0; } cp=dp+1; } if(!cp) { char msg[256]=""; snprintf(msg, sizeof(msg), "Stripped too many components: %s", sb->path.buf); if(restore_interrupt(asfd, sb, msg, cntr, protocol)) return -1; return 0; } if(!(tmp=strdup_w(cp, __func__))) return -1; free_w(&sb->path.buf); sb->path.buf=tmp; return 1; }
extern int sdirs_init(struct sdirs *sdirs, struct conf *conf) { if(!conf->directory) { logp("conf->directory unset in %s\n", __func__); goto error; } if(!(sdirs->base=strdup_w(conf->directory, __func__))) goto error; if(conf->protocol==PROTO_BURP1) { if(do_burp1_dirs(sdirs, conf)) goto error; } else { if(do_burp2_dirs(sdirs, conf)) goto error; } if(do_lock_dirs(sdirs, conf)) goto error; return 0; error: return -1; }
END_TEST START_TEST(test_check_browsedir_alloc_error) { char *path; size_t bdlen; struct sbuf *mb; const char *browsedir; char *last_bd_match=NULL; fail_unless((mb=sbuf_alloc(PROTO_1))!=NULL); browsedir=""; bdlen=0; fail_unless((path=strdup_w("aaa", __func__))!=NULL); iobuf_from_str(&mb->path, CMD_FILE, path); alloc_errors=1; fail_unless(check_browsedir( browsedir, mb, bdlen, &last_bd_match) ==-1); sbuf_free(&mb); free_w(&last_bd_match); alloc_check(); }
END_TEST static void run_check_browsedir(const char *browsedir, struct sbuf *mb, enum cmd cmd, const char *path, char **last_bd_match, const char *expected_last_bd_match, int expected_ret, int expected_isdir) { char *mbpath; size_t bdlen=0; if(browsedir) bdlen=strlen(browsedir); fail_unless((mbpath=strdup_w(path, __func__))!=NULL); iobuf_from_str(&mb->path, cmd, mbpath); fail_unless(check_browsedir( browsedir, mb, bdlen, last_bd_match) ==expected_ret); if(expected_last_bd_match) { fail_unless(*last_bd_match!=NULL); ck_assert_str_eq(expected_last_bd_match, *last_bd_match); } else fail_unless(*last_bd_match==NULL); fail_unless(expected_isdir==S_ISDIR(mb->statp.st_mode)); sbuf_free_content(mb); }
// Return 0 for lock got, 1 for lock not got, -1 for error. void lock_get(struct lock *lock) { #if defined(HAVE_WIN32) || !defined(HAVE_LOCKF) // Would somebody please tell me how to get a lock on Windows?! lock->status=GET_LOCK_GOT; return; #else char *cp=NULL; char *copy=NULL; // Try to make sure the lock directory exists. if(!(copy=strdup_w(lock->path, __func__))) { lock->status=GET_LOCK_ERROR; return; } if((cp=strrchr(copy, '/'))) { *cp='\0'; if(*copy) mkdir(copy, 0777); } free_w(©); lock_get_quick(lock); // Try to make sure the pid gets onto the disk. if(lock->status==GET_LOCK_GOT) fsync(lock->fd); return; #endif }
int lock_init(struct lock *lock, const char *path) { free_w(&lock->path); if(!(lock->path=strdup_w(path, __func__))) return -1; return 0; }
static int load_rblk(struct rblk *rblks, int ind, const char *datpath) { int r; FILE *dfp; free_w(&rblks[ind].datpath); if(!(rblks[ind].datpath=strdup_w(datpath, __func__))) return -1; printf("swap %d to: %s\n", ind, datpath); if(!(dfp=open_file(datpath, "rb"))) return -1; for(r=0; r<DATA_FILE_SIG_MAX; r++) { switch(read_next_data(dfp, rblks, ind, r)) { case 0: continue; case 1: break; case -1: default: return -1; } } rblks[ind].readbuflen=r; fclose(dfp); return 0; }
static int parse_restore_str(const char *str, enum action *act, char **backupnostr, char **restoreregex) { int ret=-1; char *cp=NULL; char *copy=NULL; if(!str) { logp("NULL passed to %s\n", __func__); goto end; } if(!(copy=strdup_w(str, __func__))) goto end; if(!strncmp_w(copy, "restore ")) *act=ACTION_RESTORE; else if(!strncmp_w(copy, "verify ")) *act=ACTION_VERIFY; else { logp("Could not parse %s in %s\n", copy, __func__); goto end; } if(!(cp=strchr(copy, ' '))) { logp("Could not parse %s in %s\n", copy, __func__); goto end; } cp++; if(!(*backupnostr=strdup_w(cp, __func__))) goto end; if((cp=strchr(*backupnostr, ':'))) { *cp='\0'; cp++; if(!(*restoreregex=strdup_w(cp, __func__))) goto end; } ret=0; end: free_w(©); return ret; }
static char *get_next_fpath(struct manio *manio, man_off_t *offset) { static char tmp[32]; if(is_single_file(manio)) return strdup_w(manio->manifest, __func__); snprintf(tmp, sizeof(tmp), "%08"PRIX64, offset->fcount++); return prepend_s(manio->manifest, tmp); }
static int init_write_dindex(struct manio *manio, const char *dir) { if(!(manio->dindex_dir=strdup_w(dir, __func__)) || !(manio->dindex_sort=(uint64_t *)calloc_w(MANIFEST_SIG_MAX, sizeof(uint64_t), __func__))) return -1; return 0; }
static int check_timebands(const char *day_now, const char *hour_now, struct strlist *timebands) { char *lower_tb=NULL; int in_timeband=0; struct strlist *t; char *lower_day_now=NULL; char *lower_hour_now=NULL; if(!(lower_day_now=strdup_w(day_now, __func__)) || !(lower_hour_now=strdup_w(hour_now, __func__))) { in_timeband=-1; goto end; } strtolower(lower_day_now); strtolower(lower_hour_now); for(t=timebands; t; t=t->next) { free_w(&lower_tb); if(!(lower_tb=strdup_w(t->path, __func__))) { in_timeband=-1; goto end; } strtolower(lower_tb); if(!strcmp(lower_tb, "always") || (strstr(lower_tb, lower_day_now) && strstr(lower_tb, lower_hour_now))) { logp("In timeband: %s\n", t->path); in_timeband=1; } else logp("Out of timeband: %s\n", t->path); } end: free_w(&lower_day_now); free_w(&lower_hour_now); free_w(&lower_tb); return in_timeband; }
int cstat_init(struct cstat *cstat, const char *name, const char *clientconfdir) { if((clientconfdir && !(cstat->conffile=prepend_s(clientconfdir, name))) || !(cstat->name=strdup_w(name, __func__))) return -1; return 0; }
static char *get_restore_style(struct asfd *asfd, struct conf **confs) { if(get_protocol(confs)==PROTO_1) return strdup_w(RESTORE_STREAM, __func__); if(asfd->simple_loop(asfd, confs, NULL, __func__, restore_style_func)) return NULL; return restore_style; }
// Return 1 if there is still stuff needing to be sent. static int do_stuff_to_send(struct asfd *asfd, struct sbuf *p1b, char **last_requested) { static struct iobuf wbuf; if(p1b->flags & SBUFL_SEND_DATAPTH) { iobuf_copy(&wbuf, &p1b->burp1->datapth); if(asfd->append_all_to_write_buffer(asfd, &wbuf)) return 1; p1b->flags &= ~SBUFL_SEND_DATAPTH; } if(p1b->flags & SBUFL_SEND_STAT) { iobuf_copy(&wbuf, &p1b->attr); if(asfd->append_all_to_write_buffer(asfd, &wbuf)) return 1; p1b->flags &= ~SBUFL_SEND_STAT; } if(p1b->flags & SBUFL_SEND_PATH) { iobuf_copy(&wbuf, &p1b->path); if(asfd->append_all_to_write_buffer(asfd, &wbuf)) return 1; p1b->flags &= ~SBUFL_SEND_PATH; if(*last_requested) free(*last_requested); if(!(*last_requested=strdup_w(p1b->path.buf, __func__))) return -1; } if(p1b->burp1->sigjob && !(p1b->flags & SBUFL_SEND_ENDOFSIG)) { rs_result sigresult; sigresult=rs_async(p1b->burp1->sigjob, &(p1b->burp1->rsbuf), p1b->burp1->infb, p1b->burp1->outfb); if(sigresult==RS_DONE) { p1b->flags |= SBUFL_SEND_ENDOFSIG; } else if(sigresult==RS_BLOCKED || sigresult==RS_RUNNING) { // keep going round the loop. return 1; } else { logp("error in rs_async: %d\n", sigresult); return -1; } } if(p1b->flags & SBUFL_SEND_ENDOFSIG) { iobuf_from_str(&wbuf, CMD_END_FILE, (char *)"endfile"); if(asfd->append_all_to_write_buffer(asfd, &wbuf)) return 1; p1b->flags &= ~SBUFL_SEND_ENDOFSIG; } return 0; }