Exemple #1
0
int csync_db_next(void *vmx, const char *err,
		int *pN, const char ***pazValue, const char ***pazColName)
{
	db_stmt_p stmt = vmx;
	int rc, busyc = 0;

	csync_debug(4, "Trying to fetch a row from the database.\n");

	while (1) {
		rc = db_stmt_next(stmt);
		if ( rc != DB_BUSY ) 
		  break;
		if (busyc++ > get_dblock_timeout()) { 
		  db = 0; 
		  csync_fatal(DEADLOCK_MESSAGE); 
		}
		csync_debug(2, "Database is busy, sleeping a sec.\n");
		sleep(1);
	}

	if ( rc != DB_OK && rc != DB_ROW &&
	     rc != DB_DONE && err )
		csync_fatal("Database Error: %s [%d]: %s\n", err, rc, db_errmsg(db));

	return rc == DB_ROW;
}
Exemple #2
0
void csync_db_fin(void *vmx, const char *err)
{
        db_stmt_p stmt = (db_stmt_p) vmx;
	int rc, busyc = 0;

	if (vmx == NULL)
	   return;

	csync_debug(2, "SQL Query finished.\n");

	while (1) {
	  rc = db_stmt_close(stmt);
	  if ( rc != DB_BUSY ) 
	    break;
	  if (busyc++ > get_dblock_timeout()) { db = 0; csync_fatal(DEADLOCK_MESSAGE); }
	  csync_debug(2, "Database is busy, sleeping a sec.\n");
	  sleep(1);
	}

	if ( rc != DB_OK && err )
		csync_fatal("Database Error: %s [%d]: %s\n", err, rc, db_errmsg(db));

	csync_db_maycommit();
	in_sql_query--;
}
Exemple #3
0
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");
	}

	csync_debug(3, "Receiving %ld bytes ..\n", size);

	while ( size > 0 ) {
		chunk = size > 512 ? 512 : size;
		rc = conn_read(buffer, chunk);

		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");

		size -= chunk;
		csync_debug(3, "Got %d bytes, %ld bytes left ..\n",
				chunk, size);
	}

	fflush(out);
	rewind(out);
	return 0;
}
Exemple #4
0
void* csync_db_begin(const char *err, const char *fmt, ...)
{
	db_stmt_p stmt = NULL;
	char *sql;
	va_list ap;
	int rc, busyc = 0;
	char *ppTail; 
	va_start(ap, fmt);
	VASPRINTF(&sql, fmt, ap);
	va_end(ap);

	in_sql_query++;
	csync_db_maybegin();

	csync_debug(2, "SQL: %s\n", sql);
	while (1) {
	        rc = db_prepare_stmt(db, sql, &stmt, &ppTail);
		if ( rc != DB_BUSY ) break;
		if (busyc++ > get_dblock_timeout()) { db = 0; csync_fatal(DEADLOCK_MESSAGE); }
		csync_debug(2, "Database is busy, sleeping a sec.\n");
		sleep(1);
	}

	if ( rc != DB_OK && err )
		csync_fatal("Database Error: %s [%d]: %s on executing %s\n", err, rc, db_errmsg(db), sql);
	free(sql);

	return stmt;
}
Exemple #5
0
static int get_tmpname(char *fnametmp, const char *fname)
{
	int maxname, added, length = 0;
	const char *f;
	char *suf;

	static unsigned counter_limit;
	unsigned counter;

	if ((f = strrchr(fname, '/')) != NULL) {
		++f;
		length = f - fname;
		/* copy up to and including the slash */
		strlcpy(fnametmp, fname, length + 1);
	} else
		f = fname;
	fnametmp[length++] = '.';

	/* The maxname value is bufsize, and includes space for the '\0'.
	 * NAME_MAX needs an extra -1 for the name's leading dot. */
	maxname = MIN(MAXPATHLEN - length - TMPNAME_SUFFIX_LEN,
		      NAME_MAX - 1 - TMPNAME_SUFFIX_LEN);

	if (maxname < 1) {
		csync_debug(1, "temporary filename too long: %s\n", fname);
		fnametmp[0] = '\0';
		return 0;
	}

	added = strlcpy(fnametmp + length, f, maxname);
	if (added >= maxname)
		added = maxname - 1;
	suf = fnametmp + 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. */
		while (1) {
			snprintf(suf, TMPNAME_SUFFIX_LEN+1, ".%d", counter);
			if (access(fnametmp, 0) < 0)
				break;
			if (++counter >= counter_limit)
				return 0;
		}
	} else
		memcpy(suf, TMPNAME_SUFFIX, TMPNAME_SUFFIX_LEN+1);

	return 1;
}
Exemple #6
0
static FILE *open_temp_file(char *fnametmp, const char *fname)
{
	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;
	}

	f = NULL;
	fd = open(fnametmp, 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;
	}

	return f;
}
Exemple #7
0
void csync_db_alarmhandler(int signum)
{
	if ( in_sql_query || begin_commit_recursion )
		alarm(2);

	if (tqueries_counter <= 0)
		return;

	begin_commit_recursion++;

	csync_debug(2, "Database idle in transaction. Forcing COMMIT.\n");
	SQL("COMMIT ", "COMMIT ");
	tqueries_counter = -10;

	begin_commit_recursion--;
}
Exemple #8
0
void csync_db_maycommit()
{
	time_t now;

	if ( !db_blocking_mode || begin_commit_recursion ) return;
	begin_commit_recursion++;

	if (tqueries_counter <= 0) {
		begin_commit_recursion--;
		return;
	}

	now = time(0);

	if ((now - last_wait_cycle) > 10) {
		SQL("COMMIT", "COMMIT ");
		if (wait) {
		  csync_debug(2, "Waiting %d secs so others can lock the database (%d - %d)...\n", wait, (int)now, (int)last_wait_cycle);
		  sleep(wait);
		}
		last_wait_cycle = 0;
		tqueries_counter = -10;
		begin_commit_recursion--;
		return;
	}

	if ((tqueries_counter > 1000) || ((now - transaction_begin) > 3)) {
	        SQL("COMMIT ", "COMMIT ");
		tqueries_counter = 0;
		begin_commit_recursion--;
		return;
	}

	signal(SIGALRM, csync_db_alarmhandler);
	alarm(10);

	begin_commit_recursion--;
	return;
}
Exemple #9
0
static FILE *paranoid_tmpfile()
{
	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);
	}
	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;
}
Exemple #10
0
void csync_rs_sig(const char *filename)
{
	FILE *basis_file = 0, *sig_file = 0;
	rs_stats_t stats;
	rs_result result;
	char tmpfname[MAXPATHLEN];

	csync_debug(3, "Csync2 / Librsync: csync_rs_sig('%s')\n", 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;

	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");
	result = rs_sig_file(basis_file, sig_file,
			RS_DEFAULT_BLOCK_LEN, RS_DEFAULT_STRONG_LEN, &stats);
	if (result != RS_DONE)
		csync_fatal("Got an error from librsync, too bad!\n");

	csync_debug(3, "Sending sig_file to peer..\n");
	csync_send_file(sig_file);

	csync_debug(3, "Signature has been created successfully.\n");
	fclose(basis_file);
	fclose(sig_file);

	return;

io_error:
	csync_debug(0, "I/O Error '%s' in rsync-sig: %s\n",
			strerror(errno), prefixsubst(filename));

	if (basis_file) fclose(basis_file);
	if (sig_file) fclose(sig_file);
}
Exemple #11
0
int csync_rs_patch(const char *filename)
{
	FILE *basis_file = 0, *delta_file = 0, *new_file = 0;
	int backup_errno;
	rs_stats_t stats;
	rs_result result;
	char *errstr = "?";
	char tmpfname[MAXPATHLEN], newfname[MAXPATHLEN];

	csync_debug(3, "Csync2 / Librsync: csync_rs_patch('%s')\n", filename);

	csync_debug(3, "Receiving delta_file from peer..\n");
	delta_file = open_temp_file(tmpfname, prefixsubst(filename));
	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");
	if ( !basis_file ) {
		basis_file = open_temp_file(tmpfname, prefixsubst(filename));
		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));
	if ( !new_file ) { errstr="creating new data temp file"; goto io_error; }

	csync_debug(3, "Running rs_patch_file() from librsync..\n");
	result = rs_patch_file(basis_file, delta_file, new_file, &stats);
	if (result != RS_DONE) {
		csync_debug(0, "Internal error from rsync library!\n");
		goto error;
	}

	csync_debug(3, "Renaming tmp file to data file..\n");
	fclose(basis_file);

#ifdef __CYGWIN__

/* TODO: needed? */
	// This creates the file using the native windows API, bypassing
	// the cygwin wrappers and so making sure that we do not mess up the
	// permissions..
	{
		char winfilename[MAX_PATH];
		HANDLE winfh;

		cygwin_conv_to_win32_path(prefixsubst(filename), winfilename);

		winfh = CreateFile(TEXT(winfilename),
				GENERIC_WRITE,          // open for writing
				0,                      // do not share
				NULL,                   // default security
				CREATE_ALWAYS,          // overwrite existing
				FILE_ATTRIBUTE_NORMAL | // normal file
				FILE_FLAG_OVERLAPPED,   // asynchronous I/O
				NULL);                  // no attr. template

		if (winfh == INVALID_HANDLE_VALUE) {
			csync_debug(0, "Win32 I/O Error %d in rsync-patch: %s\n",
					(int)GetLastError(), winfilename);
			errno = EACCES;
			goto error;
		}
		CloseHandle(winfh);
	}
#endif

	if (rename(newfname, prefixsubst(filename)) < 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);
	fclose(new_file);

	return 0;

io_error:
	csync_debug(0, "I/O Error '%s' while %s in rsync-patch: %s\n",
			strerror(errno), errstr, prefixsubst(filename));

error:;
	backup_errno = errno;
	if ( delta_file ) fclose(delta_file);
	if ( basis_file ) fclose(basis_file);
	if ( new_file )   fclose(new_file);
	errno = backup_errno;
	return -1;
}
Exemple #12
0
int csync_rs_delta(const char *filename)
{
	FILE *sig_file = 0, *new_file = 0, *delta_file = 0;
	rs_result result;
	rs_signature_t *sumset;
	rs_stats_t stats;
	char tmpfname[MAXPATHLEN];

	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));
	if ( !sig_file ) goto io_error;
	if (unlink(tmpfname) < 0) goto io_error;

	if ( csync_recv_file(sig_file) ) {
		fclose(sig_file);
		return -1;
	}
	result = rs_loadsig_file(sig_file, &sumset, &stats);
	if (result != RS_DONE)
		csync_fatal("Got an error from librsync, too bad!\n");
	fclose(sig_file);

	csync_debug(3, "Opening new_file and delta_file..\n");
	new_file = fopen(prefixsubst(filename), "rb");
	if ( !new_file ) {
		int backup_errno = errno;
		csync_debug(0, "I/O Error '%s' while %s in rsync-delta: %s\n",
				strerror(errno), "opening data file for reading", filename);
		csync_send_error();
		fclose(new_file);
		errno = backup_errno;
		return -1;
	}

	delta_file = open_temp_file(tmpfname, prefixsubst(filename));
	if ( !delta_file ) goto io_error;
	if (unlink(tmpfname) < 0) goto io_error;

	csync_debug(3, "Running rs_build_hash_table() from librsync..\n");
	result = rs_build_hash_table(sumset);
	if (result != RS_DONE)
		csync_fatal("Got an error from librsync, too bad!\n");

	csync_debug(3, "Running rs_delta_file() from librsync..\n");
	result = rs_delta_file(sumset, new_file, delta_file, &stats);
	if (result != RS_DONE)
		csync_fatal("Got an error from librsync, too bad!\n");

	csync_debug(3, "Sending delta_file to peer..\n");
	csync_send_file(delta_file);

	csync_debug(3, "Delta has been created successfully.\n");
	rs_free_sumset(sumset);
	fclose(delta_file);
	fclose(new_file);

	return 0;

io_error:
	csync_debug(0, "I/O Error '%s' in rsync-delta: %s\n",
			strerror(errno), prefixsubst(filename));

	if (new_file) fclose(new_file);
	if (delta_file) fclose(delta_file);
	if (sig_file) fclose(sig_file);

	return -1;
}
Exemple #13
0
int csync_rs_check(const char *filename, int isreg)
{
	FILE *basis_file = 0, *sig_file = 0;
	char buffer1[512], buffer2[512];
	int rc, chunk, found_diff = 0;
	int backup_errno;
	rs_stats_t stats;
	rs_result result;
	long size;
	char tmpfname[MAXPATHLEN];

	csync_debug(3, "Csync2 / Librsync: csync_rs_check('%s', %d [%s])\n",
		filename, isreg, isreg ? "regular file" : "non-regular file");

	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;

	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;
	}

	if ( isreg ) {
		csync_debug(3, "Running rs_sig_file() from librsync....\n");
		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);
	basis_file = 0;

	{
		char line[100];
		csync_debug(3, "Reading signature size from peer....\n");
		if ( !conn_gets(line, 100) || sscanf(line, "octet-stream %ld\n", &size) != 1 )
			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;
	}
	rewind(sig_file);

	csync_debug(3, "Receiving %ld bytes ..\n", size);

	while ( size > 0 ) {
		chunk = size > 512 ? 512 : size;
		rc = conn_read(buffer1, chunk);

		if ( rc <= 0 )
			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;
		}

		size -= chunk;
		csync_debug(3, "Got %d bytes, %ld bytes left ..\n",
				chunk, size);
	}

	csync_debug(3, "File has been checked successfully (%s).\n",
		found_diff ? "difference found" : "files are equal");
	fclose(sig_file);
	return found_diff;

io_error:
	csync_debug(0, "I/O Error '%s' in rsync-check: %s\n",
			strerror(errno), prefixsubst(filename));

error:;
	backup_errno = errno;
	if ( basis_file ) fclose(basis_file);
	if ( sig_file )   fclose(sig_file);
	errno = backup_errno;
	return -1;
}