Progress indicator now shows estimated rate of transfer (e.g. kB/s).
[rsync.git] / util.c
1 /*  -*- c-file-style: "linux" -*-
2     
3     Copyright (C) 1996-2000 by Andrew Tridgell 
4     Copyright (C) Paul Mackerras 1996
5     Copyright (C) 2001 by Martin Pool <mbp@samba.org>
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 /*
23   Utilities used in rsync 
24
25   tridge, June 1996
26   */
27 #include "rsync.h"
28
29 extern int verbose;
30
31
32 /****************************************************************************
33 Set a fd into nonblocking mode
34 ****************************************************************************/
35 void set_nonblocking(int fd)
36 {
37         int val;
38
39         if((val = fcntl(fd, F_GETFL, 0)) == -1)
40                 return;
41         if (!(val & NONBLOCK_FLAG)) {
42                 val |= NONBLOCK_FLAG;
43                 fcntl(fd, F_SETFL, val);
44         }
45 }
46
47 /****************************************************************************
48 Set a fd into blocking mode
49 ****************************************************************************/
50 void set_blocking(int fd)
51 {
52         int val;
53
54         if((val = fcntl(fd, F_GETFL, 0)) == -1)
55                 return;
56         if (val & NONBLOCK_FLAG) {
57                 val &= ~NONBLOCK_FLAG;
58                 fcntl(fd, F_SETFL, val);
59         }
60 }
61
62
63 /* create a file descriptor pair - like pipe() but use socketpair if
64    possible (because of blocking issues on pipes)
65
66    always set non-blocking
67  */
68 int fd_pair(int fd[2])
69 {
70         int ret;
71
72 #if HAVE_SOCKETPAIR
73         ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd);
74 #else
75         ret = pipe(fd);
76 #endif
77
78         if (ret == 0) {
79                 set_nonblocking(fd[0]);
80                 set_nonblocking(fd[1]);
81         }
82         
83         return ret;
84 }
85
86
87 /* this is derived from CVS code 
88
89    note that in the child STDIN is set to blocking and STDOUT
90    is set to non-blocking. This is necessary as rsh relies on stdin being blocking
91    and ssh relies on stdout being non-blocking
92
93    if blocking_io is set then use blocking io on both fds. That can be
94    used to cope with badly broken rsh implementations like the one on
95    solaris.
96  */
97 pid_t piped_child(char **command,int *f_in,int *f_out)
98 {
99   pid_t pid;
100   int to_child_pipe[2];
101   int from_child_pipe[2];
102   extern int blocking_io;
103
104   if (fd_pair(to_child_pipe) < 0 ||
105       fd_pair(from_child_pipe) < 0) {
106     rprintf(FERROR,"pipe: %s\n",strerror(errno));
107     exit_cleanup(RERR_IPC);
108   }
109
110
111   pid = do_fork();
112   if (pid == -1) {
113     rprintf(FERROR,"fork: %s\n",strerror(errno));
114     exit_cleanup(RERR_IPC);
115   }
116
117   if (pid == 0)
118     {
119       extern int orig_umask;
120       if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
121           close(to_child_pipe[1]) < 0 ||
122           close(from_child_pipe[0]) < 0 ||
123           dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
124         rprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
125         exit_cleanup(RERR_IPC);
126       }
127       if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
128       if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
129       umask(orig_umask);
130       set_blocking(STDIN_FILENO);
131       if (blocking_io) {
132         set_blocking(STDOUT_FILENO);
133       }
134       execvp(command[0], command);
135       rprintf(FERROR,"Failed to exec %s : %s\n",
136               command[0],strerror(errno));
137       exit_cleanup(RERR_IPC);
138     }
139
140   if (close(from_child_pipe[1]) < 0 ||
141       close(to_child_pipe[0]) < 0) {
142     rprintf(FERROR,"Failed to close : %s\n",strerror(errno));   
143     exit_cleanup(RERR_IPC);
144   }
145
146   *f_in = from_child_pipe[0];
147   *f_out = to_child_pipe[1];
148
149   return pid;
150 }
151
152 pid_t local_child(int argc, char **argv,int *f_in,int *f_out)
153 {
154         pid_t pid;
155         int to_child_pipe[2];
156         int from_child_pipe[2];
157         extern int read_batch;  /* dw */
158
159         if (fd_pair(to_child_pipe) < 0 ||
160             fd_pair(from_child_pipe) < 0) {
161                 rprintf(FERROR,"pipe: %s\n",strerror(errno));
162                 exit_cleanup(RERR_IPC);
163         }
164
165
166         pid = do_fork();
167         if (pid == -1) {
168                 rprintf(FERROR,"fork: %s\n",strerror(errno));
169                 exit_cleanup(RERR_IPC);
170         }
171
172         if (pid == 0) {
173                 extern int am_sender;
174                 extern int am_server;
175
176                 if (read_batch)
177                     am_sender = 0;
178                 else
179                     am_sender = !am_sender;
180                 am_server = 1;          
181
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(RERR_IPC);
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                 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
192         }
193
194         if (close(from_child_pipe[1]) < 0 ||
195             close(to_child_pipe[0]) < 0) {
196                 rprintf(FERROR,"Failed to close : %s\n",strerror(errno));   
197                 exit_cleanup(RERR_IPC);
198         }
199
200         *f_in = from_child_pipe[0];
201         *f_out = to_child_pipe[1];
202   
203         return pid;
204 }
205
206
207
208 void out_of_memory(char *str)
209 {
210   rprintf(FERROR,"ERROR: out of memory in %s\n",str);
211   exit_cleanup(RERR_MALLOC);
212 }
213
214 void overflow(char *str)
215 {
216   rprintf(FERROR,"ERROR: buffer overflow in %s\n",str);
217   exit_cleanup(RERR_MALLOC);
218 }
219
220
221
222 int set_modtime(char *fname,time_t modtime)
223 {
224         extern int dry_run;
225         if (dry_run) return 0;
226         {
227 #ifdef HAVE_UTIMBUF
228                 struct utimbuf tbuf;  
229                 tbuf.actime = time(NULL);
230                 tbuf.modtime = modtime;
231                 return utime(fname,&tbuf);
232 #elif defined(HAVE_UTIME)
233                 time_t t[2];
234                 t[0] = time(NULL);
235                 t[1] = modtime;
236                 return utime(fname,t);
237 #else
238                 struct timeval t[2];
239                 t[0].tv_sec = time(NULL);
240                 t[0].tv_usec = 0;
241                 t[1].tv_sec = modtime;
242                 t[1].tv_usec = 0;
243                 return utimes(fname,t);
244 #endif
245         }
246 }
247
248
249 /****************************************************************************
250 create any necessary directories in fname. Unfortunately we don't know
251 what perms to give the directory when this is called so we need to rely
252 on the umask
253 ****************************************************************************/
254 int create_directory_path(char *fname)
255 {
256         extern int orig_umask;
257         char *p;
258
259         while (*fname == '/') fname++;
260         while (strncmp(fname,"./",2)==0) fname += 2;
261
262         p = fname;
263         while ((p=strchr(p,'/'))) {
264                 *p = 0;
265                 do_mkdir(fname,0777 & ~orig_umask); 
266                 *p = '/';
267                 p++;
268         }
269         return 0;
270 }
271
272
273 /* Write LEN bytes at PTR to descriptor DESC, retrying if interrupted.
274    Return LEN upon success, write's (negative) error code otherwise.  
275
276    derived from GNU C's cccp.c.
277 */
278 static int full_write(int desc, char *ptr, int len)
279 {
280         int total_written;
281         
282         total_written = 0;
283         while (len > 0) {
284                 int written = write (desc, ptr, len);
285                 if (written < 0)  {
286 #ifdef EINTR
287                         if (errno == EINTR)
288                                 continue;
289 #endif
290                         return written;
291                 }
292                 total_written += written;
293                 ptr += written;
294                 len -= written;
295         }
296         return total_written;
297 }
298
299 /* Read LEN bytes at PTR from descriptor DESC, retrying if interrupted.
300    Return the actual number of bytes read, zero for EOF, or negative
301    for an error.  
302
303    derived from GNU C's cccp.c. */
304 static int safe_read(int desc, char *ptr, int len)
305 {
306         int n_chars;
307  
308         if (len <= 0)
309                 return len;
310  
311 #ifdef EINTR
312         do {
313                 n_chars = read(desc, ptr, len);
314         } while (n_chars < 0 && errno == EINTR);
315 #else
316         n_chars = read(desc, ptr, len);
317 #endif
318  
319         return n_chars;
320 }
321
322
323 /* copy a file - this is used in conjunction with the --temp-dir option */
324 int copy_file(char *source, char *dest, mode_t mode)
325 {
326         int ifd;
327         int ofd;
328         char buf[1024 * 8];
329         int len;   /* Number of bytes read into `buf'. */
330
331         ifd = do_open(source, O_RDONLY, 0);
332         if (ifd == -1) {
333                 rprintf(FERROR,"open %s: %s\n",
334                         source,strerror(errno));
335                 return -1;
336         }
337
338         if (robust_unlink(dest) && errno != ENOENT) {
339                 rprintf(FERROR,"unlink %s: %s\n",
340                         dest,strerror(errno));
341                 return -1;
342         }
343
344         ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode);
345         if (ofd == -1) {
346                 rprintf(FERROR,"open %s: %s\n",
347                         dest,strerror(errno));
348                 close(ifd);
349                 return -1;
350         }
351
352         while ((len = safe_read(ifd, buf, sizeof(buf))) > 0) {
353                 if (full_write(ofd, buf, len) < 0) {
354                         rprintf(FERROR,"write %s: %s\n",
355                                 dest,strerror(errno));
356                         close(ifd);
357                         close(ofd);
358                         return -1;
359                 }
360         }
361
362         close(ifd);
363         close(ofd);
364
365         if (len < 0) {
366                 rprintf(FERROR,"read %s: %s\n",
367                         source,strerror(errno));
368                 return -1;
369         }
370
371         return 0;
372 }
373
374 /*
375   Robust unlink: some OS'es (HPUX) refuse to unlink busy files, so
376   rename to <path>/.rsyncNNN instead. Note that successive rsync runs
377   will shuffle the filenames around a bit as long as the file is still
378   busy; this is because this function does not know if the unlink call
379   is due to a new file coming in, or --delete trying to remove old
380   .rsyncNNN files, hence it renames it each time.
381 */
382 /* MAX_RENAMES should be 10**MAX_RENAMES_DIGITS */
383 #define MAX_RENAMES_DIGITS 3
384 #define MAX_RENAMES 1000
385
386 int robust_unlink(char *fname)
387 {
388 #ifndef ETXTBSY
389         return do_unlink(fname);
390 #else
391         static int counter = 1;
392         int rc, pos, start;
393         char path[MAXPATHLEN];
394
395         rc = do_unlink(fname);
396         if ((rc == 0) || (errno != ETXTBSY))
397                 return rc;
398
399         strlcpy(path, fname, MAXPATHLEN);
400
401         pos = strlen(path);
402         while((path[--pos] != '/') && (pos >= 0))
403                 ;
404         ++pos;
405         strlcpy(&path[pos], ".rsync", MAXPATHLEN-pos);
406         pos += sizeof(".rsync")-1;
407
408         if (pos > (MAXPATHLEN-MAX_RENAMES_DIGITS-1)) {
409                 errno = ETXTBSY;
410                 return -1;
411         }
412
413         /* start where the last one left off to reduce chance of clashes */
414         start = counter;
415         do {
416                 sprintf(&path[pos], "%03d", counter);
417                 if (++counter >= MAX_RENAMES)
418                         counter = 1;
419         } while (((rc = access(path, 0)) == 0) && (counter != start));
420
421         if (verbose > 0)
422                 rprintf(FINFO,"renaming %s to %s because of text busy\n",
423                                             fname, path);
424
425         /* maybe we should return rename()'s exit status? Nah. */
426         if (do_rename(fname, path) != 0) {
427                 errno = ETXTBSY;
428                 return -1;
429         }
430         return 0;
431 #endif
432 }
433
434 int robust_rename(char *from, char *to)
435 {
436 #ifndef ETXTBSY
437         return do_rename(from, to);
438 #else
439         int rc = do_rename(from, to);
440         if ((rc == 0) || (errno != ETXTBSY))
441                 return rc;
442         if (robust_unlink(to) != 0)
443                 return -1;
444         return do_rename(from, to);
445 #endif
446 }
447
448
449 static pid_t all_pids[10];
450 static int num_pids;
451
452 /* fork and record the pid of the child */
453 pid_t do_fork(void)
454 {
455         pid_t newpid = fork();
456         
457         if (newpid) {
458                 all_pids[num_pids++] = newpid;
459         }
460         return newpid;
461 }
462
463 /* kill all children */
464 void kill_all(int sig)
465 {
466         int i;
467         for (i=0;i<num_pids;i++) {
468                 if (all_pids[i] != getpid())
469                         kill(all_pids[i], sig);
470         }
471 }
472
473 /* turn a user name into a uid */
474 int name_to_uid(char *name, uid_t *uid)
475 {
476         struct passwd *pass;
477         if (!name || !*name) return 0;
478         pass = getpwnam(name);
479         if (pass) {
480                 *uid = pass->pw_uid;
481                 return 1;
482         }
483         return 0;
484 }
485
486 /* turn a group name into a gid */
487 int name_to_gid(char *name, gid_t *gid)
488 {
489         struct group *grp;
490         if (!name || !*name) return 0;
491         grp = getgrnam(name);
492         if (grp) {
493                 *gid = grp->gr_gid;
494                 return 1;
495         }
496         return 0;
497 }
498
499
500 /* lock a byte range in a open file */
501 int lock_range(int fd, int offset, int len)
502 {
503         struct flock lock;
504
505         lock.l_type = F_WRLCK;
506         lock.l_whence = SEEK_SET;
507         lock.l_start = offset;
508         lock.l_len = len;
509         lock.l_pid = 0;
510         
511         return fcntl(fd,F_SETLK,&lock) == 0;
512 }
513
514
515 static void glob_expand_one(char *s, char **argv, int *argc, int maxargs)
516 {
517 #if !(defined(HAVE_GLOB) && defined(HAVE_GLOB_H))
518         if (!*s) s = ".";
519         argv[*argc] = strdup(s);
520         (*argc)++;
521         return;
522 #else
523         extern int sanitize_paths;
524         glob_t globbuf;
525         int i;
526
527         if (!*s) s = ".";
528
529         argv[*argc] = strdup(s);
530         if (sanitize_paths) {
531                 sanitize_path(argv[*argc], NULL);
532         }
533
534         memset(&globbuf, 0, sizeof(globbuf));
535         glob(argv[*argc], 0, NULL, &globbuf);
536         if (globbuf.gl_pathc == 0) {
537                 (*argc)++;
538                 globfree(&globbuf);
539                 return;
540         }
541         for (i=0; i<(maxargs - (*argc)) && i<globbuf.gl_pathc;i++) {
542                 if (i == 0) free(argv[*argc]);
543                 argv[(*argc) + i] = strdup(globbuf.gl_pathv[i]);
544                 if (!argv[(*argc) + i]) out_of_memory("glob_expand");
545         }
546         globfree(&globbuf);
547         (*argc) += i;
548 #endif
549 }
550
551 void glob_expand(char *base1, char **argv, int *argc, int maxargs)
552 {
553         char *s = argv[*argc];
554         char *p, *q;
555         char *base = base1;
556
557         if (!s || !*s) return;
558
559         if (strncmp(s, base, strlen(base)) == 0) {
560                 s += strlen(base);
561         }
562
563         s = strdup(s);
564         if (!s) out_of_memory("glob_expand");
565
566         if (asprintf(&base," %s/", base1) <= 0) out_of_memory("glob_expand");
567
568         q = s;
569         while ((p = strstr(q,base)) && ((*argc) < maxargs)) {
570                 /* split it at this point */
571                 *p = 0;
572                 glob_expand_one(q, argv, argc, maxargs);
573                 q = p+strlen(base);
574         }
575
576         if (*q && (*argc < maxargs)) glob_expand_one(q, argv, argc, maxargs);
577
578         free(s);
579         free(base);
580 }
581
582 /*******************************************************************
583   convert a string to lower case
584 ********************************************************************/
585 void strlower(char *s)
586 {
587         while (*s) {
588                 if (isupper(*s)) *s = tolower(*s);
589                 s++;
590         }
591 }
592
593 void *Realloc(void *p, int size)
594 {
595         if (!p) return (void *)malloc(size);
596         return (void *)realloc(p, size);
597 }
598
599
600 void clean_fname(char *name)
601 {
602         char *p;
603         int l;
604         int modified = 1;
605
606         if (!name) return;
607
608         while (modified) {
609                 modified = 0;
610
611                 if ((p=strstr(name,"/./"))) {
612                         modified = 1;
613                         while (*p) {
614                                 p[0] = p[2];
615                                 p++;
616                         }
617                 }
618
619                 if ((p=strstr(name,"//"))) {
620                         modified = 1;
621                         while (*p) {
622                                 p[0] = p[1];
623                                 p++;
624                         }
625                 }
626
627                 if (strncmp(p=name,"./",2) == 0) {      
628                         modified = 1;
629                         do {
630                                 p[0] = p[2];
631                         } while (*p++);
632                 }
633
634                 l = strlen(p=name);
635                 if (l > 1 && p[l-1] == '/') {
636                         modified = 1;
637                         p[l-1] = 0;
638                 }
639         }
640 }
641
642 /*
643  * Make path appear as if a chroot had occurred:
644  *    1. remove leading "/" (or replace with "." if at end)
645  *    2. remove leading ".." components (except those allowed by "reldir")
646  *    3. delete any other "<dir>/.." (recursively)
647  * Can only shrink paths, so sanitizes in place.
648  * While we're at it, remove double slashes and "." components like
649  *   clean_fname does(), but DON'T remove a trailing slash because that
650  *   is sometimes significant on command line arguments.
651  * If "reldir" is non-null, it is a sanitized directory that the path will be
652  *    relative to, so allow as many ".." at the beginning of the path as
653  *    there are components in reldir.  This is used for symbolic link targets.
654  *    If reldir is non-null and the path began with "/", to be completely like
655  *    a chroot we should add in depth levels of ".." at the beginning of the
656  *    path, but that would blow the assumption that the path doesn't grow and
657  *    it is not likely to end up being a valid symlink anyway, so just do
658  *    the normal removal of the leading "/" instead.
659  * Contributed by Dave Dykstra <dwd@bell-labs.com>
660  */
661
662 void sanitize_path(char *p, char *reldir)
663 {
664         char *start, *sanp;
665         int depth = 0;
666         int allowdotdot = 0;
667
668         if (reldir) {
669                 depth++;
670                 while (*reldir) {
671                         if (*reldir++ == '/') {
672                                 depth++;
673                         }
674                 }
675         }
676         start = p;
677         sanp = p;
678         while (*p == '/') {
679                 /* remove leading slashes */
680                 p++;
681         }
682         while (*p != '\0') {
683                 /* this loop iterates once per filename component in p.
684                  * both p (and sanp if the original had a slash) should
685                  * always be left pointing after a slash
686                  */
687                 if ((*p == '.') && ((*(p+1) == '/') || (*(p+1) == '\0'))) {
688                         /* skip "." component */
689                         while (*++p == '/') {
690                                 /* skip following slashes */
691                                 ;
692                         }
693                         continue;
694                 }
695                 allowdotdot = 0;
696                 if ((*p == '.') && (*(p+1) == '.') &&
697                             ((*(p+2) == '/') || (*(p+2) == '\0'))) {
698                         /* ".." component followed by slash or end */
699                         if ((depth > 0) && (sanp == start)) {
700                                 /* allow depth levels of .. at the beginning */
701                                 --depth;
702                                 allowdotdot = 1;
703                         } else {
704                                 p += 2;
705                                 if (*p == '/')
706                                         p++;
707                                 if (sanp != start) {
708                                         /* back up sanp one level */
709                                         --sanp; /* now pointing at slash */
710                                         while ((sanp > start) && (*(sanp - 1) != '/')) {
711                                                 /* skip back up to slash */
712                                                 sanp--;
713                                         }
714                                 }
715                                 continue;
716                         }
717                 }
718                 while (1) {
719                         /* copy one component through next slash */
720                         *sanp++ = *p++;
721                         if ((*p == '\0') || (*(p-1) == '/')) {
722                                 while (*p == '/') {
723                                         /* skip multiple slashes */
724                                         p++;
725                                 }
726                                 break;
727                         }
728                 }
729                 if (allowdotdot) {
730                         /* move the virtual beginning to leave the .. alone */
731                         start = sanp;
732                 }
733         }
734         if ((sanp == start) && !allowdotdot) {
735                 /* ended up with nothing, so put in "." component */
736                 /*
737                  * note that the !allowdotdot doesn't prevent this from
738                  *  happening in all allowed ".." situations, but I didn't
739                  *  think it was worth putting in an extra variable to ensure
740                  *  it since an extra "." won't hurt in those situations.
741                  */
742                 *sanp++ = '.';
743         }
744         *sanp = '\0';
745 }
746
747
748 static char curr_dir[MAXPATHLEN];
749
750 /* like chdir() but can be reversed with pop_dir() if save is set. It
751    is also much faster as it remembers where we have been */
752 char *push_dir(char *dir, int save)
753 {
754         char *ret = curr_dir;
755         static int initialised;
756
757         if (!initialised) {
758                 initialised = 1;
759                 getcwd(curr_dir, sizeof(curr_dir)-1);
760         }
761
762         if (!dir) return NULL; /* this call was probably just to initialize */
763
764         if (chdir(dir)) return NULL;
765
766         if (save) {
767                 ret = strdup(curr_dir);
768         }
769
770         if (*dir == '/') {
771                 strlcpy(curr_dir, dir, sizeof(curr_dir));
772         } else {
773                 strlcat(curr_dir,"/", sizeof(curr_dir));
774                 strlcat(curr_dir,dir, sizeof(curr_dir));
775         }
776
777         clean_fname(curr_dir);
778
779         return ret;
780 }
781
782 /* reverse a push_dir call */
783 int pop_dir(char *dir)
784 {
785         int ret;
786
787         ret = chdir(dir);
788         if (ret) {
789                 free(dir);
790                 return ret;
791         }
792
793         strlcpy(curr_dir, dir, sizeof(curr_dir));
794
795         free(dir);
796
797         return 0;
798 }
799
800 /* we need to supply our own strcmp function for file list comparisons
801    to ensure that signed/unsigned usage is consistent between machines. */
802 int u_strcmp(const char *cs1, const char *cs2)
803 {
804         const uchar *s1 = (const uchar *)cs1;
805         const uchar *s2 = (const uchar *)cs2;
806
807         while (*s1 && *s2 && (*s1 == *s2)) {
808                 s1++; s2++;
809         }
810         
811         return (int)*s1 - (int)*s2;
812 }
813
814 static OFF_T  last_ofs;
815 static struct timeval print_time;
816 static struct timeval start_time;
817 static OFF_T  start_ofs;
818
819 static unsigned long msdiff(struct timeval *t1, struct timeval *t2)
820 {
821     return (t2->tv_sec - t1->tv_sec) * 1000
822         + (t2->tv_usec - t1->tv_usec) / 1000;
823 }
824
825
826 /**
827  * @param is_last True if this is the last time progress will be
828  * printed for this file, so we should output a newline.  (Not
829  * necessarily the same as all bytes being received.)
830  **/
831 static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
832                             int is_last)
833 {
834     int           pct  = (int)((100.0*ofs)/size);
835     unsigned long diff = msdiff(&start_time, now);
836     double        rate = diff ? ((ofs-start_ofs) / diff) * 1000.0/1024.0 : 0;
837     const char    *units;
838
839     if (ofs == size) pct = 100;
840     
841     if (rate > 1024*1024) {
842             rate /= 1024.0 * 1024.0;
843             units = "GB/s";
844     } else if (rate > 1024) {
845             rate /= 1024.0;
846             units = "MB/s";
847     } else {
848             units = "kB/s";
849     }
850     
851     rprintf(FINFO, "%12.0f %3d%% %7.2f%s%s",
852             (double) ofs, pct, rate, units,
853             is_last ? "\n" : "\r");
854 }
855
856 void end_progress(OFF_T size)
857 {
858         extern int do_progress, am_server;
859
860         if (do_progress && !am_server) {
861                 struct timeval now;
862                 gettimeofday(&now, NULL);
863                 rprint_progress(size, size, &now, True);
864         }
865         last_ofs   = 0;
866         start_ofs  = 0;
867         print_time.tv_sec  = print_time.tv_usec  = 0;
868         start_time.tv_sec  = start_time.tv_usec  = 0;
869 }
870
871 void show_progress(OFF_T ofs, OFF_T size)
872 {
873         extern int do_progress, am_server;
874         struct timeval now;
875
876         gettimeofday(&now, NULL);
877
878         if (!start_time.tv_sec && !start_time.tv_usec) {
879                 start_time.tv_sec  = now.tv_sec;
880                 start_time.tv_usec = now.tv_usec;
881                 start_ofs          = ofs;
882         }
883
884         if (do_progress
885             && !am_server
886             && ofs > last_ofs + 1000
887             && msdiff(&print_time, &now) > 250) {
888                 rprint_progress(ofs, size, &now, False);
889                 last_ofs = ofs;
890                 print_time.tv_sec  = now.tv_sec;
891                 print_time.tv_usec = now.tv_usec;
892         }
893 }
894
895 /* determine if a symlink points outside the current directory tree */
896 int unsafe_symlink(char *dest, char *src)
897 {
898         char *tok;
899         int depth = 0;
900
901         /* all absolute and null symlinks are unsafe */
902         if (!dest || !(*dest) || (*dest == '/')) return 1;
903
904         src = strdup(src);
905         if (!src) out_of_memory("unsafe_symlink");
906
907         /* find out what our safety margin is */
908         for (tok=strtok(src,"/"); tok; tok=strtok(NULL,"/")) {
909                 if (strcmp(tok,"..") == 0) {
910                         depth=0;
911                 } else if (strcmp(tok,".") == 0) {
912                         /* nothing */
913                 } else {
914                         depth++;
915                 }
916         }
917         free(src);
918
919         /* drop by one to account for the filename portion */
920         depth--;
921
922         dest = strdup(dest);
923         if (!dest) out_of_memory("unsafe_symlink");
924
925         for (tok=strtok(dest,"/"); tok; tok=strtok(NULL,"/")) {
926                 if (strcmp(tok,"..") == 0) {
927                         depth--;
928                 } else if (strcmp(tok,".") == 0) {
929                         /* nothing */
930                 } else {
931                         depth++;
932                 }
933                 /* if at any point we go outside the current directory then
934                    stop - it is unsafe */
935                 if (depth < 0) break;
936         }
937
938         free(dest);
939         return (depth < 0);
940 }
941
942
943 /****************************************************************************
944   return the date and time as a string
945 ****************************************************************************/
946 char *timestring(time_t t)
947 {
948         static char TimeBuf[200];
949         struct tm *tm = localtime(&t);
950
951 #ifdef HAVE_STRFTIME
952         strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %T",tm);
953 #else
954         strlcpy(TimeBuf, asctime(tm), sizeof(TimeBuf));
955 #endif
956
957         if (TimeBuf[strlen(TimeBuf)-1] == '\n') {
958                 TimeBuf[strlen(TimeBuf)-1] = 0;
959         }
960
961         return(TimeBuf);
962 }
963
964
965 /**
966  * Sleep for a specified number of milliseconds.
967  *
968  * Always returns TRUE.  (In the future it might return FALSE if
969  * interrupted.)
970  **/
971 int msleep(int t)
972 {
973         int tdiff=0;
974         struct timeval tval,t1,t2;  
975
976         gettimeofday(&t1, NULL);
977         gettimeofday(&t2, NULL);
978   
979         while (tdiff < t) {
980                 tval.tv_sec = (t-tdiff)/1000;
981                 tval.tv_usec = 1000*((t-tdiff)%1000);
982  
983                 errno = 0;
984                 select(0,NULL,NULL, NULL, &tval);
985
986                 gettimeofday(&t2, NULL);
987                 tdiff = (t2.tv_sec - t1.tv_sec)*1000 + 
988                         (t2.tv_usec - t1.tv_usec)/1000;
989         }
990
991         return True;
992 }
993
994
995 /*******************************************************************
996  Determine if two file modification times are equivalent (either exact 
997  or in the modification timestamp window established by --modify-window) 
998  Returns 0 if the times should be treated as the same, 1 if the 
999  first is later and -1 if the 2nd is later
1000  *******************************************************************/
1001 int cmp_modtime(time_t file1, time_t file2)
1002 {
1003         extern int modify_window;
1004
1005         if (file2 > file1) {
1006                 if (file2 - file1 <= modify_window) return 0;
1007                 return -1;
1008         }
1009         if (file1 - file2 <= modify_window) return 0;
1010         return 1;
1011 }
1012
1013
1014 #ifdef __INSURE__XX
1015 #include <dlfcn.h>
1016
1017 /*******************************************************************
1018 This routine is a trick to immediately catch errors when debugging
1019 with insure. A xterm with a gdb is popped up when insure catches
1020 a error. It is Linux specific.
1021 ********************************************************************/
1022 int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
1023 {
1024         static int (*fn)();
1025         int ret;
1026         char *cmd;
1027
1028         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'", 
1029                 getpid(), getpid(), getpid());
1030
1031         if (!fn) {
1032                 static void *h;
1033                 h = dlopen("/usr/local/parasoft/insure++lite/lib.linux2/libinsure.so", RTLD_LAZY);
1034                 fn = dlsym(h, "_Insure_trap_error");
1035         }
1036
1037         ret = fn(a1, a2, a3, a4, a5, a6);
1038
1039         system(cmd);
1040
1041         free(cmd);
1042
1043         return ret;
1044 }
1045 #endif