Beispiel #1
0
static void proto_handle_newerthan(conn_t* cn, const char* line) {
	char buf[255];
	char* p;
	time_t ts;
	char *path;

	if(strlen(line) >= 254) {
		conn_printf(cn, "ERROR Protocol violation (%d)\n", __LINE__);
		conn_abort(cn);
		return;
	}

	strcpy(buf,line);
	
	p = buf;
	while(p && !isspace(*p))
		p++;

	*p = '\0';
	ts = atoi(buf);

	if((buf+255) < p) {
		conn_printf(cn, "ERROR Protocol violation (%d)\n", __LINE__);
		conn_abort(cn);
		return;
	}

	p++;
	path = p;

	find_newerthan_ts(cn, ts, path);

	conn_printf(cn, "END\n");
}
Beispiel #2
0
static void proto_handle_hlnk(conn_t* cn, const char* line) {
	// read next line to get target
	char target[PATH_MAX];
	if(!conn_readline(cn, target, sizeof target)) {
		conn_perror(cn, "ERROR No data\n");
		conn_abort(cn);
		return;
	}
	
	if(strcmp(target, line)==0) {
		conn_printf(cn, "ERROR Cannot make a link to itself!\n");
		conn_abort(cn);
		return;
	}

	// Check if inode is the same, if so, dont bother
	if(get_inode(target) != get_inode(line)) {
		if(link(target, line)==-1) {
			conn_perror(cn, "ERROR link()");
			conn_abort(cn);
			return;
		}
	}

	conn_printf(cn, "GET %s\n", line);
}
Beispiel #3
0
static void proto_handle_exists(conn_t* cn, const char* line) {
	int fd = open(line, O_RDONLY);

	if(fd == -1) {
		conn_printf(cn, "NO\n");
	}
	else {
		close(fd);
		conn_printf(cn, "YES\n");
	}
}
Beispiel #4
0
static void proto_delegator(conn_t* cn, const char* line, hlink_t **hardlinks) {
	if(memcmp(line, "ERROR ",6) == 0)
		proto_handle_error(cn, line+6);
	else if(memcmp(line, "WARNING ",8) == 0)
		proto_handle_warning(cn, line+8);
	else if(cn->handshaked == 0) {
		if(memcmp(line, "HELLO ",6) == 0) {
			proto_handle_hello(cn, line+6);
		}
		else {
			conn_printf(cn, "ERROR Protocol violation (%d) '%s'\n", __LINE__, line);
			conn_abort(cn);
		}
	}
	else {
		if(memcmp(line, "GETTIME\0",8) == 0) {
			proto_handle_gettime(cn);
		}
		else if(memcmp(line, "SCAN ",5) == 0) {
			proto_handle_scan(cn, line+5, hardlinks);
		}
		else if(memcmp(line, "NEWERTHAN ",10) == 0) {
			proto_handle_newerthan(cn, line+10);
		}
		else if(memcmp(line, "MKDIR ",6) == 0) {
			proto_handle_mkdir(cn, line+6);
		}
		else if(memcmp(line, "GET ",4) == 0) {
			proto_handle_get(cn, line+4);
		}
		else if(memcmp(line, "PUT ",4) == 0) {
			proto_handle_put(cn, line+4);
		}
		else if(memcmp(line, "SLNK ", 5) == 0) {
			proto_handle_slnk(cn, line+5);
		}
		else if(memcmp(line, "HLNK ", 5) == 0) {
			proto_handle_hlnk(cn, line+5);
		}
		else if(memcmp(line, "EXISTS ", 7) == 0) {
			proto_handle_exists(cn, line+7);
		}
		else if(memcmp(line, "LINKS ", 6) == 0) {
			proto_handle_links(cn, line+6, hardlinks);
		}
		else {
			conn_printf(cn, "ERROR Protocol violation (%d): %s\n", __LINE__, line);
			conn_abort(cn);
		}
	}
}
Beispiel #5
0
static void proto_handle_gettime(conn_t* cn) {
	time_t now;

	now = time(NULL);
	assert(now != (time_t)-1);
	conn_printf(cn, "GETTIME %ld\n", (long int)now);
}
Beispiel #6
0
void csync_send_file(FILE *in)
{
	char buffer[512];
	int rc, chunk;
	long size;

	fflush(in);
	size = ftell(in);
	rewind(in);

	conn_printf("octet-stream %ld\n", size);

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

		if ( rc <= 0 )
			csync_fatal("Read-error while sending data.\n");
		chunk = rc;

		rc = conn_write(buffer, chunk);
		if ( rc != chunk )
			csync_fatal("Write-error while sending data.\n");

		size -= chunk;
	}
}
Beispiel #7
0
static void proto_handle_hello(conn_t* cn, const char* line) {
	if(memcmp(line, "dmsync ", 7) != 0) {
		conn_printf(cn, "ERROR Protocol violation (%d)\n", __LINE__);
		conn_abort(cn);
		return;
	}
	int v = atoi(line+6);
	assert(v);

	if(v == PROTOCOL_VERSION) {
		conn_printf(cn, "%s", "HELLO\n");
		cn->handshaked = 1;
	}
	else {
		conn_printf(cn, "ERROR Protocol not supported\n");
		conn_abort(cn);
	}
}
Beispiel #8
0
static void proto_handle_mkdir(conn_t* cn, const char* line) {
	// line is: permission mtime ctime atime directoryname
	const char* delim = " ";
	char* saveptr = NULL;
	char* token;
	char* ptr = (char*)line;
	int c = 0;

	mode_t mode = 0;
	time_t mtime = 0;
	time_t ctime = 0;
	time_t atime = 0;
	char* name = NULL;

	while((token = strtok_r(ptr, delim, &saveptr))) {
		switch(c) {
			case 0: mode = str2mode(token); break;
			case 1: atime = atol(token); break; 
			case 2: ctime = atol(token); break;
			case 3: mtime = atol(token); break;
			case 4: name = token; break;
			default:
				conn_printf(cn, "ERROR Protocol violation (%d)\n", __LINE__);
				conn_abort(cn);
				return;
				break;
		}
		c++;
		ptr = NULL;
	}

	if(c != 5) {
		conn_printf(cn, "ERROR Protocol violation (%d)\n", __LINE__);
		conn_abort(cn);
		return ;
	}

	if(mkdir(name,mode) == -1 && errno != EEXIST) {
		conn_perror(cn, "WARNING mkdir()");
		conn_printf(cn, "ERROR Can't create directory: %s\n", name);
		conn_abort(cn);
		return;
	}

	if(chmod(name,mode)==-1) {
		conn_perror(cn,"WARNING chmod()");
		conn_printf(cn, "WARNING Can't change permissions on directory: %s\n", name);
	}

	struct utimbuf t;
	t.actime = atime;
	t.modtime = mtime;
	if(utime(name,&t)==-1) {
		conn_perror(cn, "WARNING utime");
		conn_printf(cn, "WARNING Can't timestamp on directory: %s\n", name);
	}

	conn_printf(cn, "MKDIR %s\n", name);
}
Beispiel #9
0
static void find_newerthan_ts_worker(void* data, struct stat* st, const char* file) {
	conn_t* cn = ((struct newerthan_data*)data)->cn;
	time_t  ts = ((struct newerthan_data*)data)->ts;

	if(ts >= st->st_mtime)
		return;
	
	if(S_ISREG(st->st_mode)) {	
		if(st->st_nlink>1)
			conn_printf(cn, "HLNK %s\n", file);
		else
			conn_printf(cn, "FILE %s\n", file);
	} 
	else if(S_ISDIR(st->st_mode)) {
		char* p = my_basename(file);
		if(strcmp(".", p) != 0 && strcmp("..", p) != 0)
			conn_printf(cn, "DIR  %s\n", file);
	}
	else if(S_ISLNK(st->st_mode)) {
		conn_printf(cn, "SLNK %s\n", file);
	}
}
Beispiel #10
0
static void proto_handle_scan(conn_t* cn, const char* dir, hlink_t** hardlinks) {
	char curdir[PATH_MAX];
	struct scan_data data;

	data.ts = 0;
	data.cn = cn;
	data.hardlinks = hardlinks;

	getcwd(curdir, PATH_MAX);
	traverse_directory(dir, &data, find_newest_ts_worker, find_newerthan_ts_perror);
	chdir(curdir);

	conn_printf(cn, "SCAN %ld\n", (long int)data.ts);
}
Beispiel #11
0
static void proto_handle_links(conn_t* cn, const char* line, hlink_t** hardlinks) {
	struct stat st;

	if(lstat(line,&st) == 0) {
		if(S_ISREG(st.st_mode) && st.st_nlink>1) {
			int c = 0;
			hlink_t* n = NULL;

			// Try to find which hardlinks we know of
			for(n = *hardlinks; n; n = (hlink_t*)((node_t*)n)->next) {
				if(n->inode == st.st_ino) 
					c++;
			}


			if(c) {
				conn_printf(cn, "LINKS %d %s\n", c, line);

				// show them
				for(n = *hardlinks; n; n = (hlink_t*)((node_t*)n)->next) {
					if(n->inode == st.st_ino) {
						conn_printf(cn, "%s\n", n->filename);
					}
				}

				return;
			}
		}
	}
	else {
		conn_perror(cn, "lstat()");
	}

	conn_printf(cn, "ERROR links() failed\n");
	conn_abort(cn);
}
Beispiel #12
0
static void proto_handle_get(conn_t* cn, const char* line) {
	struct stat st;

	// Reject filenames with just "." and ".."
	if(memcmp(line, ".\0", 2) == 0 || memcmp(line, "..\0", 3) == 0) {
		conn_printf(cn, "ERROR Protocol violation (%d)\n", __LINE__);
		conn_abort(cn);
		return;
	}

	if(lstat(line,&st) == 0) {
		if(S_ISREG(st.st_mode)) {
			int fd;
			md5_state_t md5_state;
			md5_init(&md5_state);
			char buffer[PATH_MAX];
			ssize_t size;
			char md5str[33];
			char modestr[11];

#ifdef O_NOATIME
			if((fd = open(line,O_RDONLY|O_NOATIME))==-1) {
#else
			if((fd = open(line,O_RDONLY))==-1) {
#endif

				conn_perror(cn, "WARNING open()");
				conn_printf(cn, "WARNING Can't open file: %s\n", line);
				return;
			}

			// Calcuate MD5
			{
				unsigned char md5bin[16];
				while((size = read(fd, buffer, sizeof buffer)))
					md5_append(&md5_state, (unsigned char*)buffer, size);
				md5_finish(&md5_state, (unsigned char*)md5bin);

				if(lseek(fd, SEEK_SET, 0)==-1) {
					conn_perror(cn, "ERROR lseek()");
					conn_abort(cn);
					return;
				}

				md5bin2str(md5bin, md5str);
			}

			mode2str(st.st_mode, modestr);
			conn_printf(cn, "PUT %ld %s %s %ld %ld %ld %s\n", 
				(long int)st.st_size,
				md5str,
				modestr,
				st.st_atime,
				st.st_ctime,
				st.st_mtime,
				line);
			while((size = read(fd, buffer, sizeof buffer))) 
				conn_write(cn, buffer, size);
			close(fd);
		}
		else if(S_ISDIR(st.st_mode)) {
			char modestr[11];
			mode2str(st.st_mode, modestr);
			conn_printf(cn, "MKDIR %s %ld %ld %ld %s\n",
				modestr,
				st.st_atime,
				st.st_ctime,
				st.st_mtime,
				line);
		}
		else if(S_ISLNK(st.st_mode)) {
			char buffer[PATH_MAX];
			conn_printf(cn, "SLNK %s\n", line);

			ssize_t l;
			if((l=readlink(line, buffer, sizeof buffer))==-1) {
				conn_perror(cn, "WARNING readlink()");
				return;
			}
			buffer[l] = '\0';
			conn_printf(cn, "%s\n", buffer);
		}
		else {
			conn_printf(cn, "WARNING Ignored %s\n", line);
		}
	}
}

static void proto_handle_put(conn_t* cn, const char* line) {
	const char* delim = " ";
	char* saveptr = NULL;
	char* token;
	char* ptr = (char*)line;
	int c = 0;

	ssize_t size = 0;
	mode_t mode = 0;
	time_t mtime = 0;
	time_t ctime = 0;
	time_t atime = 0;
	char* name = NULL;
	char* md5  = NULL;

	while((token = strtok_r(ptr, delim, &saveptr))) {
		switch(c) {
			case 0: size = atol(token); break;
			case 1: md5 = token; break;
			case 2: mode = str2mode(token); break;
			case 3: atime = atol(token); break; 
			case 4: ctime = atol(token); break;
			case 5: mtime = atol(token); break;
			case 6: name = token; break;
		}
		c++;
		ptr = NULL;
	}

	if(c != 7) {
		conn_printf(cn, "ERROR Protocol violation (%d)\n", __LINE__);
		conn_abort(cn);
		return ;
	}

	int fd = creat(name, O_CREAT|O_TRUNC);
	if(fd == -1) {
		conn_perror(cn, "WARNING creat()");
		return;
	}

	if(chmod(name,mode)==-1) {
		perror("WARNING chmod()");
	}

	struct utimbuf t;
	t.actime = atime;
	t.modtime = mtime;
	if(utime(name,&t)==-1) {
		perror("WARNING utime");
	}

	// CONTENT
	int bytes_left = size;
	int r;
	md5_state_t md5_state;
	unsigned char md5bin[16];
	char md5str[33];
	md5_init(&md5_state);
	while(!cn->abort && bytes_left) {
		if(cn->rbuf_len == 0) 
			(void)conn_read(cn);

		r = MIN(bytes_left, cn->rbuf_len);
		if(r) {
			write(fd, cn->rbuf, r);
			md5_append(&md5_state, (unsigned char*)cn->rbuf, r);
			conn_shift(cn,r);
			bytes_left -= r;
		}

		assert(bytes_left >= 0);
	}

	close(fd);
	md5_finish(&md5_state, (unsigned char*)md5bin);
	md5bin2str(md5bin, md5str);

	// Check md5
	if(strcmp(md5str,md5)!=0) {
		// Mismatch!
		conn_printf(cn, "WARNING %s md5-mismatch (%s <-> %s), removing file\n", 
			name,
			md5str, md5);
		if(unlink(name)==-1) {
			perror("WARNING: unlink()");
		}
	}
	else {
		struct utimbuf t;
		t.actime = atime;
		t.modtime = mtime;
		if(utime(name,&t)==-1) {
			perror("utime");
			conn_printf(cn, "WARNING Can't timestamp on directory: %s\n", name);
		}
		// md5 is fine
		conn_printf(cn, "GET %s\n", name);
	}
}

static void proto_handle_slnk(conn_t* cn, const char* line) {
	char curdir[PATH_MAX];

	// read next line to get target
	char target[PATH_MAX];
	if(!conn_readline(cn, target, sizeof target))
		return;

	getcwd(curdir, sizeof curdir);

	// Make sure it dosnt exist
	unlink(line);

	if(chdir(my_dirname(line))==-1) {
		conn_perror(cn, "WARNING chdir()");
		return;
	}

	if(symlink(target, my_basename(line))==-1) {
		conn_perror(cn, "ERROR symlink()");
		conn_abort(cn);
		return;
	}

	chdir(curdir);

	conn_printf(cn, "GET %s\n", line);
}
Beispiel #13
0
static void find_newerthan_ts_perror(void* data, const char* str) {
	conn_t* cn = ((struct newerthan_data*)data)->cn;
	conn_printf(cn, "WARNING %s\n",str);
}
Beispiel #14
0
void csync_send_error()
{
	conn_printf("ERROR\n");
}