[vhffs-dev] [1603] added an option on the slave to preserve owners, groups and permissions |
[ Thread Index |
Date Index
| More vhffs.org/vhffs-dev Archives
]
Revision: 1603
Author: gradator
Date: 2010-05-09 07:29:22 +0200 (Sun, 09 May 2010)
Log Message:
-----------
added an option on the slave to preserve owners, groups and permissions
Modified Paths:
--------------
trunk/vhffs-fssync/vhffsfssync_master.c
trunk/vhffs-fssync/vhffsfssync_slave.c
Modified: trunk/vhffs-fssync/vhffsfssync_master.c
===================================================================
--- trunk/vhffs-fssync/vhffsfssync_master.c 2010-04-26 15:44:54 UTC (rev 1602)
+++ trunk/vhffs-fssync/vhffsfssync_master.c 2010-05-09 05:29:22 UTC (rev 1603)
@@ -221,7 +221,7 @@
int vhffsfssync_net_file_close(vhffsfssync_conn *conn, vhffsfssync_net_file *file);
int vhffsfssync_net_remove_file(vhffsfssync_conn *conn, char *pathname);
void vhffsfssync_net_broadcast_file(char *pathname);
-char *vhffsfssync_net_parent_mtime(char *pathname);
+char *vhffsfssync_net_parent_attrib(char *pathname);
int vhffsfssync_net_send(vhffsfssync_conn *conn);
int vhffsfssync_net_recv_event(vhffsfssync_conn *conn, char *event);
int vhffsfssync_net_parse(vhffsfssync_conn *conn);
@@ -416,6 +416,10 @@
vhffsfssync_net_message_file *msg;
uint32_t maxprio = -1; // 4294967295
vhffsfssync_net_file *file;
+ struct stat st;
+ st.st_mode=0;
+ st.st_uid=-1;
+ st.st_gid=-1;
if(!conn || !pathname)
return -1;
@@ -424,9 +428,13 @@
if(!file)
return -1;
+ if( fstat(fileno(file->file_stream), &st) < 0 ) {
+ fprintf(stderr, "fstat() failed on %s: %s\n", file->file_pathname, strerror(errno));
+ }
+
//printf("%d SENDING FILE %s\n", conn->fd, pathname);
- vhffsfssync_net_send_event(conn, g_strdup_printf("open%c%s%c", '\0', pathname, '\0') , VHFFSFSSYNC_NET_PRIO_MEDIUM);
- vhffsfssync_net_send_event(conn, vhffsfssync_net_parent_mtime(pathname) , VHFFSFSSYNC_NET_PRIO_MEDIUM);
+ vhffsfssync_net_send_event(conn, g_strdup_printf("open%c%s%c%d%c%d%c%d%c", '\0', pathname, '\0', st.st_mode&07777, '\0', st.st_uid, '\0', st.st_gid, '\0') , VHFFSFSSYNC_NET_PRIO_MEDIUM);
+ vhffsfssync_net_send_event(conn, vhffsfssync_net_parent_attrib(pathname) , VHFFSFSSYNC_NET_PRIO_MEDIUM);
// the size of the file is the priority (small files are sent with more priority)
// but don't set the priority too low, low value can be used for anything else
@@ -444,7 +452,7 @@
void vhffsfssync_net_destroy_file(vhffsfssync_conn *conn, vhffsfssync_net_message_file *filemsg) {
struct stat st;
- st.st_mtime=0;
+ st.st_mtime=-1;
conn->messages = g_list_remove(conn->messages, (vhffsfssync_net_message*)filemsg);
conn->messages_num--;
@@ -570,11 +578,14 @@
}
-char *vhffsfssync_net_parent_mtime(char *pathname) {
+char *vhffsfssync_net_parent_attrib(char *pathname) {
char *cur;
struct stat st;
char *ret;
- st.st_mtime = 0;
+ st.st_mtime=-1;
+ st.st_mode=0;
+ st.st_uid=-1;
+ st.st_gid=-1;
for( cur = pathname+strlen(pathname) ; *cur != '/' ; cur-- );
*cur = '\0';
@@ -587,7 +598,7 @@
}
}
- ret = g_strdup_printf("mtime%c%s%c%ld%c", '\0', pathname, '\0', st.st_mtime, '\0');
+ ret = g_strdup_printf("attrib%c%s%c%ld%c%d%c%d%c%d%c", '\0', pathname, '\0', st.st_mtime, '\0', st.st_mode&07777, '\0', st.st_uid, '\0', st.st_gid, '\0');
*cur = '/';
return ret;
}
@@ -854,16 +865,16 @@
vhffsfssync_net_send_file(conn, pathname);
}
else if( S_ISDIR(st.st_mode) ) {
- vhffsfssync_net_send_event(conn, g_strdup_printf("mkdir%c%s%c%ld%c", '\0', pathname, '\0', st.st_mtime, '\0') , VHFFSFSSYNC_NET_PRIO_MEDIUM);
- vhffsfssync_net_send_event(conn, vhffsfssync_net_parent_mtime(pathname) , VHFFSFSSYNC_NET_PRIO_MEDIUM);
+ vhffsfssync_net_send_event(conn, g_strdup_printf("mkdir%c%s%c%ld%c%d%c%d%c%d%c", '\0', pathname, '\0', st.st_mtime, '\0', st.st_mode&07777, '\0', st.st_uid, '\0', st.st_gid, '\0') , VHFFSFSSYNC_NET_PRIO_MEDIUM);
+ vhffsfssync_net_send_event(conn, vhffsfssync_net_parent_attrib(pathname) , VHFFSFSSYNC_NET_PRIO_MEDIUM);
}
else if( S_ISLNK(st.st_mode) ) {
char *linkto;
linkto = malloc(st.st_size +1);
if( readlink(pathname, linkto, st.st_size) >= 0 ) {
linkto[st.st_size] = '\0';
- vhffsfssync_net_send_event(conn, g_strdup_printf("symlink%c%s%c%s%c%ld%c", '\0', pathname, '\0', linkto, '\0', st.st_mtime, '\0') , VHFFSFSSYNC_NET_PRIO_MEDIUM);
- vhffsfssync_net_send_event(conn, vhffsfssync_net_parent_mtime(pathname) , VHFFSFSSYNC_NET_PRIO_MEDIUM);
+ vhffsfssync_net_send_event(conn, g_strdup_printf("symlink%c%s%c%s%c%ld%c%d%c%d%c", '\0', pathname, '\0', linkto, '\0', st.st_mtime, '\0', st.st_uid, '\0', st.st_gid, '\0') , VHFFSFSSYNC_NET_PRIO_MEDIUM);
+ vhffsfssync_net_send_event(conn, vhffsfssync_net_parent_attrib(pathname) , VHFFSFSSYNC_NET_PRIO_MEDIUM);
}
free(linkto);
}
@@ -1044,10 +1055,20 @@
d = opendir(pathname);
if(d) {
struct dirent *dir;
- GString *msg = g_string_sized_new(1024);
+ GString *msg;
+ struct stat st;
+ st.st_mtime=-1;
+ st.st_mode=0;
+ st.st_uid=-1;
+ st.st_gid=-1;
- g_string_append_printf(msg, "ls%c%s%c", '\0', pathname, '\0' );
+ if(lstat(pathname, &st) ) {
+ fprintf(stderr, "cannot lstat() '%s': %s\n", pathname, strerror(errno));
+ }
+ msg = g_string_sized_new(1024);
+ g_string_append_printf(msg, "ls%c%s%c%ld%c%d%c%d%c%d%c", '\0', pathname, '\0', st.st_mtime, '\0', st.st_mode&07777, '\0', st.st_uid, '\0', st.st_gid, '\0');
+
while( (dir = readdir(d)) ) {
if( strcmp(dir->d_name, ".") && strcmp(dir->d_name, "..") ) {
char *path = g_strdup_printf("%s/%s", pathname, dir->d_name);
@@ -1057,13 +1078,13 @@
if( S_ISDIR(st.st_mode) ) {
// register a new directory
ldirs = g_list_append(ldirs, g_strdup(path));
- g_string_append_printf(msg, "%s%cdir%c0%c%ld%c", dir->d_name, '\0', '\0', '\0', st.st_mtime, '\0');
+ g_string_append_printf(msg, "%s%cdir%c0%c%ld%c%d%c%d%c%d%c", dir->d_name, '\0', '\0', '\0', st.st_mtime, '\0', st.st_mode&07777, '\0', st.st_uid, '\0', st.st_gid, '\0');
}
else if( S_ISREG(st.st_mode) ) {
- g_string_append_printf(msg, "%s%cfile%c%lld%c%ld%c", dir->d_name, '\0', '\0', (long long int)st.st_size, '\0', st.st_mtime, '\0');
+ g_string_append_printf(msg, "%s%cfile%c%lld%c%ld%c%d%c%d%c%d%c", dir->d_name, '\0', '\0', (long long int)st.st_size, '\0', st.st_mtime, '\0', st.st_mode&07777, '\0', st.st_uid, '\0', st.st_gid, '\0');
}
else if( S_ISLNK(st.st_mode) ) {
- g_string_append_printf(msg, "%s%clink%c%lld%c%ld%c", dir->d_name, '\0', '\0', (long long int)st.st_size, '\0', st.st_mtime, '\0');
+ g_string_append_printf(msg, "%s%clink%c%lld%c%ld%c%d%c%d%c%d%c", dir->d_name, '\0', '\0', (long long int)st.st_size, '\0', st.st_mtime, '\0', st.st_mode&07777, '\0', st.st_uid, '\0', st.st_gid, '\0');
}
/* we don't need other file types (chr, block, fifo, socket, ...) */
}
@@ -1193,7 +1214,7 @@
/* -- inotify stuff -- */
char *vhffsfssync_pathname(vhffsfssync_watch *watch, const char *filename) {
-
+
GString *pathname = g_string_sized_new(256);
char **dirnames, **curnames, **endnames;
uint32_t a;
@@ -1249,7 +1270,7 @@
free(pathname);
return NULL;
}
-
+
if( (watch = g_hash_table_lookup(vhffsfssync_wd_to_watch, &wd)) ) {
// this was already watched, update name and reattach to the new parent
@@ -1343,7 +1364,7 @@
conns = g_list_next(conns);
vhffsfssync_net_remove_file(conn, pathname);
vhffsfssync_net_send_event(conn, g_strdup_printf("remove%c%s%c", '\0', pathname, '\0') , VHFFSFSSYNC_NET_PRIO_MEDIUM);
- vhffsfssync_net_send_event(conn, vhffsfssync_net_parent_mtime(pathname) , VHFFSFSSYNC_NET_PRIO_MEDIUM);
+ vhffsfssync_net_send_event(conn, vhffsfssync_net_parent_attrib(pathname) , VHFFSFSSYNC_NET_PRIO_MEDIUM);
}
free(pathname);
@@ -1364,8 +1385,8 @@
printf("==> CREATE %s\n", pathname);
#endif
if(!st.st_size) {
- vhffsfssync_net_broadcast_event( g_strdup_printf("create%c%s%c%ld%c", '\0', pathname, '\0', st.st_mtime, '\0') , VHFFSFSSYNC_NET_PRIO_MEDIUM);
- vhffsfssync_net_broadcast_event( vhffsfssync_net_parent_mtime(pathname) , VHFFSFSSYNC_NET_PRIO_MEDIUM);
+ vhffsfssync_net_broadcast_event( g_strdup_printf("create%c%s%c%ld%c%d%c%d%c%d%c", '\0', pathname, '\0', st.st_mtime, '\0', st.st_mode&07777, '\0', st.st_uid, '\0', st.st_gid, '\0') , VHFFSFSSYNC_NET_PRIO_MEDIUM);
+ vhffsfssync_net_broadcast_event( vhffsfssync_net_parent_attrib(pathname) , VHFFSFSSYNC_NET_PRIO_MEDIUM);
}
else {
vhffsfssync_net_broadcast_file(pathname);
@@ -1378,8 +1399,8 @@
printf("==> MKDIR %s\n", pathname);
#endif
newwatch = vhffsfssync_add_watch(inotifyfd, watch, filename, VHFFSFSSYNC_WATCH_MASK);
- vhffsfssync_net_broadcast_event( g_strdup_printf("mkdir%c%s%c%ld%c", '\0', pathname, '\0', st.st_mtime, '\0') , VHFFSFSSYNC_NET_PRIO_MEDIUM);
- vhffsfssync_net_broadcast_event( vhffsfssync_net_parent_mtime(pathname) , VHFFSFSSYNC_NET_PRIO_MEDIUM);
+ vhffsfssync_net_broadcast_event( g_strdup_printf("mkdir%c%s%c%ld%c%d%c%d%c%d%c", '\0', pathname, '\0', st.st_mtime, '\0', st.st_mode&07777, '\0', st.st_uid, '\0', st.st_gid, '\0') , VHFFSFSSYNC_NET_PRIO_MEDIUM);
+ vhffsfssync_net_broadcast_event( vhffsfssync_net_parent_attrib(pathname) , VHFFSFSSYNC_NET_PRIO_MEDIUM);
/* there is a short delay between the mkdir() and the add_watch(),
we need to send events about the data which have already been written */
vhffsfssync_fake_events_recursively( inotifyfd, newwatch );
@@ -1395,8 +1416,8 @@
#if DEBUG_INOTIFY
printf("==> SYMLINK %s -> %s\n", pathname, linkto);
#endif
- vhffsfssync_net_broadcast_event( g_strdup_printf("symlink%c%s%c%s%c%ld%c", '\0', pathname, '\0', linkto, '\0', st.st_mtime, '\0') , VHFFSFSSYNC_NET_PRIO_MEDIUM);
- vhffsfssync_net_broadcast_event( vhffsfssync_net_parent_mtime(pathname) , VHFFSFSSYNC_NET_PRIO_MEDIUM);
+ vhffsfssync_net_broadcast_event( g_strdup_printf("symlink%c%s%c%s%c%ld%c%d%c%d%c", '\0', pathname, '\0', linkto, '\0', st.st_mtime, '\0', st.st_uid, '\0', st.st_gid, '\0') , VHFFSFSSYNC_NET_PRIO_MEDIUM);
+ vhffsfssync_net_broadcast_event( vhffsfssync_net_parent_attrib(pathname) , VHFFSFSSYNC_NET_PRIO_MEDIUM);
}
free(linkto);
if(ret < 0) {
@@ -1466,7 +1487,7 @@
printf("IN_ATTRIB\n");
#endif
if(! lstat(pathname, &st) ) {
- vhffsfssync_net_broadcast_event( g_strdup_printf("mtime%c%s%c%ld%c", '\0', pathname, '\0', st.st_mtime, '\0') , VHFFSFSSYNC_NET_PRIO_MEDIUM);
+ vhffsfssync_net_broadcast_event( g_strdup_printf("attrib%c%s%c%ld%c%d%c%d%c%d%c", '\0', pathname, '\0', st.st_mtime, '\0', st.st_mode&07777, '\0', st.st_uid, '\0', st.st_gid, '\0') , VHFFSFSSYNC_NET_PRIO_MEDIUM);
}
else {
if(errno == ENOENT) {
@@ -1555,12 +1576,12 @@
free(tmp);
#endif
if( vhffsfssync_cookie.isdir ) {
-
+
char *frompathname = vhffsfssync_pathname(vhffsfssync_cookie.watch, vhffsfssync_cookie.filename);
vhffsfssync_add_watch(inotifyfd, watch, event->name, VHFFSFSSYNC_WATCH_MASK);
vhffsfssync_net_broadcast_event( g_strdup_printf("move%c%s%c%s%c", '\0', frompathname, '\0', pathname, '\0') , VHFFSFSSYNC_NET_PRIO_MEDIUM);
- vhffsfssync_net_broadcast_event( vhffsfssync_net_parent_mtime(frompathname) , VHFFSFSSYNC_NET_PRIO_MEDIUM);
- vhffsfssync_net_broadcast_event( vhffsfssync_net_parent_mtime(pathname) , VHFFSFSSYNC_NET_PRIO_MEDIUM);
+ vhffsfssync_net_broadcast_event( vhffsfssync_net_parent_attrib(frompathname) , VHFFSFSSYNC_NET_PRIO_MEDIUM);
+ vhffsfssync_net_broadcast_event( vhffsfssync_net_parent_attrib(pathname) , VHFFSFSSYNC_NET_PRIO_MEDIUM);
free(frompathname);
}
else {
@@ -1598,7 +1619,7 @@
int vhffsfssync_fake_events_recursively(int inotifyfd, vhffsfssync_watch *watch) {
DIR *d;
char *pathname;
-
+
pathname = vhffsfssync_pathname(watch, NULL);
d = opendir(pathname);
free(pathname);
Modified: trunk/vhffs-fssync/vhffsfssync_slave.c
===================================================================
--- trunk/vhffs-fssync/vhffsfssync_slave.c 2010-04-26 15:44:54 UTC (rev 1602)
+++ trunk/vhffs-fssync/vhffsfssync_slave.c 2010-05-09 05:29:22 UTC (rev 1603)
@@ -90,14 +90,15 @@
// events protos
int vhffsfssync_remove(char *pathname);
-int vhffsfssync_mkdir(char *pathname, mode_t mode, int long long mtime);
-int vhffsfssync_checkfile(vhffsfssync_conn *conn, char *path, char *type, int long long size, int long long mtime);
+int vhffsfssync_mkdir(char *pathname, int long long mtime, int mode, int uid, int gid);
+int vhffsfssync_checkfile(vhffsfssync_conn *conn, char *path, char *type, int long long size, int long long mtime, int mode, int uid, int gid);
int vhffsfssync_event(vhffsfssync_conn *conn, char *event);
int vhffsfssync_parse(vhffsfssync_conn *conn);
// misc
double vhffsfssync_time();
static void usage_exit(int ret_code, char *progname);
+int vhffsfssync_preserve;
/* ------------------------------------------------------------ */
@@ -261,7 +262,7 @@
// the content of pathname is modified
-int vhffsfssync_mkdir(char *pathname, mode_t mode, int long long mtime) {
+int vhffsfssync_mkdir(char *pathname, int long long mtime, int mode, int uid, int gid) {
char *cur, *dirs[64];
int i, fd, fd_, argc;
@@ -288,13 +289,24 @@
}
}
if(fd >= 0) {
- if(mtime && i == argc) {
- struct timeval tv[2];
- tv[0].tv_sec = (time_t)mtime;
- tv[0].tv_usec = 0;
- tv[1].tv_sec = (time_t)mtime;
- tv[1].tv_usec = 0;
- futimes(fd, &tv[0]);
+ if(i == argc) {
+ if(mtime>=0) {
+ struct timeval tv[2];
+ tv[0].tv_sec = (time_t)mtime;
+ tv[0].tv_usec = 0;
+ tv[1].tv_sec = (time_t)mtime;
+ tv[1].tv_usec = 0;
+ futimes(fd, &tv[0]);
+ }
+
+ if(vhffsfssync_preserve && uid>=0) {
+ if( fchmod(fd, mode) ) {
+ fprintf(stderr, "fchmod() failed on %s: %s\n", pathname, strerror(errno));
+ }
+ if( fchown(fd, uid, gid) ) {
+ fprintf(stderr, "fchown() failed on %s: %s\n", pathname, strerror(errno));
+ }
+ }
}
close(fd);
}
@@ -305,7 +317,7 @@
#endif
-int vhffsfssync_checkfile(vhffsfssync_conn *conn, char *path, char *type, int long long size, int long long mtime) {
+int vhffsfssync_checkfile(vhffsfssync_conn *conn, char *path, char *type, int long long size, int long long mtime, int mode, int uid, int gid) {
gboolean fetch = FALSE;
struct stat st;
@@ -318,11 +330,9 @@
if( S_ISDIR(st.st_mode) ) {
type_ = "dir";
}
-
else if( S_ISREG(st.st_mode) ) {
type_ = "file";
}
-
else if( S_ISLNK(st.st_mode) ) {
type_ = "link";
}
@@ -340,6 +350,27 @@
else if(st.st_mtime != mtime) {
fetch = TRUE;
}
+
+ if(!fetch && vhffsfssync_preserve) {
+ if(!S_ISLNK(st.st_mode) && (st.st_mode&07777) != mode) {
+#ifndef CHECK
+ if( chmod(path, mode) ) {
+ fprintf(stderr, "chmod() failed on %s: %s\n", path, strerror(errno));
+ }
+#else
+ printf("%s mode is not synched\n", path );
+#endif
+ }
+ if(st.st_uid != uid || st.st_gid != gid) {
+#ifndef CHECK
+ if( lchown(path, uid, gid) ) {
+ fprintf(stderr, "lchown() failed on %s: %s\n", path, strerror(errno));
+ }
+#else
+ printf("%s uid or gid are not synched\n", path );
+#endif
+ }
+ }
}
else {
if(errno == ENOENT) {
@@ -397,9 +428,15 @@
else if(!strcmp(args[0], "create")) {
char *pathname = args[1];
int long long mtime = atoll(args[2]);
+ int mode = atol(args[3]);
+ int uid = atol(args[4]);
+ int gid = atol(args[5]);
int fd;
- fd = open(pathname, O_CREAT|O_WRONLY|O_TRUNC, 0644);
+ if(!vhffsfssync_preserve || uid<0)
+ mode = 0644;
+
+ fd = open(pathname, O_CREAT|O_WRONLY|O_TRUNC, mode);
if(fd >= 0) {
struct timeval tv[2];
@@ -412,6 +449,15 @@
fprintf(stderr, "futimes() failed on %s: %s\n", pathname, strerror(errno));
}
+ if(vhffsfssync_preserve && uid>=0) {
+ if( fchmod(fd, mode) ) {
+ fprintf(stderr, "fchmod() failed on %s: %s\n", pathname, strerror(errno));
+ }
+ if( fchown(fd, uid, gid) ) {
+ fprintf(stderr, "fchown() failed on %s: %s\n", pathname, strerror(errno));
+ }
+ }
+
close(fd);
}
else {
@@ -420,12 +466,30 @@
}
else if(!strcmp(args[0], "open")) {
char *pathname = args[1];
+ int mode = atol(args[2]);
+ int uid = atol(args[3]);
+ int gid = atol(args[4]);
int fd;
+ if(!vhffsfssync_preserve || uid<0)
+ mode = 0644;
+
if( !g_hash_table_lookup(conn->openfiles, pathname) ) {
- fd = open(pathname, O_CREAT|O_WRONLY|O_TRUNC, 0644);
+
+ fd = open(pathname, O_CREAT|O_WRONLY|O_TRUNC, mode);
if(fd >= 0) {
- FILE *f = fdopen(fd, "w");
+ FILE *f;
+
+ if(vhffsfssync_preserve && uid>=0) {
+ if( fchmod(fd, mode) ) {
+ fprintf(stderr, "fchmod() failed on %s: %s\n", pathname, strerror(errno));
+ }
+ if( fchown(fd, uid, gid) ) {
+ fprintf(stderr, "fchown() failed on %s: %s\n", pathname, strerror(errno));
+ }
+ }
+
+ f = fdopen(fd, "w");
if(f) {
g_hash_table_insert(conn->openfiles, strdup(pathname), f);
}
@@ -446,17 +510,18 @@
f = g_hash_table_lookup(conn->openfiles, pathname);
if(f) {
- struct timeval tv[2];
-
fflush(f);
- tv[0].tv_sec = (time_t)mtime;
- tv[0].tv_usec = 0;
- tv[1].tv_sec = (time_t)mtime;
- tv[1].tv_usec = 0;
+ if(mtime>=0) {
+ struct timeval tv[2];
+ tv[0].tv_sec = (time_t)mtime;
+ tv[0].tv_usec = 0;
+ tv[1].tv_sec = (time_t)mtime;
+ tv[1].tv_usec = 0;
- if( futimes(fileno(f), tv) ) {
- fprintf(stderr, "futimes() failed on %s: %s\n", pathname, strerror(errno));
+ if( futimes(fileno(f), tv) ) {
+ fprintf(stderr, "futimes() failed on %s: %s\n", pathname, strerror(errno));
+ }
}
}
g_hash_table_remove(conn->openfiles, pathname);
@@ -464,13 +529,18 @@
else if(!strcmp(args[0], "mkdir")) {
char *path = args[1];
int long long mtime = atoll(args[2]);
+ int mode = atol(args[3]);
+ int uid = atol(args[4]);
+ int gid = atol(args[5]);
- vhffsfssync_mkdir(path, 0755, mtime);
+ vhffsfssync_mkdir(path, mtime, mode, uid, gid);
}
else if(!strcmp(args[0], "symlink")) {
char *from = args[1];
char *to = args[2];
int long long mtime = atoll(args[3]);
+ int uid = atol(args[4]);
+ int gid = atol(args[5]);
struct stat st;
if(! lstat(from, &st) ) {
@@ -486,6 +556,12 @@
tv[1].tv_usec = 0;
lutimes(from, &tv[0]);
+
+ if(vhffsfssync_preserve) {
+ if( lchown(from, uid, gid) ) {
+ fprintf(stderr, "lchown() failed on %s: %s\n", from, strerror(errno));
+ }
+ }
}
}
else if(!strcmp(args[0], "move")) {
@@ -538,25 +614,49 @@
conn->chunk_file = NULL;
}
}
- else if(!strcmp(args[0], "mtime")) {
+ else if(!strcmp(args[0], "attrib")) {
char *pathname = args[1];
int long long mtime = atoll(args[2]);
- struct timeval tv[2];
+ int mode = atol(args[3]);
+ int uid = atol(args[4]);
+ int gid = atol(args[5]);
- tv[0].tv_sec = (time_t)mtime;
- tv[0].tv_usec = 0;
- tv[1].tv_sec = (time_t)mtime;
- tv[1].tv_usec = 0;
+ if(mtime>=0) {
+ struct timeval tv[2];
+ tv[0].tv_sec = (time_t)mtime;
+ tv[0].tv_usec = 0;
+ tv[1].tv_sec = (time_t)mtime;
+ tv[1].tv_usec = 0;
- lutimes(pathname, &tv[0]);
+ lutimes(pathname, &tv[0]);
+ }
+
+ if(vhffsfssync_preserve && uid>=0) {
+ struct stat st;
+
+ if(! lstat(pathname, &st) ) {
+
+ if( !S_ISLNK(st.st_mode) ) {
+ if( chmod(pathname, mode) ) {
+ fprintf(stderr, "chmod() failed on %s: %s\n", pathname, strerror(errno));
+ }
+ }
+
+ if( lchown(pathname, uid, gid) ) {
+ fprintf(stderr, "lchown() failed on %s: %s\n", pathname, strerror(errno));
+ }
+ }
+ }
}
else if(!strcmp(args[0], "ls")) {
- char *root, *root_;
+ char *root = args[1];
+ int long long mtime = atoll(args[2]);
+ int mode = atol(args[3]);
+ int uid = atol(args[4]);
+ int gid = atol(args[5]);
+ char *root_ = strdup(root);
- root = args[1];
- root_ = strdup(root);
-
- if(! vhffsfssync_mkdir(root, 0755, 0) ) {
+ if(! vhffsfssync_mkdir(root, mtime, mode, uid, gid) ) {
int i;
GHashTable *filesindex;
DIR *d;
@@ -565,12 +665,12 @@
filesindex = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
// check each file
- for( i = 2 ; i < argc ; i+=4 ) {
+ for( i = 6 ; i < argc ; i+=7 ) {
char *path;
g_hash_table_insert(filesindex, args[i], args[i]);
path = g_strdup_printf("%s/%s", root_, args[i]);
- vhffsfssync_checkfile(conn, path, args[i+1], atoll(args[i+2]), atoll(args[i+3]) );
+ vhffsfssync_checkfile(conn, path, args[i+1], atoll(args[i+2]), atoll(args[i+3]), atol(args[i+4]), atol(args[i+5]), atol(args[i+6]) );
free(path);
}
@@ -663,7 +763,7 @@
ssize_t size = atol(args[3]);
conn->chunk_stilltoread = size;
}
- else if(!strcmp(args[0], "mtime")) {
+ else if(!strcmp(args[0], "attrib")) {
}
else if(!strcmp(args[0], "ls")) {
char *root, *root_;
@@ -687,12 +787,12 @@
filesindex = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
// check each file
- for( i = 2 ; i < argc ; i+=4 ) {
+ for( i = 6 ; i < argc ; i+=7 ) {
char *path;
g_hash_table_insert(filesindex, args[i], args[i]);
path = g_strdup_printf("%s/%s", root_, args[i]);
- vhffsfssync_checkfile(conn, path, args[i+1], atoll(args[i+2]), atoll(args[i+3]) );
+ vhffsfssync_checkfile(conn, path, args[i+1], atoll(args[i+2]), atoll(args[i+3]), atol(args[i+4]), atol(args[i+5]), atol(args[i+6]) );
free(path);
}
@@ -842,6 +942,7 @@
"Remote synchronous file-copying tool, this is the client (the slave)\n\n"
" -f, --foreground\tDo not daemonise the client, display errors on the console\n"
" -r, --limit-rate=kB/s\tLimit I/O bandwidth; kBytes per second\n"
+ " -p, --preserve\tPreserve owners, groups and permissions\n"
" -h, --help\t\tDisplay this help and exit\n"
" -v, --version\t\tOutput version information and exit\n",
progname);
@@ -861,6 +962,7 @@
char *root = NULL;
int limitrate = 0;
+ vhffsfssync_preserve = 0;
#ifdef CHECK
foreground = 1;
#endif
@@ -868,6 +970,7 @@
struct option long_options[] = {
{ "foreground", no_argument, NULL, 'f' },
{ "limit-rate", required_argument, NULL, 'r' },
+ { "preserve", no_argument, NULL, 'p' },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'v' },
{ 0, 0, 0, 0 }
@@ -875,7 +978,7 @@
while(1) {
int option_index = 0, c;
- c = getopt_long(argc, argv, "fr:hv", long_options, &option_index);
+ c = getopt_long(argc, argv, "fr:phv", long_options, &option_index);
if(c == -1)
break;
@@ -888,6 +991,10 @@
limitrate = atoi(optarg)*1000;
break;
+ case 'p':
+ vhffsfssync_preserve = 1;
+ break;
+
case 'h':
usage_exit(0, argv[0]);
@@ -930,6 +1037,9 @@
if(fork()) exit(0);
}
+ // so that open() and mkdir() will not enforce wanted mode with mode&~umask
+ umask(0);
+
/* chdir() to the filesystem to write the data */
if( chdir(root) < 0 ) {
fprintf(stderr, "cannot chdir() to %s: %s\n", root, strerror(errno));
@@ -937,6 +1047,8 @@
}
if( chroot(".") < 0 ) {
fprintf(stderr, "cannot chroot() to %s: %s\n", root, strerror(errno));
+ // disable permissions, owners and groups preservation if we are not root
+ vhffsfssync_preserve = 0;
//return -1;
}
root = ".";