Check for EINVAL from a rename error call in addition to ENOENT because
[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/* turn a user name into a uid */
362int name_to_uid(char *name, uid_t *uid)
363{
364 struct passwd *pass;
365 if (!name || !*name) return 0;
366 pass = getpwnam(name);
367 if (pass) {
368 *uid = pass->pw_uid;
369 return 1;
370 }
371 return 0;
372}
373
374/* turn a group name into a gid */
375int name_to_gid(char *name, gid_t *gid)
376{
377 struct group *grp;
378 if (!name || !*name) return 0;
379 grp = getgrnam(name);
380 if (grp) {
381 *gid = grp->gr_gid;
382 return 1;
383 }
384 return 0;
385}
386
387
388/* lock a byte range in a open file */
389int lock_range(int fd, int offset, int len)
390{
391 struct flock lock;
392
393 lock.l_type = F_WRLCK;
394 lock.l_whence = SEEK_SET;
395 lock.l_start = offset;
396 lock.l_len = len;
397 lock.l_pid = 0;
398
399 return fcntl(fd,F_SETLK,&lock) == 0;
400}
401
402
403static void glob_expand_one(char *s, char **argv, int *argc, int maxargs, int sanitize_paths)
404{
405#if !(defined(HAVE_GLOB) && defined(HAVE_GLOB_H))
406 if (!*s) s = ".";
407 argv[*argc] = strdup(s);
408 (*argc)++;
409 return;
410#else
411 glob_t globbuf;
412 int i;
413
414 if (!*s) s = ".";
415
416 s = strdup(s);
417 sanitize_path(s);
418 argv[*argc] = s;
419
420 memset(&globbuf, 0, sizeof(globbuf));
421 glob(argv[*argc], 0, NULL, &globbuf);
422 if (globbuf.gl_pathc == 0) {
423 (*argc)++;
424 globfree(&globbuf);
425 return;
426 }
427 for (i=0; i<(maxargs - (*argc)) && i<globbuf.gl_pathc;i++) {
428 if (i == 0) free(argv[*argc]);
429 argv[(*argc) + i] = strdup(globbuf.gl_pathv[i]);
430 if (!argv[(*argc) + i]) out_of_memory("glob_expand");
431 }
432 globfree(&globbuf);
433 (*argc) += i;
434#endif
435}
436
437void glob_expand(char *base1, char **argv, int *argc, int maxargs, int sanitize_paths)
438{
439 char *s = argv[*argc];
440 char *p, *q;
441 char *base = base1;
442
443 if (!s || !*s) return;
444
445 if (strncmp(s, base, strlen(base)) == 0) {
446 s += strlen(base);
447 }
448
449 s = strdup(s);
450 if (!s) out_of_memory("glob_expand");
451
452 base = (char *)malloc(strlen(base1)+3);
453 if (!base) out_of_memory("glob_expand");
454
455 sprintf(base," %s/", base1);
456
457 q = s;
458 while ((p = strstr(q,base)) && ((*argc) < maxargs)) {
459 /* split it at this point */
460 *p = 0;
461 glob_expand_one(q, argv, argc, maxargs, sanitize_paths);
462 q = p+strlen(base);
463 }
464
465 if (*q && (*argc < maxargs)) glob_expand_one(q, argv, argc, maxargs, sanitize_paths);
466
467 free(s);
468 free(base);
469}
470
471/*******************************************************************
472 convert a string to lower case
473********************************************************************/
474void strlower(char *s)
475{
476 while (*s) {
477 if (isupper(*s)) *s = tolower(*s);
478 s++;
479 }
480}
481
482/* this is like vsnprintf but it always null terminates, so you
483 can fit at most n-1 chars in */
484int vslprintf(char *str, int n, const char *format, va_list ap)
485{
486 int ret = vsnprintf(str, n, format, ap);
487 if (ret >= n || ret < 0) {
488 str[n-1] = 0;
489 return -1;
490 }
491 str[ret] = 0;
492 return ret;
493}
494
495
496/* like snprintf but always null terminates */
497int slprintf(char *str, int n, char *format, ...)
498{
499 va_list ap;
500 int ret;
501
502 va_start(ap, format);
503 ret = vslprintf(str,n,format,ap);
504 va_end(ap);
505 return ret;
506}
507
508
509void *Realloc(void *p, int size)
510{
511 if (!p) return (void *)malloc(size);
512 return (void *)realloc(p, size);
513}
514
515
516void clean_fname(char *name)
517{
518 char *p;
519 int l;
520 int modified = 1;
521
522 if (!name) return;
523
524 while (modified) {
525 modified = 0;
526
527 if ((p=strstr(name,"/./"))) {
528 modified = 1;
529 while (*p) {
530 p[0] = p[2];
531 p++;
532 }
533 }
534
535 if ((p=strstr(name,"//"))) {
536 modified = 1;
537 while (*p) {
538 p[0] = p[1];
539 p++;
540 }
541 }
542
543 if (strncmp(p=name,"./",2) == 0) {
544 modified = 1;
545 do {
546 p[0] = p[2];
547 } while (*p++);
548 }
549
550 l = strlen(p=name);
551 if (l > 1 && p[l-1] == '/') {
552 modified = 1;
553 p[l-1] = 0;
554 }
555 }
556}
557
558/*
559 * Make path appear as if a chroot had occurred:
560 * 1. remove leading "/" (or replace with "." if at end)
561 * 2. remove leading ".." components
562 * 3. delete any other "<dir>/.." (recursively)
563 * While we're at it, remove double slashes and "." components like
564 * clean_fname does(), but DON'T remove a trailing slash because that
565 * is sometimes significant on command line arguments.
566 * Can only shrink paths, so sanitizes in place.
567 * Contributed by Dave Dykstra <dwd@bell-labs.com>
568 */
569
570void sanitize_path(char *p)
571{
572 char *start, *sanp;
573
574 start = p;
575 sanp = p;
576 while (*p == '/') {
577 /* remove leading slashes */
578 p++;
579 }
580 while (*p != '\0') {
581 /* this loop iterates once per filename component in p.
582 * both p (and sanp if the original had a slash) should
583 * always be left pointing after a slash
584 */
585 if ((*p == '.') && ((*(p+1) == '/') || (*(p+1) == '\0'))) {
586 /* skip "." component */
587 while (*++p == '/') {
588 /* skip following slashes */
589 ;
590 }
591 } else if ((*p == '.') && (*(p+1) == '.') &&
592 ((*(p+2) == '/') || (*(p+2) == '\0'))) {
593 /* skip ".." component followed by slash or end */
594 p += 2;
595 if (*p == '/')
596 p++;
597 if (sanp != start) {
598 /* back up sanp one level */
599 --sanp; /* now pointing at slash */
600 while ((sanp > start) && (*(sanp - 1) != '/')) {
601 /* skip back up to slash */
602 sanp--;
603 }
604 }
605 } else {
606 while (1) {
607 /* copy one component through next slash */
608 *sanp++ = *p++;
609 if ((*p == '\0') || (*(p-1) == '/')) {
610 while (*p == '/') {
611 /* skip multiple slashes */
612 p++;
613 }
614 break;
615 }
616 }
617 }
618 }
619 if (sanp == start) {
620 /* ended up with nothing, so put in "." component */
621 *sanp++ = '.';
622 }
623 *sanp = '\0';
624}
625
626
627static char curr_dir[MAXPATHLEN];
628
629/* like chdir() but can be reversed with pop_dir() if save is set. It
630 is also much faster as it remembers where we have been */
631char *push_dir(char *dir, int save)
632{
633 char *ret = curr_dir;
634 static int initialised;
635
636 if (!initialised) {
637 initialised = 1;
638 getcwd(curr_dir, sizeof(curr_dir)-1);
639 }
640
641 if (!dir) return NULL; /* this call was probably just to initialize */
642
643 if (chdir(dir)) return NULL;
644
645 if (save) {
646 ret = strdup(curr_dir);
647 }
648
649 if (*dir == '/') {
650 strlcpy(curr_dir, dir, sizeof(curr_dir));
651 } else {
652 strlcat(curr_dir,"/", sizeof(curr_dir));
653 strlcat(curr_dir,dir, sizeof(curr_dir));
654 }
655
656 clean_fname(curr_dir);
657
658 return ret;
659}
660
661/* reverse a push_dir call */
662int pop_dir(char *dir)
663{
664 int ret;
665
666 ret = chdir(dir);
667 if (ret) {
668 free(dir);
669 return ret;
670 }
671
672 strlcpy(curr_dir, dir, sizeof(curr_dir));
673
674 free(dir);
675
676 return 0;
677}
678
679/* we need to supply our own strcmp function for file list comparisons
680 to ensure that signed/unsigned usage is consistent between machines. */
681int u_strcmp(const char *cs1, const char *cs2)
682{
683 const uchar *s1 = (const uchar *)cs1;
684 const uchar *s2 = (const uchar *)cs2;
685
686 while (*s1 && *s2 && (*s1 == *s2)) {
687 s1++; s2++;
688 }
689
690 return (int)*s1 - (int)*s2;
691}
692
693static OFF_T last_ofs;
694
695void end_progress(void)
696{
697 extern int do_progress, am_server;
698
699 if (do_progress && !am_server) {
700 rprintf(FINFO,"\n");
701 }
702 last_ofs = 0;
703}
704
705void show_progress(OFF_T ofs, OFF_T size)
706{
707 extern int do_progress, am_server;
708
709 if (do_progress && !am_server) {
710 if (ofs > last_ofs + 1000) {
711 int pct = (int)((100.0*ofs)/size);
712 rprintf(FINFO,"%.0f (%d%%)\r", (double)ofs, pct);
713 last_ofs = ofs;
714 }
715 }
716}
717
718/* determine if a symlink points outside the current directory tree */
719int unsafe_symlink(char *dest, char *src)
720{
721 char *tok;
722 int depth = 0;
723
724 /* all absolute and null symlinks are unsafe */
725 if (!dest || !(*dest) || (*dest == '/')) return 1;
726
727 src = strdup(src);
728 if (!src) out_of_memory("unsafe_symlink");
729
730 /* find out what our safety margin is */
731 for (tok=strtok(src,"/"); tok; tok=strtok(NULL,"/")) {
732 if (strcmp(tok,"..") == 0) {
733 depth=0;
734 } else if (strcmp(tok,".") == 0) {
735 /* nothing */
736 } else {
737 depth++;
738 }
739 }
740 free(src);
741
742 /* drop by one to account for the filename portion */
743 depth--;
744
745 dest = strdup(dest);
746 if (!dest) out_of_memory("unsafe_symlink");
747
748 for (tok=strtok(dest,"/"); tok; tok=strtok(NULL,"/")) {
749 if (strcmp(tok,"..") == 0) {
750 depth--;
751 } else if (strcmp(tok,".") == 0) {
752 /* nothing */
753 } else {
754 depth++;
755 }
756 /* if at any point we go outside the current directory then
757 stop - it is unsafe */
758 if (depth < 0) break;
759 }
760
761 free(dest);
762 return (depth < 0);
763}
764
765
766/****************************************************************************
767 return the date and time as a string
768****************************************************************************/
769char *timestring(time_t t)
770{
771 static char TimeBuf[200];
772 struct tm *tm = localtime(&t);
773
774#ifdef HAVE_STRFTIME
775 strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %T",tm);
776#else
777 strlcpy(TimeBuf, asctime(tm), sizeof(TimeBuf));
778#endif
779
780 if (TimeBuf[strlen(TimeBuf)-1] == '\n') {
781 TimeBuf[strlen(TimeBuf)-1] = 0;
782 }
783
784 return(TimeBuf);
785}
786