Skip to content

Commit

Permalink
Adding the --fake-super option.
Browse files Browse the repository at this point in the history
  • Loading branch information
Wayne Davison committed Apr 24, 2007
1 parent 2ed790f commit 9439c0c
Show file tree
Hide file tree
Showing 17 changed files with 422 additions and 84 deletions.
2 changes: 1 addition & 1 deletion Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ popt_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \
popt/popthelp.o popt/poptparse.o
OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ) @BUILD_POPT@

TLS_OBJ = tls.o syscall.o lib/compat.o lib/snprintf.o lib/permstring.o
TLS_OBJ = tls.o syscall.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o

# Programs we must have to run the test cases
CHECK_PROGS = rsync$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) getfsdev$(EXEEXT) \
Expand Down
46 changes: 24 additions & 22 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ Changes since 2.6.9:
option. Prior versions used to output too many creation events for
matching items.

- The code that waits for a child pid now handles being interrupted by
a signal. This fixes a problem with the pre-xfer exec function not
being able to get the exit status from the script.
- The code that waits for a child pid now handles being interrupted by a
signal. This fixes a problem with the pre-xfer exec function not being
able to get the exit status from the script.

- A negated filter rule now sends the negation option when sending the
filter rules.
Expand Down Expand Up @@ -41,12 +41,11 @@ Changes since 2.6.9:

- The default --delete algorithm is now --delete-during when talking to a
3.x rsync. This is a faster scan than using --delete-before (which is
the default when talking to older rsync versions), and is compatible
with the new incremental recursion mode.
the default when talking to older rsync versions), and is compatible with
the new incremental recursion mode.

- Added the --delete-delay option, which is a more efficient way to
delete files at the end of the transfer without needing a separate
delete pass.
- Added the --delete-delay option, which is a more efficient way to delete
files at the end of the transfer without needing a separate delete pass.

- Added the --acls (-A) option to preserve Access Control Lists. This is
an improved version of the prior patch that was available. (If you need
Expand All @@ -58,22 +57,25 @@ Changes since 2.6.9:
to have backward compatibility with old, patched versions, the new
xattrs.diff patch that will add that.)

- You may specify --max-delete=0 to a 3.0.0 client as long as the
receiving side is at least version 3.0.0. This means that you
can pull from an older rsync with this option, but pushing to an
older rsync will generate an error. *Be sure to never specify a 0
value to an older rsync client, or it will be silently ignored.*
- Added the --fake-super option that allows a non-super user to preserve
all attributes of a file by using a special extended-attribute idiom.
There is also an analogous "fake super" option for an rsync daemon.

- You may specify --max-delete=0 to a 3.0.0 client as long as the receiving
side is at least version 3.0.0. This means that you can pull from an
older rsync with this option, but pushing to an older rsync will generate
an error. *Be sure to never specify a 0 value to an older rsync client,
or it will be silently ignored.*

- The --hard-link option now uses less memory on both the sending and
receiving side for all protocol versions. For protocol 30, the use
of a hashtable on the sending side allows us to more efficiently
convey to the receiver what files are linked together. This reduces
the amount of data sent over the socket by a considerable margin
(rather than adding more data), and limits the in-memory storage of
the device+inode information to just the sending side for the new
protocol 30, or to the receiving side when speaking an older protocol
(note that older rsync versions kept the device+inode information on
both sides).
receiving side for all protocol versions. For protocol 30, the use of a
hashtable on the sending side allows us to more efficiently convey to the
receiver what files are linked together. This reduces the amount of data
sent over the socket by a considerable margin (rather than adding more
data), and limits the in-memory storage of the device+inode information
to just the sending side for the new protocol 30, or to the receiving
side when speaking an older protocol (note that older rsync versions kept
the device+inode information on both sides).

INTERNAL:

Expand Down
4 changes: 2 additions & 2 deletions backup.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ static int make_bak_dir(char *fullpath)
if (p >= rel) {
/* Try to transfer the directory settings of the
* actual dir that the files are coming from. */
if (do_stat(rel, &sx.st) < 0) {
if (x_stat(rel, &sx.st, NULL) < 0) {
rsyserr(FERROR, errno,
"make_bak_dir stat %s failed",
full_fname(rel));
Expand Down Expand Up @@ -200,7 +200,7 @@ static int keep_backup(const char *fname)
int ret_code;

/* return if no file to keep */
if (do_lstat(fname, &sx.st) < 0)
if (x_lstat(fname, &sx.st, NULL) < 0)
return 1;
#ifdef SUPPORT_ACLS
sx.acc_acl = sx.def_acl = NULL;
Expand Down
5 changes: 5 additions & 0 deletions clientserver.c
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,11 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
if (lp_ignore_errors(module_id))
ignore_errors = 1;

if (lp_fake_super(i))
am_root = -1;
else if (am_root < 0) /* Treat --fake-super from client as --super. */
am_root = 2;

if (filesfrom_fd == 0)
filesfrom_fd = f_in;

Expand Down
36 changes: 8 additions & 28 deletions flist.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,30 +197,30 @@ static int readlink_stat(const char *path, STRUCT_STAT *stp, char *linkbuf)
rprintf(FINFO,"copying unsafe symlink \"%s\" -> \"%s\"\n",
path, linkbuf);
}
return do_stat(path, stp);
return x_stat(path, stp, NULL);
}
}
return 0;
#else
return do_stat(path, stp);
return x_stat(path, stp, NULL);
#endif
}

int link_stat(const char *path, STRUCT_STAT *stp, int follow_dirlinks)
{
#ifdef SUPPORT_LINKS
if (copy_links)
return do_stat(path, stp);
if (do_lstat(path, stp) < 0)
return x_stat(path, stp, NULL);
if (x_lstat(path, stp, NULL) < 0)
return -1;
if (follow_dirlinks && S_ISLNK(stp->st_mode)) {
STRUCT_STAT st;
if (do_stat(path, &st) == 0 && S_ISDIR(st.st_mode))
if (x_stat(path, &st, NULL) == 0 && S_ISDIR(st.st_mode))
*stp = st;
}
return 0;
#else
return do_stat(path, stp);
return x_stat(path, stp, NULL);
#endif
}

Expand Down Expand Up @@ -255,26 +255,6 @@ static int is_excluded(char *fname, int is_dir, int filter_level)
return 0;
}

static int to_wire_mode(mode_t mode)
{
#ifdef SUPPORT_LINKS
#if _S_IFLNK != 0120000
if (S_ISLNK(mode))
return (mode & ~(_S_IFMT)) | 0120000;
#endif
#endif
return mode;
}

static mode_t from_wire_mode(int mode)
{
#if _S_IFLNK != 0120000
if ((mode & (_S_IFMT)) == 0120000)
return (mode & ~(_S_IFMT)) | _S_IFLNK;
#endif
return mode;
}

static void send_directory(int f, struct file_list *flist, int ndx,
char *fbuf, int len, int flags);

Expand Down Expand Up @@ -970,7 +950,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
if (save_errno == ENOENT) {
#ifdef SUPPORT_LINKS
/* Avoid "vanished" error if symlink points nowhere. */
if (copy_links && do_lstat(thisname, &st) == 0
if (copy_links && x_lstat(thisname, &st, NULL) == 0
&& S_ISLNK(st.st_mode)) {
io_error |= IOERR_GENERAL;
rprintf(FERROR, "symlink has no referent: %s\n",
Expand Down Expand Up @@ -1142,7 +1122,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
int save_mode = file->mode;
file->mode = S_IFDIR; /* Find a directory with our name. */
if (flist_find(dir_flist, file) >= 0
&& do_stat(thisname, &st2) == 0 && S_ISDIR(st2.st_mode)) {
&& x_stat(thisname, &st2, NULL) == 0 && S_ISDIR(st2.st_mode)) {
file->modtime = st2.st_mtime;
file->len32 = 0;
file->mode = st2.st_mode;
Expand Down
6 changes: 5 additions & 1 deletion loadparm.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ typedef struct
int syslog_facility;
int timeout;

BOOL fake_super;
BOOL ignore_errors;
BOOL ignore_nonreadable;
BOOL list;
Expand Down Expand Up @@ -196,6 +197,7 @@ static service sDefault =
/* syslog_facility; */ LOG_DAEMON,
/* timeout; */ 0,

/* fake_super; */ False,
/* ignore_errors; */ False,
/* ignore_nonreadable; */ False,
/* list; */ True,
Expand Down Expand Up @@ -297,6 +299,7 @@ static struct parm_struct parm_table[] =
{"dont compress", P_STRING, P_LOCAL, &sDefault.dont_compress, NULL,0},
{"exclude from", P_STRING, P_LOCAL, &sDefault.exclude_from, NULL,0},
{"exclude", P_STRING, P_LOCAL, &sDefault.exclude, NULL,0},
{"fake super", P_BOOL, P_LOCAL, &sDefault.fake_super, NULL,0},
{"filter", P_STRING, P_LOCAL, &sDefault.filter, NULL,0},
{"gid", P_STRING, P_LOCAL, &sDefault.gid, NULL,0},
{"hosts allow", P_STRING, P_LOCAL, &sDefault.hosts_allow, NULL,0},
Expand Down Expand Up @@ -411,6 +414,7 @@ FN_LOCAL_INTEGER(lp_max_connections, max_connections)
FN_LOCAL_INTEGER(lp_max_verbosity, max_verbosity)
FN_LOCAL_INTEGER(lp_timeout, timeout)

FN_LOCAL_BOOL(lp_fake_super, fake_super)
FN_LOCAL_BOOL(lp_ignore_errors, ignore_errors)
FN_LOCAL_BOOL(lp_ignore_nonreadable, ignore_nonreadable)
FN_LOCAL_BOOL(lp_list, list)
Expand Down Expand Up @@ -814,7 +818,7 @@ BOOL lp_load(char *pszFname, int globals_only)

if (pszFname)
pstrcpy(n2,pszFname);
else if (am_server && !am_root)
else if (am_server && am_root <= 0)
pstrcpy(n2,RSYNCD_USERCONF);
else
pstrcpy(n2,RSYNCD_SYSCONF);
Expand Down
14 changes: 13 additions & 1 deletion options.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ int protocol_version = PROTOCOL_VERSION;
int sparse_files = 0;
int do_compression = 0;
int def_compress_level = Z_DEFAULT_COMPRESSION;
int am_root = 0;
int am_root = 0; /* 0 = normal, 1 = root, 2 = --super, -1 = --fake-super */
int am_server = 0;
int am_sender = 0;
int am_generator = 0;
Expand Down Expand Up @@ -328,6 +328,9 @@ void usage(enum logcode F)
rprintf(F," -t, --times preserve times\n");
rprintf(F," -O, --omit-dir-times omit directories when preserving times\n");
rprintf(F," --super receiver attempts super-user activities\n");
#ifdef SUPPORT_XATTRS
rprintf(F," --fake-super store/recover privileged attrs using xattrs\n");
#endif
rprintf(F," -S, --sparse handle sparse files efficiently\n");
rprintf(F," -n, --dry-run show what would have been transferred\n");
rprintf(F," -W, --whole-file copy files whole (without rsync algorithm)\n");
Expand Down Expand Up @@ -457,6 +460,7 @@ static struct poptOption long_options[] = {
{"modify-window", 0, POPT_ARG_INT, &modify_window, OPT_MODIFY_WINDOW, 0, 0 },
{"super", 0, POPT_ARG_VAL, &am_root, 2, 0, 0 },
{"no-super", 0, POPT_ARG_VAL, &am_root, 0, 0, 0 },
{"fake-super", 0, POPT_ARG_VAL, &am_root, -1, 0, 0 },
{"owner", 'o', POPT_ARG_VAL, &preserve_uid, 1, 0, 0 },
{"no-owner", 0, POPT_ARG_VAL, &preserve_uid, 0, 0, 0 },
{"no-o", 0, POPT_ARG_VAL, &preserve_uid, 0, 0, 0 },
Expand Down Expand Up @@ -1189,6 +1193,14 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
}
#endif

#ifndef SUPPORT_XATTRS
if (am_root < 0) {
snprintf(err_buf, sizeof err_buf,
"--fake-super requires an rsync with extended attributes enabled\n");
return 0;
}
#endif

if (write_batch && read_batch) {
snprintf(err_buf, sizeof err_buf,
"--write-batch and --read-batch can not be used together\n");
Expand Down
10 changes: 7 additions & 3 deletions rsync.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,8 @@ int set_file_attrs(const char *fname, struct file_struct *file, statx *sxp,
#ifdef SUPPORT_XATTRS
if (preserve_xattrs && fnamecmp)
set_xattr(fname, file, fnamecmp, sxp);
if (am_root < 0)
set_stat_xattr(fname, file);
#endif

if (!preserve_times || (S_ISDIR(sxp->st.st_mode) && omit_dir_times))
Expand Down Expand Up @@ -296,7 +298,9 @@ int set_file_attrs(const char *fname, struct file_struct *file, statx *sxp,
(long)sxp->st.st_gid, (long)F_GID(file));
}
}
if (do_lchown(fname,
if (am_root < 0) {
;
} else if (do_lchown(fname,
change_uid ? F_UID(file) : sxp->st.st_uid,
change_gid ? F_GID(file) : sxp->st.st_gid) != 0) {
/* shouldn't have attempted to change uid or gid
Expand All @@ -305,7 +309,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, statx *sxp,
change_uid ? "chown" : "chgrp",
full_fname(fname));
goto cleanup;
}
} else
/* a lchown had been done - we have to re-stat if the
* destination had the setuid or setgid bits set due
* to the side effect of the chown call */
Expand All @@ -332,7 +336,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, statx *sxp,

#ifdef HAVE_CHMOD
if (!BITS_EQUAL(sxp->st.st_mode, new_mode, CHMOD_BITS)) {
int ret = do_chmod(fname, new_mode);
int ret = am_root < 0 ? 0 : do_chmod(fname, new_mode);
if (ret < 0) {
rsyserr(FERROR, errno,
"failed to set permissions on %s",
Expand Down
26 changes: 26 additions & 0 deletions rsync.h
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,12 @@ typedef struct {

#include "proto.h"

#ifndef SUPPORT_XATTRS
#define x_stat(fn,fst,xst) do_stat(fn,fst)
#define x_lstat(fn,fst,xst) do_lstat(fn,fst)
#define x_fstat(fd,fst,xst) do_fstat(fd,fst)
#endif

/* We have replacement versions of these if they're missing. */
#ifndef HAVE_ASPRINTF
int asprintf(char **ptr, const char *format, ...);
Expand Down Expand Up @@ -1029,6 +1035,26 @@ int inet_pton(int af, const char *src, void *dst);
const char *get_panic_action(void);
#endif

static inline int to_wire_mode(mode_t mode)
{
#ifdef SUPPORT_LINKS
#if _S_IFLNK != 0120000
if (S_ISLNK(mode))
return (mode & ~(_S_IFMT)) | 0120000;
#endif
#endif
return mode;
}

static inline mode_t from_wire_mode(int mode)
{
#if _S_IFLNK != 0120000
if ((mode & (_S_IFMT)) == 0120000)
return (mode & ~(_S_IFMT)) | _S_IFLNK;
#endif
return mode;
}

static inline int
isDigit(const char *ptr)
{
Expand Down
Loading

0 comments on commit 9439c0c

Please sign in to comment.