00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "rsync.h"
00029
00030 extern int verbose;
00031
00032 int sanitize_paths = 0;
00033
00034
00035
00036
00037
00038
00039 void set_nonblocking(int fd)
00040 {
00041 int val;
00042
00043 if ((val = fcntl(fd, F_GETFL, 0)) == -1)
00044 return;
00045 if (!(val & NONBLOCK_FLAG)) {
00046 val |= NONBLOCK_FLAG;
00047 fcntl(fd, F_SETFL, val);
00048 }
00049 }
00050
00051
00052
00053
00054 void set_blocking(int fd)
00055 {
00056 int val;
00057
00058 if ((val = fcntl(fd, F_GETFL, 0)) == -1)
00059 return;
00060 if (val & NONBLOCK_FLAG) {
00061 val &= ~NONBLOCK_FLAG;
00062 fcntl(fd, F_SETFL, val);
00063 }
00064 }
00065
00066
00067
00068
00069
00070
00071
00072
00073 int fd_pair(int fd[2])
00074 {
00075 int ret;
00076
00077 #if HAVE_SOCKETPAIR
00078 ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd);
00079 #else
00080 ret = pipe(fd);
00081 #endif
00082
00083 if (ret == 0) {
00084 set_nonblocking(fd[0]);
00085 set_nonblocking(fd[1]);
00086 }
00087
00088 return ret;
00089 }
00090
00091
00092 void print_child_argv(char **cmd)
00093 {
00094 rprintf(FINFO, "opening connection using ");
00095 for (; *cmd; cmd++) {
00096
00097
00098
00099 if (strspn(*cmd, "abcdefghijklmnopqrstuvwxyz"
00100 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
00101 "0123456789"
00102 ",.-_=+@/") != strlen(*cmd)) {
00103 rprintf(FINFO, "\"%s\" ", *cmd);
00104 } else {
00105 rprintf(FINFO, "%s ", *cmd);
00106 }
00107 }
00108 rprintf(FINFO, "\n");
00109 }
00110
00111
00112 void out_of_memory(char *str)
00113 {
00114 rprintf(FERROR,"ERROR: out of memory in %s\n",str);
00115 exit_cleanup(RERR_MALLOC);
00116 }
00117
00118 void overflow(char *str)
00119 {
00120 rprintf(FERROR,"ERROR: buffer overflow in %s\n",str);
00121 exit_cleanup(RERR_MALLOC);
00122 }
00123
00124
00125
00126 int set_modtime(char *fname, time_t modtime)
00127 {
00128 extern int dry_run;
00129 if (dry_run)
00130 return 0;
00131
00132 if (verbose > 2) {
00133 rprintf(FINFO, "set modtime of %s to (%ld) %s",
00134 fname, (long) modtime,
00135 asctime(localtime(&modtime)));
00136 }
00137
00138 {
00139 #ifdef HAVE_UTIMBUF
00140 struct utimbuf tbuf;
00141 tbuf.actime = time(NULL);
00142 tbuf.modtime = modtime;
00143 return utime(fname,&tbuf);
00144 #elif defined(HAVE_UTIME)
00145 time_t t[2];
00146 t[0] = time(NULL);
00147 t[1] = modtime;
00148 return utime(fname,t);
00149 #else
00150 struct timeval t[2];
00151 t[0].tv_sec = time(NULL);
00152 t[0].tv_usec = 0;
00153 t[1].tv_sec = modtime;
00154 t[1].tv_usec = 0;
00155 return utimes(fname,t);
00156 #endif
00157 }
00158 }
00159
00160
00161
00162
00163
00164
00165
00166 int create_directory_path(char *fname, int base_umask)
00167 {
00168 char *p;
00169
00170 while (*fname == '/') fname++;
00171 while (strncmp(fname,"./",2)==0) fname += 2;
00172
00173 p = fname;
00174 while ((p=strchr(p,'/'))) {
00175 *p = 0;
00176 do_mkdir(fname, 0777 & ~base_umask);
00177 *p = '/';
00178 p++;
00179 }
00180 return 0;
00181 }
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 static int full_write(int desc, char *ptr, size_t len)
00195 {
00196 int total_written;
00197
00198 total_written = 0;
00199 while (len > 0) {
00200 int written = write (desc, ptr, len);
00201 if (written < 0) {
00202 #ifdef EINTR
00203 if (errno == EINTR)
00204 continue;
00205 #endif
00206 return written;
00207 }
00208 total_written += written;
00209 ptr += written;
00210 len -= written;
00211 }
00212 return total_written;
00213 }
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 static int safe_read(int desc, char *ptr, size_t len)
00228 {
00229 int n_chars;
00230
00231 if (len == 0)
00232 return len;
00233
00234 #ifdef EINTR
00235 do {
00236 n_chars = read(desc, ptr, len);
00237 } while (n_chars < 0 && errno == EINTR);
00238 #else
00239 n_chars = read(desc, ptr, len);
00240 #endif
00241
00242 return n_chars;
00243 }
00244
00245
00246
00247
00248
00249 int copy_file(char *source, char *dest, mode_t mode)
00250 {
00251 int ifd;
00252 int ofd;
00253 char buf[1024 * 8];
00254 int len;
00255
00256 ifd = do_open(source, O_RDONLY, 0);
00257 if (ifd == -1) {
00258 rprintf(FERROR,"open %s: %s\n",
00259 source,strerror(errno));
00260 return -1;
00261 }
00262
00263 if (robust_unlink(dest) && errno != ENOENT) {
00264 rprintf(FERROR,"unlink %s: %s\n",
00265 dest,strerror(errno));
00266 return -1;
00267 }
00268
00269 ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode);
00270 if (ofd == -1) {
00271 rprintf(FERROR,"open %s: %s\n",
00272 dest,strerror(errno));
00273 close(ifd);
00274 return -1;
00275 }
00276
00277 while ((len = safe_read(ifd, buf, sizeof(buf))) > 0) {
00278 if (full_write(ofd, buf, len) < 0) {
00279 rprintf(FERROR,"write %s: %s\n",
00280 dest,strerror(errno));
00281 close(ifd);
00282 close(ofd);
00283 return -1;
00284 }
00285 }
00286
00287 close(ifd);
00288 close(ofd);
00289
00290 if (len < 0) {
00291 rprintf(FERROR,"read %s: %s\n",
00292 source,strerror(errno));
00293 return -1;
00294 }
00295
00296 return 0;
00297 }
00298
00299
00300 #define MAX_RENAMES_DIGITS 3
00301 #define MAX_RENAMES 1000
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313 int robust_unlink(char *fname)
00314 {
00315 #ifndef ETXTBSY
00316 return do_unlink(fname);
00317 #else
00318 static int counter = 1;
00319 int rc, pos, start;
00320 char path[MAXPATHLEN];
00321
00322 rc = do_unlink(fname);
00323 if ((rc == 0) || (errno != ETXTBSY))
00324 return rc;
00325
00326 strlcpy(path, fname, MAXPATHLEN);
00327
00328 pos = strlen(path);
00329 while((path[--pos] != '/') && (pos >= 0))
00330 ;
00331 ++pos;
00332 strlcpy(&path[pos], ".rsync", MAXPATHLEN-pos);
00333 pos += sizeof(".rsync")-1;
00334
00335 if (pos > (MAXPATHLEN-MAX_RENAMES_DIGITS-1)) {
00336 errno = ETXTBSY;
00337 return -1;
00338 }
00339
00340
00341 start = counter;
00342 do {
00343 sprintf(&path[pos], "%03d", counter);
00344 if (++counter >= MAX_RENAMES)
00345 counter = 1;
00346 } while (((rc = access(path, 0)) == 0) && (counter != start));
00347
00348 if (verbose > 0)
00349 rprintf(FINFO,"renaming %s to %s because of text busy\n",
00350 fname, path);
00351
00352
00353 if (do_rename(fname, path) != 0) {
00354 errno = ETXTBSY;
00355 return -1;
00356 }
00357 return 0;
00358 #endif
00359 }
00360
00361 int robust_rename(char *from, char *to)
00362 {
00363 #ifndef ETXTBSY
00364 return do_rename(from, to);
00365 #else
00366 int rc = do_rename(from, to);
00367 if ((rc == 0) || (errno != ETXTBSY))
00368 return rc;
00369 if (robust_unlink(to) != 0)
00370 return -1;
00371 return do_rename(from, to);
00372 #endif
00373 }
00374
00375
00376 static pid_t all_pids[10];
00377 static int num_pids;
00378
00379
00380 pid_t do_fork(void)
00381 {
00382 pid_t newpid = fork();
00383
00384 if (newpid != 0 && newpid != -1) {
00385 all_pids[num_pids++] = newpid;
00386 }
00387 return newpid;
00388 }
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400 void kill_all(int sig)
00401 {
00402 int i;
00403
00404 for (i = 0; i < num_pids; i++) {
00405
00406
00407
00408 pid_t p = all_pids[i];
00409
00410 if (p == getpid())
00411 continue;
00412 if (p <= 0)
00413 continue;
00414
00415 kill(p, sig);
00416 }
00417 }
00418
00419
00420
00421 int name_to_uid(char *name, uid_t *uid)
00422 {
00423 struct passwd *pass;
00424 if (!name || !*name) return 0;
00425 pass = getpwnam(name);
00426 if (pass) {
00427 *uid = pass->pw_uid;
00428 return 1;
00429 }
00430 return 0;
00431 }
00432
00433
00434 int name_to_gid(char *name, gid_t *gid)
00435 {
00436 struct group *grp;
00437 if (!name || !*name) return 0;
00438 grp = getgrnam(name);
00439 if (grp) {
00440 *gid = grp->gr_gid;
00441 return 1;
00442 }
00443 return 0;
00444 }
00445
00446
00447
00448 int lock_range(int fd, int offset, int len)
00449 {
00450 struct flock lock;
00451
00452 lock.l_type = F_WRLCK;
00453 lock.l_whence = SEEK_SET;
00454 lock.l_start = offset;
00455 lock.l_len = len;
00456 lock.l_pid = 0;
00457
00458 return fcntl(fd,F_SETLK,&lock) == 0;
00459 }
00460
00461
00462 static void glob_expand_one(char *s, char **argv, int *argc, int maxargs)
00463 {
00464 #if !(defined(HAVE_GLOB) && defined(HAVE_GLOB_H))
00465 if (!*s) s = ".";
00466 argv[*argc] = strdup(s);
00467 (*argc)++;
00468 return;
00469 #else
00470 extern int sanitize_paths;
00471 glob_t globbuf;
00472 int i;
00473
00474 if (!*s) s = ".";
00475
00476 argv[*argc] = strdup(s);
00477 if (sanitize_paths) {
00478 sanitize_path(argv[*argc], NULL);
00479 }
00480
00481 memset(&globbuf, 0, sizeof(globbuf));
00482 glob(argv[*argc], 0, NULL, &globbuf);
00483 if (globbuf.gl_pathc == 0) {
00484 (*argc)++;
00485 globfree(&globbuf);
00486 return;
00487 }
00488 for (i=0; i<(maxargs - (*argc)) && i < (int) globbuf.gl_pathc;i++) {
00489 if (i == 0) free(argv[*argc]);
00490 argv[(*argc) + i] = strdup(globbuf.gl_pathv[i]);
00491 if (!argv[(*argc) + i]) out_of_memory("glob_expand");
00492 }
00493 globfree(&globbuf);
00494 (*argc) += i;
00495 #endif
00496 }
00497
00498 void glob_expand(char *base1, char **argv, int *argc, int maxargs)
00499 {
00500 char *s = argv[*argc];
00501 char *p, *q;
00502 char *base = base1;
00503
00504 if (!s || !*s) return;
00505
00506 if (strncmp(s, base, strlen(base)) == 0) {
00507 s += strlen(base);
00508 }
00509
00510 s = strdup(s);
00511 if (!s) out_of_memory("glob_expand");
00512
00513 if (asprintf(&base," %s/", base1) <= 0) out_of_memory("glob_expand");
00514
00515 q = s;
00516 while ((p = strstr(q,base)) && ((*argc) < maxargs)) {
00517
00518 *p = 0;
00519 glob_expand_one(q, argv, argc, maxargs);
00520 q = p+strlen(base);
00521 }
00522
00523 if (*q && (*argc < maxargs)) glob_expand_one(q, argv, argc, maxargs);
00524
00525 free(s);
00526 free(base);
00527 }
00528
00529
00530
00531
00532 void strlower(char *s)
00533 {
00534 while (*s) {
00535 if (isupper(* (unsigned char *) s))
00536 *s = tolower(* (unsigned char *) s);
00537 s++;
00538 }
00539 }
00540
00541 void *Realloc(void *p, int size)
00542 {
00543 if (!p) return (void *)malloc(size);
00544 return (void *)realloc(p, size);
00545 }
00546
00547
00548 void clean_fname(char *name)
00549 {
00550 char *p;
00551 int l;
00552 int modified = 1;
00553
00554 if (!name) return;
00555
00556 while (modified) {
00557 modified = 0;
00558
00559 if ((p=strstr(name,"/./"))) {
00560 modified = 1;
00561 while (*p) {
00562 p[0] = p[2];
00563 p++;
00564 }
00565 }
00566
00567 if ((p=strstr(name,"//"))) {
00568 modified = 1;
00569 while (*p) {
00570 p[0] = p[1];
00571 p++;
00572 }
00573 }
00574
00575 if (strncmp(p=name,"./",2) == 0) {
00576 modified = 1;
00577 do {
00578 p[0] = p[2];
00579 } while (*p++);
00580 }
00581
00582 l = strlen(p=name);
00583 if (l > 1 && p[l-1] == '/') {
00584 modified = 1;
00585 p[l-1] = 0;
00586 }
00587 }
00588 }
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616 void sanitize_path(char *p, char *reldir)
00617 {
00618 char *start, *sanp;
00619 int depth = 0;
00620 int allowdotdot = 0;
00621
00622 if (reldir) {
00623 depth++;
00624 while (*reldir) {
00625 if (*reldir++ == '/') {
00626 depth++;
00627 }
00628 }
00629 }
00630 start = p;
00631 sanp = p;
00632 while (*p == '/') {
00633
00634 p++;
00635 }
00636 while (*p != '\0') {
00637
00638
00639
00640
00641 if ((*p == '.') && ((*(p+1) == '/') || (*(p+1) == '\0'))) {
00642
00643 while (*++p == '/') {
00644
00645 ;
00646 }
00647 continue;
00648 }
00649 allowdotdot = 0;
00650 if ((*p == '.') && (*(p+1) == '.') &&
00651 ((*(p+2) == '/') || (*(p+2) == '\0'))) {
00652
00653 if ((depth > 0) && (sanp == start)) {
00654
00655 --depth;
00656 allowdotdot = 1;
00657 } else {
00658 p += 2;
00659 if (*p == '/')
00660 p++;
00661 if (sanp != start) {
00662
00663 --sanp;
00664 while ((sanp > start) && (*(sanp - 1) != '/')) {
00665
00666 sanp--;
00667 }
00668 }
00669 continue;
00670 }
00671 }
00672 while (1) {
00673
00674 *sanp++ = *p++;
00675 if ((*p == '\0') || (*(p-1) == '/')) {
00676 while (*p == '/') {
00677
00678 p++;
00679 }
00680 break;
00681 }
00682 }
00683 if (allowdotdot) {
00684
00685 start = sanp;
00686 }
00687 }
00688 if ((sanp == start) && !allowdotdot) {
00689
00690
00691
00692
00693
00694
00695
00696 *sanp++ = '.';
00697 }
00698 *sanp = '\0';
00699 }
00700
00701
00702 static char curr_dir[MAXPATHLEN];
00703
00704
00705
00706
00707
00708 char *push_dir(char *dir, int save)
00709 {
00710 char *ret = curr_dir;
00711 static int initialised;
00712
00713 if (!initialised) {
00714 initialised = 1;
00715 getcwd(curr_dir, sizeof(curr_dir)-1);
00716 }
00717
00718 if (!dir) return NULL;
00719
00720 if (chdir(dir)) return NULL;
00721
00722 if (save) {
00723 ret = strdup(curr_dir);
00724 }
00725
00726 if (*dir == '/') {
00727 strlcpy(curr_dir, dir, sizeof(curr_dir));
00728 } else {
00729 strlcat(curr_dir,"/", sizeof(curr_dir));
00730 strlcat(curr_dir,dir, sizeof(curr_dir));
00731 }
00732
00733 clean_fname(curr_dir);
00734
00735 return ret;
00736 }
00737
00738
00739 int pop_dir(char *dir)
00740 {
00741 int ret;
00742
00743 ret = chdir(dir);
00744 if (ret) {
00745 free(dir);
00746 return ret;
00747 }
00748
00749 strlcpy(curr_dir, dir, sizeof(curr_dir));
00750
00751 free(dir);
00752
00753 return 0;
00754 }
00755
00756
00757
00758 int u_strcmp(const char *cs1, const char *cs2)
00759 {
00760 const uchar *s1 = (const uchar *)cs1;
00761 const uchar *s2 = (const uchar *)cs2;
00762
00763 while (*s1 && *s2 && (*s1 == *s2)) {
00764 s1++; s2++;
00765 }
00766
00767 return (int)*s1 - (int)*s2;
00768 }
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796 int unsafe_symlink(char *dest, char *src)
00797 {
00798 char *tok;
00799 int depth = 0;
00800
00801
00802 if (!dest || !(*dest) || (*dest == '/')) return 1;
00803
00804 src = strdup(src);
00805 if (!src) out_of_memory("unsafe_symlink");
00806
00807
00808 for (tok=strtok(src,"/"); tok; tok=strtok(NULL,"/")) {
00809 if (strcmp(tok,"..") == 0) {
00810 depth=0;
00811 } else if (strcmp(tok,".") == 0) {
00812
00813 } else {
00814 depth++;
00815 }
00816 }
00817 free(src);
00818
00819
00820 depth--;
00821
00822 dest = strdup(dest);
00823 if (!dest) out_of_memory("unsafe_symlink");
00824
00825 for (tok=strtok(dest,"/"); tok; tok=strtok(NULL,"/")) {
00826 if (strcmp(tok,"..") == 0) {
00827 depth--;
00828 } else if (strcmp(tok,".") == 0) {
00829
00830 } else {
00831 depth++;
00832 }
00833
00834
00835 if (depth < 0) break;
00836 }
00837
00838 free(dest);
00839 return (depth < 0);
00840 }
00841
00842
00843
00844
00845
00846 char *timestring(time_t t)
00847 {
00848 static char TimeBuf[200];
00849 struct tm *tm = localtime(&t);
00850
00851 #ifdef HAVE_STRFTIME
00852 strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %T",tm);
00853 #else
00854 strlcpy(TimeBuf, asctime(tm), sizeof(TimeBuf));
00855 #endif
00856
00857 if (TimeBuf[strlen(TimeBuf)-1] == '\n') {
00858 TimeBuf[strlen(TimeBuf)-1] = 0;
00859 }
00860
00861 return(TimeBuf);
00862 }
00863
00864
00865
00866
00867
00868
00869
00870
00871 int msleep(int t)
00872 {
00873 int tdiff=0;
00874 struct timeval tval,t1,t2;
00875
00876 gettimeofday(&t1, NULL);
00877 gettimeofday(&t2, NULL);
00878
00879 while (tdiff < t) {
00880 tval.tv_sec = (t-tdiff)/1000;
00881 tval.tv_usec = 1000*((t-tdiff)%1000);
00882
00883 errno = 0;
00884 select(0,NULL,NULL, NULL, &tval);
00885
00886 gettimeofday(&t2, NULL);
00887 tdiff = (t2.tv_sec - t1.tv_sec)*1000 +
00888 (t2.tv_usec - t1.tv_usec)/1000;
00889 }
00890
00891 return True;
00892 }
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906 int cmp_modtime(time_t file1, time_t file2)
00907 {
00908 extern int modify_window;
00909
00910 if (file2 > file1) {
00911 if (file2 - file1 <= modify_window) return 0;
00912 return -1;
00913 }
00914 if (file1 - file2 <= modify_window) return 0;
00915 return 1;
00916 }
00917
00918
00919 #ifdef __INSURE__XX
00920 #include <dlfcn.h>
00921
00922
00923
00924
00925
00926
00927 int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
00928 {
00929 static int (*fn)();
00930 int ret;
00931 char *cmd;
00932
00933 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'",
00934 getpid(), getpid(), getpid());
00935
00936 if (!fn) {
00937 static void *h;
00938 h = dlopen("/usr/local/parasoft/insure++lite/lib.linux2/libinsure.so", RTLD_LAZY);
00939 fn = dlsym(h, "_Insure_trap_error");
00940 }
00941
00942 ret = fn(a1, a2, a3, a4, a5, a6);
00943
00944 system(cmd);
00945
00946 free(cmd);
00947
00948 return ret;
00949 }
00950 #endif