diff --git a/csync2_trunk/.git/index b/csync2_tempdir_patch/.git/index index 4b52483..c458a42 100644 Binary files a/csync2_trunk/.git/index and b/csync2_tempdir_patch/.git/index differ diff --git a/csync2_trunk/conn.c b/csync2_tempdir_patch/conn.c index 8dda10d..bfc5aed 100644 --- a/csync2_trunk/conn.c +++ b/csync2_tempdir_patch/conn.c @@ -46,6 +46,14 @@ static gnutls_session_t conn_tls_session; static gnutls_certificate_credentials_t conn_x509_cred; #endif +const char* response_command_finished="OK (cmd_finished)."; +const char* response_data_follows="OK (data_follows)."; +const char* response_see_you_later="OK (cu_later)."; +const char* response_path_not_found="OK (path_not_found)."; +const char* response_parent_dir_missing="OK (parent_dir_missing)."; +const char* response_activating_ssl="OK (activating_ssl)."; +const char* response_send_data="OK (send_data)."; +const char* response_file_marked_dirty_here="File is also marked dirty here!"; /* getaddrinfo stuff mostly copied from its manpage */ int conn_connect(const char *peername) diff --git a/csync2_trunk/csync2.h b/csync2_tempdir_patch/csync2.h index d76f880..0b41432 100644 --- a/csync2_trunk/csync2.h +++ b/csync2_tempdir_patch/csync2.h @@ -102,6 +102,24 @@ extern void conn_printf(const char *fmt, ...); extern int conn_fgets(char *s, int size); extern size_t conn_gets(char *s, size_t size); +extern const char* response_command_finished; +extern const char* response_data_follows; +extern const char* response_see_you_later; +extern const char* response_path_not_found; +extern const char* response_parent_dir_missing; +extern const char* response_activating_ssl; +extern const char* response_send_data; +extern const char* response_file_marked_dirty_here; + +typedef enum connection_response { + CONNECTION_RESPONSE_OK, + CONNECTION_RESPONSE_PATH_DIRTY, + CONNECTION_RESPONSE_PATH_NOT_FOUND, + CONNECTION_RESPONSE_PARENT_DIR_MISSING, + CONNECTION_RESPONSE_ERROR +} connection_response; + +//#define CSYNC_RESPONSE_CMD_OK(response) strncmp(response,response_command_finished , strlen(response_command_finished)); /* db.c */ @@ -175,7 +193,7 @@ extern int csync_rs_check(const char *filename, int isreg); extern void csync_rs_sig(const char *filename); extern int csync_rs_delta(const char *filename); extern int csync_rs_patch(const char *filename); - +//extern void get_parent_child_from_path(char *dirname, char* filename,const char *filepath); /* checktxt.c */ diff --git a/csync2_trunk/csync2.xinetd b/csync2_tempdir_patch/csync2.xinetd index 146d356..842a8f8 100644 --- a/csync2_trunk/csync2.xinetd +++ b/csync2_tempdir_patch/csync2.xinetd @@ -8,7 +8,7 @@ service csync2 user = root group = root server = /usr/sbin/csync2 - server_args = -i + server_args = -i -l #log_on_failure += USERID disable = no # only_from = 192.168.199.3 192.168.199.4 diff --git a/csync2_trunk/daemon.c b/csync2_tempdir_patch/daemon.c index 2c054ed..96b0b71 100644 --- a/csync2_trunk/daemon.c +++ b/csync2_tempdir_patch/daemon.c @@ -103,23 +103,37 @@ void csync_file_flush(const char *filename) url_encode(filename)); } -int csync_file_backup(const char *filename) +int csync_file_backup(const char *filepath) { static char error_buffer[1024]; const struct csync_group *g = NULL; struct stat buf; int rc; - while ( (g=csync_find_next(g, filename)) ) { - if (g->backup_directory && g->backup_generations > 1) { + /* ============================================================================================== + * As of now, filepath may only contain prefixes but we may need to resolve other + * dynamic references like environment variables, symbolic links, etc in future + * if we plan to support those in later releases + *==============================================================================================*/ + char *filename=prefixsubst(filepath); + int filename_len = strlen(filename);//can filename be null? + while ( (g=csync_find_next(g, filepath)) ) { + + if (g->backup_directory && g->backup_generations > 1) { + if(stat(g->backup_directory, &buf)!=0) { + csync_debug(3,"backup directory configured is not present, so creating it"); + mkpath(g->backup_directory); + } else if (!S_ISDIR(buf.st_mode)) { + csync_debug(1, "ERROR : location configured for backup %s is not a directory; backup failed \n",g->backup_directory); + return 1; + } int bak_dir_len = strlen(g->backup_directory); - int filename_len = strlen(filename); char backup_filename[bak_dir_len + filename_len + 10]; char backup_otherfilename[bak_dir_len + filename_len + 10]; int fd_in, fd_out, i; int lastSlash = 0; mode_t mode; - csync_debug(1, "backup\n"); + csync_debug(1, "backup %s \n", filename); // Skip generation of directories rc = stat(filename, &buf); if (S_ISDIR(buf.st_mode)) { @@ -207,10 +221,8 @@ int csync_file_backup(const char *filename) // return 1; } csync_setBackupFileStatus(backup_filename, bak_dir_len); - csync_debug(1, "csync_backup loop end\n"); } } - csync_debug(1, "csync_backup end\n"); return 0; } @@ -428,6 +440,36 @@ void set_peername_from_env(address_t *p, const char *env) freeaddrinfo(result); } +static int setup_tag(char *tag[32], char *line) { + int i = 0; + char *context; + + tag[0] = strtok_r(line, "\t \r\n", &context); + + while ( tag[i] && i < 31 ) { + tag[++i] = strtok_r(NULL, "\t \r\n", &context); + } + while ( i < 32 ) { + tag[i++] = ""; + } + + if ( !tag[0][0] ) { + return 0; + } + + for (i=0; i<32; i++) { + tag[i] = strdup(url_decode(tag[i])); + } + + return 1; +} + +static void destroy_tag(char *tag[32]) { + int i = 0; + for (i=0; i<32; i++) + free(tag[i]); +} + void csync_daemon_session() { struct stat sb; @@ -456,18 +498,10 @@ void csync_daemon_session() while ( conn_gets(line, 4096) ) { int cmdnr; - - tag[i=0] = strtok(line, "\t \r\n"); - while ( tag[i] && i < 31 ) - tag[++i] = strtok(0, "\t \r\n"); - while ( i < 32 ) - tag[i++] = ""; - - if ( !tag[0][0] ) continue; - - for (i=0; i<32; i++) - tag[i] = strdup(url_decode(tag[i])); - + + if (!setup_tag(tag, line)) + continue; + for (cmdnr=0; cmdtab[cmdnr].text; cmdnr++) if ( !strcasecmp(cmdtab[cmdnr].text, tag[0]) ) break; @@ -516,10 +550,18 @@ void csync_daemon_session() struct stat st; if ( lstat_strict(prefixsubst(tag[2]), &st) != 0 ) { - if ( errno == ENOENT ) - conn_printf("OK (not_found).\n---\noctet-stream 0\n"); - else + if ( errno == ENOENT ) { + struct stat sb; + char parent_dirname[strlen(tag[2])]; + get_parent_child_from_path(parent_dirname,NULL,tag[2]); + if ( lstat_strict(prefixsubst(parent_dirname), &sb) != 0 ) { + conn_printf("OK (parent_dir_missing).\n---\noctet-stream 0\n"); + } else { + conn_printf("OK (path_not_found).\n---\noctet-stream 0\n"); + } + } else { cmd_error = strerror(errno); + } break; } else if ( csync_check_pure(tag[2]) ) { @@ -756,7 +798,6 @@ abort_cmd: conn_printf("OK (cmd_finished).\n"); next_cmd: - for (i=0; i<32; i++) - free(tag[i]); + destroy_tag(tag); } } diff --git a/csync2_trunk/rsync.c b/csync2_tempdir_patch/rsync.c index 86482ee..a2b2ca5 100644 --- a/csync2_trunk/rsync.c +++ b/csync2_tempdir_patch/rsync.c @@ -62,6 +62,60 @@ static size_t strlcpy(char *d, const char *s, size_t bufsize) return ret; } +void get_parent_child_from_path(char *dirname, char* filename,const char *filepath) { + char *temp; + if ((temp = strrchr(filepath, '/')) != NULL) { + /* copy up to and excluding the slash */ + if(dirname!=NULL) { + strlcpy( dirname, filepath, ( (strlen(filepath)-strlen(temp)) + 1) ); + } + ++temp;//forward one character to skip '/' in the filename + if(filename!=NULL) { + strlcpy( filename, temp, (strlen(temp) + 1) ); + } + } else { + if(filename!=NULL) { + strlcpy( filename, filepath, (strlen(filepath) + 1) ); + } + } +} + +static int get_tempdir_name(char * tempdir_name, const char* currentdir_name) +{ + int found=0; int length; + if ( access(currentdir_name, R_OK|W_OK|X_OK) >= 0 ) { + strlcpy(tempdir_name, currentdir_name, strlen(currentdir_name)+ 1); + found=1; + } else { + csync_debug(2,"the directory '%s' seems to have been deleted, hence creating the temp file under 'tempdir'!\n", currentdir_name); + if(csync_tempdir!=NULL) { + if ( access(csync_tempdir, R_OK|W_OK|X_OK) >= 0 ) { + strlcpy(tempdir_name, csync_tempdir, strlen(csync_tempdir)+1); + found=1; + } else { + csync_debug(1,"csync configuration option 'tempdir' is set to %s but that directory does not exit; ensure that it exists and is accessible to the user running 'csync2' process",csync_tempdir); + } + } + if( !found ) { + csync_debug(2,"falling back to system temp dir : %s",P_tmpdir); + if ( access(P_tmpdir, R_OK|W_OK|X_OK) >= 0 ) { + strlcpy(tempdir_name, P_tmpdir, strlen(P_tmpdir)+1); + found=1; + } else { + csync_debug(0,"could not find a usable temporary directory"); + } + } + } + if(found) { + length=strlen(tempdir_name); + if(length= maxname) - added = maxname - 1; - suf = fnametmp + length + added; - + added = maxname - 1; + suffix = tempfile_name + length + added; if (!counter_limit) { counter_limit = (unsigned)getpid() + MAX_UNIQUE_LOOP; if (counter_limit > MAX_UNIQUE_NUMBER || counter_limit < MAX_UNIQUE_LOOP) counter_limit = MAX_UNIQUE_LOOP; counter = counter_limit - MAX_UNIQUE_LOOP; - /* This doesn't have to be very good because we don't need - * to worry about someone trying to guess the values: all - * a conflict will do is cause a device, special file, hard - * link, or symlink to fail to be created. Also: avoid - * using mktemp() due to gcc's annoying warning. */ + * to worry about someone trying to guess the values: all + * a conflict will do is cause a device, special file, hard + * link, or symlink to fail to be created. Also: avoid + * using mktemp() due to gcc's annoying warning. */ while (1) { - snprintf(suf, TMPNAME_SUFFIX_LEN+1, ".%d", counter); - if (access(fnametmp, 0) < 0) + snprintf(suffix, TMPNAME_SUFFIX_LEN+1, ".%d", counter); + if (access(tempfile_name, 0) < 0) break; if (++counter >= counter_limit) return 0; } - } else - memcpy(suf, TMPNAME_SUFFIX, TMPNAME_SUFFIX_LEN+1); - + } else { + //memcpy(suffix, TMPNAME_SUFFIX, TMPNAME_SUFFIX_LEN+1); + snprintf(suffix, TMPNAME_SUFFIX_LEN+1, ".%d", counter_limit); + } return 1; } +/* + * Recursively creates the given path, with the given mode + * Note that path argument is not directory name here but rather + * a path to a file that you are going to create after calling mkpath(). + * Works with relative paths as well. + * Shamelessly copied from + * Stackoverlow.com#http://stackoverflow.com/questions/2336242/recursive-mkdir-system-call-on-unix + * Returns: 0 on success and -1 on error + */ + +int mkpath(const char *path, mode_t mode) { + char temp[MAXPATHLEN]; + char *remaining; + + if(!mode) { + mode=S_IRWXU; + } + if(!path){ + csync_debug(2,"invalid path"); + return -1; + } + + strlcpy(temp,path,strlen(path)); + csync_debug(0,"full path : %s",temp); + for( remaining=strchr(temp+1, '/'); remaining!=NULL; remaining=strchr(remaining+1, '/') ){ + *remaining='\0'; + if(mkdir(temp, mode)==-1) { //strchr keeps the parent in temp and child[ren] in remaining + if(errno != EEXIST) { + *remaining='/'; + csync_debug(1,"error occured while creating path %s; cause : %s",temp,strerror(errno)); + return -1; + } + } + csync_debug(0,"parent dir : %s",temp); + *remaining='/'; + } + return 0; +} /* Returns open file handle for a temp file that resides in the - same directory as file fname. The file must be removed after + same directory as file filepath. The file must be removed after usage. */ -static FILE *open_temp_file(char *fnametmp, const char *fname) +#ifdef _SVID_SOURCE +static FILE *paranoid_tempfile(const char *filepath) { FILE *f; - int fd; - - if (get_tmpname(fnametmp, fname) == 0) { - csync_debug(1, "ERROR: Couldn't find tempname for file %s\n", fname); - return NULL; + int fd; int tempdir_length; int filename_length; + char template[MAXPATHLEN]; + char filename[MAXPATHLEN]; + char currentdir_name[MAXPATHLEN]; + char tempdir_name[MAXPATHLEN]; + + get_parent_child_from_path(currentdir_name,filename,filepath); + + if(get_tempdir_name(tempdir_name,currentdir_name)>0){ + tempdir_length=strlen(tempdir_name); + filename_length=strlen(filename); + csync_debug(3,"creating paranoid tempfile (SYSV) ==> tempdir_name : %s ; filename : %s",tempdir_name,filename); + + if( tempdir_length!=0 && filename_length!=0 && (tempdir_length < ( MAXPATHLEN-filename_length+20) ) ) { + snprintf(template,MAXPATHLEN,"%s.csync2_%s_XXXXXX",tempdir_name,filename); + } else { + csync_debug(2,"could not create tempfile for %s under the tempdir %s because of MAXPATHLEN restiction; leaving upto the system for deciding where to create the tempfile",filepath,tempdir_name); + strcpy(template,".csync2_XXXXXX"); + } + } else { + csync_debug(2,"could not find a usable tempdir to create tempfile for file %s; leaving upto the system for deciding where to create the tempfile",filepath); + strcpy(template,".csync2_XXXXXX"); } - - f = NULL; - fd = open(fnametmp, O_CREAT | O_EXCL | O_RDWR, S_IWUSR | S_IRUSR); + + fd = mkstemp(template); + unlink(template); + + if (fd < 0 || f==NULL) { + csync_fatal("ERROR: Could not create temporary file using mkstemp(%s)!\n", template); + } + //fd = open(name, O_CREAT | O_EXCL | O_RDWR, S_IWUSR | S_IRUSR); */ if (fd >= 0) { f = fdopen(fd, "wb+"); - /* not unlinking since rename wouldn't work then */ } - if (fd < 0 || !f) { - csync_debug(1, "ERROR: Could not open result from tempnam(%s)!\n", fnametmp); - return NULL; - } - + csync_debug(3, "Tempfilename is %s\n", template); return f; } - - - -#ifdef _SVID_SOURCE -static FILE *paranoid_tmpfile() +#else +static FILE *paranoid_tempfile(const char *filepath) { - char *name; FILE *f; - int fd; - - name = tempnam(csync_tempdir, "csync2"); - if (!name) - csync_fatal("ERROR: tempnam() didn't return a valid filename!\n"); - - f = NULL; - fd = open(name, O_CREAT | O_EXCL | O_RDWR, S_IWUSR | S_IRUSR); - if (fd >= 0) { - f = fdopen(fd, "wb+"); - unlink(name); + char filename[MAXPATHLEN]; + char tempdir_name[MAXPATHLEN]: + get_parent_child_from_path(tempdir_name,filename,filepath); + csync_debug(3,"creating paranoid tempfile ==> tempdir_name : %s ; filename : %s",tempdir_name,filename); + if ( !(f = tempnam(tempdir_name,filename)) ) { + csync_fatal("ERROR: tempnam(%s,%s) didn't return a valid file handle!\n",tempdir_name,filename); } - if (fd < 0 || !f) - csync_fatal("ERROR: Could not open result from tempnam(%s)!\n", name); - - csync_debug(3, "Tempfilename is %s\n", name); - free(name); return f; } -#else -static FILE *paranoid_tmpfile() +#endif + +static FILE *open_temp_file(char *tempfile_name, const char *filepath, int paranoid) { FILE *f; - - if ( access(P_tmpdir, R_OK|W_OK|X_OK) < 0 ) - csync_fatal("Temp directory '%s' does not exist!\n", P_tmpdir); - - if ( !(f = tmpfile()) ) - csync_fatal("ERROR: tmpfile() didn't return a valid file handle!\n"); - + int fd; + + if(paranoid) { + f=paranoid_tempfile(filepath); + } else { + if (get_tempfile_name(tempfile_name, filepath) == 0) { + csync_debug(1, "ERROR: Couldn't find tempname for file %s\n", filepath); + return NULL; + } + fd = open(tempfile_name, O_CREAT | O_EXCL | O_RDWR, S_IWUSR | S_IRUSR); + if (fd >= 0) { + f = fdopen(fd, "wb+"); + /* not unlinking since rename wouldn't work then */ + } + } + if (fd < 0 || !f) { + csync_debug(1, "ERROR: Could not open result from tempnam(%s)!\n", tempfile_name); + return NULL; + } return f; } -#endif void csync_send_file(FILE *in) { @@ -259,7 +364,7 @@ int csync_recv_file(FILE *out) char buffer[512]; int rc, chunk; long size; - + if ( !conn_gets(buffer, 100) || sscanf(buffer, "octet-stream %ld\n", &size) != 1 ) { if (!strcmp(buffer, "ERROR\n")) { errno=EIO; return -1; } csync_fatal("Format-error while receiving data.\n"); @@ -274,7 +379,7 @@ int csync_recv_file(FILE *out) if ( rc <= 0 ) csync_fatal("Read-error while receiving data.\n"); chunk = rc; - + rc = fwrite(buffer, chunk, 1, out); if ( rc != 1 ) csync_fatal("Write-error while receiving data.\n"); @@ -305,28 +410,26 @@ int csync_rs_check(const char *filename, int isreg) csync_debug(3, "Opening basis_file and sig_file..\n"); - sig_file = open_temp_file(tmpfname, prefixsubst(filename)); + sig_file = open_temp_file(tmpfname, prefixsubst(filename),1); + //sig_file = paranoid_tmpfile(); if ( !sig_file ) goto io_error; - if (unlink(tmpfname) < 0) goto io_error; - - basis_file = fopen(prefixsubst(filename), "rb"); - if ( !basis_file ) { /* ?? why a tmp file? */ - basis_file = open_temp_file(tmpfname, prefixsubst(filename)); - if ( !basis_file ) goto io_error; - if (unlink(tmpfname) < 0) goto io_error; - } + unlink(tmpfname); if ( isreg ) { + basis_file = fopen(prefixsubst(filename), "rb"); + if ( !basis_file ) { + basis_file = fopen("/dev/null", "rb"); + } csync_debug(3, "Running rs_sig_file() from librsync....\n"); + if (basis_file) result = rs_sig_file(basis_file, sig_file, RS_DEFAULT_BLOCK_LEN, RS_DEFAULT_STRONG_LEN, &stats); if (result != RS_DONE) { csync_debug(0, "Internal error from rsync library!\n"); goto error; } + fclose(basis_file); } - - fclose(basis_file); basis_file = 0; { @@ -336,14 +439,18 @@ int csync_rs_check(const char *filename, int isreg) csync_fatal("Format-error while receiving data.\n"); } - fflush(sig_file); - if ( size != ftell(sig_file) ) { - csync_debug(2, "Signature size differs: local=%d, peer=%d\n", - ftell(sig_file), size); - found_diff = 1; + if (sig_file) { + fflush(sig_file); + if ( size != ftell(sig_file) ) { + csync_debug(2, "Signature size differs: local=%d, peer=%d\n",ftell(sig_file), size); + found_diff = 1; + } + rewind(sig_file); + } + else { + csync_debug(2, "Signature size differs: local don't exist, peer=%d\n", size); + found_diff = 1; } - rewind(sig_file); - csync_debug(3, "Receiving %ld bytes ..\n", size); while ( size > 0 ) { @@ -354,16 +461,17 @@ int csync_rs_check(const char *filename, int isreg) csync_fatal("Read-error while receiving data.\n"); chunk = rc; - if ( fread(buffer2, chunk, 1, sig_file) != 1 ) { - csync_debug(2, "Found EOF in local sig file.\n"); - found_diff = 1; - } - if ( memcmp(buffer1, buffer2, chunk) ) { - csync_debug(2, "Found diff in sig at -%d:-%d\n", - size, size-chunk); - found_diff = 1; + if (sig_file) { + if ( fread(buffer2, chunk, 1, sig_file) != 1 ) { + csync_debug(2, "Found EOF in local sig file.\n"); + found_diff = 1; + } + if ( memcmp(buffer1, buffer2, chunk) ) { + csync_debug(2, "Found diff in sig at -%d:-%d\n", + size, size-chunk); + found_diff = 1; + } } - size -= chunk; csync_debug(3, "Got %d bytes, %ld bytes left ..\n", chunk, size); @@ -371,7 +479,8 @@ int csync_rs_check(const char *filename, int isreg) csync_debug(3, "File has been checked successfully (%s).\n", found_diff ? "difference found" : "files are equal"); - fclose(sig_file); + if (sig_file) + fclose(sig_file); return found_diff; io_error: @@ -397,9 +506,11 @@ void csync_rs_sig(const char *filename) csync_debug(3, "Opening basis_file and sig_file..\n"); - sig_file = open_temp_file(tmpfname, prefixsubst(filename)); - if ( !sig_file ) goto io_error; - if (unlink(tmpfname) < 0) goto io_error; + sig_file = open_temp_file(tmpfname, prefixsubst(filename),0); + if ( !sig_file ) + goto io_error; + if (unlink(tmpfname) < 0) + goto io_error; basis_file = fopen(prefixsubst(filename), "rb"); if ( !basis_file ) basis_file = fopen("/dev/null", "rb"); @@ -440,7 +551,7 @@ int csync_rs_delta(const char *filename) csync_debug(3, "Csync2 / Librsync: csync_rs_delta('%s')\n", filename); csync_debug(3, "Receiving sig_file from peer..\n"); - sig_file = open_temp_file(tmpfname, prefixsubst(filename)); + sig_file = open_temp_file(tmpfname, prefixsubst(filename),0); if ( !sig_file ) goto io_error; if (unlink(tmpfname) < 0) goto io_error; @@ -465,7 +576,7 @@ int csync_rs_delta(const char *filename) return -1; } - delta_file = open_temp_file(tmpfname, prefixsubst(filename)); + delta_file = open_temp_file(tmpfname, prefixsubst(filename),0); if ( !delta_file ) goto io_error; if (unlink(tmpfname) < 0) goto io_error; @@ -500,33 +611,47 @@ io_error: return -1; } -int csync_rs_patch(const char *filename) +int csync_rs_patch(const char *filepath) { FILE *basis_file = 0, *delta_file = 0, *new_file = 0; int backup_errno; rs_stats_t stats; rs_result result; char *errstr = "?"; + struct stat sb; + char filename[MAXPATHLEN]; + char dirname[MAXPATHLEN]; char tmpfname[MAXPATHLEN], newfname[MAXPATHLEN]; - csync_debug(3, "Csync2 / Librsync: csync_rs_patch('%s')\n", filename); + csync_debug(3, "Csync2 / Librsync: csync_rs_patch('%s')\n", filepath); csync_debug(3, "Receiving delta_file from peer..\n"); - delta_file = open_temp_file(tmpfname, prefixsubst(filename)); + + get_parent_child_from_path(dirname,NULL,filepath); + + if (stat (dirname, &sb) != 0) { + csync_debug(2,"one or more subdirectories in path %s seems to have deleted",filepath); + if(mkpath(filepath,0755)!=0) { + csync_debug(1,"failed to create path %s",dirname); + goto io_error; + } + } + + delta_file = open_temp_file(tmpfname, prefixsubst(filepath),0); if ( !delta_file ) { errstr="creating delta temp file"; goto io_error; } if (unlink(tmpfname) < 0) { errstr="removing delta temp file"; goto io_error; } if ( csync_recv_file(delta_file) ) goto error; csync_debug(3, "Opening to be patched file on local host..\n"); - basis_file = fopen(prefixsubst(filename), "rb"); + basis_file = fopen(prefixsubst(filepath), "rb"); if ( !basis_file ) { - basis_file = open_temp_file(tmpfname, prefixsubst(filename)); + basis_file = open_temp_file(tmpfname, prefixsubst(filepath),0); if ( !basis_file ) { errstr="opening data file for reading"; goto io_error; } if (unlink(tmpfname) < 0) { errstr="removing data temp file"; goto io_error; } } csync_debug(3, "Opening temp file for new data on local host..\n"); - new_file = open_temp_file(newfname, prefixsubst(filename)); + new_file = open_temp_file(newfname, prefixsubst(filepath),0); if ( !new_file ) { errstr="creating new data temp file"; goto io_error; } csync_debug(3, "Running rs_patch_file() from librsync..\n"); @@ -549,7 +674,7 @@ int csync_rs_patch(const char *filename) char winfilename[MAX_PATH]; HANDLE winfh; - cygwin_conv_to_win32_path(prefixsubst(filename), winfilename); + cygwin_conv_to_win32_path(prefixsubst(filepath), winfilename); winfh = CreateFile(TEXT(winfilename), GENERIC_WRITE, // open for writing @@ -570,7 +695,7 @@ int csync_rs_patch(const char *filename) } #endif - if (rename(newfname, prefixsubst(filename)) < 0) { errstr="renaming tmp file to to be patched file"; goto io_error; } + if (rename(newfname, prefixsubst(filepath)) < 0) { errstr="renaming tmp file to to be patched file"; goto io_error; } csync_debug(3, "File has been patched successfully.\n"); fclose(delta_file); @@ -580,7 +705,7 @@ int csync_rs_patch(const char *filename) io_error: csync_debug(0, "I/O Error '%s' while %s in rsync-patch: %s\n", - strerror(errno), errstr, prefixsubst(filename)); + strerror(errno), errstr, prefixsubst(filepath)); error:; backup_errno = errno; diff --git a/csync2_trunk/update.c b/csync2_tempdir_patch/update.c index b2c2b85..609190b 100644 --- a/csync2_trunk/update.c +++ b/csync2_tempdir_patch/update.c @@ -33,22 +33,46 @@ static int connection_closed_error = 1; -int read_conn_status(const char *file, const char *host) +connection_response read_conn_status(const char *file, const char *host) { char line[4096]; + connection_response conn_status; + if ( conn_gets(line, 4096) ) { - if ( !strncmp(line, "OK (", 4) ) return 0; + int cmd_finished=strncmp(line,response_command_finished , strlen(response_command_finished)); + int cu_later=strncmp(line,response_see_you_later,strlen(response_see_you_later)); + int data_follows=strncmp(line,response_data_follows,strlen(response_data_follows)); + int activating_ssl=strncmp(line,response_activating_ssl,strlen(response_activating_ssl)); + int send_data=strncmp(line,response_send_data,strlen(response_send_data)); + int marked_dirty=strncmp(line, response_file_marked_dirty_here,strlen(response_file_marked_dirty_here)); + int path_not_found=strncmp(line, response_path_not_found,strlen(response_path_not_found)); + int parent_dir_missing=strncmp(line, response_parent_dir_missing,strlen(response_parent_dir_missing)); + + if ( !cmd_finished || !cu_later || !data_follows || !activating_ssl || !send_data ) {//if ( !strncmp(line, "OK (", 4) ) { + conn_status=CONNECTION_RESPONSE_OK;//ideally the function looking OK conn_status should instead check only those OK states that they are interested in + }else if(!marked_dirty) { + conn_status=CONNECTION_RESPONSE_PATH_DIRTY; + csync_error_count++; + } else if(!path_not_found){ + conn_status=CONNECTION_RESPONSE_PATH_NOT_FOUND; + } else if(!parent_dir_missing){ + conn_status=CONNECTION_RESPONSE_PARENT_DIR_MISSING; + } else { + conn_status=CONNECTION_RESPONSE_ERROR; + csync_error_count++; + } } else { + csync_error_count++; connection_closed_error = 1; strcpy(line, "Connection closed.\n"); + conn_status=CONNECTION_RESPONSE_ERROR; } if ( file ) - csync_debug(0, "While syncing file %s:\n", file); + csync_debug(2, "While syncing file %s:\n", file); else - file = ""; - csync_debug(0, "ERROR from peer(%s): %s %s", file, host, line); - csync_error_count++; - return !strcmp(line, "File is also marked dirty here!") ? 1 : 2; + file = ""; + csync_debug(3, "response from peer(%s): %s %s", file, host, line); + return conn_status; } int connect_to_host(const char *peername) @@ -74,7 +98,7 @@ int connect_to_host(const char *peername) if ( use_ssl ) { #if HAVE_LIBGNUTLS conn_printf("SSL\n"); - if ( read_conn_status(0, peername) ) { + if ( read_conn_status(0, peername) !=CONNECTION_RESPONSE_OK ) { csync_debug(1, "SSL command failed.\n"); conn_close(); return -1; @@ -89,7 +113,7 @@ int connect_to_host(const char *peername) } conn_printf("CONFIG %s\n", url_encode(cfgname)); - if ( read_conn_status(0, peername) ) { + if ( read_conn_status(0, peername) !=CONNECTION_RESPONSE_OK ) { csync_debug(1, "Config command failed.\n"); conn_close(); return -1; @@ -97,7 +121,7 @@ int connect_to_host(const char *peername) if (active_grouplist) { conn_printf("GROUP %s\n", url_encode(active_grouplist)); - if ( read_conn_status(0, peername) ) { + if ( read_conn_status(0, peername) !=CONNECTION_RESPONSE_OK ) { csync_debug(1, "Group command failed.\n"); conn_close(); return -1; @@ -147,7 +171,7 @@ static int get_master_slave_status(const char *peername, const char *filename) void csync_update_file_del(const char *peername, const char *filename, int force, int dry_run) { - int last_conn_status = 0, auto_resolve_run = 0; + connection_response last_conn_status; int auto_resolve_run = 0; const char *key = csync_key(peername, filename); if ( !key ) { @@ -164,7 +188,7 @@ auto_resolve_entry_point: return; } conn_printf("FLUSH %s %s\n", url_encode(key), url_encode(filename)); - if ( read_conn_status(filename, peername) ) + if ( read_conn_status(filename, peername) !=CONNECTION_RESPONSE_OK ) goto got_error; } else { int i, found_diff = 0; @@ -174,7 +198,7 @@ auto_resolve_entry_point: conn_printf("SIG %s %s\n", url_encode(key), url_encode(filename)); - if ( read_conn_status(filename, peername) ) goto got_error; + if ( read_conn_status(filename, peername) !=CONNECTION_RESPONSE_OK ) goto got_error; if ( !conn_gets(chk1, 4096) ) goto got_error; for (i=0; chk1[i] && chk1[i] != '\n' && chk2[i]; i++) @@ -192,7 +216,7 @@ auto_resolve_entry_point: csync_debug(2, "File is different on peer (rsync sig).\n"); found_diff=1; } - if ( read_conn_status(filename, peername) ) goto got_error; + if ( read_conn_status(filename, peername) !=CONNECTION_RESPONSE_OK ) goto got_error; if ( !found_diff ) { csync_debug(1, "File is already up to date on peer.\n"); @@ -211,7 +235,7 @@ auto_resolve_entry_point: conn_printf("DEL %s %s\n", url_encode(key), url_encode(filename)); - if ( (last_conn_status=read_conn_status(filename, peername)) ) + if ( (last_conn_status=read_conn_status(filename, peername))!=CONNECTION_RESPONSE_OK ) goto maybe_auto_resolve; skip_action: @@ -226,8 +250,9 @@ skip_action: return; maybe_auto_resolve: - if (!auto_resolve_run && last_conn_status == 2) + if (!auto_resolve_run && (last_conn_status == CONNECTION_RESPONSE_PATH_DIRTY ) ) { + csync_debug(0,"auto resolving... response = %d",last_conn_status); if (get_master_slave_status(peername, filename)) { csync_debug(0, "Auto-resolving conflict: Won 'master/slave' test.\n"); auto_resolve_run = 1; @@ -276,7 +301,7 @@ void csync_update_file_mod(const char *peername, const char *filename, int force, int dry_run) { struct stat st; - int last_conn_status = 0, auto_resolve_run = 0; + connection_response last_conn_status; int auto_resolve_run = 0; const char *key = csync_key(peername, filename); if ( !key ) { @@ -300,7 +325,7 @@ auto_resolve_entry_point: } conn_printf("FLUSH %s %s\n", url_encode(key), url_encode(filename)); - if ( read_conn_status(filename, peername) ) + if ( read_conn_status(filename, peername) !=CONNECTION_RESPONSE_OK ) goto got_error; } else { int i, found_diff = 0; @@ -310,13 +335,47 @@ auto_resolve_entry_point: conn_printf("SIG %s %s\n", url_encode(key), url_encode(filename)); - if ( read_conn_status(filename, peername) ) goto got_error; - + last_conn_status=read_conn_status(filename, peername); + + if ( last_conn_status!=CONNECTION_RESPONSE_OK ){ + + if(last_conn_status==CONNECTION_RESPONSE_PARENT_DIR_MISSING) + { + int filename_length=strlen(filename); + char parent_dirname[filename_length]; + char* file_name=NULL; + struct stat sb; + get_parent_child_from_path(parent_dirname,NULL,filename); + csync_debug(2,"missing parent dir : %s",parent_dirname); + + struct textlist *tl = 0, *t; + SQL_BEGIN("Query File Table for missing files on the peer","SELECT filename from file where filename = '%s' UNION ALL SELECT filename from file where filename > '%s/' and filename < '%s0' ORDER BY filename;",url_encode(parent_dirname),url_encode(parent_dirname), url_encode(parent_dirname)) + { + const char *fn = url_decode(SQL_V(0)); + if ( lstat_strict(prefixsubst(fn), &sb) == 0 && csync_check_pure(fn) ==0 ) { + textlist_add(&tl, fn, 0); + csync_debug(3,"path %s added to dirty path list",fn); + } + } SQL_END; + + for (t = tl; t != 0; t = t->next) { + csync_mark(t->value, peername, 0); + //csync_update_file_mod(peername,t->value,1,0); + } + textlist_free(tl); + + } else if(last_conn_status==CONNECTION_RESPONSE_ERROR) + { + csync_debug(3,"error from peer"); + goto got_error; + } + } + if ( !conn_gets(chk1, 4096) ) goto got_error; chk2 = csync_genchecktxt(&st, filename, 1); for (i=0; chk1[i] && chk1[i] != '\n' && chk2[i]; i++) if ( chk1[i] != chk2[i] ) { - csync_debug(2, "File is different on peer (cktxt char #%d).\n", i); + csync_debug(2, "File %s is different on peer (cktxt char #%d).\n",filename, i); csync_debug(2, ">>> PEER: %s>>> LOCAL: %s\n", chk1, chk2); found_diff=1; break; @@ -329,8 +388,8 @@ auto_resolve_entry_point: csync_debug(2, "File is different on peer (rsync sig).\n"); found_diff=1; } - if ( read_conn_status(filename, peername) ) goto got_error; - + if ( read_conn_status(filename, peername) !=CONNECTION_RESPONSE_OK ) goto got_error; + if ( !found_diff ) { csync_debug(1, "File is already up to date on peer.\n"); if ( dry_run ) { @@ -349,37 +408,37 @@ auto_resolve_entry_point: if ( S_ISREG(st.st_mode) ) { conn_printf("PATCH %s %s\n", url_encode(key), url_encode(filename)); - if ( (last_conn_status = read_conn_status(filename, peername)) ) + if ( (last_conn_status = read_conn_status(filename, peername)) !=CONNECTION_RESPONSE_OK ) goto maybe_auto_resolve; if ( csync_rs_delta(filename) ) { - read_conn_status(filename, peername); + read_conn_status(filename, peername);//why is the response ignored? goto got_error; } - if ( read_conn_status(filename, peername) ) + if ( read_conn_status(filename, peername) !=CONNECTION_RESPONSE_OK ) goto got_error; } else if ( S_ISDIR(st.st_mode) ) { conn_printf("MKDIR %s %s\n", url_encode(key), url_encode(filename)); - if ( (last_conn_status = read_conn_status(filename, peername)) ) + if ( (last_conn_status = read_conn_status(filename, peername)) !=CONNECTION_RESPONSE_OK ) goto maybe_auto_resolve; } else if ( S_ISCHR(st.st_mode) ) { conn_printf("MKCHR %s %s\n", url_encode(key), url_encode(filename)); - if ( (last_conn_status = read_conn_status(filename, peername)) ) + if ( (last_conn_status = read_conn_status(filename, peername)) !=CONNECTION_RESPONSE_OK ) goto maybe_auto_resolve; } else if ( S_ISBLK(st.st_mode) ) { conn_printf("MKBLK %s %s\n", url_encode(key), url_encode(filename)); - if ( (last_conn_status = read_conn_status(filename, peername)) ) + if ( (last_conn_status = read_conn_status(filename, peername)) !=CONNECTION_RESPONSE_OK ) goto maybe_auto_resolve; } else if ( S_ISFIFO(st.st_mode) ) { conn_printf("MKFIFO %s %s\n", url_encode(key), url_encode(filename)); - if ( (last_conn_status = read_conn_status(filename, peername)) ) + if ( (last_conn_status = read_conn_status(filename, peername)) !=CONNECTION_RESPONSE_OK ) goto maybe_auto_resolve; } else if ( S_ISLNK(st.st_mode) ) { @@ -391,7 +450,7 @@ auto_resolve_entry_point: conn_printf("MKLINK %s %s %s\n", url_encode(key), url_encode(filename), url_encode(target)); - if ( (last_conn_status = read_conn_status(filename, peername)) ) + if ( (last_conn_status = read_conn_status(filename, peername)) !=CONNECTION_RESPONSE_OK ) goto maybe_auto_resolve; } else { csync_debug(1, "File is a symlink but radlink() failed.\n", st.st_mode); @@ -401,7 +460,7 @@ auto_resolve_entry_point: if ( S_ISSOCK(st.st_mode) ) { conn_printf("MKSOCK %s %s\n", url_encode(key), url_encode(filename)); - if ( (last_conn_status = read_conn_status(filename, peername)) ) + if ( (last_conn_status = read_conn_status(filename, peername)) !=CONNECTION_RESPONSE_OK ) goto maybe_auto_resolve; } else { csync_debug(1, "File type (mode=%o) is not supported.\n", st.st_mode); @@ -411,13 +470,13 @@ auto_resolve_entry_point: conn_printf("SETOWN %s %s %d %d\n", url_encode(key), url_encode(filename), st.st_uid, st.st_gid); - if ( read_conn_status(filename, peername) ) + if ( read_conn_status(filename, peername) !=CONNECTION_RESPONSE_OK ) goto got_error; if ( !S_ISLNK(st.st_mode) ) { conn_printf("SETMOD %s %s %d\n", url_encode(key), url_encode(filename), st.st_mode); - if ( read_conn_status(filename, peername) ) + if ( read_conn_status(filename, peername) !=CONNECTION_RESPONSE_OK ) goto got_error; } @@ -426,7 +485,7 @@ skip_action: conn_printf("SETIME %s %s %Ld\n", url_encode(key), url_encode(filename), (long long)st.st_mtime); - if ( read_conn_status(filename, peername) ) + if ( read_conn_status(filename, peername) !=CONNECTION_RESPONSE_OK ) goto got_error; } @@ -441,7 +500,7 @@ skip_action: return; maybe_auto_resolve: - if (!auto_resolve_run && last_conn_status == 2) + if (!auto_resolve_run && (last_conn_status == CONNECTION_RESPONSE_PATH_DIRTY ) ) { if (get_master_slave_status(peername, filename)) { csync_debug(0, "Auto-resolving conflict: Won 'master/slave' test.\n"); @@ -484,7 +543,7 @@ maybe_auto_resolve: } conn_printf("%s %s %s\n", cmd, url_encode(key), url_encode(filename)); - if ( read_conn_status(filename, peername) ) goto got_error_in_autoresolve; + if ( read_conn_status(filename, peername) !=CONNECTION_RESPONSE_OK ) goto got_error_in_autoresolve; if ( !conn_gets(buffer, 4096) ) goto got_error_in_autoresolve; remotedata = atol(buffer); @@ -590,7 +649,7 @@ void csync_update_host(const char *peername, csync_debug(3, "Dirty item %s %s %d \n", t->value, t->value2, t->intvalue); if ( !current_name || strcmp(current_name, t->value2) ) { conn_printf("HELLO %s\n", url_encode(t->value2)); - if ( read_conn_status(t->value, peername) ) + if ( read_conn_status(t->value, peername) !=CONNECTION_RESPONSE_OK ) goto ident_failed_1; current_name = t->value2; } @@ -606,7 +665,7 @@ ident_failed_1: if ( !current_name || strcmp(current_name, t->value2) ) { csync_debug(3, "Dirty item %s %s %d ", t->value, t->value2, t->intvalue); conn_printf("HELLO %s\n", url_encode(t->value2)); - if ( read_conn_status(t->value, peername) ) + if ( read_conn_status(t->value, peername) !=CONNECTION_RESPONSE_OK ) goto ident_failed_2; current_name = t->value2; } @@ -620,7 +679,7 @@ ident_failed_2:; textlist_free(tl); conn_printf("BYE\n"); - read_conn_status(0, peername); + read_conn_status(0, peername);//why is response ignored? conn_close(); } @@ -682,10 +741,10 @@ found_host_check: } conn_printf("HELLO %s\n", myname); - if ( read_conn_status(0, peername) ) goto finish; + if ( read_conn_status(0, peername) !=CONNECTION_RESPONSE_OK ) goto finish; conn_printf("TYPE %s %s\n", g->key, filename); - if ( read_conn_status(0, peername) ) goto finish; + if ( read_conn_status(0, peername) !=CONNECTION_RESPONSE_OK ) goto finish; /* FIXME * verify type of file first! @@ -784,7 +843,7 @@ found_host_check: } conn_printf("HELLO %s\n", myname); - read_conn_status(0, peername); + read_conn_status(0, peername); //why is response ignored? conn_printf("LIST %s %s", peername, filename ? url_encode(filename) : "-"); for (g = csync_group; g; g = g->next) { @@ -867,7 +926,7 @@ got_remote_eof: if (r_checktxt) free(r_checktxt); conn_printf("BYE\n"); - read_conn_status(0, peername); + read_conn_status(0, peername);//why is response ignored? conn_close(); for (diff_ent=diff_list; diff_ent; diff_ent=diff_ent->next)