X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/f0359dd00d60d72c4b3dec85de8e490692f6015c..ab94af5c6f93c3b81af95888197f60522e2eb144:/util.c diff --git a/util.c b/util.c index 03a626eb..df2af3e8 100644 --- a/util.c +++ b/util.c @@ -1,6 +1,7 @@ -/* - Copyright (C) Andrew Tridgell 1996 - Copyright (C) Paul Mackerras 1996 +/* -*- c-file-style: "linux" -*- + + Copyright (C) 1996-2000 by Andrew Tridgell + Copyright (C) Paul Mackerras 1996 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,10 +29,7 @@ extern int verbose; /**************************************************************************** -Set a fd into nonblocking mode. Uses POSIX O_NONBLOCK if available, -else -if SYSV use O_NDELAY -if BSD use FNDELAY +Set a fd into nonblocking mode ****************************************************************************/ void set_nonblocking(int fd) { @@ -45,6 +43,21 @@ void set_nonblocking(int fd) } } +/**************************************************************************** +Set a fd into blocking mode +****************************************************************************/ +void set_blocking(int fd) +{ + int val; + + if((val = fcntl(fd, F_GETFL, 0)) == -1) + return; + if (val & NONBLOCK_FLAG) { + val &= ~NONBLOCK_FLAG; + fcntl(fd, F_SETFL, val); + } +} + /* create a file descriptor pair - like pipe() but use socketpair if possible (because of blocking issues on pipes) @@ -70,12 +83,22 @@ int fd_pair(int fd[2]) } -/* this is taken from CVS */ -int piped_child(char **command,int *f_in,int *f_out) +/* this is derived from CVS code + + note that in the child STDIN is set to blocking and STDOUT + is set to non-blocking. This is necessary as rsh relies on stdin being blocking + and ssh relies on stdout being non-blocking + + if blocking_io is set then use blocking io on both fds. That can be + used to cope with badly broken rsh implementations like the one on + solaris. + */ +pid_t piped_child(char **command,int *f_in,int *f_out) { - int pid; + pid_t pid; int to_child_pipe[2]; int from_child_pipe[2]; + extern int blocking_io; if (fd_pair(to_child_pipe) < 0 || fd_pair(from_child_pipe) < 0) { @@ -85,7 +108,7 @@ int piped_child(char **command,int *f_in,int *f_out) pid = do_fork(); - if (pid < 0) { + if (pid == -1) { rprintf(FERROR,"fork: %s\n",strerror(errno)); exit_cleanup(RERR_IPC); } @@ -103,6 +126,10 @@ int piped_child(char **command,int *f_in,int *f_out) if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]); if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]); umask(orig_umask); + set_blocking(STDIN_FILENO); + if (blocking_io) { + set_blocking(STDOUT_FILENO); + } execvp(command[0], command); rprintf(FERROR,"Failed to exec %s : %s\n", command[0],strerror(errno)); @@ -121,9 +148,9 @@ int piped_child(char **command,int *f_in,int *f_out) return pid; } -int local_child(int argc, char **argv,int *f_in,int *f_out) +pid_t local_child(int argc, char **argv,int *f_in,int *f_out) { - int pid; + pid_t pid; int to_child_pipe[2]; int from_child_pipe[2]; @@ -135,7 +162,7 @@ int local_child(int argc, char **argv,int *f_in,int *f_out) pid = do_fork(); - if (pid < 0) { + if (pid == -1) { rprintf(FERROR,"fork: %s\n",strerror(errno)); exit_cleanup(RERR_IPC); } @@ -531,10 +558,7 @@ void glob_expand(char *base1, char **argv, int *argc, int maxargs) s = strdup(s); if (!s) out_of_memory("glob_expand"); - base = (char *)malloc(strlen(base1)+3); - if (!base) out_of_memory("glob_expand"); - - sprintf(base," %s/", base1); + if (asprintf(&base," %s/", base1) <= 0) out_of_memory("glob_expand"); q = s; while ((p = strstr(q,base)) && ((*argc) < maxargs)) { @@ -561,33 +585,6 @@ void strlower(char *s) } } -/* this is like vsnprintf but it always null terminates, so you - can fit at most n-1 chars in */ -int vslprintf(char *str, int n, const char *format, va_list ap) -{ - int ret = vsnprintf(str, n, format, ap); - if (ret >= n || ret < 0) { - str[n-1] = 0; - return -1; - } - str[ret] = 0; - return ret; -} - - -/* like snprintf but always null terminates */ -int slprintf(char *str, int n, char *format, ...) -{ - va_list ap; - int ret; - - va_start(ap, format); - ret = vslprintf(str,n,format,ap); - va_end(ap); - return ret; -} - - void *Realloc(void *p, int size) { if (!p) return (void *)malloc(size); @@ -904,14 +901,79 @@ char *timestring(time_t t) } -/**************************************************************************** - like waitpid but does the WEXITSTATUS -****************************************************************************/ -#ifndef WEXITSTATUS -#define WEXITSTATUS(stat) ((int)(((stat)>>8)&0xFF)) -#endif -void wait_process(pid_t pid, int *status) +/******************************************************************* +sleep for a specified number of milliseconds +********************************************************************/ +void msleep(int t) +{ + int tdiff=0; + struct timeval tval,t1,t2; + + gettimeofday(&t1, NULL); + gettimeofday(&t2, NULL); + + while (tdiff < t) { + tval.tv_sec = (t-tdiff)/1000; + tval.tv_usec = 1000*((t-tdiff)%1000); + + errno = 0; + select(0,NULL,NULL, NULL, &tval); + + gettimeofday(&t2, NULL); + tdiff = (t2.tv_sec - t1.tv_sec)*1000 + + (t2.tv_usec - t1.tv_usec)/1000; + } +} + + +/******************************************************************* + Determine if two file modification times are equivalent (either exact + or in the modification timestamp window established by --modify-window) + Returns 0 if the times should be treated as the same, 1 if the + first is later and -1 if the 2nd is later + *******************************************************************/ +int cmp_modtime(time_t file1, time_t file2) +{ + extern int modify_window; + + if (file2 > file1) { + if (file2 - file1 <= modify_window) return 0; + return -1; + } + if (file1 - file2 <= modify_window) return 0; + return 1; +} + + +#ifdef __INSURE__XX +#include + +/******************************************************************* +This routine is a trick to immediately catch errors when debugging +with insure. A xterm with a gdb is popped up when insure catches +a error. It is Linux specific. +********************************************************************/ +int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6) { - waitpid(pid, status, 0); - *status = WEXITSTATUS(*status); + static int (*fn)(); + int ret; + char *cmd; + + asprintf(&cmd, "/usr/X11R6/bin/xterm -display :0 -T Panic -n Panic -e /bin/sh -c 'cat /tmp/ierrs.*.%d ; gdb /proc/%d/exe %d'", + getpid(), getpid(), getpid()); + + if (!fn) { + static void *h; + h = dlopen("/usr/local/parasoft/insure++lite/lib.linux2/libinsure.so", RTLD_LAZY); + fn = dlsym(h, "_Insure_trap_error"); + } + + ret = fn(a1, a2, a3, a4, a5, a6); + + system(cmd); + + free(cmd); + + return ret; } +#endif