|
version 1.1.1.2, 2013/10/14 07:51:14
|
version 1.1.1.3, 2016/11/01 09:54:32
|
|
Line 4
|
Line 4
|
| * Copyright (C) 1996 Andrew Tridgell |
* Copyright (C) 1996 Andrew Tridgell |
| * Copyright (C) 1996 Paul Mackerras |
* Copyright (C) 1996 Paul Mackerras |
| * Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org> |
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org> |
| * Copyright (C) 2002-2013 Wayne Davison | * Copyright (C) 2002-2015 Wayne Davison |
| * |
* |
| * This program is free software; you can redistribute it and/or modify |
* This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
* it under the terms of the GNU General Public License as published by |
|
Line 736 static struct file_struct *recv_file_entry(int f, stru
|
Line 736 static struct file_struct *recv_file_entry(int f, stru
|
| } |
} |
| #endif |
#endif |
| |
|
| if (*thisname) | if (*thisname |
| clean_fname(thisname, 0); | && (clean_fname(thisname, CFN_REFUSE_DOT_DOT_DIRS) < 0 || (!relative_paths && *thisname == '/'))) { |
| | rprintf(FERROR, "ABORTING due to unsafe pathname from sender: %s\n", thisname); |
| | exit_cleanup(RERR_PROTOCOL); |
| | } |
| |
|
| if (sanitize_paths) |
if (sanitize_paths) |
| sanitize_path(thisname, thisname, "", 0, SP_DEFAULT); |
sanitize_path(thisname, thisname, "", 0, SP_DEFAULT); |
|
Line 945 static struct file_struct *recv_file_entry(int f, stru
|
Line 948 static struct file_struct *recv_file_entry(int f, stru
|
| memcpy(bp, basename, basename_len); |
memcpy(bp, basename, basename_len); |
| |
|
| #ifdef SUPPORT_HARD_LINKS |
#ifdef SUPPORT_HARD_LINKS |
| if (xflags & XMIT_HLINKED) | if (xflags & XMIT_HLINKED |
| | #ifndef CAN_HARDLINK_SYMLINK |
| | && !S_ISLNK(mode) |
| | #endif |
| | #ifndef CAN_HARDLINK_SPECIAL |
| | && !IS_SPECIAL(mode) && !IS_DEVICE(mode) |
| | #endif |
| | ) |
| file->flags |= FLAG_HLINKED; |
file->flags |= FLAG_HLINKED; |
| #endif |
#endif |
| file->modtime = (time_t)modtime; |
file->modtime = (time_t)modtime; |
|
Line 1156 struct file_struct *make_file(const char *fname, struc
|
Line 1166 struct file_struct *make_file(const char *fname, struc
|
| if (sanitize_paths) |
if (sanitize_paths) |
| sanitize_path(thisname, thisname, "", 0, SP_DEFAULT); |
sanitize_path(thisname, thisname, "", 0, SP_DEFAULT); |
| |
|
| if (stp && (S_ISDIR(stp->st_mode) || stp->st_mode == 0)) { | if (stp && (S_ISDIR(stp->st_mode) || IS_MISSING_FILE(*stp))) { |
| /* This is needed to handle a "symlink/." with a --relative |
/* This is needed to handle a "symlink/." with a --relative |
| * dir, or a request to delete a specific file. */ |
* dir, or a request to delete a specific file. */ |
| st = *stp; |
st = *stp; |
|
Line 1200 struct file_struct *make_file(const char *fname, struc
|
Line 1210 struct file_struct *make_file(const char *fname, struc
|
| full_fname(thisname)); |
full_fname(thisname)); |
| } |
} |
| return NULL; |
return NULL; |
| } else if (st.st_mode == 0) { | } else if (IS_MISSING_FILE(st)) { |
| io_error |= IOERR_GENERAL; |
io_error |= IOERR_GENERAL; |
| rprintf(FINFO, "skipping file with bogus (zero) st_mode: %s\n", |
rprintf(FINFO, "skipping file with bogus (zero) st_mode: %s\n", |
| full_fname(thisname)); |
full_fname(thisname)); |
|
Line 1303 struct file_struct *make_file(const char *fname, struc
|
Line 1313 struct file_struct *make_file(const char *fname, struc
|
| #endif |
#endif |
| |
|
| if (always_checksum && am_sender && S_ISREG(st.st_mode)) { |
if (always_checksum && am_sender && S_ISREG(st.st_mode)) { |
| file_checksum(thisname, tmp_sum, st.st_size); | file_checksum(thisname, &st, tmp_sum); |
| if (sender_keeps_checksum) |
if (sender_keeps_checksum) |
| extra_len += SUM_EXTRA_CNT * EXTRA_LEN; |
extra_len += SUM_EXTRA_CNT * EXTRA_LEN; |
| } |
} |
|
Line 2290 struct file_list *send_file_list(int f, int argc, char
|
Line 2300 struct file_list *send_file_list(int f, int argc, char
|
| } else |
} else |
| fn = p; |
fn = p; |
| send_implied_dirs(f, flist, fbuf, fbuf, p, flags, |
send_implied_dirs(f, flist, fbuf, fbuf, p, flags, |
| st.st_mode == 0 ? MISSING_NAME : name_type); | IS_MISSING_FILE(st) ? MISSING_NAME : name_type); |
| if (fn == p) |
if (fn == p) |
| continue; |
continue; |
| } |
} |
|
Line 2425 struct file_list *send_file_list(int f, int argc, char
|
Line 2435 struct file_list *send_file_list(int f, int argc, char
|
| return flist; |
return flist; |
| } |
} |
| |
|
| struct file_list *recv_file_list(int f) | struct file_list *recv_file_list(int f, int dir_ndx) |
| { |
{ |
| |
const char *good_dirname = NULL; |
| struct file_list *flist; |
struct file_list *flist; |
| int dstart, flags; |
int dstart, flags; |
| int64 start_read; |
int64 start_read; |
|
Line 2482 struct file_list *recv_file_list(int f)
|
Line 2493 struct file_list *recv_file_list(int f)
|
| flist_expand(flist, 1); |
flist_expand(flist, 1); |
| file = recv_file_entry(f, flist, flags); |
file = recv_file_entry(f, flist, flags); |
| |
|
| |
if (inc_recurse) { |
| |
static const char empty_dir[] = "\0"; |
| |
const char *cur_dir = file->dirname ? file->dirname : empty_dir; |
| |
if (relative_paths && *cur_dir == '/') |
| |
cur_dir++; |
| |
if (cur_dir != good_dirname) { |
| |
const char *d = dir_ndx >= 0 ? f_name(dir_flist->files[dir_ndx], NULL) : empty_dir; |
| |
if (strcmp(cur_dir, d) != 0) { |
| |
rprintf(FERROR, |
| |
"ABORTING due to invalid path from sender: %s/%s\n", |
| |
cur_dir, file->basename); |
| |
exit_cleanup(RERR_PROTOCOL); |
| |
} |
| |
good_dirname = cur_dir; |
| |
} |
| |
} |
| |
|
| if (S_ISREG(file->mode)) { |
if (S_ISREG(file->mode)) { |
| /* Already counted */ |
/* Already counted */ |
| } else if (S_ISDIR(file->mode)) { |
} else if (S_ISDIR(file->mode)) { |
|
Line 2553 struct file_list *recv_file_list(int f)
|
Line 2581 struct file_list *recv_file_list(int f)
|
| rprintf(FINFO, "[%s] flist_eof=1\n", who_am_i()); |
rprintf(FINFO, "[%s] flist_eof=1\n", who_am_i()); |
| } |
} |
| |
|
| |
/* The --relative option sends paths with a leading slash, so we need |
| |
* to specify the strip_root option here. We rejected leading slashes |
| |
* for a non-relative transfer in recv_file_entry(). */ |
| flist_sort_and_clean(flist, relative_paths); |
flist_sort_and_clean(flist, relative_paths); |
| |
|
| if (protocol_version < 30) { |
if (protocol_version < 30) { |
|
Line 2602 void recv_additional_file_list(int f)
|
Line 2633 void recv_additional_file_list(int f)
|
| rprintf(FINFO, "[%s] receiving flist for dir %d\n", |
rprintf(FINFO, "[%s] receiving flist for dir %d\n", |
| who_am_i(), ndx); |
who_am_i(), ndx); |
| } |
} |
| flist = recv_file_list(f); | flist = recv_file_list(f, ndx); |
| flist->parent_ndx = ndx; |
flist->parent_ndx = ndx; |
| } |
} |
| } |
} |
|
Line 2656 int flist_find(struct file_list *flist, struct file_st
|
Line 2687 int flist_find(struct file_list *flist, struct file_st
|
| high = mid - 1; |
high = mid - 1; |
| } |
} |
| return -1; |
return -1; |
| |
} |
| |
|
| |
/* Search for a name in the file list. You must specify want_dir_match as: |
| |
* 1=match directories, 0=match non-directories, or -1=match either. */ |
| |
int flist_find_name(struct file_list *flist, const char *fname, int want_dir_match) |
| |
{ |
| |
struct { /* We have to create a temporary file_struct for the search. */ |
| |
struct file_struct f; |
| |
char name_space[MAXPATHLEN]; |
| |
} t; |
| |
char fbuf[MAXPATHLEN]; |
| |
const char *slash = strrchr(fname, '/'); |
| |
const char *basename = slash ? slash+1 : fname; |
| |
|
| |
memset(&t.f, 0, FILE_STRUCT_LEN); |
| |
memcpy((void *)t.f.basename, basename, strlen(basename)+1); |
| |
|
| |
if (slash) { |
| |
strlcpy(fbuf, fname, slash - fname + 1); |
| |
t.f.dirname = fbuf; |
| |
} else |
| |
t.f.dirname = NULL; |
| |
|
| |
t.f.mode = want_dir_match > 0 ? S_IFDIR : S_IFREG; |
| |
|
| |
if (want_dir_match < 0) |
| |
return flist_find_ignore_dirness(flist, &t.f); |
| |
return flist_find(flist, &t.f); |
| } |
} |
| |
|
| /* Search for an identically-named item in the file list. Differs from |
/* Search for an identically-named item in the file list. Differs from |