データ構造 | |
struct | bitbag |
関数 | |
void | set_nonblocking (int fd) |
Set a fd into nonblocking mode | |
void | set_blocking (int fd) |
Set a fd into blocking mode | |
int | fd_pair (int fd[2]) |
Create a file descriptor pair - like pipe() but use socketpair if possible (because of blocking issues on pipes). | |
void | print_child_argv (char **cmd) |
void | out_of_memory (char *str) |
void | overflow_exit (char *str) |
int | set_modtime (char *fname, time_t modtime, mode_t mode) |
int | mkdir_defmode (char *fname) |
int | create_directory_path (char *fname) |
int | full_write (int desc, char *ptr, size_t len) |
Write len bytes at ptr to descriptor desc , retrying if interrupted. | |
static int | safe_read (int desc, char *ptr, size_t len) |
Read len bytes at ptr from descriptor desc , retrying if interrupted. | |
int | copy_file (const char *source, const char *dest, mode_t mode) |
Copy a file. | |
int | robust_unlink (const char *fname) |
Robust unlink: some OS'es (HPUX) refuse to unlink busy files, so rename to <path>/.rsyncNNN instead. | |
int | robust_rename (char *from, char *to, char *partialptr, int mode) |
pid_t | do_fork (void) |
Fork and record the pid of the child. | |
void | kill_all (int sig) |
Kill all children. | |
int | name_to_uid (char *name, uid_t *uid) |
Turn a user name into a uid | |
int | name_to_gid (char *name, gid_t *gid) |
Turn a group name into a gid | |
int | lock_range (int fd, int offset, int len) |
Lock a byte range in a open file | |
static int | filter_server_path (char *arg) |
static void | glob_expand_one (char *s, char ***argv_ptr, int *argc_ptr, int *maxargs_ptr) |
void | glob_expand (char *base1, char ***argv_ptr, int *argc_ptr, int *maxargs_ptr) |
void | strlower (char *s) |
Convert a string to lower case | |
size_t | pathjoin (char *dest, size_t destsize, const char *p1, const char *p2) |
size_t | stringjoin (char *dest, size_t destsize,...) |
int | count_dir_elements (const char *p) |
unsigned int | clean_fname (char *name, BOOL collapse_dot_dot) |
char * | sanitize_path (char *dest, const char *p, const char *rootdir, int depth) |
int | push_dir (char *dir) |
Like chdir(), but it keeps track of the current directory (in the global "curr_dir"), and ensures that the path size doesn't overflow. | |
int | pop_dir (char *dir) |
Reverse a push_dir() call. | |
char * | full_fname (const char *fn) |
Return a quoted string with the full pathname of the indicated filename. | |
char * | partial_dir_fname (const char *fname) |
int | handle_partial_dir (const char *fname, int create) |
int | unsafe_symlink (const char *dest, const char *src) |
Determine if a symlink points outside the current directory tree. | |
char * | human_num (int64 num) |
char * | human_dnum (double dnum, int decimal_digits) |
char * | timestring (time_t t) |
Return the date and time as a string | |
int | msleep (int t) |
Sleep for a specified number of milliseconds. | |
int | cmp_time (time_t file1, time_t file2) |
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. | |
void * | _new_array (unsigned int size, unsigned long num) |
void * | _realloc_array (void *ptr, unsigned int size, unsigned long num) |
const char * | find_filename_suffix (const char *fn, int fn_len, int *len_ptr) |
uint32 | fuzzy_distance (const char *s1, int len1, const char *s2, int len2) |
bitbag * | bitbag_create (int max_ndx) |
void | bitbag_set_bit (struct bitbag *bb, int ndx) |
void | bitbag_clear_bit (struct bitbag *bb, int ndx) |
int | bitbag_check_bit (struct bitbag *bb, int ndx) |
int | bitbag_next_bit (struct bitbag *bb, int after) |
変数 | |
int | verbose |
int | dry_run |
int | module_id |
int | modify_window |
int | relative_paths |
int | human_readable |
mode_t | orig_umask |
char * | partial_dir |
filter_list_struct | server_filter_list |
int | sanitize_paths = 0 |
static pid_t | all_pids [10] |
static int | num_pids |
char | curr_dir [MAXPATHLEN] |
unsigned int | curr_dir_len |
static char | partial_fname [MAXPATHLEN] |
util.c で定義されています。
void set_nonblocking | ( | int | fd | ) |
void set_blocking | ( | int | fd | ) |
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.
参照先 set_nonblocking().
参照元 do_cmd()・do_recv()・local_child()・piped_child().
00081 { 00082 int ret; 00083 00084 #ifdef HAVE_SOCKETPAIR 00085 ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd); 00086 #else 00087 ret = pipe(fd); 00088 #endif 00089 00090 if (ret == 0) { 00091 set_nonblocking(fd[0]); 00092 set_nonblocking(fd[1]); 00093 } 00094 00095 return ret; 00096 }
void print_child_argv | ( | char ** | cmd | ) |
参照元 piped_child()・start_inband_exchange().
00099 { 00100 rprintf(FINFO, "opening connection using "); 00101 for (; *cmd; cmd++) { 00102 /* Look for characters that ought to be quoted. This 00103 * is not a great quoting algorithm, but it's 00104 * sufficient for a log message. */ 00105 if (strspn(*cmd, "abcdefghijklmnopqrstuvwxyz" 00106 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 00107 "0123456789" 00108 ",.-_=+@/") != strlen(*cmd)) { 00109 rprintf(FINFO, "\"%s\" ", *cmd); 00110 } else { 00111 rprintf(FINFO, "%s ", *cmd); 00112 } 00113 } 00114 rprintf(FINFO, "\n"); 00115 }
void out_of_memory | ( | char * | str | ) |
参照元 access_match()・add_rule()・add_to_list()・auth_server()・bitbag_create()・bitbag_set_bit()・build_hash_table()・do_cmd()・expand_file_acl_index_list()・expand_ida_list()・expand_rsync_acl_list()・expand_smb_acl_list()・finish_pre_exec()・flist_expand()・flist_ndx_push()・flist_new()・get_checksum2()・glob_expand()・glob_expand_one()・init_hard_links()・io_start_buffering_in()・io_start_buffering_out()・is_in_group()・link_idev_data()・make_file()・map_file()・map_ptr()・msg_list_add()・open_socket_in()・parse_size_arg()・push_local_filters()・readfd_unbuffered()・receive_sums()・receive_xattr()・recv_deflated_token()・recv_file_list()・recv_uid_list()・rsync_module()・rsync_xal_get()・rsync_xal_store()・sanitize_path()・send_deflated_token()・server_options()・set_compression()・set_socket_options()・simple_recv_token()・write_file().
00118 { 00119 rprintf(FERROR, "ERROR: out of memory in %s\n", str); 00120 exit_cleanup(RERR_MALLOC); 00121 }
void overflow_exit | ( | char * | str | ) |
参照元 receive_file_entry()・recv_filter_list()・send_file_list().
00124 { 00125 rprintf(FERROR, "ERROR: buffer overflow in %s\n", str); 00126 exit_cleanup(RERR_MALLOC); 00127 }
int set_modtime | ( | char * | fname, | |
time_t | modtime, | |||
mode_t | mode | |||
) |
参照先 dry_run・FINFO・rprintf()・verbose.
参照元 set_file_attrs().
00130 { 00131 #if !defined HAVE_LUTIMES || !defined HAVE_UTIMES 00132 if (S_ISLNK(mode)) 00133 return 1; 00134 #endif 00135 00136 if (verbose > 2) { 00137 rprintf(FINFO, "set modtime of %s to (%ld) %s", 00138 fname, (long)modtime, 00139 asctime(localtime(&modtime))); 00140 } 00141 00142 if (dry_run) 00143 return 0; 00144 00145 { 00146 #ifdef HAVE_UTIMES 00147 struct timeval t[2]; 00148 t[0].tv_sec = time(NULL); 00149 t[0].tv_usec = 0; 00150 t[1].tv_sec = modtime; 00151 t[1].tv_usec = 0; 00152 # ifdef HAVE_LUTIMES 00153 if (S_ISLNK(mode)) 00154 return lutimes(fname, t); 00155 # endif 00156 return utimes(fname, t); 00157 #elif defined HAVE_UTIMBUF 00158 struct utimbuf tbuf; 00159 tbuf.actime = time(NULL); 00160 tbuf.modtime = modtime; 00161 return utime(fname,&tbuf); 00162 #elif defined HAVE_UTIME 00163 time_t t[2]; 00164 t[0] = time(NULL); 00165 t[1] = modtime; 00166 return utime(fname,t); 00167 #else 00168 #error No file-time-modification routine found! 00169 #endif 00170 } 00171 }
int mkdir_defmode | ( | char * | fname | ) |
参照先 do_mkdir()・orig_umask.
参照元 get_local_name()・make_bak_dir().
00177 { 00178 int ret; 00179 00180 umask(orig_umask); 00181 ret = do_mkdir(fname, ACCESSPERMS); 00182 umask(0); 00183 00184 return ret; 00185 }
int create_directory_path | ( | char * | fname | ) |
参照先 do_mkdir()・errno・orig_umask.
参照元 recv_files()・recv_generator().
00190 { 00191 char *p; 00192 int ret = 0; 00193 00194 while (*fname == '/') 00195 fname++; 00196 while (strncmp(fname, "./", 2) == 0) 00197 fname += 2; 00198 00199 umask(orig_umask); 00200 p = fname; 00201 while ((p = strchr(p,'/')) != NULL) { 00202 *p = '\0'; 00203 if (do_mkdir(fname, ACCESSPERMS) < 0 && errno != EEXIST) 00204 ret = -1; 00205 *p++ = '/'; 00206 } 00207 umask(0); 00208 00209 return ret; 00210 }
int full_write | ( | int | desc, | |
char * | ptr, | |||
size_t | len | |||
) |
Write len
bytes at ptr
to descriptor desc
, retrying if interrupted.
len | upon success | |
<0 | write's (negative) error code |
参照先 errno・total_written.
参照元 copy_file()・generate_and_send_sums().
00223 { 00224 int total_written; 00225 00226 total_written = 0; 00227 while (len > 0) { 00228 int written = write(desc, ptr, len); 00229 if (written < 0) { 00230 if (errno == EINTR) 00231 continue; 00232 return written; 00233 } 00234 total_written += written; 00235 ptr += written; 00236 len -= written; 00237 } 00238 return total_written; 00239 }
static int safe_read | ( | int | desc, | |
char * | ptr, | |||
size_t | len | |||
) | [static] |
Read len
bytes at ptr
from descriptor desc
, retrying if interrupted.
>0 | the actual number of bytes read | |
0 | for EOF | |
<0 | for an error. |
参照先 errno.
参照元 copy_file().
00253 { 00254 int n_chars; 00255 00256 if (len == 0) 00257 return len; 00258 00259 do { 00260 n_chars = read(desc, ptr, len); 00261 } while (n_chars < 0 && errno == EINTR); 00262 00263 return n_chars; 00264 }
int copy_file | ( | const char * | source, | |
const char * | dest, | |||
mode_t | mode | |||
) |
Copy a file.
This is used in conjunction with the --temp-dir, --backup, and --copy-dest options.
参照先 buf・do_open()・errno・FERROR・FINFO・full_fname()・full_write()・robust_unlink()・rsyserr()・safe_read().
参照元 robust_rename()・try_dests_reg().
00271 { 00272 int ifd; 00273 int ofd; 00274 char buf[1024 * 8]; 00275 int len; /* Number of bytes read into `buf'. */ 00276 00277 ifd = do_open(source, O_RDONLY, 0); 00278 if (ifd == -1) { 00279 rsyserr(FERROR, errno, "open %s", full_fname(source)); 00280 return -1; 00281 } 00282 00283 if (robust_unlink(dest) && errno != ENOENT) { 00284 rsyserr(FERROR, errno, "unlink %s", full_fname(dest)); 00285 return -1; 00286 } 00287 00288 ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode); 00289 if (ofd == -1) { 00290 rsyserr(FERROR, errno, "open %s", full_fname(dest)); 00291 close(ifd); 00292 return -1; 00293 } 00294 00295 while ((len = safe_read(ifd, buf, sizeof buf)) > 0) { 00296 if (full_write(ofd, buf, len) < 0) { 00297 rsyserr(FERROR, errno, "write %s", full_fname(dest)); 00298 close(ifd); 00299 close(ofd); 00300 return -1; 00301 } 00302 } 00303 00304 if (len < 0) { 00305 rsyserr(FERROR, errno, "read %s", full_fname(source)); 00306 close(ifd); 00307 close(ofd); 00308 return -1; 00309 } 00310 00311 if (close(ifd) < 0) { 00312 rsyserr(FINFO, errno, "close failed on %s", 00313 full_fname(source)); 00314 } 00315 00316 if (close(ofd) < 0) { 00317 rsyserr(FERROR, errno, "close failed on %s", 00318 full_fname(dest)); 00319 return -1; 00320 } 00321 00322 return 0; 00323 }
int robust_unlink | ( | const 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.
参照先 do_rename()・do_unlink()・errno・FINFO・rprintf()・sprintf()・strlcpy()・verbose.
参照元 copy_file()・delete_item()・keep_backup()・maybe_hard_link()・recv_generator()・robust_rename().
00340 { 00341 #ifndef ETXTBSY 00342 return do_unlink(fname); 00343 #else 00344 static int counter = 1; 00345 int rc, pos, start; 00346 char path[MAXPATHLEN]; 00347 00348 rc = do_unlink(fname); 00349 if (rc == 0 || errno != ETXTBSY) 00350 return rc; 00351 00352 if ((pos = strlcpy(path, fname, MAXPATHLEN)) >= MAXPATHLEN) 00353 pos = MAXPATHLEN - 1; 00354 00355 while (pos > 0 && path[pos-1] != '/') 00356 pos--; 00357 pos += strlcpy(path+pos, ".rsync", MAXPATHLEN-pos); 00358 00359 if (pos > (MAXPATHLEN-MAX_RENAMES_DIGITS-1)) { 00360 errno = ETXTBSY; 00361 return -1; 00362 } 00363 00364 /* start where the last one left off to reduce chance of clashes */ 00365 start = counter; 00366 do { 00367 sprintf(&path[pos], "%03d", counter); 00368 if (++counter >= MAX_RENAMES) 00369 counter = 1; 00370 } while ((rc = access(path, 0)) == 0 && counter != start); 00371 00372 if (verbose > 0) { 00373 rprintf(FINFO,"renaming %s to %s because of text busy\n", 00374 fname, path); 00375 } 00376 00377 /* maybe we should return rename()'s exit status? Nah. */ 00378 if (do_rename(fname, path) != 0) { 00379 errno = ETXTBSY; 00380 return -1; 00381 } 00382 return 0; 00383 #endif 00384 }
int robust_rename | ( | char * | from, | |
char * | to, | |||
char * | partialptr, | |||
int | mode | |||
) |
参照先 copy_file()・do_rename()・do_unlink()・errno・handle_partial_dir()・robust_unlink().
参照元 finish_transfer()・robust_move().
00392 { 00393 int tries = 4; 00394 00395 while (tries--) { 00396 if (do_rename(from, to) == 0) 00397 return 0; 00398 00399 switch (errno) { 00400 #ifdef ETXTBSY 00401 case ETXTBSY: 00402 if (robust_unlink(to) != 0) 00403 return -1; 00404 break; 00405 #endif 00406 case EXDEV: 00407 if (partialptr) { 00408 if (!handle_partial_dir(partialptr,PDIR_CREATE)) 00409 return -1; 00410 to = partialptr; 00411 } 00412 if (copy_file(from, to, mode) != 0) 00413 return -2; 00414 do_unlink(from); 00415 return 1; 00416 default: 00417 return -1; 00418 } 00419 } 00420 return -1; 00421 }
pid_t do_fork | ( | void | ) |
Fork and record the pid of the child.
参照元 do_recv()・local_child()・piped_child().
00428 { 00429 pid_t newpid = fork(); 00430 00431 if (newpid != 0 && newpid != -1) { 00432 all_pids[num_pids++] = newpid; 00433 } 00434 return newpid; 00435 }
void kill_all | ( | int | sig | ) |
Kill all children.
参照元 _exit_cleanup().
00448 { 00449 int i; 00450 00451 for (i = 0; i < num_pids; i++) { 00452 /* Let's just be a little careful where we 00453 * point that gun, hey? See kill(2) for the 00454 * magic caused by negative values. */ 00455 pid_t p = all_pids[i]; 00456 00457 if (p == getpid()) 00458 continue; 00459 if (p <= 0) 00460 continue; 00461 00462 kill(p, sig); 00463 } 00464 }
int name_to_uid | ( | char * | name, | |
uid_t * | uid | |||
) |
int name_to_gid | ( | char * | name, | |
gid_t * | gid | |||
) |
int lock_range | ( | int | fd, | |
int | offset, | |||
int | len | |||
) |
Lock a byte range in a open file
参照元 claim_connection().
00496 { 00497 struct flock lock; 00498 00499 lock.l_type = F_WRLCK; 00500 lock.l_whence = SEEK_SET; 00501 lock.l_start = offset; 00502 lock.l_len = len; 00503 lock.l_pid = 0; 00504 00505 return fcntl(fd,F_SETLK,&lock) == 0; 00506 }
static int filter_server_path | ( | char * | arg | ) | [static] |
参照先 check_filter()・filter_list_struct::head・server_filter_list.
参照元 glob_expand_one().
00509 { 00510 char *s; 00511 00512 if (server_filter_list.head) { 00513 for (s = arg; (s = strchr(s, '/')) != NULL; ) { 00514 *s = '\0'; 00515 if (check_filter(&server_filter_list, arg, 1) < 0) { 00516 /* We must leave arg truncated! */ 00517 return 1; 00518 } 00519 *s++ = '/'; 00520 } 00521 } 00522 return 0; 00523 }
static void glob_expand_one | ( | char * | s, | |
char *** | argv_ptr, | |||
int * | argc_ptr, | |||
int * | maxargs_ptr | |||
) | [static] |
参照先 filter_server_path()・out_of_memory()・sanitize_path()・sanitize_paths・strdup().
参照元 glob_expand().
00527 { 00528 char **argv = *argv_ptr; 00529 int argc = *argc_ptr; 00530 int maxargs = *maxargs_ptr; 00531 #if !defined HAVE_GLOB || !defined HAVE_GLOB_H 00532 if (argc == maxargs) { 00533 maxargs += MAX_ARGS; 00534 if (!(argv = realloc_array(argv, char *, maxargs))) 00535 out_of_memory("glob_expand_one"); 00536 *argv_ptr = argv; 00537 *maxargs_ptr = maxargs; 00538 } 00539 if (!*s) 00540 s = "."; 00541 s = argv[argc++] = strdup(s); 00542 filter_server_path(s); 00543 #else 00544 glob_t globbuf; 00545 00546 if (maxargs <= argc) 00547 return; 00548 if (!*s) 00549 s = "."; 00550 00551 if (sanitize_paths) 00552 s = sanitize_path(NULL, s, "", 0); 00553 else 00554 s = strdup(s); 00555 00556 memset(&globbuf, 0, sizeof globbuf); 00557 if (!filter_server_path(s)) 00558 glob(s, 0, NULL, &globbuf); 00559 if (MAX((int)globbuf.gl_pathc, 1) > maxargs - argc) { 00560 maxargs += globbuf.gl_pathc + MAX_ARGS; 00561 if (!(argv = realloc_array(argv, char *, maxargs))) 00562 out_of_memory("glob_expand_one"); 00563 *argv_ptr = argv; 00564 *maxargs_ptr = maxargs; 00565 } 00566 if (globbuf.gl_pathc == 0) 00567 argv[argc++] = s; 00568 else { 00569 int i; 00570 free(s); 00571 for (i = 0; i < (int)globbuf.gl_pathc; i++) { 00572 if (!(argv[argc++] = strdup(globbuf.gl_pathv[i]))) 00573 out_of_memory("glob_expand_one"); 00574 } 00575 } 00576 globfree(&globbuf); 00577 #endif 00578 *argc_ptr = argc; 00579 }
void glob_expand | ( | char * | base1, | |
char *** | argv_ptr, | |||
int * | argc_ptr, | |||
int * | maxargs_ptr | |||
) |
参照先 asprintf()・glob_expand_one()・out_of_memory()・strdup().
参照元 rsync_module().
00583 { 00584 char *s = (*argv_ptr)[*argc_ptr]; 00585 char *p, *q; 00586 char *base = base1; 00587 int base_len = strlen(base); 00588 00589 if (!s || !*s) 00590 return; 00591 00592 if (strncmp(s, base, base_len) == 0) 00593 s += base_len; 00594 00595 if (!(s = strdup(s))) 00596 out_of_memory("glob_expand"); 00597 00598 if (asprintf(&base," %s/", base1) <= 0) 00599 out_of_memory("glob_expand"); 00600 base_len++; 00601 00602 for (q = s; *q; q = p + base_len) { 00603 if ((p = strstr(q, base)) != NULL) 00604 *p = '\0'; /* split it at this point */ 00605 glob_expand_one(q, argv_ptr, argc_ptr, maxargs_ptr); 00606 if (!p) 00607 break; 00608 } 00609 00610 free(s); 00611 free(base); 00612 }
void strlower | ( | char * | s | ) |
Convert a string to lower case
参照元 access_match().
00618 { 00619 while (*s) { 00620 if (isupper(*(unsigned char *)s)) 00621 *s = tolower(*(unsigned char *)s); 00622 s++; 00623 } 00624 }
size_t pathjoin | ( | char * | dest, | |
size_t | destsize, | |||
const char * | p1, | |||
const char * | p2 | |||
) |
参照先 strlcpy().
参照元 get_cvs_excludes()・hard_link_check()・log_formatted()・partial_dir_fname()・recv_files()・setup_merge_file()・try_dests_non()・try_dests_reg().
00631 { 00632 size_t len = strlcpy(dest, p1, destsize); 00633 if (len < destsize - 1) { 00634 if (!len || dest[len-1] != '/') 00635 dest[len++] = '/'; 00636 if (len < destsize - 1) 00637 len += strlcpy(dest + len, p2, destsize - len); 00638 else { 00639 dest[len] = '\0'; 00640 len += strlen(p2); 00641 } 00642 } 00643 else 00644 len += strlen(p2) + 1; /* Assume we'd insert a '/'. */ 00645 return len; 00646 }
size_t stringjoin | ( | char * | dest, | |
size_t | destsize, | |||
... | ||||
) |
参照元 establish_proxy_connection()・get_backup_name()・successful_send()・write_batch_shell_file().
00653 { 00654 va_list ap; 00655 size_t len, ret = 0; 00656 const char *src; 00657 00658 va_start(ap, destsize); 00659 while (1) { 00660 if (!(src = va_arg(ap, const char *))) 00661 break; 00662 len = strlen(src); 00663 ret += len; 00664 if (destsize > 1) { 00665 if (len >= destsize) 00666 len = destsize - 1; 00667 memcpy(dest, src, len); 00668 destsize -= len; 00669 dest += len; 00670 } 00671 } 00672 *dest = '\0'; 00673 va_end(ap); 00674 00675 return ret; 00676 }
int count_dir_elements | ( | const char * | p | ) |
参照元 receive_file_entry()・set_filter_dir().
00679 { 00680 int cnt = 0, new_component = 1; 00681 while (*p) { 00682 if (*p++ == '/') 00683 new_component = 1; 00684 else if (new_component) { 00685 new_component = 0; 00686 cnt++; 00687 } 00688 } 00689 return cnt; 00690 }
unsigned int clean_fname | ( | char * | name, | |
BOOL | collapse_dot_dot | |||
) |
参照元 log_formatted()・make_file()・parse_arguments()・parse_filter_file()・parse_merge_name()・push_dir()・receive_file_entry()・set_filter_dir()・setup_merge_file().
00697 { 00698 char *limit = name - 1, *t = name, *f = name; 00699 int anchored; 00700 00701 if (!name) 00702 return 0; 00703 00704 if ((anchored = *f == '/') != 0) 00705 *t++ = *f++; 00706 while (*f) { 00707 /* discard extra slashes */ 00708 if (*f == '/') { 00709 f++; 00710 continue; 00711 } 00712 if (*f == '.') { 00713 /* discard "." dirs (but NOT a trailing '.'!) */ 00714 if (f[1] == '/') { 00715 f += 2; 00716 continue; 00717 } 00718 /* collapse ".." dirs */ 00719 if (collapse_dot_dot 00720 && f[1] == '.' && (f[2] == '/' || !f[2])) { 00721 char *s = t - 1; 00722 if (s == name && anchored) { 00723 f += 2; 00724 continue; 00725 } 00726 while (s > limit && *--s != '/') {} 00727 if (s != t - 1 && (s < name || *s == '/')) { 00728 t = s + 1; 00729 f += 2; 00730 continue; 00731 } 00732 limit = t + 2; 00733 } 00734 } 00735 while (*f && (*t++ = *f++) != '/') {} 00736 } 00737 00738 if (t > name+anchored && t[-1] == '/') 00739 t--; 00740 if (t == name) 00741 *t++ = '.'; 00742 *t = '\0'; 00743 00744 return t - name; 00745 }
char* sanitize_path | ( | char * | dest, | |
const char * | p, | |||
const char * | rootdir, | |||
int | depth | |||
) |
参照先 lp_path()・module_id・out_of_memory()・relative_paths.
参照元 glob_expand_one()・make_file()・parse_arguments()・parse_merge_name()・receive_file_entry()・send_file_list().
00770 { 00771 char *start, *sanp; 00772 int rlen = 0, leave_one_dotdir = relative_paths; 00773 00774 if (dest != p) { 00775 int plen = strlen(p); 00776 if (*p == '/') { 00777 if (!rootdir) 00778 rootdir = lp_path(module_id); 00779 rlen = strlen(rootdir); 00780 depth = 0; 00781 p++; 00782 } 00783 if (dest) { 00784 if (rlen + plen + 1 >= MAXPATHLEN) 00785 return NULL; 00786 } else if (!(dest = new_array(char, rlen + plen + 1))) 00787 out_of_memory("sanitize_path"); 00788 if (rlen) { 00789 memcpy(dest, rootdir, rlen); 00790 if (rlen > 1) 00791 dest[rlen++] = '/'; 00792 } 00793 } 00794 00795 start = sanp = dest + rlen; 00796 while (*p != '\0') { 00797 /* discard leading or extra slashes */ 00798 if (*p == '/') { 00799 p++; 00800 continue; 00801 } 00802 /* this loop iterates once per filename component in p. 00803 * both p (and sanp if the original had a slash) should 00804 * always be left pointing after a slash 00805 */ 00806 if (*p == '.' && (p[1] == '/' || p[1] == '\0')) { 00807 if (leave_one_dotdir && p[1]) 00808 leave_one_dotdir = 0; 00809 else { 00810 /* skip "." component */ 00811 p++; 00812 continue; 00813 } 00814 } 00815 if (*p == '.' && p[1] == '.' && (p[2] == '/' || p[2] == '\0')) { 00816 /* ".." component followed by slash or end */ 00817 if (depth <= 0 || sanp != start) { 00818 p += 2; 00819 if (sanp != start) { 00820 /* back up sanp one level */ 00821 --sanp; /* now pointing at slash */ 00822 while (sanp > start && sanp[-1] != '/') { 00823 /* skip back up to slash */ 00824 sanp--; 00825 } 00826 } 00827 continue; 00828 } 00829 /* allow depth levels of .. at the beginning */ 00830 depth--; 00831 /* move the virtual beginning to leave the .. alone */ 00832 start = sanp + 3; 00833 } 00834 /* copy one component through next slash */ 00835 while (*p && (*sanp++ = *p++) != '/') {} 00836 } 00837 if (sanp == dest) { 00838 /* ended up with nothing, so put in "." component */ 00839 *sanp++ = '.'; 00840 } 00841 *sanp = '\0'; 00842 00843 return dest; 00844 }
int push_dir | ( | char * | dir | ) |
Like chdir(), but it keeps track of the current directory (in the global "curr_dir"), and ensures that the path size doesn't overflow.
Also cleans the path using the clean_fname() function.
参照先 clean_fname()・curr_dir・curr_dir_len・getcwd().
参照元 do_server_recv()・do_server_sender()・get_local_name()・main()・rsync_module()・send_file_list().
00855 { 00856 static int initialised; 00857 unsigned int len; 00858 00859 if (!initialised) { 00860 initialised = 1; 00861 getcwd(curr_dir, sizeof curr_dir - 1); 00862 curr_dir_len = strlen(curr_dir); 00863 } 00864 00865 if (!dir) /* this call was probably just to initialize */ 00866 return 0; 00867 00868 len = strlen(dir); 00869 if (len == 1 && *dir == '.') 00870 return 1; 00871 00872 if ((*dir == '/' ? len : curr_dir_len + 1 + len) >= sizeof curr_dir) 00873 return 0; 00874 00875 if (chdir(dir)) 00876 return 0; 00877 00878 if (*dir == '/') { 00879 memcpy(curr_dir, dir, len + 1); 00880 curr_dir_len = len; 00881 } else { 00882 curr_dir[curr_dir_len++] = '/'; 00883 memcpy(curr_dir + curr_dir_len, dir, len + 1); 00884 curr_dir_len += len; 00885 } 00886 00887 curr_dir_len = clean_fname(curr_dir, 1); 00888 00889 return 1; 00890 }
int pop_dir | ( | char * | dir | ) |
Reverse a push_dir() call.
You must pass in an absolute path that was copied from a prior value of "curr_dir".
参照先 curr_dir・curr_dir_len・strlcpy().
参照元 send_file_list().
00897 { 00898 if (chdir(dir)) 00899 return 0; 00900 00901 curr_dir_len = strlcpy(curr_dir, dir, sizeof curr_dir); 00902 if (curr_dir_len >= sizeof curr_dir) 00903 curr_dir_len = sizeof curr_dir - 1; 00904 00905 return 1; 00906 }
char* full_fname | ( | const char * | fn | ) |
Return a quoted string with the full pathname of the indicated filename.
The string " (in MODNAME)" may also be appended. The returned pointer remains valid until the next time full_fname() is called.
参照先 asprintf()・curr_dir・lp_name()・lp_path()・lp_use_chroot()・module_id.
参照元 copy_file()・delete_item()・do_server_recv()・do_server_sender()・finish_transfer()・generate_files()・get_local_name()・handle_delayed_updates()・hard_link_check()・hard_link_one()・keep_backup()・main()・make_bak_dir()・make_file()・maybe_hard_link()・receive_data()・recv_files()・recv_generator()・send_directory()・send_file_list()・send_files()・send_if_directory()・set_file_attrs()・try_dests_reg().
00914 { 00915 static char *result = NULL; 00916 char *m1, *m2, *m3; 00917 char *p1, *p2; 00918 00919 if (result) 00920 free(result); 00921 00922 if (*fn == '/') 00923 p1 = p2 = ""; 00924 else { 00925 p1 = curr_dir; 00926 for (p2 = p1; *p2 == '/'; p2++) {} 00927 if (*p2) 00928 p2 = "/"; 00929 } 00930 if (module_id >= 0) { 00931 m1 = " (in "; 00932 m2 = lp_name(module_id); 00933 m3 = ")"; 00934 if (p1 == curr_dir) { 00935 if (!lp_use_chroot(module_id)) { 00936 char *p = lp_path(module_id); 00937 if (*p != '/' || p[1]) 00938 p1 += strlen(p); 00939 } 00940 } 00941 } else 00942 m1 = m2 = m3 = ""; 00943 00944 asprintf(&result, "\"%s%s%s\"%s%s%s", p1, p2, fn, m1, m2, m3); 00945 00946 return result; 00947 }
char* partial_dir_fname | ( | const char * | fname | ) |
参照先 check_filter()・filter_list_struct::head・partial_dir・pathjoin()・server_filter_list.
参照元 handle_delayed_updates()・recv_files()・recv_generator().
00952 { 00953 char *t = partial_fname; 00954 int sz = sizeof partial_fname; 00955 const char *fn; 00956 00957 if ((fn = strrchr(fname, '/')) != NULL) { 00958 fn++; 00959 if (*partial_dir != '/') { 00960 int len = fn - fname; 00961 strncpy(t, fname, len); /* safe */ 00962 t += len; 00963 sz -= len; 00964 } 00965 } else 00966 fn = fname; 00967 if ((int)pathjoin(t, sz, partial_dir, fn) >= sz) 00968 return NULL; 00969 if (server_filter_list.head) { 00970 static int len; 00971 if (!len) 00972 len = strlen(partial_dir); 00973 t[len] = '\0'; 00974 if (check_filter(&server_filter_list, partial_fname, 1) < 0) 00975 return NULL; 00976 t[len] = '/'; 00977 if (check_filter(&server_filter_list, partial_fname, 0) < 0) 00978 return NULL; 00979 } 00980 00981 return partial_fname; 00982 }
int handle_partial_dir | ( | const char * | fname, | |
int | create | |||
) |
参照先 do_lstat()・do_mkdir()・do_rmdir()・do_unlink()・partial_dir.
参照元 _exit_cleanup()・finish_transfer()・handle_delayed_updates()・recv_files()・recv_generator()・robust_rename().
00987 { 00988 char *fn, *dir; 00989 00990 if (fname != partial_fname) 00991 return 1; 00992 if (!create && *partial_dir == '/') 00993 return 1; 00994 if (!(fn = strrchr(partial_fname, '/'))) 00995 return 1; 00996 00997 *fn = '\0'; 00998 dir = partial_fname; 00999 if (create) { 01000 STRUCT_STAT st; 01001 int statret = do_lstat(dir, &st); 01002 if (statret == 0 && !S_ISDIR(st.st_mode)) { 01003 if (do_unlink(dir) < 0) 01004 return 0; 01005 statret = -1; 01006 } 01007 if (statret < 0 && do_mkdir(dir, 0700) < 0) 01008 return 0; 01009 } else 01010 do_rmdir(dir); 01011 *fn = '/'; 01012 01013 return 1; 01014 }
int unsafe_symlink | ( | const char * | dest, | |
const 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.
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. |
True | if unsafe | |
False | is unsafe |
参照先 name.
参照元 keep_backup()・main()・readlink_stat()・recv_generator().
01041 { 01042 const char *name, *slash; 01043 int depth = 0; 01044 01045 /* all absolute and null symlinks are unsafe */ 01046 if (!dest || !*dest || *dest == '/') 01047 return 1; 01048 01049 /* find out what our safety margin is */ 01050 for (name = src; (slash = strchr(name, '/')) != 0; name = slash+1) { 01051 if (strncmp(name, "../", 3) == 0) { 01052 depth = 0; 01053 } else if (strncmp(name, "./", 2) == 0) { 01054 /* nothing */ 01055 } else { 01056 depth++; 01057 } 01058 } 01059 if (strcmp(name, "..") == 0) 01060 depth = 0; 01061 01062 for (name = dest; (slash = strchr(name, '/')) != 0; name = slash+1) { 01063 if (strncmp(name, "../", 3) == 0) { 01064 /* if at any point we go outside the current directory 01065 then stop - it is unsafe */ 01066 if (--depth < 0) 01067 return 1; 01068 } else if (strncmp(name, "./", 2) == 0) { 01069 /* nothing */ 01070 } else { 01071 depth++; 01072 } 01073 } 01074 if (strcmp(name, "..") == 0) 01075 depth--; 01076 01077 return (depth < 0); 01078 }
char* human_num | ( | int64 | num | ) |
参照先 human_readable・sprintf().
参照元 human_dnum()・output_summary()・rprint_progress().
01084 { 01085 static char bufs[4][128]; /* more than enough room */ 01086 static unsigned int n; 01087 char *s; 01088 01089 n = (n + 1) % (sizeof bufs / sizeof bufs[0]); 01090 01091 if (human_readable) { 01092 char units = '\0'; 01093 int mult = human_readable == 1 ? 1000 : 1024; 01094 double dnum = 0; 01095 if (num > mult*mult*mult) { 01096 dnum = (double)num / (mult*mult*mult); 01097 units = 'G'; 01098 } else if (num > mult*mult) { 01099 dnum = (double)num / (mult*mult); 01100 units = 'M'; 01101 } else if (num > mult) { 01102 dnum = (double)num / mult; 01103 units = 'K'; 01104 } 01105 if (units) { 01106 sprintf(bufs[n], "%.2f%c", dnum, units); 01107 return bufs[n]; 01108 } 01109 } 01110 01111 s = bufs[n] + sizeof bufs[0] - 1; 01112 *s = '\0'; 01113 01114 if (!num) 01115 *--s = '0'; 01116 while (num) { 01117 *--s = (num % 10) + '0'; 01118 num /= 10; 01119 } 01120 return s; 01121 }
char* human_dnum | ( | double | dnum, | |
int | decimal_digits | |||
) |
参照先 buf・human_num()・snprintf().
参照元 output_summary().
01127 { 01128 char *buf = human_num(dnum); 01129 int len = strlen(buf); 01130 if (isdigit(*(uchar*)(buf+len-1))) { 01131 /* There's extra room in buf prior to the start of the num. */ 01132 buf -= decimal_digits + 1; 01133 snprintf(buf, len + decimal_digits + 2, "%.*f", decimal_digits, dnum); 01134 } 01135 return buf; 01136 }
char* timestring | ( | time_t | t | ) |
Return the date and time as a string
参照先 strlcpy().
参照元 list_file_entry()・log_formatted()・logit().
01142 { 01143 static char TimeBuf[200]; 01144 struct tm *tm = localtime(&t); 01145 char *p; 01146 01147 #ifdef HAVE_STRFTIME 01148 strftime(TimeBuf, sizeof TimeBuf - 1, "%Y/%m/%d %H:%M:%S", tm); 01149 #else 01150 strlcpy(TimeBuf, asctime(tm), sizeof TimeBuf); 01151 #endif 01152 01153 if ((p = strchr(TimeBuf, '\n')) != NULL) 01154 *p = '\0'; 01155 01156 return TimeBuf; 01157 }
int msleep | ( | int | t | ) |
Sleep for a specified number of milliseconds.
Always returns TRUE. (In the future it might return FALSE if interrupted.)
参照先 errno.
参照元 do_recv()・option_error()・rsync_module()・sig_int()・wait_process_with_flush()・whine_about_eof()・writefd_unbuffered().
01166 { 01167 int tdiff = 0; 01168 struct timeval tval, t1, t2; 01169 01170 gettimeofday(&t1, NULL); 01171 01172 while (tdiff < t) { 01173 tval.tv_sec = (t-tdiff)/1000; 01174 tval.tv_usec = 1000*((t-tdiff)%1000); 01175 01176 errno = 0; 01177 select(0,NULL,NULL, NULL, &tval); 01178 01179 gettimeofday(&t2, NULL); 01180 tdiff = (t2.tv_sec - t1.tv_sec)*1000 + 01181 (t2.tv_usec - t1.tv_usec)/1000; 01182 } 01183 01184 return True; 01185 }
int cmp_time | ( | time_t | file1, | |
time_t | file2 | |||
) |
参照先 modify_window.
参照元 find_fuzzy()・itemize()・recv_generator()・set_file_attrs()・try_dests_reg()・unchanged_file().
01197 { 01198 if (file2 > file1) { 01199 if (file2 - file1 <= modify_window) 01200 return 0; 01201 return -1; 01202 } 01203 if (file1 - file2 <= modify_window) 01204 return 0; 01205 return 1; 01206 }
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.
参照先 asprintf().
01218 { 01219 static int (*fn)(); 01220 int ret; 01221 char *cmd; 01222 01223 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'", 01224 getpid(), getpid(), getpid()); 01225 01226 if (!fn) { 01227 static void *h; 01228 h = dlopen("/usr/local/parasoft/insure++lite/lib.linux2/libinsure.so", RTLD_LAZY); 01229 fn = dlsym(h, "_Insure_trap_error"); 01230 } 01231 01232 ret = fn(a1, a2, a3, a4, a5, a6); 01233 01234 system(cmd); 01235 01236 free(cmd); 01237 01238 return ret; 01239 }
void* _new_array | ( | unsigned int | size, | |
unsigned long | num | |||
) |
void* _realloc_array | ( | void * | ptr, | |
unsigned int | size, | |||
unsigned long | num | |||
) |
const char* find_filename_suffix | ( | const char * | fn, | |
int | fn_len, | |||
int * | len_ptr | |||
) |
参照元 find_fuzzy().
01265 { 01266 const char *suf, *s; 01267 BOOL had_tilde; 01268 int s_len; 01269 01270 /* One or more dots at the start aren't a suffix. */ 01271 while (fn_len && *fn == '.') fn++, fn_len--; 01272 01273 /* Ignore the ~ in a "foo~" filename. */ 01274 if (fn_len > 1 && fn[fn_len-1] == '~') 01275 fn_len--, had_tilde = True; 01276 else 01277 had_tilde = False; 01278 01279 /* Assume we don't find an suffix. */ 01280 suf = ""; 01281 *len_ptr = 0; 01282 01283 /* Find the last significant suffix. */ 01284 for (s = fn + fn_len; fn_len > 1; ) { 01285 while (*--s != '.' && s != fn) {} 01286 if (s == fn) 01287 break; 01288 s_len = fn_len - (s - fn); 01289 fn_len = s - fn; 01290 if (s_len == 4) { 01291 if (strcmp(s+1, "bak") == 0 01292 || strcmp(s+1, "old") == 0) 01293 continue; 01294 } else if (s_len == 5) { 01295 if (strcmp(s+1, "orig") == 0) 01296 continue; 01297 } else if (s_len > 2 && had_tilde 01298 && s[1] == '~' && isdigit(*(uchar*)(s+2))) 01299 continue; 01300 *len_ptr = s_len; 01301 suf = s; 01302 if (s_len == 1) 01303 break; 01304 /* Determine if the suffix is all digits. */ 01305 for (s++, s_len--; s_len > 0; s++, s_len--) { 01306 if (!isdigit(*(uchar*)s)) 01307 return suf; 01308 } 01309 /* An all-digit suffix may not be that signficant. */ 01310 s = suf; 01311 } 01312 01313 return suf; 01314 }
uint32 fuzzy_distance | ( | const char * | s1, | |
int | len1, | |||
const char * | s2, | |||
int | len2 | |||
) |
参照元 find_fuzzy().
01326 { 01327 uint32 a[MAXPATHLEN], diag, above, left, diag_inc, above_inc, left_inc; 01328 int32 cost; 01329 int i1, i2; 01330 01331 if (!len1 || !len2) { 01332 if (!len1) { 01333 s1 = s2; 01334 len1 = len2; 01335 } 01336 for (i1 = 0, cost = 0; i1 < len1; i1++) 01337 cost += s1[i1]; 01338 return (int32)len1 * UNIT + cost; 01339 } 01340 01341 for (i2 = 0; i2 < len2; i2++) 01342 a[i2] = (i2+1) * UNIT; 01343 01344 for (i1 = 0; i1 < len1; i1++) { 01345 diag = i1 * UNIT; 01346 above = (i1+1) * UNIT; 01347 for (i2 = 0; i2 < len2; i2++) { 01348 left = a[i2]; 01349 if ((cost = *((uchar*)s1+i1) - *((uchar*)s2+i2)) != 0) { 01350 if (cost < 0) 01351 cost = UNIT - cost; 01352 else 01353 cost = UNIT + cost; 01354 } 01355 diag_inc = diag + cost; 01356 left_inc = left + UNIT + *((uchar*)s1+i1); 01357 above_inc = above + UNIT + *((uchar*)s2+i2); 01358 a[i2] = above = left < above 01359 ? (left_inc < diag_inc ? left_inc : diag_inc) 01360 : (above_inc < diag_inc ? above_inc : diag_inc); 01361 diag = left; 01362 } 01363 } 01364 01365 return a[len2-1]; 01366 }
struct bitbag* bitbag_create | ( | int | max_ndx | ) |
参照先 bitbag::bits・out_of_memory()・bitbag::slot_cnt.
参照元 recv_files().
01378 { 01379 struct bitbag *bb = new(struct bitbag); 01380 bb->slot_cnt = (max_ndx + BB_PER_SLOT_BITS - 1) / BB_PER_SLOT_BITS; 01381 01382 if (!(bb->bits = (uint32**)calloc(bb->slot_cnt, sizeof (uint32*)))) 01383 out_of_memory("bitbag_create"); 01384 01385 return bb; 01386 }
void bitbag_set_bit | ( | struct bitbag * | bb, | |
int | ndx | |||
) |
参照先 bitbag::bits・out_of_memory().
参照元 recv_files().
01389 { 01390 int slot = ndx / BB_PER_SLOT_BITS; 01391 ndx %= BB_PER_SLOT_BITS; 01392 01393 if (!bb->bits[slot]) { 01394 if (!(bb->bits[slot] = (uint32*)calloc(BB_PER_SLOT_INTS, 4))) 01395 out_of_memory("bitbag_set_bit"); 01396 } 01397 01398 bb->bits[slot][ndx/32] |= 1u << (ndx % 32); 01399 }
void bitbag_clear_bit | ( | struct bitbag * | bb, | |
int | ndx | |||
) |
参照先 bitbag::bits.
01403 { 01404 int slot = ndx / BB_PER_SLOT_BITS; 01405 ndx %= BB_PER_SLOT_BITS; 01406 01407 if (!bb->bits[slot]) 01408 return; 01409 01410 bb->bits[slot][ndx/32] &= ~(1u << (ndx % 32)); 01411 }
int bitbag_check_bit | ( | struct bitbag * | bb, | |
int | ndx | |||
) |
参照先 bitbag::bits.
01414 { 01415 int slot = ndx / BB_PER_SLOT_BITS; 01416 ndx %= BB_PER_SLOT_BITS; 01417 01418 if (!bb->bits[slot]) 01419 return 0; 01420 01421 return bb->bits[slot][ndx/32] & (1u << (ndx % 32)) ? 1 : 0; 01422 }
int bitbag_next_bit | ( | struct bitbag * | bb, | |
int | after | |||
) |
参照先 bitbag::bits・bitbag::slot_cnt.
01427 { 01428 uint32 bits, mask; 01429 int i, ndx = after + 1; 01430 int slot = ndx / BB_PER_SLOT_BITS; 01431 ndx %= BB_PER_SLOT_BITS; 01432 01433 mask = (1u << (ndx % 32)) - 1; 01434 for (i = ndx / 32; slot < bb->slot_cnt; slot++, i = mask = 0) { 01435 if (!bb->bits[slot]) 01436 continue; 01437 for ( ; i < BB_PER_SLOT_INTS; i++, mask = 0) { 01438 if (!(bits = bb->bits[slot][i] & ~mask)) 01439 continue; 01440 /* The xor magic figures out the lowest enabled bit in 01441 * bits, and the switch quickly computes log2(bit). */ 01442 switch (bits ^ (bits & (bits-1))) { 01443 #define LOG2(n) case 1u << n: return slot*BB_PER_SLOT_BITS + i*32 + n 01444 LOG2(0); LOG2(1); LOG2(2); LOG2(3); 01445 LOG2(4); LOG2(5); LOG2(6); LOG2(7); 01446 LOG2(8); LOG2(9); LOG2(10); LOG2(11); 01447 LOG2(12); LOG2(13); LOG2(14); LOG2(15); 01448 LOG2(16); LOG2(17); LOG2(18); LOG2(19); 01449 LOG2(20); LOG2(21); LOG2(22); LOG2(23); 01450 LOG2(24); LOG2(25); LOG2(26); LOG2(27); 01451 LOG2(28); LOG2(29); LOG2(30); LOG2(31); 01452 } 01453 return -1; /* impossible... */ 01454 } 01455 } 01456 01457 return -1; 01458 }
int module_id |
clientserver.c の 60 行で定義されています。
int modify_window |
int relative_paths |
int human_readable |
mode_t orig_umask |
char* partial_dir |
int sanitize_paths = 0 |
pid_t all_pids[10] [static] |
int num_pids [static] |
unsigned int curr_dir_len |
char partial_fname[MAXPATHLEN] [static] |