compile with optimisation by default on all compilers
[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
27/****************************************************************************
28Set a fd into nonblocking mode. Uses POSIX O_NONBLOCK if available,
29else
30if SYSV use O_NDELAY
31if BSD use FNDELAY
32****************************************************************************/
33int set_nonblocking(int fd)
34{
35 int val;
36#ifdef O_NONBLOCK
37#define FLAG_TO_SET O_NONBLOCK
38#else
39#ifdef SYSV
40#define FLAG_TO_SET O_NDELAY
41#else /* BSD */
42#define FLAG_TO_SET FNDELAY
43#endif
44#endif
45
46 if((val = fcntl(fd, F_GETFL, 0)) == -1)
47 return -1;
48 val |= FLAG_TO_SET;
49 return fcntl( fd, F_SETFL, val);
50#undef FLAG_TO_SET
51}
52
53
54/* this is taken from CVS */
55int piped_child(char **command,int *f_in,int *f_out)
56{
57 int pid;
58 int to_child_pipe[2];
59 int from_child_pipe[2];
60
61 if (pipe(to_child_pipe) < 0 ||
62 pipe(from_child_pipe) < 0) {
63 rprintf(FERROR,"pipe: %s\n",strerror(errno));
64 exit_cleanup(RERR_IPC);
65 }
66
67
68 pid = do_fork();
69 if (pid < 0) {
70 rprintf(FERROR,"fork: %s\n",strerror(errno));
71 exit_cleanup(RERR_IPC);
72 }
73
74 if (pid == 0)
75 {
76 extern int orig_umask;
77 if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
78 close(to_child_pipe[1]) < 0 ||
79 close(from_child_pipe[0]) < 0 ||
80 dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
81 rprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
82 exit_cleanup(RERR_IPC);
83 }
84 if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
85 if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
86 umask(orig_umask);
87 execvp(command[0], command);
88 rprintf(FERROR,"Failed to exec %s : %s\n",
89 command[0],strerror(errno));
90 exit_cleanup(RERR_IPC);
91 }
92
93 if (close(from_child_pipe[1]) < 0 ||
94 close(to_child_pipe[0]) < 0) {
95 rprintf(FERROR,"Failed to close : %s\n",strerror(errno));
96 exit_cleanup(RERR_IPC);
97 }
98
99 *f_in = from_child_pipe[0];
100 *f_out = to_child_pipe[1];
101
102 set_nonblocking(*f_in);
103 set_nonblocking(*f_out);
104
105 return pid;
106}
107
108int local_child(int argc, char **argv,int *f_in,int *f_out)
109{
110 int pid;
111 int to_child_pipe[2];
112 int from_child_pipe[2];
113
114 if (pipe(to_child_pipe) < 0 ||
115 pipe(from_child_pipe) < 0) {
116 rprintf(FERROR,"pipe: %s\n",strerror(errno));
117 exit_cleanup(RERR_IPC);
118 }
119
120
121 pid = do_fork();
122 if (pid < 0) {
123 rprintf(FERROR,"fork: %s\n",strerror(errno));
124 exit_cleanup(RERR_IPC);
125 }
126
127 if (pid == 0) {
128 extern int am_sender;
129 extern int am_server;
130
131 am_sender = !am_sender;
132 am_server = 1;
133
134 if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
135 close(to_child_pipe[1]) < 0 ||
136 close(from_child_pipe[0]) < 0 ||
137 dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
138 rprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
139 exit_cleanup(RERR_IPC);
140 }
141 if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
142 if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
143 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
144 }
145
146 if (close(from_child_pipe[1]) < 0 ||
147 close(to_child_pipe[0]) < 0) {
148 rprintf(FERROR,"Failed to close : %s\n",strerror(errno));
149 exit_cleanup(RERR_IPC);
150 }
151
152 *f_in = from_child_pipe[0];
153 *f_out = to_child_pipe[1];
154
155 return pid;
156}
157
158
159
160void out_of_memory(char *str)
161{
162 rprintf(FERROR,"ERROR: out of memory in %s\n",str);
163 exit_cleanup(RERR_MALLOC);
164}
165
166void overflow(char *str)
167{
168 rprintf(FERROR,"ERROR: buffer overflow in %s\n",str);
169 exit_cleanup(RERR_MALLOC);
170}
171
172
173
174int set_modtime(char *fname,time_t modtime)
175{
176 extern int dry_run;
177 if (dry_run) return 0;
178 {
179#ifdef HAVE_UTIMBUF
180 struct utimbuf tbuf;
181 tbuf.actime = time(NULL);
182 tbuf.modtime = modtime;
183 return utime(fname,&tbuf);
184#elif defined(HAVE_UTIME)
185 time_t t[2];
186 t[0] = time(NULL);
187 t[1] = modtime;
188 return utime(fname,t);
189#else
190 struct timeval t[2];
191 t[0].tv_sec = time(NULL);
192 t[0].tv_usec = 0;
193 t[1].tv_sec = modtime;
194 t[1].tv_usec = 0;
195 return utimes(fname,t);
196#endif
197 }
198}
199
200
201/****************************************************************************
202create any necessary directories in fname. Unfortunately we don't know
203what perms to give the directory when this is called so we need to rely
204on the umask
205****************************************************************************/
206int create_directory_path(char *fname)
207{
208 extern int orig_umask;
209 char *p;
210
211 while (*fname == '/') fname++;
212 while (strncmp(fname,"./",2)==0) fname += 2;
213
214 p = fname;
215 while ((p=strchr(p,'/'))) {
216 *p = 0;
217 do_mkdir(fname,0777 & ~orig_umask);
218 *p = '/';
219 p++;
220 }
221 return 0;
222}
223
224
225/* Write LEN bytes at PTR to descriptor DESC, retrying if interrupted.
226 Return LEN upon success, write's (negative) error code otherwise.
227
228 derived from GNU C's cccp.c.
229*/
230static int full_write(int desc, char *ptr, int len)
231{
232 int total_written;
233
234 total_written = 0;
235 while (len > 0) {
236 int written = write (desc, ptr, len);
237 if (written < 0) {
238#ifdef EINTR
239 if (errno == EINTR)
240 continue;
241#endif
242 return written;
243 }
244 total_written += written;
245 ptr += written;
246 len -= written;
247 }
248 return total_written;
249}
250
251/* Read LEN bytes at PTR from descriptor DESC, retrying if interrupted.
252 Return the actual number of bytes read, zero for EOF, or negative
253 for an error.
254
255 derived from GNU C's cccp.c. */
256static int safe_read(int desc, char *ptr, int len)
257{
258 int n_chars;
259
260 if (len <= 0)
261 return len;
262
263#ifdef EINTR
264 do {
265 n_chars = read(desc, ptr, len);
266 } while (n_chars < 0 && errno == EINTR);
267#else
268 n_chars = read(desc, ptr, len);
269#endif
270
271 return n_chars;
272}
273
274
275/* copy a file - this is used in conjunction with the --temp-dir option */
276int copy_file(char *source, char *dest, mode_t mode)
277{
278 int ifd;
279 int ofd;
280 char buf[1024 * 8];
281 int len; /* Number of bytes read into `buf'. */
282
283 ifd = open(source, O_RDONLY);
284 if (ifd == -1) {
285 rprintf(FERROR,"open %s: %s\n",
286 source,strerror(errno));
287 return -1;
288 }
289
290 if (do_unlink(dest) && errno != ENOENT) {
291 rprintf(FERROR,"unlink %s: %s\n",
292 dest,strerror(errno));
293 return -1;
294 }
295
296 ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode);
297 if (ofd == -1) {
298 rprintf(FERROR,"open %s: %s\n",
299 dest,strerror(errno));
300 close(ifd);
301 return -1;
302 }
303
304 while ((len = safe_read(ifd, buf, sizeof(buf))) > 0) {
305 if (full_write(ofd, buf, len) < 0) {
306 rprintf(FERROR,"write %s: %s\n",
307 dest,strerror(errno));
308 close(ifd);
309 close(ofd);
310 return -1;
311 }
312 }
313
314 close(ifd);
315 close(ofd);
316
317 if (len < 0) {
318 rprintf(FERROR,"read %s: %s\n",
319 source,strerror(errno));
320 return -1;
321 }
322
323 return 0;
324}
325
326/* sleep for a while via select */
327void u_sleep(int usec)
328{
329 struct timeval tv;
330
331 tv.tv_sec = 0;
332 tv.tv_usec = usec;
333 select(0, NULL, NULL, NULL, &tv);
334}
335
336
337static pid_t all_pids[10];
338static int num_pids;
339
340/* fork and record the pid of the child */
341pid_t do_fork(void)
342{
343 pid_t newpid = fork();
344
345 if (newpid) {
346 all_pids[num_pids++] = newpid;
347 }
348 return newpid;
349}
350
351/* kill all children */
352void kill_all(int sig)
353{
354 int i;
355 for (i=0;i<num_pids;i++) {
356 if (all_pids[i] != getpid())
357 kill(all_pids[i], sig);
358 }
359}
360
361/* like strncpy but does not 0 fill the buffer and always null
362 terminates. bufsize is the size of the destination buffer */
363size_t strlcpy(char *d, const char *s, size_t bufsize)
364{
365 size_t len = strlen(s);
366 size_t ret = len;
367 if (len >= bufsize) len = bufsize-1;
368 memcpy(d, s, len);
369 d[len] = 0;
370 return ret;
371}
372
373/* like strncat but does not 0 fill the buffer and always null
374 terminates. bufsize is the length of the buffer, which should
375 be one more than the maximum resulting string length */
376size_t strlcat(char *d, const char *s, size_t bufsize)
377{
378 size_t len1 = strlen(d);
379 size_t len2 = strlen(s);
380 size_t ret = len1 + len2;
381
382 if (len1+len2 >= bufsize) {
383 len2 = bufsize - (len1+1);
384 }
385 if (len2 > 0) {
386 memcpy(d+len1, s, len2);
387 d[len1+len2] = 0;
388 }
389 return ret;
390}
391
392/* turn a user name into a uid */
393int name_to_uid(char *name, uid_t *uid)
394{
395 struct passwd *pass;
396 if (!name || !*name) return 0;
397 pass = getpwnam(name);
398 if (pass) {
399 *uid = pass->pw_uid;
400 return 1;
401 }
402 return 0;
403}
404
405/* turn a group name into a gid */
406int name_to_gid(char *name, gid_t *gid)
407{
408 struct group *grp;
409 if (!name || !*name) return 0;
410 grp = getgrnam(name);
411 if (grp) {
412 *gid = grp->gr_gid;
413 return 1;
414 }
415 return 0;
416}
417
418
419/* lock a byte range in a open file */
420int lock_range(int fd, int offset, int len)
421{
422 struct flock lock;
423
424 lock.l_type = F_WRLCK;
425 lock.l_whence = SEEK_SET;
426 lock.l_start = offset;
427 lock.l_len = len;
428 lock.l_pid = 0;
429
430 return fcntl(fd,F_SETLK,&lock) == 0;
431}
432
433
434static void glob_expand_one(char *s, char **argv, int *argc, int maxargs)
435{
436#if !(defined(HAVE_GLOB) && defined(HAVE_GLOB_H))
437 if (!*s) s = ".";
438 argv[*argc] = strdup(s);
439 (*argc)++;
440 return;
441#else
442 glob_t globbuf;
443 int i;
444
445 if (!*s) s = ".";
446
447 argv[*argc] = strdup(s);
448
449 memset(&globbuf, 0, sizeof(globbuf));
450 glob(argv[*argc], 0, NULL, &globbuf);
451 if (globbuf.gl_pathc == 0) {
452 (*argc)++;
453 globfree(&globbuf);
454 return;
455 }
456 for (i=0; i<(maxargs - (*argc)) && i<globbuf.gl_pathc;i++) {
457 if (i == 0) free(argv[*argc]);
458 argv[(*argc) + i] = strdup(globbuf.gl_pathv[i]);
459 if (!argv[(*argc) + i]) out_of_memory("glob_expand");
460 }
461 globfree(&globbuf);
462 (*argc) += i;
463#endif
464}
465
466void glob_expand(char *base1, char **argv, int *argc, int maxargs)
467{
468 char *s = argv[*argc];
469 char *p, *q;
470 char *base = base1;
471
472 if (!s || !*s) return;
473
474 if (strncmp(s, base, strlen(base)) == 0) {
475 s += strlen(base);
476 }
477
478 s = strdup(s);
479 if (!s) out_of_memory("glob_expand");
480
481 base = (char *)malloc(strlen(base1)+3);
482 if (!base) out_of_memory("glob_expand");
483
484 sprintf(base," %s/", base1);
485
486 q = s;
487 while ((p = strstr(q,base)) && ((*argc) < maxargs)) {
488 /* split it at this point */
489 *p = 0;
490 glob_expand_one(q, argv, argc, maxargs);
491 q = p+strlen(base);
492 }
493
494 if (*q && (*argc < maxargs)) glob_expand_one(q, argv, argc, maxargs);
495
496 free(s);
497 free(base);
498}
499
500/*******************************************************************
501 convert a string to lower case
502********************************************************************/
503void strlower(char *s)
504{
505 while (*s) {
506 if (isupper(*s)) *s = tolower(*s);
507 s++;
508 }
509}
510
511/* this is like vsnprintf but it always null terminates, so you
512 can fit at most n-1 chars in */
513int vslprintf(char *str, int n, const char *format, va_list ap)
514{
515 int ret = vsnprintf(str, n, format, ap);
516 if (ret >= n || ret < 0) {
517 str[n-1] = 0;
518 return -1;
519 }
520 str[ret] = 0;
521 return ret;
522}
523
524
525/* like snprintf but always null terminates */
526int slprintf(char *str, int n, char *format, ...)
527{
528 va_list ap;
529 int ret;
530
531 va_start(ap, format);
532 ret = vslprintf(str,n,format,ap);
533 va_end(ap);
534 return ret;
535}
536
537
538void *Realloc(void *p, int size)
539{
540 if (!p) return (void *)malloc(size);
541 return (void *)realloc(p, size);
542}
543
544
545void clean_fname(char *name)
546{
547 char *p;
548 int l;
549 int modified = 1;
550
551 if (!name) return;
552
553 while (modified) {
554 modified = 0;
555
556 if ((p=strstr(name,"/./"))) {
557 modified = 1;
558 while (*p) {
559 p[0] = p[2];
560 p++;
561 }
562 }
563
564 if ((p=strstr(name,"//"))) {
565 modified = 1;
566 while (*p) {
567 p[0] = p[1];
568 p++;
569 }
570 }
571
572 if (strncmp(p=name,"./",2) == 0) {
573 modified = 1;
574 do {
575 p[0] = p[2];
576 } while (*p++);
577 }
578
579 l = strlen(p=name);
580 if (l > 1 && p[l-1] == '/') {
581 modified = 1;
582 p[l-1] = 0;
583 }
584 }
585}
586
587/*
588 * Make path appear as if a chroot had occurred:
589 * 1. remove leading "/" (or replace with "." if at end)
590 * 2. remove leading ".." components
591 * 3. delete any other "<dir>/.." (recursively)
592 * While we're at it, remove double slashes and "." components like
593 * clean_fname does(), but DON'T remove a trailing slash because that
594 * is sometimes significant on command line arguments.
595 * Return a malloc'ed copy.
596 * Contributed by Dave Dykstra <dwd@bell-labs.com>
597 */
598
599char *sanitize_path(char *p)
600{
601 char *copy, *copyp;
602
603 copy = (char *) malloc(strlen(p)+1);
604 copyp = copy;
605 while (*p == '/') {
606 /* remove leading slashes */
607 p++;
608 }
609 while (*p != '\0') {
610 /* this loop iterates once per filename component in p.
611 * both p (and copyp if the original had a slash) should
612 * always be left pointing after a slash
613 */
614 if ((*p == '.') && ((*(p+1) == '/') || (*(p+1) == '\0'))) {
615 /* skip "." component */
616 while (*++p == '/') {
617 /* skip following slashes */
618 ;
619 }
620 } else if ((*p == '.') && (*(p+1) == '.') &&
621 ((*(p+2) == '/') || (*(p+2) == '\0'))) {
622 /* skip ".." component followed by slash or end */
623 p += 2;
624 if (*p == '/')
625 p++;
626 if (copyp != copy) {
627 /* back up the copy one level */
628 --copyp; /* now pointing at slash */
629 while ((copyp > copy) && (*(copyp - 1) != '/')) {
630 /* skip back up to slash */
631 copyp--;
632 }
633 }
634 } else {
635 while (1) {
636 /* copy one component through next slash */
637 *copyp++ = *p++;
638 if ((*p == '\0') || (*(p-1) == '/')) {
639 while (*p == '/') {
640 /* skip multiple slashes */
641 p++;
642 }
643 break;
644 }
645 }
646 }
647 }
648 if (copyp == copy) {
649 /* ended up with nothing, so put in "." component */
650 *copyp++ = '.';
651 }
652 *copyp = '\0';
653 return(copy);
654}
655
656
657static char curr_dir[MAXPATHLEN];
658
659/* like chdir() but can be reversed with pop_dir() if save is set. It
660 is also much faster as it remembers where we have been */
661char *push_dir(char *dir, int save)
662{
663 char *ret = curr_dir;
664 static int initialised;
665
666 if (!initialised) {
667 initialised = 1;
668 getcwd(curr_dir, sizeof(curr_dir)-1);
669 }
670
671 if (chdir(dir)) return NULL;
672
673 if (save) {
674 ret = strdup(curr_dir);
675 }
676
677 if (*dir == '/') {
678 strlcpy(curr_dir, dir, sizeof(curr_dir));
679 } else {
680 strlcat(curr_dir,"/", sizeof(curr_dir));
681 strlcat(curr_dir,dir, sizeof(curr_dir));
682 }
683
684 clean_fname(curr_dir);
685
686 return ret;
687}
688
689/* reverse a push_dir call */
690int pop_dir(char *dir)
691{
692 int ret;
693
694 ret = chdir(dir);
695 if (ret) {
696 free(dir);
697 return ret;
698 }
699
700 strlcpy(curr_dir, dir, sizeof(curr_dir));
701
702 free(dir);
703
704 return 0;
705}
706
707/* we need to supply our own strcmp function for file list comparisons
708 to ensure that signed/unsigned usage is consistent between machines. */
709int u_strcmp(const char *cs1, const char *cs2)
710{
711 const uchar *s1 = (uchar *)cs1;
712 const uchar *s2 = (uchar *)cs2;
713
714 while (*s1 && *s2 && (*s1 == *s2)) {
715 s1++; s2++;
716 }
717
718 return (int)*s1 - (int)*s2;
719}
720
721static OFF_T last_ofs;
722
723void end_progress(void)
724{
725 extern int do_progress, am_server;
726
727 if (do_progress && !am_server) {
728 rprintf(FINFO,"\n");
729 }
730 last_ofs = 0;
731}
732
733void show_progress(OFF_T ofs, OFF_T size)
734{
735 extern int do_progress, am_server;
736
737 if (do_progress && !am_server) {
738 if (ofs > last_ofs + 1000) {
739 int pct = (int)((100.0*ofs)/size);
740 rprintf(FINFO,"%.0f (%d%%)\r", (double)ofs, pct);
741 last_ofs = ofs;
742 }
743 }
744}
745
746/* determine if a symlink points outside the current directory tree */
747int unsafe_symlink(char *dest, char *src)
748{
749 char *tok;
750 int depth = 0;
751
752 /* all absolute and null symlinks are unsafe */
753 if (!dest || !(*dest) || (*dest == '/')) return 1;
754
755 src = strdup(src);
756 if (!src) out_of_memory("unsafe_symlink");
757
758 /* find out what our safety margin is */
759 for (tok=strtok(src,"/"); tok; tok=strtok(NULL,"/")) {
760 if (strcmp(tok,"..") == 0) {
761 depth=0;
762 } else if (strcmp(tok,".") == 0) {
763 /* nothing */
764 } else {
765 depth++;
766 }
767 }
768 free(src);
769
770 /* drop by one to account for the filename portion */
771 depth--;
772
773 dest = strdup(dest);
774 if (!dest) out_of_memory("unsafe_symlink");
775
776 for (tok=strtok(dest,"/"); tok; tok=strtok(NULL,"/")) {
777 if (strcmp(tok,"..") == 0) {
778 depth--;
779 } else if (strcmp(tok,".") == 0) {
780 /* nothing */
781 } else {
782 depth++;
783 }
784 /* if at any point we go outside the current directory then
785 stop - it is unsafe */
786 if (depth < 0) break;
787 }
788
789 free(dest);
790 return (depth < 0);
791}
792
793
794/****************************************************************************
795 return the date and time as a string
796****************************************************************************/
797char *timestring(time_t t)
798{
799 static char TimeBuf[200];
800 struct tm *tm = localtime(&t);
801
802#ifdef HAVE_STRFTIME
803 strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %T",tm);
804#else
805 strlcpy(TimeBuf, asctime(tm), sizeof(TimeBuf));
806#endif
807
808 if (TimeBuf[strlen(TimeBuf)-1] == '\n') {
809 TimeBuf[strlen(TimeBuf)-1] = 0;
810 }
811
812 return(TimeBuf);
813}
814