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; }
static int extra_comms_read(struct async *as, struct vers *vers, int *srestore, char **incexc, struct conf **globalcs, struct conf **cconfs) { int ret=-1; struct asfd *asfd; struct iobuf *rbuf; asfd=as->asfd; rbuf=asfd->rbuf; while(1) { iobuf_free_content(rbuf); if(asfd->read(asfd)) goto end; if(rbuf->cmd!=CMD_GEN) { iobuf_log_unexpected(rbuf, __func__); goto end; } if(!strcmp(rbuf->buf, "extra_comms_end")) { if(asfd->write_str(asfd, CMD_GEN, "extra_comms_end ok")) goto end; break; } else if(!strncmp_w(rbuf->buf, "autoupgrade:")) { char *os=NULL; const char *autoupgrade_dir= get_string(globalcs[OPT_AUTOUPGRADE_DIR]); os=rbuf->buf+strlen("autoupgrade:"); iobuf_free_content(rbuf); if(os && *os && autoupgrade_server(as, vers->ser, vers->cli, os, get_cntr(globalcs), autoupgrade_dir)) goto end; } else if(!strcmp(rbuf->buf, "srestore ok")) { iobuf_free_content(rbuf); // Client can accept the restore. // Load the restore config, then send it. *srestore=1; if(conf_parse_incexcs_path(cconfs, get_string(cconfs[OPT_RESTORE_PATH])) || incexc_send_server_restore(asfd, cconfs)) goto end; // Do not unlink it here - wait until // the client says that it wants to do the // restore. // Also need to leave it around if the // restore is to an alternative client, so // that the code below that reloads the config // can read it again. //unlink(get_string(cconfs[OPT_RESTORE_PATH])); } else if(!strcmp(rbuf->buf, "srestore not ok")) { const char *restore_path=get_string( cconfs[OPT_RESTORE_PATH]); // Client will not accept the restore. unlink(restore_path); if(set_string(cconfs[OPT_RESTORE_PATH], NULL)) goto end; logp("Client not accepting server initiated restore.\n"); } else if(!strcmp(rbuf->buf, "sincexc ok")) { // Client can accept incexc conf from the // server. iobuf_free_content(rbuf); if(incexc_send_server(asfd, cconfs)) goto end; } else if(!strcmp(rbuf->buf, "incexc")) { // Client is telling server its incexc // configuration so that it can better decide // what to do on resume. iobuf_free_content(rbuf); if(incexc_recv_server(asfd, incexc, globalcs)) goto end; if(*incexc) { char *tmp=NULL; char comp[32]=""; snprintf(comp, sizeof(comp), "compression = %d\n", get_int(cconfs[OPT_COMPRESSION])); if(!(tmp=prepend(*incexc, comp))) goto end; free_w(incexc); *incexc=tmp; } } else if(!strcmp(rbuf->buf, "countersok")) { // Client can accept counters on // resume/verify/restore. logp("Client supports being sent counters.\n"); set_int(cconfs[OPT_SEND_CLIENT_CNTR], 1); } else if(!strncmp_w(rbuf->buf, "uname=") && strlen(rbuf->buf)>strlen("uname=")) { char *uname=rbuf->buf+strlen("uname="); if(!strncasecmp("Windows", uname, strlen("Windows"))) set_int(cconfs[OPT_CLIENT_IS_WINDOWS], 1); } else if(!strncmp_w(rbuf->buf, "orig_client=") && strlen(rbuf->buf)>strlen("orig_client=")) { if(conf_switch_to_orig_client(globalcs, cconfs, rbuf->buf+strlen("orig_client="))) goto end; // If this started out as a server-initiated // restore, need to load the restore file // again. if(*srestore) { if(conf_parse_incexcs_path(cconfs, get_string(cconfs[OPT_RESTORE_PATH]))) goto end; } if(asfd->write_str(asfd, CMD_GEN, "orig_client ok")) goto end; } else if(!strncmp_w(rbuf->buf, "restore_spool=")) { // Client supports temporary spool directory // for restores. if(set_string(cconfs[OPT_RESTORE_SPOOL], rbuf->buf+strlen("restore_spool="))) goto end; } else if(!strncmp_w(rbuf->buf, "protocol=")) { char msg[128]=""; // Client wants to set protocol. enum protocol protocol=get_protocol(cconfs); if(protocol!=PROTO_AUTO) { snprintf(msg, sizeof(msg), "Client is trying to use protocol=%s but server is set to protocol=%d\n", rbuf->buf, protocol); log_and_send_oom(asfd, __func__); goto end; } else if(!strcmp(rbuf->buf+strlen("protocol="), "1")) { set_protocol(cconfs, PROTO_1); set_protocol(globalcs, PROTO_1); } else if(!strcmp(rbuf->buf+strlen("protocol="), "2")) { set_protocol(cconfs, PROTO_2); set_protocol(globalcs, PROTO_2); } else { snprintf(msg, sizeof(msg), "Client is trying to use protocol=%s, which is unknown\n", rbuf->buf); log_and_send_oom(asfd, __func__); goto end; } logp("Client has set protocol=%d\n", (int)get_protocol(cconfs)); } else if(!strncmp_w(rbuf->buf, "rshash=blake2")) { #ifdef RS_DEFAULT_STRONG_LEN logp("Client is trying to use librsync hash blake2, but server does not support it.\n"); goto end; #else set_e_rshash(cconfs[OPT_RSHASH], RSHASH_BLAKE2); set_e_rshash(globalcs[OPT_RSHASH], RSHASH_BLAKE2); #endif } else if(!strncmp_w(rbuf->buf, "msg")) { set_int(cconfs[OPT_MESSAGE], 1); set_int(globalcs[OPT_MESSAGE], 1); } else { iobuf_log_unexpected(rbuf, __func__); goto end; } } ret=0; end: iobuf_free_content(rbuf); return ret; }