X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/9486289ce452ab82ca8b3f16fae8c2ef5247a923..e42c9458c2f1e3a78d6d45e99741d6edb38fc0cc:/util.c diff --git a/util.c b/util.c index 59f94182..cc39cdb4 100644 --- a/util.c +++ b/util.c @@ -446,58 +446,222 @@ void kill_all(int sig) } } -/* this is the rsync debugging function. Call it with FINFO or FERROR */ -void rprintf(int fd, const char *format, ...) +/* like strncpy but does not 0 fill the buffer and always null + terminates (thus it can use maxlen+1 space in d) */ +void strlcpy(char *d, char *s, int maxlen) { - va_list ap; - char buf[1024]; - int len; - FILE *f=NULL; + int len = strlen(s); + if (len > maxlen) len = maxlen; + memcpy(d, s, len); + d[len] = 0; +} + +/* like strncat but does not 0 fill the buffer and always null + terminates (thus it can use maxlen+1 space in d) */ +void strlcat(char *d, char *s, int maxlen) +{ + int len1 = strlen(d); + int len2 = strlen(s); + if (len1+len2 > maxlen) { + len2 = maxlen-len1; + } + if (len2 > 0) { + memcpy(d+len1, s, len2); + d[len1+len2] = 0; + } +} + +/* turn a user name into a uid */ +int name_to_uid(char *name, uid_t *uid) +{ + struct passwd *pass; + if (!name || !*name) return 0; + pass = getpwnam(name); + if (pass) { + *uid = pass->pw_uid; + return 1; + } + return 0; +} + +/* turn a group name into a gid */ +int name_to_gid(char *name, gid_t *gid) +{ + struct group *grp; + if (!name || !*name) return 0; + grp = getgrnam(name); + if (grp) { + *gid = grp->gr_gid; + return 1; + } + return 0; +} - va_start(ap, format); -#if HAVE_VSNPRINTF - len = vsnprintf(buf, sizeof(buf)-1, format, ap); +/**************************************************************************** +check if a process exists. +****************************************************************************/ +int process_exists(int pid) +{ + return(kill(pid,0) == 0 || errno != ESRCH); +} + +/* lock a byte range in a open file */ +int lock_range(int fd, int offset, int len) +{ + struct flock lock; + + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = offset; + lock.l_len = len; + lock.l_pid = 0; + + return fcntl(fd,F_SETLK,&lock) == 0; +} + + +static void glob_expand_one(char *s, char **argv, int *argc, int maxargs) +{ +#ifndef HAVE_GLOB + if (!*s) s = "."; + argv[*argc] = strdup(s); + (*argc)++; + return; #else - len = vsprintf(buf, format, ap); + glob_t globbuf; + int i; + + if (!*s) s = "."; + + argv[*argc] = strdup(s); + + memset(&globbuf, 0, sizeof(globbuf)); + glob(argv[*argc], 0, NULL, &globbuf); + if (globbuf.gl_pathc == 0) { + (*argc)++; + globfree(&globbuf); + return; + } + for (i=0; i<(maxargs - (*argc)) && i n || ret < 0) { + str[n] = 0; + return -1; + } + str[ret] = 0; + return ret; +#else + static char *buf; + static int len=MAXPATHLEN*8; + int ret; + + /* this code is NOT a proper vsnprintf() implementation. It + relies on the fact that all calls to slprintf() in rsync + pass strings which have already been checked to be less + than MAXPATHLEN in length and never more than 2 strings are + concatenated. This means the above buffer is absolutely + ample and can never be overflowed. + + In the future we would like to replace this with a proper + vsnprintf() implementation but right now we need a solution + that is secure and portable. This is it. */ + + if (!buf) { + buf = malloc(len); + if (!buf) { + /* can't call debug or we would recurse */ + exit(1); + } + } - if (fd == FINFO) { - extern int am_server; - if (am_server) - f = stderr; - else - f = stdout; - } - - if (!f) exit_cleanup(1); - fflush(f); + ret = vsprintf(buf, format, ap); + + if (ret < 0) { + str[0] = 0; + return -1; + } + + if (ret < n) { + n = ret; + } else if (ret > n) { + ret = -1; + } + + buf[n] = 0; + + memcpy(str, buf, n+1); + + return ret; +#endif +} + + +/* 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; }