this fixes two problems:
[rsync/rsync.git] / util.c
... / ...
CommitLineData
1/*
2 Copyright (C) Andrew Tridgell 1996
3 Copyright (C) Paul Mackerras 1996
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18*/
19
20/*
21 Utilities used in rsync
22
23 tridge, June 1996
24 */
25#include "rsync.h"
26
27int num_waiting(int fd)
28{
29 int len=0;
30 ioctl(fd,FIONREAD,&len);
31 return(len);
32}
33
34
35struct map_struct *map_file(int fd,OFF_T len)
36{
37 struct map_struct *ret;
38 ret = (struct map_struct *)malloc(sizeof(*ret));
39 if (!ret) out_of_memory("map_file");
40
41 ret->map = NULL;
42 ret->fd = fd;
43 ret->size = len;
44 ret->p = NULL;
45 ret->p_size = 0;
46 ret->p_offset = 0;
47 ret->p_len = 0;
48
49#ifdef HAVE_MMAP
50 len = MIN(len, MAX_MAP_SIZE);
51 ret->map = (char *)do_mmap(NULL,len,PROT_READ,MAP_SHARED,fd,0);
52 if (ret->map == (char *)-1) {
53 ret->map = NULL;
54 } else {
55 ret->p_len = len;
56 }
57#endif
58 return ret;
59}
60
61
62char *map_ptr(struct map_struct *map,OFF_T offset,int len)
63{
64 int nread;
65
66 if (len == 0)
67 return NULL;
68
69 if (len > (map->size-offset))
70 len = map->size-offset;
71
72 if (map->map) {
73 if (offset >= map->p_offset &&
74 offset+len <= map->p_offset+map->p_len) {
75 return (map->map + (offset - map->p_offset));
76 }
77 if (munmap(map->map, map->p_len) != 0) {
78 rprintf(FERROR,"munmap failed : %s\n", strerror(errno));
79 exit_cleanup(1);
80 }
81
82 /* align the mmap region on a nice boundary back a bit from
83 where it is asked for to allow for some seeking */
84 if (offset > 2*CHUNK_SIZE) {
85 map->p_offset = offset - 2*CHUNK_SIZE;
86 map->p_offset &= ~((OFF_T)(CHUNK_SIZE-1));
87 } else {
88 map->p_offset = 0;
89 }
90
91 /* map up to MAX_MAP_SIZE */
92 map->p_len = MAX(len, MAX_MAP_SIZE);
93 map->p_len = MIN(map->p_len, map->size - map->p_offset);
94
95 map->map = (char *)do_mmap(NULL,map->p_len,PROT_READ,
96 MAP_SHARED,map->fd,map->p_offset);
97
98 if (map->map == (char *)-1) {
99 map->map = NULL;
100 map->p_len = 0;
101 map->p_offset = 0;
102 } else {
103 return (map->map + (offset - map->p_offset));
104 }
105 }
106
107 if (offset >= map->p_offset &&
108 offset+len <= map->p_offset+map->p_len) {
109 return (map->p + (offset - map->p_offset));
110 }
111
112 len = MAX(len,CHUNK_SIZE);
113 if (len > (map->size-offset))
114 len = map->size-offset;
115
116 if (len > map->p_size) {
117 if (map->p) free(map->p);
118 map->p = (char *)malloc(len);
119 if (!map->p) out_of_memory("map_ptr");
120 map->p_size = len;
121 }
122
123 map->p_offset = offset;
124 map->p_len = len;
125
126 if (do_lseek(map->fd,offset,SEEK_SET) != offset) {
127 rprintf(FERROR,"lseek failed in map_ptr\n");
128 exit_cleanup(1);
129 }
130
131 if ((nread=read(map->fd,map->p,len)) != len) {
132 if (nread < 0) nread = 0;
133 /* the best we can do is zero the buffer - the file
134 has changed mid transfer! */
135 memset(map->p+nread, 0, len - nread);
136 }
137
138 return map->p;
139}
140
141
142void unmap_file(struct map_struct *map)
143{
144#ifdef HAVE_MMAP
145 if (map->map) {
146 munmap(map->map,map->p_len);
147 map->map = NULL;
148 }
149#endif
150 if (map->p) {
151 free(map->p);
152 map->p = NULL;
153 }
154 memset(map, 0, sizeof(*map));
155 free(map);
156}
157
158
159/* this is taken from CVS */
160int piped_child(char **command,int *f_in,int *f_out)
161{
162 int pid;
163 int to_child_pipe[2];
164 int from_child_pipe[2];
165
166 if (pipe(to_child_pipe) < 0 ||
167 pipe(from_child_pipe) < 0) {
168 rprintf(FERROR,"pipe: %s\n",strerror(errno));
169 exit_cleanup(1);
170 }
171
172
173 pid = do_fork();
174 if (pid < 0) {
175 rprintf(FERROR,"fork: %s\n",strerror(errno));
176 exit_cleanup(1);
177 }
178
179 if (pid == 0)
180 {
181 extern int orig_umask;
182 if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
183 close(to_child_pipe[1]) < 0 ||
184 close(from_child_pipe[0]) < 0 ||
185 dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
186 rprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
187 exit_cleanup(1);
188 }
189 if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
190 if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
191 umask(orig_umask);
192 execvp(command[0], command);
193 rprintf(FERROR,"Failed to exec %s : %s\n",
194 command[0],strerror(errno));
195 exit_cleanup(1);
196 }
197
198 if (close(from_child_pipe[1]) < 0 ||
199 close(to_child_pipe[0]) < 0) {
200 rprintf(FERROR,"Failed to close : %s\n",strerror(errno));
201 exit_cleanup(1);
202 }
203
204 *f_in = from_child_pipe[0];
205 *f_out = to_child_pipe[1];
206
207 return pid;
208}
209
210int local_child(int argc, char **argv,int *f_in,int *f_out)
211{
212 int pid;
213 int to_child_pipe[2];
214 int from_child_pipe[2];
215
216 if (pipe(to_child_pipe) < 0 ||
217 pipe(from_child_pipe) < 0) {
218 rprintf(FERROR,"pipe: %s\n",strerror(errno));
219 exit_cleanup(1);
220 }
221
222
223 pid = do_fork();
224 if (pid < 0) {
225 rprintf(FERROR,"fork: %s\n",strerror(errno));
226 exit_cleanup(1);
227 }
228
229 if (pid == 0) {
230 extern int am_sender;
231 extern int am_server;
232
233 am_sender = !am_sender;
234 am_server = 1;
235
236 if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
237 close(to_child_pipe[1]) < 0 ||
238 close(from_child_pipe[0]) < 0 ||
239 dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
240 rprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
241 exit_cleanup(1);
242 }
243 if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
244 if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
245 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
246 }
247
248 if (close(from_child_pipe[1]) < 0 ||
249 close(to_child_pipe[0]) < 0) {
250 rprintf(FERROR,"Failed to close : %s\n",strerror(errno));
251 exit_cleanup(1);
252 }
253
254 *f_in = from_child_pipe[0];
255 *f_out = to_child_pipe[1];
256
257 return pid;
258}
259
260
261
262void out_of_memory(char *str)
263{
264 rprintf(FERROR,"ERROR: out of memory in %s\n",str);
265 exit_cleanup(1);
266}
267
268void overflow(char *str)
269{
270 rprintf(FERROR,"ERROR: buffer overflow in %s\n",str);
271 exit_cleanup(1);
272}
273
274
275
276int set_modtime(char *fname,time_t modtime)
277{
278 extern int dry_run;
279 if (dry_run) return 0;
280 {
281#ifdef HAVE_UTIMBUF
282 struct utimbuf tbuf;
283 tbuf.actime = time(NULL);
284 tbuf.modtime = modtime;
285 return utime(fname,&tbuf);
286#elif defined(HAVE_UTIME)
287 time_t t[2];
288 t[0] = time(NULL);
289 t[1] = modtime;
290 return utime(fname,t);
291#else
292 struct timeval t[2];
293 t[0].tv_sec = time(NULL);
294 t[0].tv_usec = 0;
295 t[1].tv_sec = modtime;
296 t[1].tv_usec = 0;
297 return utimes(fname,t);
298#endif
299 }
300}
301
302
303
304/****************************************************************************
305Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
306else
307if SYSV use O_NDELAY
308if BSD use FNDELAY
309****************************************************************************/
310int set_blocking(int fd, int set)
311{
312 int val;
313#ifdef O_NONBLOCK
314#define FLAG_TO_SET O_NONBLOCK
315#else
316#ifdef SYSV
317#define FLAG_TO_SET O_NDELAY
318#else /* BSD */
319#define FLAG_TO_SET FNDELAY
320#endif
321#endif
322
323 if((val = fcntl(fd, F_GETFL, 0)) == -1)
324 return -1;
325 if(set) /* Turn blocking on - ie. clear nonblock flag */
326 val &= ~FLAG_TO_SET;
327 else
328 val |= FLAG_TO_SET;
329 return fcntl( fd, F_SETFL, val);
330#undef FLAG_TO_SET
331}
332
333/****************************************************************************
334create any necessary directories in fname. Unfortunately we don't know
335what perms to give the directory when this is called so we need to rely
336on the umask
337****************************************************************************/
338int create_directory_path(char *fname)
339{
340 extern int orig_umask;
341 char *p;
342
343 while (*fname == '/') fname++;
344 while (strncmp(fname,"./",2)==0) fname += 2;
345
346 p = fname;
347 while ((p=strchr(p,'/'))) {
348 *p = 0;
349 do_mkdir(fname,0777 & ~orig_umask);
350 *p = '/';
351 p++;
352 }
353 return 0;
354}
355
356
357/* Write LEN bytes at PTR to descriptor DESC, retrying if interrupted.
358 Return LEN upon success, write's (negative) error code otherwise.
359
360 derived from GNU C's cccp.c.
361*/
362int full_write(int desc, char *ptr, int len)
363{
364 int total_written;
365
366 total_written = 0;
367 while (len > 0) {
368 int written = write (desc, ptr, len);
369 if (written < 0) {
370#ifdef EINTR
371 if (errno == EINTR)
372 continue;
373#endif
374 return written;
375 }
376 total_written += written;
377 ptr += written;
378 len -= written;
379 }
380 return total_written;
381}
382
383/* Read LEN bytes at PTR from descriptor DESC, retrying if interrupted.
384 Return the actual number of bytes read, zero for EOF, or negative
385 for an error.
386
387 derived from GNU C's cccp.c. */
388int safe_read(int desc, char *ptr, int len)
389{
390 int n_chars;
391
392 if (len <= 0)
393 return len;
394
395#ifdef EINTR
396 do {
397 n_chars = read(desc, ptr, len);
398 } while (n_chars < 0 && errno == EINTR);
399#else
400 n_chars = read(desc, ptr, len);
401#endif
402
403 return n_chars;
404}
405
406
407/* copy a file - this is used in conjunction with the --temp-dir option */
408int copy_file(char *source, char *dest, mode_t mode)
409{
410 int ifd;
411 int ofd;
412 char buf[1024 * 8];
413 int len; /* Number of bytes read into `buf'. */
414
415 ifd = open(source, O_RDONLY);
416 if (ifd == -1) {
417 rprintf(FERROR,"open %s: %s\n",
418 source,strerror(errno));
419 return -1;
420 }
421
422 if (do_unlink(dest) && errno != ENOENT) {
423 rprintf(FERROR,"unlink %s: %s\n",
424 dest,strerror(errno));
425 return -1;
426 }
427
428 ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode);
429 if (ofd < 0) {
430 rprintf(FERROR,"open %s: %s\n",
431 dest,strerror(errno));
432 close(ifd);
433 return -1;
434 }
435
436 while ((len = safe_read(ifd, buf, sizeof(buf))) > 0) {
437 if (full_write(ofd, buf, len) < 0) {
438 rprintf(FERROR,"write %s: %s\n",
439 dest,strerror(errno));
440 close(ifd);
441 close(ofd);
442 return -1;
443 }
444 }
445
446 close(ifd);
447 close(ofd);
448
449 if (len < 0) {
450 rprintf(FERROR,"read %s: %s\n",
451 source,strerror(errno));
452 return -1;
453 }
454
455 return 0;
456}
457
458/* sleep for a while via select */
459void u_sleep(int usec)
460{
461 struct timeval tv;
462
463 tv.tv_sec = 0;
464 tv.tv_usec = usec;
465 select(0, NULL, NULL, NULL, &tv);
466}
467
468
469static pid_t all_pids[10];
470static int num_pids;
471
472/* fork and record the pid of the child */
473pid_t do_fork(void)
474{
475 pid_t newpid = fork();
476
477 if (newpid) {
478 all_pids[num_pids++] = newpid;
479 }
480 return newpid;
481}
482
483/* kill all children */
484void kill_all(int sig)
485{
486 int i;
487 for (i=0;i<num_pids;i++) {
488 if (all_pids[i] != getpid())
489 kill(all_pids[i], sig);
490 }
491}
492
493/* like strncpy but does not 0 fill the buffer and always null
494 terminates (thus it can use maxlen+1 space in d) */
495void strlcpy(char *d, char *s, int maxlen)
496{
497 int len = strlen(s);
498 if (len > maxlen) len = maxlen;
499 memcpy(d, s, len);
500 d[len] = 0;
501}
502
503/* like strncat but does not 0 fill the buffer and always null
504 terminates (thus it can use maxlen+1 space in d) */
505void strlcat(char *d, char *s, int maxlen)
506{
507 int len1 = strlen(d);
508 int len2 = strlen(s);
509 if (len1+len2 > maxlen) {
510 len2 = maxlen-len1;
511 }
512 if (len2 > 0) {
513 memcpy(d+len1, s, len2);
514 d[len1+len2] = 0;
515 }
516}
517
518/* turn a user name into a uid */
519int name_to_uid(char *name, uid_t *uid)
520{
521 struct passwd *pass;
522 if (!name || !*name) return 0;
523 pass = getpwnam(name);
524 if (pass) {
525 *uid = pass->pw_uid;
526 return 1;
527 }
528 return 0;
529}
530
531/* turn a group name into a gid */
532int name_to_gid(char *name, gid_t *gid)
533{
534 struct group *grp;
535 if (!name || !*name) return 0;
536 grp = getgrnam(name);
537 if (grp) {
538 *gid = grp->gr_gid;
539 return 1;
540 }
541 return 0;
542}
543
544
545/****************************************************************************
546check if a process exists.
547****************************************************************************/
548int process_exists(int pid)
549{
550 return(kill(pid,0) == 0 || errno != ESRCH);
551}
552
553/* lock a byte range in a open file */
554int lock_range(int fd, int offset, int len)
555{
556 struct flock lock;
557
558 lock.l_type = F_WRLCK;
559 lock.l_whence = SEEK_SET;
560 lock.l_start = offset;
561 lock.l_len = len;
562 lock.l_pid = 0;
563
564 return fcntl(fd,F_SETLK,&lock) == 0;
565}
566
567
568static void glob_expand_one(char *s, char **argv, int *argc, int maxargs)
569{
570#ifndef HAVE_GLOB
571 if (!*s) s = ".";
572 argv[*argc] = strdup(s);
573 (*argc)++;
574 return;
575#else
576 glob_t globbuf;
577 int i;
578
579 if (!*s) s = ".";
580
581 argv[*argc] = strdup(s);
582
583 memset(&globbuf, 0, sizeof(globbuf));
584 glob(argv[*argc], 0, NULL, &globbuf);
585 if (globbuf.gl_pathc == 0) {
586 (*argc)++;
587 globfree(&globbuf);
588 return;
589 }
590 for (i=0; i<(maxargs - (*argc)) && i<globbuf.gl_pathc;i++) {
591 if (i == 0) free(argv[*argc]);
592 argv[(*argc) + i] = strdup(globbuf.gl_pathv[i]);
593 if (!argv[(*argc) + i]) out_of_memory("glob_expand");
594 }
595 globfree(&globbuf);
596 (*argc) += i;
597#endif
598}
599
600void glob_expand(char *base1, char **argv, int *argc, int maxargs)
601{
602 char *s = argv[*argc];
603 char *p, *q;
604 char *base = base1;
605
606 if (!s || !*s) return;
607
608 if (strncmp(s, base, strlen(base)) == 0) {
609 s += strlen(base);
610 }
611
612 s = strdup(s);
613 if (!s) out_of_memory("glob_expand");
614
615 base = (char *)malloc(strlen(base1)+3);
616 if (!base) out_of_memory("glob_expand");
617
618 sprintf(base," %s/", base1);
619
620 q = s;
621 while ((p = strstr(q,base)) && ((*argc) < maxargs)) {
622 /* split it at this point */
623 *p = 0;
624 glob_expand_one(q, argv, argc, maxargs);
625 q = p+strlen(base);
626 }
627
628 if (*q && (*argc < maxargs)) glob_expand_one(q, argv, argc, maxargs);
629
630 free(s);
631 free(base);
632}
633
634/*******************************************************************
635 convert a string to lower case
636********************************************************************/
637void strlower(char *s)
638{
639 while (*s) {
640 if (isupper(*s)) *s = tolower(*s);
641 s++;
642 }
643}
644
645/* this is like vsnprintf but the 'n' limit does not include
646 the terminating null. So if you have a 1024 byte buffer then
647 pass 1023 for n */
648int vslprintf(char *str, int n, const char *format, va_list ap)
649{
650#ifdef HAVE_VSNPRINTF
651 int ret = vsnprintf(str, n, format, ap);
652 if (ret > n || ret < 0) {
653 str[n] = 0;
654 return -1;
655 }
656 str[ret] = 0;
657 return ret;
658#else
659 static char *buf;
660 static int len=MAXPATHLEN*8;
661 int ret;
662
663 /* this code is NOT a proper vsnprintf() implementation. It
664 relies on the fact that all calls to slprintf() in rsync
665 pass strings which have already been checked to be less
666 than MAXPATHLEN in length and never more than 2 strings are
667 concatenated. This means the above buffer is absolutely
668 ample and can never be overflowed.
669
670 In the future we would like to replace this with a proper
671 vsnprintf() implementation but right now we need a solution
672 that is secure and portable. This is it. */
673
674 if (!buf) {
675 buf = malloc(len);
676 if (!buf) {
677 /* can't call debug or we would recurse */
678 exit_cleanup(1);
679 }
680 }
681
682 vsprintf(buf, format, ap);
683 ret = strlen(buf);
684 if (ret > n) {
685 /* yikes! */
686 exit_cleanup(1);
687 }
688 buf[ret] = 0;
689
690 memcpy(str, buf, ret+1);
691
692 return ret;
693#endif
694}
695
696
697/* like snprintf but always null terminates */
698int slprintf(char *str, int n, char *format, ...)
699{
700 va_list ap;
701 int ret;
702
703 va_start(ap, format);
704 ret = vslprintf(str,n,format,ap);
705 va_end(ap);
706 return ret;
707}
708