summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>1998-07-17 10:00:43 +0000
committerAndrew Tridgell <tridge@samba.org>1998-07-17 10:00:43 +0000
commitd853783f213a67f9461c1f72eb612bc3c99f87be (patch)
treeb057e3261e283bee1d06b6f576b9efd922343240
parent298c10d5bb83a6c3fc1ee6583383c6ae26e12751 (diff)
downloadrsync-d853783f213a67f9461c1f72eb612bc3c99f87be.tar.gz
rsync-d853783f213a67f9461c1f72eb612bc3c99f87be.tar.bz2
rsync-d853783f213a67f9461c1f72eb612bc3c99f87be.zip
added the --safe-links option to disallow symlinks outside the
destination tree
-rw-r--r--options.c596
-rw-r--r--rsync.c12
-rw-r--r--rsync.yo13
3 files changed, 327 insertions, 294 deletions
diff --git a/options.c b/options.c
index 02434d5e..bd0e5232 100644
--- a/options.c
+++ b/options.c
@@ -58,6 +58,7 @@ int am_client=0;
int do_stats=0;
int do_progress=0;
int keep_partial=0;
+int safe_symlinks=0;
int block_size=BLOCK_SIZE;
@@ -95,6 +96,7 @@ void usage(int F)
rprintf(F," -u, --update update only (don't overwrite newer files)\n");
rprintf(F," -l, --links preserve soft links\n");
rprintf(F," -L, --copy-links treat soft links like regular files\n");
+ rprintf(F," --safe-links ignore links outside the destination tree\n");
rprintf(F," -H, --hard-links preserve hard links\n");
rprintf(F," -p, --perms preserve permissions\n");
rprintf(F," -o, --owner preserve owner (root only)\n");
@@ -141,7 +143,8 @@ void usage(int F)
enum {OPT_VERSION,OPT_SUFFIX,OPT_SENDER,OPT_SERVER,OPT_EXCLUDE,
OPT_EXCLUDE_FROM,OPT_DELETE,OPT_NUMERIC_IDS,OPT_RSYNC_PATH,
OPT_FORCE,OPT_TIMEOUT,OPT_DAEMON,OPT_CONFIG,OPT_PORT,
- OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_STATS, OPT_PARTIAL, OPT_PROGRESS};
+ OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_STATS, OPT_PARTIAL, OPT_PROGRESS,
+ OPT_SAFE_LINKS};
static char *short_options = "oblLWHpguDCtcahvrRIxnSe:B:T:z";
@@ -174,6 +177,7 @@ static struct option long_options[] = {
{"perms", 0, 0, 'p'},
{"links", 0, 0, 'l'},
{"copy-links", 0, 0, 'L'},
+ {"safe-links", 0, 0, OPT_SAFE_LINKS},
{"whole-file", 0, 0, 'W'},
{"hard-links", 0, 0, 'H'},
{"owner", 0, 0, 'o'},
@@ -195,316 +199,322 @@ static struct option long_options[] = {
void parse_arguments(int argc, char *argv[])
{
- int opt;
- int option_index;
-
- while ((opt = getopt_long(argc, argv,
- short_options, long_options, &option_index))
- != -1) {
- switch (opt)
- {
- case OPT_VERSION:
- rprintf(FINFO,"rsync version %s protocol version %d\n\n",
- VERSION,PROTOCOL_VERSION);
- rprintf(FINFO,"Written by Andrew Tridgell and Paul Mackerras\n");
- exit_cleanup(0);
-
- case OPT_SUFFIX:
- backup_suffix = optarg;
- break;
-
- case OPT_RSYNC_PATH:
- rsync_path = optarg;
- break;
-
- case 'I':
- ignore_times = 1;
- break;
-
- case 'x':
- one_file_system=1;
- break;
-
- case OPT_DELETE:
- delete_mode = 1;
- break;
-
- case OPT_FORCE:
- force_delete = 1;
- break;
-
- case OPT_NUMERIC_IDS:
- numeric_ids = 1;
- break;
-
- case OPT_EXCLUDE:
- add_exclude(optarg, 0);
- break;
-
- case OPT_INCLUDE:
- add_exclude(optarg, 1);
- break;
-
- case OPT_EXCLUDE_FROM:
- add_exclude_file(optarg,1, 0);
- break;
-
- case OPT_INCLUDE_FROM:
- add_exclude_file(optarg,1, 1);
- break;
-
- case 'h':
- usage(FINFO);
- exit_cleanup(0);
-
- case 'b':
- make_backups=1;
- break;
-
- case 'n':
- dry_run=1;
- break;
-
- case 'S':
- sparse_files=1;
- break;
-
- case 'C':
- cvs_exclude=1;
- break;
-
- case 'u':
- update_only=1;
- break;
-
- case 'l':
- preserve_links=1;
- break;
-
- case 'L':
- copy_links=1;
- break;
-
- case 'W':
- whole_file=1;
- break;
-
- case 'H':
+ int opt;
+ int option_index;
+
+ while ((opt = getopt_long(argc, argv,
+ short_options, long_options, &option_index))
+ != -1) {
+ switch (opt) {
+ case OPT_VERSION:
+ rprintf(FINFO,"rsync version %s protocol version %d\n\n",
+ VERSION,PROTOCOL_VERSION);
+ rprintf(FINFO,"Written by Andrew Tridgell and Paul Mackerras\n");
+ exit_cleanup(0);
+
+ case OPT_SUFFIX:
+ backup_suffix = optarg;
+ break;
+
+ case OPT_RSYNC_PATH:
+ rsync_path = optarg;
+ break;
+
+ case 'I':
+ ignore_times = 1;
+ break;
+
+ case 'x':
+ one_file_system=1;
+ break;
+
+ case OPT_DELETE:
+ delete_mode = 1;
+ break;
+
+ case OPT_FORCE:
+ force_delete = 1;
+ break;
+
+ case OPT_NUMERIC_IDS:
+ numeric_ids = 1;
+ break;
+
+ case OPT_EXCLUDE:
+ add_exclude(optarg, 0);
+ break;
+
+ case OPT_INCLUDE:
+ add_exclude(optarg, 1);
+ break;
+
+ case OPT_EXCLUDE_FROM:
+ add_exclude_file(optarg,1, 0);
+ break;
+
+ case OPT_INCLUDE_FROM:
+ add_exclude_file(optarg,1, 1);
+ break;
+
+ case OPT_SAFE_LINKS:
+ safe_symlinks=1;
+ break;
+
+ case 'h':
+ usage(FINFO);
+ exit_cleanup(0);
+
+ case 'b':
+ make_backups=1;
+ break;
+
+ case 'n':
+ dry_run=1;
+ break;
+
+ case 'S':
+ sparse_files=1;
+ break;
+
+ case 'C':
+ cvs_exclude=1;
+ break;
+
+ case 'u':
+ update_only=1;
+ break;
+
+ case 'l':
+ preserve_links=1;
+ break;
+
+ case 'L':
+ copy_links=1;
+ break;
+
+ case 'W':
+ whole_file=1;
+ break;
+
+ case 'H':
#if SUPPORT_HARD_LINKS
- preserve_hard_links=1;
+ preserve_hard_links=1;
#else
- rprintf(FERROR,"ERROR: hard links not supported on this platform\n");
- exit_cleanup(1);
+ rprintf(FERROR,"ERROR: hard links not supported on this platform\n");
+ exit_cleanup(1);
#endif
- break;
+ break;
- case 'p':
- preserve_perms=1;
- break;
+ case 'p':
+ preserve_perms=1;
+ break;
- case 'o':
- preserve_uid=1;
- break;
+ case 'o':
+ preserve_uid=1;
+ break;
- case 'g':
- preserve_gid=1;
- break;
+ case 'g':
+ preserve_gid=1;
+ break;
- case 'D':
- preserve_devices=1;
- break;
+ case 'D':
+ preserve_devices=1;
+ break;
- case 't':
- preserve_times=1;
- break;
+ case 't':
+ preserve_times=1;
+ break;
- case 'c':
- always_checksum=1;
- break;
+ case 'c':
+ always_checksum=1;
+ break;
- case 'v':
- verbose++;
- break;
+ case 'v':
+ verbose++;
+ break;
- case 'a':
- recurse=1;
+ case 'a':
+ recurse=1;
#if SUPPORT_LINKS
- preserve_links=1;
+ preserve_links=1;
#endif
- preserve_perms=1;
- preserve_times=1;
- preserve_gid=1;
- if (am_root) {
- preserve_devices=1;
- preserve_uid=1;
- }
- break;
-
- case OPT_SERVER:
- am_server = 1;
- break;
-
- case OPT_SENDER:
- if (!am_server) {
- usage(FERROR);
- exit_cleanup(1);
- }
- am_sender = 1;
- break;
-
- case 'r':
- recurse = 1;
- break;
-
- case 'R':
- relative_paths = 1;
- break;
-
- case 'e':
- shell_cmd = optarg;
- break;
-
- case 'B':
- block_size = atoi(optarg);
- break;
-
- case OPT_TIMEOUT:
- io_timeout = atoi(optarg);
- break;
-
- case 'T':
- tmpdir = optarg;
- break;
-
- case 'z':
- do_compression = 1;
- break;
-
- case OPT_DAEMON:
- am_daemon = 1;
- break;
-
- case OPT_STATS:
- do_stats = 1;
- break;
-
- case OPT_PROGRESS:
- do_progress = 1;
- break;
-
- case OPT_PARTIAL:
- keep_partial = 1;
- break;
-
- case OPT_CONFIG:
- config_file = optarg;
- break;
-
- case OPT_PORT:
- rsync_port = atoi(optarg);
- break;
-
- default:
- /* rprintf(FERROR,"bad option -%c\n",opt); */
- exit_cleanup(1);
+ preserve_perms=1;
+ preserve_times=1;
+ preserve_gid=1;
+ if (am_root) {
+ preserve_devices=1;
+ preserve_uid=1;
+ }
+ break;
+
+ case OPT_SERVER:
+ am_server = 1;
+ break;
+
+ case OPT_SENDER:
+ if (!am_server) {
+ usage(FERROR);
+ exit_cleanup(1);
+ }
+ am_sender = 1;
+ break;
+
+ case 'r':
+ recurse = 1;
+ break;
+
+ case 'R':
+ relative_paths = 1;
+ break;
+
+ case 'e':
+ shell_cmd = optarg;
+ break;
+
+ case 'B':
+ block_size = atoi(optarg);
+ break;
+
+ case OPT_TIMEOUT:
+ io_timeout = atoi(optarg);
+ break;
+
+ case 'T':
+ tmpdir = optarg;
+ break;
+
+ case 'z':
+ do_compression = 1;
+ break;
+
+ case OPT_DAEMON:
+ am_daemon = 1;
+ break;
+
+ case OPT_STATS:
+ do_stats = 1;
+ break;
+
+ case OPT_PROGRESS:
+ do_progress = 1;
+ break;
+
+ case OPT_PARTIAL:
+ keep_partial = 1;
+ break;
+
+ case OPT_CONFIG:
+ config_file = optarg;
+ break;
+
+ case OPT_PORT:
+ rsync_port = atoi(optarg);
+ break;
+
+ default:
+ /* rprintf(FERROR,"bad option -%c\n",opt); */
+ exit_cleanup(1);
+ }
}
- }
}
void server_options(char **args,int *argc)
{
- int ac = *argc;
- static char argstr[50];
- static char bsize[30];
- static char iotime[30];
- int i, x;
-
- args[ac++] = "--server";
-
- if (!am_sender)
- args[ac++] = "--sender";
-
- x = 1;
- argstr[0] = '-';
- for (i=0;i<verbose;i++)
- argstr[x++] = 'v';
- if (make_backups)
- argstr[x++] = 'b';
- if (update_only)
- argstr[x++] = 'u';
- if (dry_run)
- argstr[x++] = 'n';
- if (preserve_links)
- argstr[x++] = 'l';
- if (copy_links)
- argstr[x++] = 'L';
- if (whole_file)
- argstr[x++] = 'W';
- if (preserve_hard_links)
- argstr[x++] = 'H';
- if (preserve_uid)
- argstr[x++] = 'o';
- if (preserve_gid)
- argstr[x++] = 'g';
- if (preserve_devices)
- argstr[x++] = 'D';
- if (preserve_times)
- argstr[x++] = 't';
- if (preserve_perms)
- argstr[x++] = 'p';
- if (recurse)
- argstr[x++] = 'r';
- if (always_checksum)
- argstr[x++] = 'c';
- if (cvs_exclude)
- argstr[x++] = 'C';
- if (ignore_times)
- argstr[x++] = 'I';
- if (relative_paths)
- argstr[x++] = 'R';
- if (one_file_system)
- argstr[x++] = 'x';
- if (sparse_files)
- argstr[x++] = 'S';
- if (do_compression)
- argstr[x++] = 'z';
- argstr[x] = 0;
-
- if (x != 1) args[ac++] = argstr;
-
- if (block_size != BLOCK_SIZE) {
- sprintf(bsize,"-B%d",block_size);
- args[ac++] = bsize;
- }
-
- if (io_timeout) {
- sprintf(iotime,"--timeout=%d",io_timeout);
- args[ac++] = iotime;
- }
-
- if (strcmp(backup_suffix, BACKUP_SUFFIX)) {
- args[ac++] = "--suffix";
- args[ac++] = backup_suffix;
- }
-
- if (delete_mode)
- args[ac++] = "--delete";
-
- if (keep_partial)
- args[ac++] = "--partial";
-
- if (force_delete)
- args[ac++] = "--force";
-
- if (numeric_ids)
- args[ac++] = "--numeric-ids";
-
- if (tmpdir) {
- args[ac++] = "--temp-dir";
- args[ac++] = tmpdir;
- }
-
- *argc = ac;
+ int ac = *argc;
+ static char argstr[50];
+ static char bsize[30];
+ static char iotime[30];
+ int i, x;
+
+ args[ac++] = "--server";
+
+ if (!am_sender)
+ args[ac++] = "--sender";
+
+ x = 1;
+ argstr[0] = '-';
+ for (i=0;i<verbose;i++)
+ argstr[x++] = 'v';
+ if (make_backups)
+ argstr[x++] = 'b';
+ if (update_only)
+ argstr[x++] = 'u';
+ if (dry_run)
+ argstr[x++] = 'n';
+ if (preserve_links)
+ argstr[x++] = 'l';
+ if (copy_links)
+ argstr[x++] = 'L';
+ if (whole_file)
+ argstr[x++] = 'W';
+ if (preserve_hard_links)
+ argstr[x++] = 'H';
+ if (preserve_uid)
+ argstr[x++] = 'o';
+ if (preserve_gid)
+ argstr[x++] = 'g';
+ if (preserve_devices)
+ argstr[x++] = 'D';
+ if (preserve_times)
+ argstr[x++] = 't';
+ if (preserve_perms)
+ argstr[x++] = 'p';
+ if (recurse)
+ argstr[x++] = 'r';
+ if (always_checksum)
+ argstr[x++] = 'c';
+ if (cvs_exclude)
+ argstr[x++] = 'C';
+ if (ignore_times)
+ argstr[x++] = 'I';
+ if (relative_paths)
+ argstr[x++] = 'R';
+ if (one_file_system)
+ argstr[x++] = 'x';
+ if (sparse_files)
+ argstr[x++] = 'S';
+ if (do_compression)
+ argstr[x++] = 'z';
+ argstr[x] = 0;
+
+ if (x != 1) args[ac++] = argstr;
+
+ if (block_size != BLOCK_SIZE) {
+ sprintf(bsize,"-B%d",block_size);
+ args[ac++] = bsize;
+ }
+
+ if (io_timeout) {
+ sprintf(iotime,"--timeout=%d",io_timeout);
+ args[ac++] = iotime;
+ }
+
+ if (strcmp(backup_suffix, BACKUP_SUFFIX)) {
+ args[ac++] = "--suffix";
+ args[ac++] = backup_suffix;
+ }
+
+ if (delete_mode)
+ args[ac++] = "--delete";
+
+ if (keep_partial)
+ args[ac++] = "--partial";
+
+ if (force_delete)
+ args[ac++] = "--force";
+
+ if (safe_symlinks)
+ args[ac++] = "--safe-links";
+
+ if (numeric_ids)
+ args[ac++] = "--numeric-ids";
+
+ if (tmpdir) {
+ args[ac++] = "--temp-dir";
+ args[ac++] = tmpdir;
+ }
+
+ *argc = ac;
}
diff --git a/rsync.c b/rsync.c
index 96818277..0ed4a58b 100644
--- a/rsync.c
+++ b/rsync.c
@@ -441,6 +441,15 @@ static void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
#if SUPPORT_LINKS
char lnk[MAXPATHLEN];
int l;
+ extern int safe_symlinks;
+
+ if (safe_symlinks && unsafe_symlink(file->link, fname)) {
+ if (verbose) {
+ rprintf(FINFO,"ignoring unsafe symlink %s -> %s\n",
+ fname,file->link);
+ }
+ return;
+ }
if (statret == 0) {
l = readlink(fname,lnk,MAXPATHLEN-1);
if (l > 0) {
@@ -457,9 +466,10 @@ static void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
fname,file->link,strerror(errno));
} else {
set_perms(fname,file,NULL,0);
- if (verbose)
+ if (verbose) {
rprintf(FINFO,"%s -> %s\n",
fname,file->link);
+ }
}
#endif
return;
diff --git a/rsync.yo b/rsync.yo
index 9847ac90..36d8590b 100644
--- a/rsync.yo
+++ b/rsync.yo
@@ -193,6 +193,13 @@ Here is a short summary of the options avalable in rsync. Please refer
to the detailed description below for a complete description.
verb(
+Usage: rsync [OPTION]... SRC [USER@]HOST:DEST
+ or rsync [OPTION]... [USER@]HOST:SRC DEST
+ or rsync [OPTION]... SRC DEST
+ or rsync [OPTION]... [USER@]HOST::SRC DEST
+ or rsync [OPTION]... SRC [USER@]HOST::DEST
+
+Options
-v, --verbose increase verbosity
-c, --checksum always checksum
-a, --archive archive mode
@@ -202,6 +209,7 @@ verb(
-u, --update update only (don't overwrite newer files)
-l, --links preserve soft links
-L, --copy-links treat soft links like regular files
+ --safe-links ignore links outside the destination tree
-H, --hard-links preserve hard links
-p, --perms preserve permissions
-o, --owner preserve owner (root only)
@@ -307,6 +315,11 @@ option all symbolic links are skipped.
dit(bf(-L, --copy-links)) This tells rsync to treat symbolic links just
like ordinary files.
+dit(bf(--safe-links)) This tells rsync to ignore any symbolic links
+which point outside the destination tree. All absolute symlinks are
+also ignored. Using this option in conjunction with --relative may
+give unexpecetd results.
+
dit(bf(-H, --hard-links)) This tells rsync to recreate hard links on
the remote system to be the same as the local system. Without this
option hard links are treated like regular files.