*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
- * Copyright (C) 2003-2009 Wayne Davison
+ * Copyright (C) 2003-2014 Wayne Davison
*
* 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
extern int preserve_times;
extern int am_root;
extern int am_server;
+extern int am_daemon;
extern int am_sender;
extern int am_receiver;
extern int am_generator;
extern int am_starting_up;
extern int allow_8bit_chars;
extern int protocol_version;
+extern int got_kill_signal;
extern int inc_recurse;
extern int inplace;
extern int flist_eof;
if (errno == EINVAL) {
if (!(flags & ICB_INCLUDE_INCOMPLETE))
goto finish;
+ if (!ocnt)
+ goto e2big;
} else if (errno == EILSEQ) {
if (!(flags & ICB_INCLUDE_BAD))
goto finish;
+ if (!ocnt)
+ goto e2big;
} else if (errno == E2BIG) {
size_t siz;
+ e2big:
opos = obuf - out->buf;
if (flags & ICB_CIRCULAR_OUT && out->pos > 1 && opos > out->pos) {
/* We are in a divided circular buffer at the physical
}
*obuf++ = *ibuf++;
ocnt--, icnt--;
+ if (!icnt)
+ break;
}
}
get_acl(fname, sxp);
#endif
-#ifdef SUPPORT_XATTRS
- if (am_root < 0)
- set_stat_xattr(fname, file, new_mode);
- if (preserve_xattrs && fnamecmp)
- set_xattr(fname, file, fnamecmp, sxp);
-#endif
-
- if (!preserve_times
- || (!(preserve_times & PRESERVE_DIR_TIMES) && S_ISDIR(sxp->st.st_mode))
- || (!(preserve_times & PRESERVE_LINK_TIMES) && S_ISLNK(sxp->st.st_mode)))
- flags |= ATTRS_SKIP_MTIME;
- if (!(flags & ATTRS_SKIP_MTIME)
- && cmp_time(sxp->st.st_mtime, file->modtime) != 0) {
- int ret = set_modtime(fname, file->modtime, F_MOD_NSEC(file), sxp->st.st_mode);
- if (ret < 0) {
- rsyserr(FERROR_XFER, errno, "failed to set times on %s",
- full_fname(fname));
- goto cleanup;
- }
- if (ret == 0) /* ret == 1 if symlink could not be set */
- updated = 1;
- else
- file->flags |= FLAG_TIME_FAILED;
- }
-
change_uid = am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file);
change_gid = gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
&& sxp->st.st_gid != (gid_t)F_GROUP(file);
updated = 1;
}
+#ifdef SUPPORT_XATTRS
+ if (am_root < 0)
+ set_stat_xattr(fname, file, new_mode);
+ if (preserve_xattrs && fnamecmp)
+ set_xattr(fname, file, fnamecmp, sxp);
+#endif
+
+ if (!preserve_times
+ || (!(preserve_times & PRESERVE_DIR_TIMES) && S_ISDIR(sxp->st.st_mode))
+ || (!(preserve_times & PRESERVE_LINK_TIMES) && S_ISLNK(sxp->st.st_mode)))
+ flags |= ATTRS_SKIP_MTIME;
+ if (!(flags & ATTRS_SKIP_MTIME)
+ && cmp_time(sxp->st.st_mtime, file->modtime) != 0) {
+ int ret = set_modtime(fname, file->modtime, F_MOD_NSEC(file), sxp->st.st_mode);
+ if (ret < 0) {
+ rsyserr(FERROR_XFER, errno, "failed to set times on %s",
+ full_fname(fname));
+ goto cleanup;
+ }
+ if (ret == 0) /* ret == 1 if symlink could not be set */
+ updated = 1;
+ else
+ file->flags |= FLAG_TIME_FAILED;
+ }
+
#ifdef SUPPORT_ACLS
/* It's OK to call set_acl() now, even for a dir, as the generator
* will enable owner-writability using chmod, if necessary.
rprintf(FCLIENT, "%s is uptodate\n", fname);
}
cleanup:
- if (sxp == &sx2) {
-#ifdef SUPPORT_ACLS
- if (preserve_acls)
- free_acl(&sx2);
-#endif
-#ifdef SUPPORT_XATTRS
- if (preserve_xattrs)
- free_xattr(&sx2);
-#endif
- }
+ if (sxp == &sx2)
+ free_stat_x(&sx2);
return updated;
}
-RETSIGTYPE sig_int(UNUSED(int val))
+/* This is only called for SIGINT, SIGHUP, and SIGTERM. */
+RETSIGTYPE sig_int(int sig_num)
{
/* KLUGE: if the user hits Ctrl-C while ssh is prompting
* for a password, then our cleanup's sending of a SIGUSR1
* not ssh waiting for a password, then this tiny delay
* shouldn't hurt anything. */
msleep(400);
+
+ /* If we're an rsync daemon listener (not a daemon server),
+ * we'll exit with status 0 if we received SIGTERM. */
+ if (am_daemon && !am_server && sig_num == SIGTERM)
+ exit_cleanup(0);
+
+ /* If the signal arrived on the server side (or for the receiver
+ * process on the client), we want to try to do a controlled shutdown
+ * that lets the client side (generator process) know what happened.
+ * To do this, we set a flag and let the normal process handle the
+ * shutdown. We only attempt this if multiplexed IO is in effect and
+ * we didn't already set the flag. */
+ if (!got_kill_signal && (am_server || am_receiver)) {
+ got_kill_signal = sig_num;
+ return;
+ }
+
exit_cleanup(RERR_SIGNAL);
}