summaryrefslogtreecommitdiff
path: root/flist.c
diff options
context:
space:
mode:
authorDavid Dykstra <dwd@samba.org>1999-02-17 19:34:40 +0000
committerDavid Dykstra <dwd@samba.org>1999-02-17 19:34:40 +0000
commitb53136076392ff881a03baff19232aadc4617f92 (patch)
treef4a49d1f2f59be4b633503c1262a0f52658ca882 /flist.c
parentb567933566b3b2d5e863685f43f7330b4369b5e9 (diff)
downloadrsync-b53136076392ff881a03baff19232aadc4617f92.tar.gz
rsync-b53136076392ff881a03baff19232aadc4617f92.tar.bz2
rsync-b53136076392ff881a03baff19232aadc4617f92.zip
Added --copy-unsafe-links option which is like --copy-links except it is
only for symlinks that point outside the source tree. Suggested by Charles Hines <chuck_hines@VNET.IBM.COM> in PR#1376. Also apply the option to any symbolic links in the source portion of a path when --relative is used, as suggested by Francis Montagnac <Francis.Montagnac@sophia.inria.fr> on the rsync mailing list in a message titled "New option: --copy-parent-links".
Diffstat (limited to 'flist.c')
-rw-r--r--flist.c50
1 files changed, 36 insertions, 14 deletions
diff --git a/flist.c b/flist.c
index e7b1f139..2ec04c88 100644
--- a/flist.c
+++ b/flist.c
@@ -44,9 +44,12 @@ extern int preserve_gid;
extern int preserve_times;
extern int relative_paths;
extern int copy_links;
+extern int copy_unsafe_links;
extern int remote_version;
extern int io_error;
+static char topsrcname[MAXPATHLEN];
+
static struct exclude_struct **local_exclude_list;
static void clean_flist(struct file_list *flist, int strip_root);
@@ -85,6 +88,32 @@ static void list_file_entry(struct file_struct *f)
}
+int readlink_stat(const char *Path, STRUCT_STAT *Buffer, char *Linkbuf)
+{
+#if SUPPORT_LINKS
+ if (copy_links) {
+ return do_stat(Path, Buffer);
+ }
+ if (do_lstat(Path, Buffer) == -1) {
+ return -1;
+ }
+ if (S_ISLNK(Buffer->st_mode)) {
+ int l;
+ if ((l = readlink(Path,Linkbuf,MAXPATHLEN-1)) == -1) {
+ return -1;
+ }
+ Linkbuf[l] = 0;
+ if (copy_unsafe_links && (topsrcname[0] != '\0') &&
+ unsafe_symlink(Linkbuf, topsrcname)) {
+ return do_stat(Path, Buffer);
+ }
+ }
+ return 0;
+#else
+ return do_stat(Path, Buffer);
+#endif
+}
+
int link_stat(const char *Path, STRUCT_STAT *Buffer)
{
#if SUPPORT_LINKS
@@ -373,6 +402,7 @@ static struct file_struct *make_file(char *fname)
char sum[SUM_LENGTH];
char *p;
char cleaned_name[MAXPATHLEN];
+ char linkbuf[MAXPATHLEN];
strlcpy(cleaned_name, fname, MAXPATHLEN);
cleaned_name[MAXPATHLEN-1] = 0;
@@ -381,7 +411,7 @@ static struct file_struct *make_file(char *fname)
memset(sum,0,SUM_LENGTH);
- if (link_stat(fname,&st) != 0) {
+ if (readlink_stat(fname,&st,linkbuf) != 0) {
io_error = 1;
rprintf(FERROR,"%s: %s\n",
fname,strerror(errno));
@@ -437,16 +467,7 @@ static struct file_struct *make_file(char *fname)
#if SUPPORT_LINKS
if (S_ISLNK(st.st_mode)) {
- int l;
- char lnk[MAXPATHLEN];
- if ((l=readlink(fname,lnk,MAXPATHLEN-1)) == -1) {
- io_error=1;
- rprintf(FERROR,"readlink %s : %s\n",
- fname,strerror(errno));
- return NULL;
- }
- lnk[l] = 0;
- file->link = strdup(lnk);
+ file->link = strdup(linkbuf);
}
#endif
@@ -609,8 +630,7 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
}
for (i=0;i<argc;i++) {
- char fname2[MAXPATHLEN];
- char *fname = fname2;
+ char *fname = topsrcname;
strlcpy(fname,argv[i],MAXPATHLEN);
@@ -653,7 +673,7 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
for (p=fname+1; (p=strchr(p,'/')); p++) {
int copy_links_saved = copy_links;
*p = 0;
- copy_links = 0;
+ copy_links = copy_unsafe_links;
send_file_name(f, flist, fname, 0, 0);
copy_links = copy_links_saved;
*p = '/';
@@ -695,6 +715,8 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
}
}
+ topsrcname[0] = '\0';
+
if (f != -1) {
send_file_entry(NULL,f,0);
}