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