first vesrion of working socket based rsync. It still needs a lot of
authorAndrew Tridgell <tridge@samba.org>
Sat, 9 May 1998 13:58:54 +0000 (13:58 +0000)
committerAndrew Tridgell <tridge@samba.org>
Sat, 9 May 1998 13:58:54 +0000 (13:58 +0000)
work, but at least it works :-)

Makefile.in
configure.in
io.c
main.c
mkproto.awk
rsync.h
socket.c
syscall.c
util.c

index 8d1c173..f8ed546 100644 (file)
@@ -21,8 +21,9 @@ SHELL=/bin/sh
 .SUFFIXES: .c .o
 
 LIBOBJ=lib/getopt.o lib/fnmatch.o lib/zlib.o lib/compat.o
-OBJS1=rsync.o exclude.o util.o md4.o main.o checksum.o match.o syscall.o
-OBJS=$(OBJS1) flist.o io.o compat.o hlink.o token.o uidlist.o socket.o $(LIBOBJ)
+OBJS1=rsync.o exclude.o util.o md4.o main.o checksum.o match.o syscall.o log.o
+DAEMON_OBJ = params.o loadparm.o 
+OBJS=$(OBJS1) $(DAEMON_OBJ) flist.o io.o compat.o hlink.o token.o uidlist.o socket.o $(LIBOBJ)
 
 # note that the -I. is needed to handle config.h when using VPATH
 .c.o:
index 9749558..7755272 100644 (file)
@@ -42,7 +42,7 @@ AC_FUNC_MMAP
 AC_FUNC_UTIME_NULL
 AC_CHECK_FUNCS(waitpid strtok pipe getcwd mkdir strdup strerror chown chmod mknod)
 AC_CHECK_FUNCS(fchmod fstat strchr bcopy bzero readlink link utime utimes)
-AC_CHECK_FUNCS(memmove getopt_long lchown setlinebuf vsnprintf)
+AC_CHECK_FUNCS(memmove getopt_long lchown setlinebuf vsnprintf setsid)
 
 echo $ac_n "checking for working fnmatch... $ac_c"
 AC_TRY_RUN([#include <fnmatch.h>
diff --git a/io.c b/io.c
index f5816ed..587b3c7 100644 (file)
--- a/io.c
+++ b/io.c
@@ -423,10 +423,16 @@ void write_buf(int f,char *buf,int len)
   total_written += len;
 }
 
+/* write a string to the connection */
+void write_sbuf(int f,char *buf)
+{
+       write_buf(f, buf, strlen(buf));
+}
+
 
 void write_byte(int f,unsigned char c)
 {
-  write_buf(f,(char *)&c,1);
+       write_buf(f,(char *)&c,1);
 }
 
 void write_flush(int f)
@@ -434,3 +440,43 @@ void write_flush(int f)
 }
 
 
+int read_line(int f, char *buf, int maxlen)
+{
+       while (maxlen) {
+               read_buf(f, buf, 1);
+               if (buf[0] == '\n') {
+                       buf[0] = 0;
+                       break;
+               }
+               if (buf[0] != '\r') {
+                       buf++;
+                       maxlen--;
+               }
+       }
+       if (maxlen == 0) {
+               *buf = 0;
+               return 0;
+       }
+       return 1;
+}
+
+
+void io_printf(int fd, const char *format, ...)
+{
+       va_list ap;  
+       char buf[1024];
+       int len;
+       
+       va_start(ap, format);
+
+#if HAVE_VSNPRINTF
+       len = vsnprintf(buf, sizeof(buf)-1, format, ap);
+#else
+       len = vsprintf(buf, format, ap);
+#endif
+       va_end(ap);
+
+       if (len < 0) exit_cleanup(1);
+
+       write_sbuf(fd, buf);
+}
diff --git a/main.c b/main.c
index 527daeb..0bcc7f5 100644 (file)
--- a/main.c
+++ b/main.c
@@ -21,7 +21,7 @@
 
 int verbose = 0;
 int always_checksum = 0;
-time_t starttime;
+time_t starttime = 0;
 int64 total_size = 0;
 int block_size=BLOCK_SIZE;
 
@@ -57,6 +57,9 @@ int numeric_ids = 0;
 int force_delete = 0;
 int io_timeout = 0;
 int io_error = 0;
+int read_only = 0;
+static int module_id;
+
 static int port = RSYNC_PORT;
 
 static char *shell_cmd;
@@ -64,9 +67,9 @@ static char *shell_cmd;
 extern int csum_length;
 
 int am_server = 0;
-int am_sender;
+int am_sender=0;
 int recurse = 0;
-int am_daemon;
+int am_daemon=0;
 
 static void usage(int fd);
 
@@ -335,12 +338,24 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
                  argv[i] += l+1;
   }
 
+  if (am_daemon) {
+         char *name = lp_name(module_id);
+         int l = strlen(name);
+         for (i=0;i<argc;i++) {
+                 if (strncmp(argv[i], name, l) == 0) {
+                         argv[i] += l;
+                         if (!*argv[i]) argv[i] = ".";
+                 }
+         }
+  }
+
   if (argc == 0 && recurse) {
          argc=1;
          argv--;
          argv[0] = ".";
   }
-    
+
+  rprintf(FINFO,"sending file list\n");
 
   flist = send_file_list(f_out,argc,argv);
   send_files(flist,f_out,f_in);
@@ -389,11 +404,23 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
   if (verbose > 2)
     rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
 
+  if (am_daemon) {
+         char *name = lp_name(module_id);
+         int i, l = strlen(name);
+         for (i=0;i<argc;i++) {
+                 if (strncmp(argv[i], name, l) == 0) {
+                         argv[i] += l;
+                         if (!*argv[i]) argv[i] = ".";
+                 }
+                 rprintf(FINFO,"argv[%d]=%s\n", i, argv[i]);
+         }
+  }
+
   if (argc > 0) {
          dir = argv[0];
          argc--;
          argv++;
-         if (chdir(dir) != 0) {
+         if (!am_daemon && chdir(dir) != 0) {
                  rprintf(FERROR,"chdir %s : %s (4)\n",
                          dir,strerror(errno));
                  exit_cleanup(1);
@@ -487,13 +514,15 @@ static int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
 
 int start_socket_client(char *host, char *path, int argc, char *argv[])
 {
-       int fd;
-       char *sargs[100];
+       int fd, i;
+       char *sargs[MAX_ARGS];
        int sargc=0;
-       
+       char line[1024];
+       char *p;
+       int version;
+
        fd = open_socket_out(host, port);
        if (fd == -1) {
-               rprintf(FERROR,"failed to connect to %s - %s\n", host, strerror(errno));
                exit_cleanup(1);
        }
        
@@ -506,6 +535,41 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
 
        sargs[sargc] = NULL;
 
+       p = strchr(path,'/');
+       if (p) *p = 0;
+       io_printf(fd,"%s\n",path);
+       if (p) *p = '/';
+
+       if (!read_line(fd, line, sizeof(line)-1)) {
+               return -1;
+       }
+
+       if (sscanf(line,"RSYNCD %d", &version) != 1) {
+               return -1;
+       }
+
+       while (1) {
+               if (!read_line(fd, line, sizeof(line)-1)) {
+                       return -1;
+               }
+               if (strcmp(line,"RSYNCD: OK") == 0) break;
+               rprintf(FINFO,"%s\n", line);
+       }
+
+       for (i=0;i<sargc;i++) {
+               io_printf(fd,"%s\n", sargs[i]);
+       }
+       io_printf(fd,"\n");
+
+#if 0
+       while (1) {
+               if (!read_line(fd, line, sizeof(line)-1)) {
+                       return -1;
+               }
+               rprintf(FINFO,"%s\n", line);
+       }
+#endif
+
        return client_run(fd, fd, -1, argc, argv);
 }
 
@@ -874,6 +938,161 @@ static void parse_arguments(int argc, char *argv[])
     }
 }
 
+static int rsync_module(int fd, int i)
+{
+       int argc=0;
+       char *argv[MAX_ARGS];
+       char **argp;
+       char line[1024];
+
+       module_id = i;
+
+       if (lp_read_only(i))
+               read_only = 1;
+
+       rprintf(FERROR,"rsyncd starting\n");
+
+       if (chroot(lp_path(i))) {
+               io_printf(fd,"ERROR: chroot failed\n");
+               return -1;
+       }
+
+       if (chdir("/")) {
+               io_printf(fd,"ERROR: chdir failed\n");
+               return -1;
+       }
+
+       if (setgid(lp_gid(i))) {
+               io_printf(fd,"ERROR: setgid failed\n");
+               return -1;
+       }
+
+       if (setuid(lp_uid(i))) {
+               io_printf(fd,"ERROR: setuid failed\n");
+               return -1;
+       }
+
+       io_printf(fd,"RSYNCD: OK\n");
+
+       argv[argc++] = "rsyncd";
+
+       while (1) {
+               if (!read_line(fd, line, sizeof(line)-1)) {
+                       return -1;
+               }
+
+               if (!*line) break;
+
+               argv[argc] = strdup(line);
+               if (!argv[argc]) {
+                       return -1;
+               }
+
+               argc++;
+               if (argc == MAX_ARGS) {
+                       return -1;
+               }
+       }
+
+       parse_arguments(argc, argv);
+
+       /* don't allow the logs to be flooded too fast */
+       if (verbose > 1) verbose = 1;
+
+       argc -= optind;
+       argp = argv + optind;
+       optind = 0;
+
+       start_server(fd, fd, argc, argp);
+
+       return 0;
+}
+
+static void send_listing(int fd)
+{
+       int n = lp_numservices();
+       int i;
+       
+       for (i=0;i<n;i++)
+               if (lp_list(i))
+                   io_printf(fd, "%-15s\t%s\n", lp_name(i), lp_comment(i));
+}
+
+/* this is called when a socket connection is established to a client
+   and we want to start talking. The setup of the system is done from
+   here */
+static int start_daemon(int fd)
+{
+       char line[1024];
+       char *motd;
+
+       set_socket_options(fd,"SO_KEEPALIVE");
+
+       io_printf(fd,"RSYNCD %d\n", PROTOCOL_VERSION);
+
+       motd = lp_motd_file();
+       if (*motd) {
+               FILE *f = fopen(motd,"r");
+               while (f && !feof(f)) {
+                       int len = fread(line, 1, sizeof(line)-1, f);
+                       if (len > 0) {
+                               line[len] = 0;
+                               io_printf(fd,"%s", line);
+                       }
+               }
+               if (f) fclose(f);
+               io_printf(fd,"\n");
+       }
+
+       /* read a single line indicating the resource that is wanted */
+       while (1) {
+               int i;
+
+               line[0] = 0;
+               if (!read_line(fd, line, sizeof(line)-1)) {
+                       return -1;
+               }
+
+               if (!*line || strcmp(line,"#list")==0) {
+                       send_listing(fd);
+                       return -1;
+               } 
+
+               if (*line == '#') {
+                       /* it's some sort of command that I don't understand */
+                       io_printf(fd,"ERROR: Unknown command '%s'\n", line);
+                       return -1;
+               }
+
+               i = lp_number(line);
+               if (i == -1) {
+                       io_printf(fd,"ERROR: Unknown module '%s'\n", line);
+                       return -1;
+               }
+
+               return rsync_module(fd, i);
+       }
+
+       return 0;
+}
+
+
+static int daemon_main(void)
+{
+       if (!lp_load(RSYNCD_CONF)) {
+               exit_cleanup(1);
+       }
+
+       if (is_a_socket(STDIN_FILENO)) {
+               /* we are running via inetd */
+               return start_daemon(STDIN_FILENO);
+       }
+
+       become_daemon();
+
+       return start_accept_loop(port, start_daemon);
+}
+
 int main(int argc,char *argv[])
 {
 
@@ -888,17 +1107,19 @@ int main(int argc,char *argv[])
 
     parse_arguments(argc, argv);
 
-    while (optind) {
-      argc--;
-      argv++;
-      optind--;
-    }
+    argc -= optind;
+    argv += optind;
+    optind = 0;
 
     signal(SIGCHLD,SIG_IGN);
     signal(SIGINT,SIGNAL_CAST sig_int);
     signal(SIGPIPE,SIGNAL_CAST sig_int);
     signal(SIGHUP,SIGNAL_CAST sig_int);
 
+    if (am_daemon) {
+           return daemon_main();
+    }
+
     if (dry_run)
       verbose = MAX(verbose,1);
 
index 0e3f5bf..a08b1af 100644 (file)
@@ -19,6 +19,41 @@ BEGIN {
   }
 }
 
+/^FN_LOCAL_BOOL/ {
+  split($0,a,"[,()]")
+  printf "BOOL %s(int );\n", a[2]
+}
+
+/^FN_LOCAL_STRING/ {
+  split($0,a,"[,()]")
+  printf "char *%s(int );\n", a[2]
+}
+
+/^FN_LOCAL_INT/ {
+  split($0,a,"[,()]")
+  printf "int %s(int );\n", a[2]
+}
+
+/^FN_LOCAL_CHAR/ {
+  split($0,a,"[,()]")
+  printf "char %s(int );\n", a[2]
+}
+
+/^FN_GLOBAL_BOOL/ {
+  split($0,a,"[,()]")
+  printf "BOOL %s(void);\n", a[2]
+}
+
+/^FN_GLOBAL_STRING/ {
+  split($0,a,"[,()]")
+  printf "char *%s(void);\n", a[2]
+}
+
+/^FN_GLOBAL_INT/ {
+  split($0,a,"[,()]")
+  printf "int %s(void);\n", a[2]
+}
+
 /^static|^extern/ || !/^[a-zA-Z]/ || /[;]/ {
   next;
 }
diff --git a/rsync.h b/rsync.h
index e520640..e2d7745 100644 (file)
--- a/rsync.h
+++ b/rsync.h
@@ -21,6 +21,9 @@
 #define RSYNC_RSH_ENV "RSYNC_RSH"
 
 #define RSYNC_NAME "rsync"
+#define RSYNCD_CONF "/etc/rsyncd.conf"
+#define RSYNCD_LOG "/var/adm/rsyncd.log"
+
 #define BACKUP_SUFFIX "~"
 
 /* a non-zero CHAR_OFFSET makes the rolling sum stronger, but is
@@ -50,6 +53,8 @@
 #define CHUNK_SIZE (32*1024)
 #define MAX_MAP_SIZE (4*1024*1024)
 
+#define MAX_ARGS 100
+
 #define BLOCKING_TIMEOUT 10
 
 #define FERROR 1
 #include <grp.h>
 
 #include <stdarg.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
 
 #ifndef S_IFLNK
 #define S_IFLNK  0120000
 #define S_ISLNK(mode) (((mode) & S_IFLNK) == S_IFLNK)
 #endif
 
+#define BOOL int
+
 #ifndef uchar
 #define uchar unsigned char
 #endif
index 71aa6c2..7027338 100644 (file)
--- a/socket.c
+++ b/socket.c
 
   */
 
+#include "rsync.h"
+
+/* open a socket to a tcp remote host with the specified port 
+   based on code from Warren */
 int open_socket_out(char *host, int port)
 {
-       return -1;
+       int type = SOCK_STREAM;
+       struct sockaddr_in sock_out;
+       int res;
+       struct hostent *hp;
+  
+
+       res = socket(PF_INET, type, 0);
+       if (res == -1) {
+               return -1;
+       }
+
+       hp = gethostbyname(host);
+       if (!hp) {
+               rprintf(FERROR,"unknown host: %s\n", host);
+               return -1;
+       }
+
+       memcpy(&sock_out.sin_addr, hp->h_addr, hp->h_length);
+       sock_out.sin_port = htons(port);
+       sock_out.sin_family = PF_INET;
+
+       if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))) {
+               close(res);
+               rprintf(FERROR,"failed to connect to %s - %s\n", host, strerror(errno));
+               return -1;
+       }
+
+       return res;
+}
+
+
+/****************************************************************************
+open a socket of the specified type, port and address for incoming data
+****************************************************************************/
+static int open_socket_in(int type, int port)
+{
+       struct hostent *hp;
+       struct sockaddr_in sock;
+       char host_name[200];
+       int res;
+       int one=1;
+
+       /* get my host name */
+       if (gethostname(host_name, sizeof(host_name)) == -1) { 
+               rprintf(FERROR,"gethostname failed\n"); 
+               return -1; 
+       } 
+
+       /* get host info */
+       if ((hp = gethostbyname(host_name)) == 0) {
+               rprintf(FERROR,"gethostbyname: Unknown host %s\n",host_name);
+               return -1;
+       }
+  
+       bzero((char *)&sock,sizeof(sock));
+       memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length);
+       sock.sin_port = htons(port);
+       sock.sin_family = hp->h_addrtype;
+       sock.sin_addr.s_addr = INADDR_ANY;
+       res = socket(hp->h_addrtype, type, 0);
+       if (res == -1) { 
+               rprintf(FERROR,"socket failed\n"); 
+               return -1; 
+       }
+
+       setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
+
+       /* now we've got a socket - we need to bind it */
+       if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) == -1) { 
+               rprintf(FERROR,"bind failed on port %d\n", port);
+               close(res); 
+               return -1;
+       }
+
+       return res;
+}
+
+
+/****************************************************************************
+determine if a file descriptor is in fact a socket
+****************************************************************************/
+int is_a_socket(int fd)
+{
+  int v,l;
+  l = sizeof(int);
+  return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
+}
+
+
+int start_accept_loop(int port, int (*fn)(int ))
+{
+       int s;
+
+       signal(SIGCLD, SIG_IGN);
+
+       /* open an incoming socket */
+       s = open_socket_in(SOCK_STREAM, port);
+       if (s == -1)
+               return(-1);
+
+       /* ready to listen */
+       if (listen(s, 5) == -1) {
+               close(s);
+               return -1;
+       }
+
+
+       /* now accept incoming connections - forking a new process
+          for each incoming connection */
+       while (1) {
+               fd_set fds;
+               int fd;
+               struct sockaddr addr;
+               int in_addrlen = sizeof(addr);
+
+               FD_ZERO(&fds);
+               FD_SET(s, &fds);
+
+               if (select(s+1, &fds, NULL, NULL, NULL) != 1) {
+                       continue;
+               }
+
+               if(!FD_ISSET(s, &fds)) continue;
+
+               fd = accept(s,&addr,&in_addrlen);
+
+               if (fd == -1) continue;
+
+               if (fork()==0) {
+                       close(s);
+
+                       _exit(fn(fd));
+               }
+
+               close(fd);
+       }
+       return 0;
+}
+
+
+enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
+
+struct
+{
+  char *name;
+  int level;
+  int option;
+  int value;
+  int opttype;
+} socket_options[] = {
+  {"SO_KEEPALIVE",      SOL_SOCKET,    SO_KEEPALIVE,    0,                 OPT_BOOL},
+  {"SO_REUSEADDR",      SOL_SOCKET,    SO_REUSEADDR,    0,                 OPT_BOOL},
+  {"SO_BROADCAST",      SOL_SOCKET,    SO_BROADCAST,    0,                 OPT_BOOL},
+#ifdef TCP_NODELAY
+  {"TCP_NODELAY",       IPPROTO_TCP,   TCP_NODELAY,     0,                 OPT_BOOL},
+#endif
+#ifdef IPTOS_LOWDELAY
+  {"IPTOS_LOWDELAY",    IPPROTO_IP,    IP_TOS,          IPTOS_LOWDELAY,    OPT_ON},
+#endif
+#ifdef IPTOS_THROUGHPUT
+  {"IPTOS_THROUGHPUT",  IPPROTO_IP,    IP_TOS,          IPTOS_THROUGHPUT,  OPT_ON},
+#endif
+#ifdef SO_SNDBUF
+  {"SO_SNDBUF",         SOL_SOCKET,    SO_SNDBUF,       0,                 OPT_INT},
+#endif
+#ifdef SO_RCVBUF
+  {"SO_RCVBUF",         SOL_SOCKET,    SO_RCVBUF,       0,                 OPT_INT},
+#endif
+#ifdef SO_SNDLOWAT
+  {"SO_SNDLOWAT",       SOL_SOCKET,    SO_SNDLOWAT,     0,                 OPT_INT},
+#endif
+#ifdef SO_RCVLOWAT
+  {"SO_RCVLOWAT",       SOL_SOCKET,    SO_RCVLOWAT,     0,                 OPT_INT},
+#endif
+#ifdef SO_SNDTIMEO
+  {"SO_SNDTIMEO",       SOL_SOCKET,    SO_SNDTIMEO,     0,                 OPT_INT},
+#endif
+#ifdef SO_RCVTIMEO
+  {"SO_RCVTIMEO",       SOL_SOCKET,    SO_RCVTIMEO,     0,                 OPT_INT},
+#endif
+  {NULL,0,0,0,0}};
+
+       
+
+/****************************************************************************
+set user socket options
+****************************************************************************/
+void set_socket_options(int fd, char *options)
+{
+       char *tok;
+       options = strdup(options);
+       
+       if (!options) out_of_memory("set_socket_options");
+
+       for (tok=strtok(options, " \t,"); tok; tok=strtok(NULL," \t,")) {
+               int ret=0,i;
+               int value = 1;
+               char *p;
+               int got_value = 0;
+
+               if ((p = strchr(tok,'='))) {
+                       *p = 0;
+                       value = atoi(p+1);
+                       got_value = 1;
+               }
+
+               for (i=0;socket_options[i].name;i++)
+                       if (strcmp(socket_options[i].name,tok)==0)
+                               break;
+
+               if (!socket_options[i].name) {
+                       rprintf(FERROR,"Unknown socket option %s\n",tok);
+                       continue;
+               }
+
+               switch (socket_options[i].opttype) {
+               case OPT_BOOL:
+               case OPT_INT:
+                       ret = setsockopt(fd,socket_options[i].level,
+                                        socket_options[i].option,(char *)&value,sizeof(int));
+                       break;
+                       
+               case OPT_ON:
+                       if (got_value)
+                               rprintf(FERROR,"syntax error - %s does not take a value\n",tok);
+
+                       {
+                               int on = socket_options[i].value;
+                               ret = setsockopt(fd,socket_options[i].level,
+                                                socket_options[i].option,(char *)&on,sizeof(int));
+                       }
+                       break;    
+               }
+               
+               if (ret != 0)
+                       rprintf(FERROR,"Failed to set socket option %s\n",tok);
+       }
+
+       free(options);
+}
+
+/****************************************************************************
+become a daemon, discarding the controlling terminal
+****************************************************************************/
+void become_daemon(void)
+{
+       if (fork())
+               _exit(0);
+
+       /* detach from the terminal */
+#ifdef HAVE_SETSID
+       setsid();
+#else
+#ifdef TIOCNOTTY
+       {
+               int i = open("/dev/tty", O_RDWR);
+               if (i >= 0) 
+                       {
+                               ioctl(i, (int) TIOCNOTTY, (char *)0);      
+                               close(i);
+                       }
+       }
+#endif /* TIOCNOTTY */
+#endif
+       close(0);
+       close(1);
+       close(2);
 }
index c6fd354..c655969 100644 (file)
--- a/syscall.c
+++ b/syscall.c
 #include "rsync.h"
 
 extern int dry_run;
+extern int read_only;
+
+#define CHECK_RO if (read_only) {errno = EROFS; return -1;}
 
 int do_unlink(char *fname)
 {
        if (dry_run) return 0;
+       CHECK_RO
        return unlink(fname);
 }
 
 int do_symlink(char *fname1, char *fname2)
 {
        if (dry_run) return 0;
+       CHECK_RO
        return symlink(fname1, fname2);
 }
 
@@ -40,6 +45,7 @@ int do_symlink(char *fname1, char *fname2)
 int do_link(char *fname1, char *fname2)
 {
        if (dry_run) return 0;
+       CHECK_RO
        return link(fname1, fname2);
 }
 #endif
@@ -47,6 +53,7 @@ int do_link(char *fname1, char *fname2)
 int do_lchown(const char *path, uid_t owner, gid_t group)
 {
        if (dry_run) return 0;
+       CHECK_RO
        return lchown(path, owner, group);
 }
 
@@ -54,6 +61,7 @@ int do_lchown(const char *path, uid_t owner, gid_t group)
 int do_mknod(char *pathname, mode_t mode, dev_t dev)
 {
        if (dry_run) return 0;
+       CHECK_RO
        return mknod(pathname, mode, dev);
 }
 #endif
@@ -61,12 +69,14 @@ int do_mknod(char *pathname, mode_t mode, dev_t dev)
 int do_rmdir(char *pathname)
 {
        if (dry_run) return 0;
+       CHECK_RO
        return rmdir(pathname);
 }
 
 int do_open(char *pathname, int flags, mode_t mode)
 {
        if (dry_run) return -1;
+       CHECK_RO
        return open(pathname, flags, mode);
 }
 
@@ -74,6 +84,7 @@ int do_open(char *pathname, int flags, mode_t mode)
 int do_chmod(const char *path, mode_t mode)
 {
        if (dry_run) return 0;
+       CHECK_RO
        return chmod(path, mode);
 }
 #endif
@@ -81,18 +92,21 @@ int do_chmod(const char *path, mode_t mode)
 int do_rename(char *fname1, char *fname2)
 {
        if (dry_run) return 0;
+       CHECK_RO
        return rename(fname1, fname2);
 }
 
 int do_mkdir(char *fname, mode_t mode)
 {
        if (dry_run) return 0;
+       CHECK_RO
        return mkdir(fname, mode);
 }
 
 char *do_mktemp(char *template)
 {
        if (dry_run) return NULL;
+       if (read_only) {errno = EROFS; return NULL;}
        return mktemp(template);
 }
 
diff --git a/util.c b/util.c
index 59f9418..f74228e 100644 (file)
--- a/util.c
+++ b/util.c
@@ -446,58 +446,3 @@ void kill_all(int sig)
        }
 }
 
-/* this is the rsync debugging function. Call it with FINFO or FERROR */
-void rprintf(int fd, const char *format, ...)
-{
-       va_list ap;  
-       char buf[1024];
-       int len;
-       FILE *f=NULL;
-
-       va_start(ap, format);
-
-#if HAVE_VSNPRINTF
-       len = vsnprintf(buf, sizeof(buf)-1, format, ap);
-#else
-       len = vsprintf(buf, format, ap);
-#endif
-       va_end(ap);
-
-       if (len < 0) exit_cleanup(1);
-
-       if (fd == FERROR) {
-               f = stderr;
-       } 
-
-       if (fd == FINFO) {
-               extern int am_server;
-               if (am_server) 
-                       f = stderr;
-               else
-                       f = stdout;
-       } 
-
-       if (!f) exit_cleanup(1);
-
-       if (fwrite(buf, len, 1, f) != 1) exit_cleanup(1);
-}
-
-void rflush(int fd)
-{
-       FILE *f = NULL;
-
-       if (fd == FERROR) {
-               f = stderr;
-       } 
-
-       if (fd == FINFO) {
-               extern int am_server;
-               if (am_server) 
-                       f = stderr;
-               else
-                       f = stdout;
-       } 
-
-       if (!f) exit_cleanup(1);
-       fflush(f);
-}