Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

util.c File Reference

Utilities used in rsync. More...

Go to the source code of this file.

Functions

void set_nonblocking (int fd)
 Set a fd into nonblocking mode. More...

void set_blocking (int fd)
 Set a fd into blocking mode. More...

int fd_pair (int fd[2])
 Create a file descriptor pair - like pipe() but use socketpair if possible (because of blocking issues on pipes). More...

void print_child_argv (char **cmd)
void out_of_memory (char *str)
void overflow (char *str)
int set_modtime (char *fname, time_t modtime)
int create_directory_path (char *fname, int base_umask)
 Create any necessary directories in fname. More...

int full_write (int desc, char *ptr, size_t len)
 Write len bytes at ptr to descriptor desc, retrying if interrupted. More...

int safe_read (int desc, char *ptr, size_t len)
 Read len bytes at ptr from descriptor desc, retrying if interrupted. More...

int copy_file (char *source, char *dest, mode_t mode)
 Copy a file. More...

int robust_unlink (char *fname)
 Robust unlink: some OS'es (HPUX) refuse to unlink busy files, so rename to <path>/.rsyncNNN instead. More...

int robust_rename (char *from, char *to)
pid_t do_fork (void)
 Fork and record the pid of the child. More...

void kill_all (int sig)
 Kill all children. More...

int name_to_uid (char *name, uid_t *uid)
 Turn a user name into a uid. More...

int name_to_gid (char *name, gid_t *gid)
 Turn a group name into a gid. More...

int lock_range (int fd, int offset, int len)
 Lock a byte range in a open file. More...

void glob_expand_one (char *s, char **argv, int *argc, int maxargs)
void glob_expand (char *base1, char **argv, int *argc, int maxargs)
void strlower (char *s)
 Convert a string to lower case. More...

void * Realloc (void *p, int size)
void clean_fname (char *name)
void sanitize_path (char *p, char *reldir)
 Make path appear as if a chroot had occurred:. More...

char * push_dir (char *dir, int save)
 Like chdir() but can be reversed with pop_dir() if save is set. More...

int pop_dir (char *dir)
 Reverse a push_dir() call. More...

int u_strcmp (const char *cs1, const char *cs2)
 We need to supply our own strcmp function for file list comparisons to ensure that signed/unsigned usage is consistent between machines. More...

int unsafe_symlink (char *dest, char *src)
 Determine if a symlink points outside the current directory tree. More...

char * timestring (time_t t)
 Return the date and time as a string. More...

int msleep (int t)
 Sleep for a specified number of milliseconds. More...

int cmp_modtime (time_t file1, time_t file2)
 Determine if two file modification times are equivalent (either exact or in the modification timestamp window established by --modify-window). More...

int _Insure_trap_error (int a1, int a2, int a3, int a4, int a5, int a6)
 This routine is a trick to immediately catch errors when debugging with insure. More...


Variables

int verbose
int sanitize_paths = 0
pid_t all_pids [10]
int num_pids
char curr_dir [MAXPATHLEN]


Detailed Description

Utilities used in rsync.

Definition in file util.c.


Function Documentation

void set_nonblocking int    fd
 

Set a fd into nonblocking mode.

Definition at line 39 of file util.c.

Referenced by client_run(), fd_pair(), main(), set_error_fd(), socketpair_tcp(), start_daemon(), and start_server().

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 }

void set_blocking int    fd
 

Set a fd into blocking mode.

Definition at line 54 of file util.c.

Referenced by piped_child(), and socketpair_tcp().

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 }

int fd_pair int    fd[2]
 

Create a file descriptor pair - like pipe() but use socketpair if possible (because of blocking issues on pipes).

Always set non-blocking.

Definition at line 73 of file util.c.

References set_nonblocking().

Referenced by do_recv(), local_child(), and piped_child().

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 }

void print_child_argv char **    cmd
 

Definition at line 92 of file util.c.

References FINFO, and rprintf().

Referenced by piped_child().

00093 {
00094         rprintf(FINFO, "opening connection using ");
00095         for (; *cmd; cmd++) {
00096                 /* Look for characters that ought to be quoted.  This
00097                 * is not a great quoting algorithm, but it's
00098                 * sufficient for a log message. */
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 }

void out_of_memory char *    str
 

Definition at line 112 of file util.c.

References FERROR, and rprintf().

Referenced by access_match(), add_delete_entry(), add_exclude_line(), add_exclude_list(), add_include_line(), add_list(), build_hash_table(), create_flist_from_batch(), do_cmd(), flist_expand(), flist_new(), generate_sums(), get_checksum2(), glob_expand(), glob_expand_one(), io_start_buffering(), make_exclude(), make_file(), map_file(), map_ptr(), read_batch_flist_info(), receive_file_entry(), receive_sums(), recv_deflated_token(), recv_file_list(), recv_uid_list(), send_deflated_token(), set_socket_options(), simple_recv_token(), string_area_new(), and unsafe_symlink().

00113 {
00114   rprintf(FERROR,"ERROR: out of memory in %s\n",str);
00115   exit_cleanup(RERR_MALLOC);
00116 }

void overflow char *    str
 

Definition at line 118 of file util.c.

References FERROR, and rprintf().

Referenced by receive_file_entry(), and recv_exclude_list().

00119 {
00120   rprintf(FERROR,"ERROR: buffer overflow in %s\n",str);
00121   exit_cleanup(RERR_MALLOC);
00122 }

int set_modtime char *    fname,
time_t    modtime
 

Definition at line 126 of file util.c.

References FINFO, rprintf(), and verbose.

Referenced by make_bak_dir(), and set_perms().

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 }

int create_directory_path char *    fname,
int    base_umask
 

Create any necessary directories in fname.

Unfortunately we don't know what perms to give the directory when this is called so we need to rely on the umask

Definition at line 166 of file util.c.

References do_mkdir().

Referenced by recv_files(), and recv_generator().

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 }

int full_write int    desc,
char *    ptr,
size_t    len
[static]
 

Write len bytes at ptr to descriptor desc, retrying if interrupted.

Return values:
len  upon success
<0  write's (negative) error code
Derived from GNU C's cccp.c.

Definition at line 194 of file util.c.

Referenced by copy_file().

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 }

int safe_read int    desc,
char *    ptr,
size_t    len
[static]
 

Read len bytes at ptr from descriptor desc, retrying if interrupted.

Return values:
>0  the actual number of bytes read
0  for EOF
<0  for an error.
Derived from GNU C's cccp.c.

Definition at line 227 of file util.c.

Referenced by copy_file().

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 }

int copy_file char *    source,
char *    dest,
mode_t    mode
 

Copy a file.

This is used in conjunction with the --temp-dir option

Definition at line 249 of file util.c.

References do_open(), FERROR, full_write(), robust_unlink(), rprintf(), and safe_read().

Referenced by finish_transfer(), and robust_move().

00250 {
00251         int ifd;
00252         int ofd;
00253         char buf[1024 * 8];
00254         int len;   /* Number of bytes read into `buf'. */
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 }

int robust_unlink char *    fname
 

Robust unlink: some OS'es (HPUX) refuse to unlink busy files, so rename to <path>/.rsyncNNN instead.

Note that successive rsync runs will shuffle the filenames around a bit as long as the file is still busy; this is because this function does not know if the unlink call is due to a new file coming in, or --delete trying to remove old .rsyncNNN files, hence it renames it each time.

Definition at line 313 of file util.c.

References do_rename(), do_unlink(), FINFO, rprintf(), sprintf(), strlcpy(), and verbose.

Referenced by copy_file(), delete_file(), delete_one(), hard_link_one(), recv_generator(), and robust_rename().

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         /* start where the last one left off to reduce chance of clashes */
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         /* maybe we should return rename()'s exit status? Nah. */
00353         if (do_rename(fname, path) != 0) {
00354                 errno = ETXTBSY;
00355                 return -1;
00356         }
00357         return 0;
00358 #endif
00359 }

int robust_rename char *    from,
char *    to
 

Definition at line 361 of file util.c.

References do_rename(), and robust_unlink().

Referenced by finish_transfer(), and robust_move().

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 }

pid_t do_fork void   
 

Fork and record the pid of the child.

*

Definition at line 380 of file util.c.

References all_pids, and num_pids.

Referenced by do_recv(), local_child(), and piped_child().

00381 {
00382         pid_t newpid = fork();
00383         
00384         if (newpid != 0  &&  newpid != -1) {
00385                 all_pids[num_pids++] = newpid;
00386         }
00387         return newpid;
00388 }

void kill_all int    sig
 

Kill all children.

Todo:
It would be kind of nice to make sure that they are actually all our children before we kill them, because their pids may have been recycled by some other process. Perhaps when we wait for a child, we should remove it from this array. Alternatively we could perhaps use process groups, but I think that would not work on ancient Unix versions that don't support them.

Definition at line 400 of file util.c.

References all_pids, and num_pids.

Referenced by _exit_cleanup().

00401 {
00402         int i;
00403 
00404         for (i = 0; i < num_pids; i++) {
00405                 /* Let's just be a little careful where we
00406                  * point that gun, hey?  See kill(2) for the
00407                  * magic caused by negative values. */
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 }

int name_to_uid char *    name,
uid_t *    uid
 

Turn a user name into a uid.

Definition at line 421 of file util.c.

Referenced by map_uid(), and rsync_module().

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 }

int name_to_gid char *    name,
gid_t *    gid
 

Turn a group name into a gid.

Definition at line 434 of file util.c.

Referenced by map_gid(), and rsync_module().

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 }

int lock_range int    fd,
int    offset,
int    len
 

Lock a byte range in a open file.

Definition at line 448 of file util.c.

Referenced by claim_connection().

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 }

void glob_expand_one char *    s,
char **    argv,
int *    argc,
int    maxargs
[static]
 

Definition at line 462 of file util.c.

References out_of_memory(), sanitize_path(), sanitize_paths, and strdup().

Referenced by glob_expand().

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 }

void glob_expand char *    base1,
char **    argv,
int *    argc,
int    maxargs
 

Definition at line 498 of file util.c.

References asprintf(), glob_expand_one(), out_of_memory(), and strdup().

Referenced by rsync_module().

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                 /* split it at this point */
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 }

void strlower char *    s
 

Convert a string to lower case.

Definition at line 532 of file util.c.

Referenced by access_match(), and set_compression().

00533 {
00534         while (*s) {
00535                 if (isupper(* (unsigned char *) s))
00536                         *s = tolower(* (unsigned char *) s);
00537                 s++;
00538         }
00539 }

void* Realloc void *    p,
int    size
 

Definition at line 541 of file util.c.

Referenced by add_a_service(), map_ptr(), Parameter(), and Section().

00542 {
00543         if (!p) return (void *)malloc(size);
00544         return (void *)realloc(p, size);
00545 }

void clean_fname char *    name
 

Definition at line 548 of file util.c.

Referenced by log_formatted(), make_file(), push_dir(), and receive_file_entry().

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 }

void sanitize_path char *    p,
char *    reldir
 

Make path appear as if a chroot had occurred:.

  • 1. remove leading "/" (or replace with "." if at end)
  • 2. remove leading ".." components (except those allowed by reldir)
  • 3. delete any other "<dir>/.." (recursively)
Can only shrink paths, so sanitizes in place.

While we're at it, remove double slashes and "." components like clean_fname() does, but DON'T remove a trailing slash because that is sometimes significant on command line arguments.

If reldir is non-null, it is a sanitized directory that the path will be relative to, so allow as many ".." at the beginning of the path as there are components in reldir. This is used for symbolic link targets. If reldir is non-null and the path began with "/", to be completely like a chroot we should add in depth levels of ".." at the beginning of the path, but that would blow the assumption that the path doesn't grow and it is not likely to end up being a valid symlink anyway, so just do the normal removal of the leading "/" instead.

Contributed by Dave Dykstra <dwd@bell-labs.com>

Definition at line 616 of file util.c.

Referenced by glob_expand_one(), make_file(), receive_file_entry(), and rsync_module().

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                 /* remove leading slashes */
00634                 p++;
00635         }
00636         while (*p != '\0') {
00637                 /* this loop iterates once per filename component in p.
00638                  * both p (and sanp if the original had a slash) should
00639                  * always be left pointing after a slash
00640                  */
00641                 if ((*p == '.') && ((*(p+1) == '/') || (*(p+1) == '\0'))) {
00642                         /* skip "." component */
00643                         while (*++p == '/') {
00644                                 /* skip following slashes */
00645                                 ;
00646                         }
00647                         continue;
00648                 }
00649                 allowdotdot = 0;
00650                 if ((*p == '.') && (*(p+1) == '.') &&
00651                             ((*(p+2) == '/') || (*(p+2) == '\0'))) {
00652                         /* ".." component followed by slash or end */
00653                         if ((depth > 0) && (sanp == start)) {
00654                                 /* allow depth levels of .. at the beginning */
00655                                 --depth;
00656                                 allowdotdot = 1;
00657                         } else {
00658                                 p += 2;
00659                                 if (*p == '/')
00660                                         p++;
00661                                 if (sanp != start) {
00662                                         /* back up sanp one level */
00663                                         --sanp; /* now pointing at slash */
00664                                         while ((sanp > start) && (*(sanp - 1) != '/')) {
00665                                                 /* skip back up to slash */
00666                                                 sanp--;
00667                                         }
00668                                 }
00669                                 continue;
00670                         }
00671                 }
00672                 while (1) {
00673                         /* copy one component through next slash */
00674                         *sanp++ = *p++;
00675                         if ((*p == '\0') || (*(p-1) == '/')) {
00676                                 while (*p == '/') {
00677                                         /* skip multiple slashes */
00678                                         p++;
00679                                 }
00680                                 break;
00681                         }
00682                 }
00683                 if (allowdotdot) {
00684                         /* move the virtual beginning to leave the .. alone */
00685                         start = sanp;
00686                 }
00687         }
00688         if ((sanp == start) && !allowdotdot) {
00689                 /* ended up with nothing, so put in "." component */
00690                 /*
00691                  * note that the !allowdotdot doesn't prevent this from
00692                  *  happening in all allowed ".." situations, but I didn't
00693                  *  think it was worth putting in an extra variable to ensure
00694                  *  it since an extra "." won't hurt in those situations.
00695                  */
00696                 *sanp++ = '.';
00697         }
00698         *sanp = '\0';
00699 }

char* push_dir char *    dir,
int    save
 

Like chdir() but can be reversed with pop_dir() if save is set.

It is also much faster as it remembers where we have been.

Definition at line 708 of file util.c.

References clean_fname(), curr_dir, getcwd(), strdup(), strlcat(), and strlcpy().

Referenced by do_server_recv(), do_server_sender(), get_local_name(), main(), rsync_module(), and send_file_list().

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; /* this call was probably just to initialize */
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 }

int pop_dir char *    dir
 

Reverse a push_dir() call.

Definition at line 739 of file util.c.

References curr_dir, and strlcpy().

Referenced by send_file_list().

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 }

int u_strcmp const char *    cs1,
const char *    cs2
 

We need to supply our own strcmp function for file list comparisons to ensure that signed/unsigned usage is consistent between machines.

Definition at line 758 of file util.c.

Referenced by file_compare().

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 }

int unsafe_symlink char *    dest,
char *    src
 

Determine if a symlink points outside the current directory tree.

This is considered "unsafe" because e.g. when mirroring somebody else's machine it might allow them to establish a symlink to /etc/passwd, and then read it through a web server.

Null symlinks and absolute symlinks are always unsafe.

Basically here we are concerned with symlinks whose target contains "..", because this might cause us to walk back up out of the transferred directory. We are not allowed to go back up and reenter.

Parameters:
dest  Target of the symlink in question.
src  Top source directory currently applicable. Basically this is the first parameter to rsync in a simple invocation, but it's modified by flist.c in slightly complex ways.
Return values:
True  if unsafe
False  is unsafe
See also:
t_unsafe.c

Definition at line 796 of file util.c.

References out_of_memory(), and strdup().

Referenced by keep_backup(), main(), readlink_stat(), and recv_generator().

00797 {
00798         char *tok;
00799         int depth = 0;
00800 
00801         /* all absolute and null symlinks are unsafe */
00802         if (!dest || !(*dest) || (*dest == '/')) return 1;
00803 
00804         src = strdup(src);
00805         if (!src) out_of_memory("unsafe_symlink");
00806 
00807         /* find out what our safety margin is */
00808         for (tok=strtok(src,"/"); tok; tok=strtok(NULL,"/")) {
00809                 if (strcmp(tok,"..") == 0) {
00810                         depth=0;
00811                 } else if (strcmp(tok,".") == 0) {
00812                         /* nothing */
00813                 } else {
00814                         depth++;
00815                 }
00816         }
00817         free(src);
00818 
00819         /* drop by one to account for the filename portion */
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                         /* nothing */
00830                 } else {
00831                         depth++;
00832                 }
00833                 /* if at any point we go outside the current directory then
00834                    stop - it is unsafe */
00835                 if (depth < 0) break;
00836         }
00837 
00838         free(dest);
00839         return (depth < 0);
00840 }

char* timestring time_t    t
 

Return the date and time as a string.

Definition at line 846 of file util.c.

References strlcpy().

Referenced by list_file_entry(), log_formatted(), and logit().

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 }

int msleep int    t
 

Sleep for a specified number of milliseconds.

Always returns TRUE. (In the future it might return FALSE if interrupted.)

Definition at line 871 of file util.c.

Referenced by do_recv(), wait_process(), and writefd_unbuffered().

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 }

int cmp_modtime time_t    file1,
time_t    file2
 

Determine if two file modification times are equivalent (either exact or in the modification timestamp window established by --modify-window).

Return values:
0  if the times should be treated as the same
1  if the first is later
-1  if the 2nd is later

Definition at line 906 of file util.c.

Referenced by recv_generator(), set_perms(), and skip_file().

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 }

int _Insure_trap_error int    a1,
int    a2,
int    a3,
int    a4,
int    a5,
int    a6
 

This routine is a trick to immediately catch errors when debugging with insure.

A xterm with a gdb is popped up when insure catches a error. It is Linux specific.

Definition at line 927 of file util.c.

References asprintf().

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 }


Variable Documentation

int verbose
 

Definition at line 30 of file util.c.

Referenced by robust_unlink(), and set_modtime().

int sanitize_paths = 0
 

Definition at line 32 of file util.c.

Referenced by glob_expand_one().

pid_t all_pids[10] [static]
 

Definition at line 376 of file util.c.

Referenced by do_fork(), and kill_all().

int num_pids [static]
 

Definition at line 377 of file util.c.

Referenced by do_fork(), and kill_all().

char curr_dir[MAXPATHLEN] [static]
 

Definition at line 702 of file util.c.

Referenced by pop_dir(), and push_dir().


Generated on Tue Apr 16 12:37:39 2002 for rsync by doxygen1.2.15