Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save thread13/d3929856865a525093f9473e240805ea to your computer and use it in GitHub Desktop.
Save thread13/d3929856865a525093f9473e240805ea to your computer and use it in GitHub Desktop.
rsync 3.1.1 : --ignore-missing-args
// definition
#line 941 options.c
{"delete-missing-args",0,POPT_BIT_SET, &missing_args, 2, 0, 0 },
{"ignore-missing-args",0,POPT_BIT_SET, &missing_args, 1, 0, 0 },
// structure definition -- just in case )
#line 115 popt/popt.h
/** \ingroup popt
*/
struct poptOption {
/*@observer@*/ /*@null@*/
const char * longName; /*!< may be NULL */
char shortName; /*!< may be NUL */
int argInfo;
/*@shared@*/ /*@null@*/
void * arg; /*!< depends on argInfo */
int val; /*!< 0 means don't return, just update flag */
/*@observer@*/ /*@null@*/
const char * descrip; /*!< description for autohelp -- may be NULL */
/*@observer@*/ /*@null@*/
const char * argDescrip; /*!< argument description for autohelp */
};
// declaration
#line 88 --//--
int missing_args = 0; /* 0 = FERROR_XFER, 1 = ignore, 2 = delete */
// usage
#line 2275 flist.c
if (link_stat(fbuf, &st, copy_dirlinks || name_type != NORMAL_NAME) != 0
|| (name_type != DOTDIR_NAME && is_daemon_excluded(fbuf, S_ISDIR(st.st_mode)))
|| (relative_paths && path_is_daemon_excluded(fbuf, 1))) {
if (errno != ENOENT || missing_args == 0) {
/* This is a transfer error, but inhibit deletion
* only if we might be omitting an existing file. */
if (errno != ENOENT)
io_error |= IOERR_GENERAL;
rsyserr(FERROR_XFER, errno, "link_stat %s failed",
full_fname(fbuf));
continue;
} else if (missing_args == 1) {
/* Just ignore the arg. */
continue;
} else /* (missing_args == 2) */ {
/* Send the arg as a "missing" entry with
* mode 0, which tells the generator to delete it. */
memset(&st, 0, sizeof st);
}
}
//
// now for the error:
//
// message origin
#line 554 rsync.c
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;
}
// 'FERROR_XFER' : definition
#line 223 rsync.h
/* Log-message categories. FLOG only goes to the log file, not the client;
* FCLIENT is the opposite. */
enum logcode {
FNONE=0, /* never sent */
FERROR_XFER=1, FINFO=2, /* sent over socket for any protocol */
FERROR=3, FWARNING=4, /* sent over socket for protocols >= 30 */
FERROR_SOCKET=5, FLOG=6, /* only sent via receiver -> generator pipe */
FERROR_UTF8=8, /* only sent via receiver -> generator pipe */
FCLIENT=7 /* never transmitted (e.g. server converts to FINFO) */
};
// NB: mentioned --
#line 1235 OLDNEWS
- There are more internal logging categories available in protocol 30 than
the age-old FINFO and FERROR, including FERROR_XFER and FWARN. These new
categories allow some errors and warnings to go to stderr without causing
an erroneous end-of-run warning about some files not being able to be
transferred.
// rsyserr(FERROR_XFER) code -- calls rwrite(FERROR_XFER)
#line 444 log.c
/* This is like rprintf, but it also tries to print some
* representation of the error code. Normally errcode = errno.
*
* Unlike rprintf, this always adds a newline and there should not be
* one in the format string.
*
* Note that since strerror might involve dynamically loading a
* message catalog we need to call it once before chroot-ing. */
void rsyserr(enum logcode code, int errcode, const char *format, ...)
{
va_list ap;
char buf[BIGPATHBUFLEN];
size_t len;
strlcpy(buf, RSYNC_NAME ": ", sizeof buf);
len = (sizeof RSYNC_NAME ": ") - 1;
va_start(ap, format);
len += vsnprintf(buf + len, sizeof buf - len, format, ap);
va_end(ap);
if (len < sizeof buf) {
len += snprintf(buf + len, sizeof buf - len,
": %s (%d)\n", strerror(errcode), errcode);
}
if (len >= sizeof buf)
exit_cleanup(RERR_MESSAGEIO);
rwrite(code, buf, len, 0);
}
// FERROR_XFER -- consequences
#line 333 log.c
/* this is the underlying (unformatted) rsync debugging function. Call
* it with FINFO, FERROR_*, FWARNING, FLOG, or FCLIENT. Note: recursion
* can happen with certain fatal conditions. */
void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
{
// ...
output_msg:
switch (code) {
case FERROR_XFER:
got_xfer_error = 1;
/* FALL THROUGH */
// ...
}
// 'got_xfer_error' -- consequences:
#line 218 cleanup.c
if (exit_code == 0) {
if (code)
exit_code = code;
if (io_error & IOERR_DEL_LIMIT)
exit_code = RERR_DEL_LIMIT;
if (io_error & IOERR_VANISHED)
exit_code = RERR_VANISHED;
if (io_error & IOERR_GENERAL || got_xfer_error)
exit_code = RERR_PARTIAL;
}
// 'got_xfer_error' -- alt consequences
#line 1424 main.c
static RETSIGTYPE sigusr2_handler(UNUSED(int val))
{
if (!am_server)
output_summary();
close_all();
if (got_xfer_error)
_exit(RERR_PARTIAL);
_exit(0);
}
// RERR_PARTIAL -- error message
#line 96 log.c
struct {
int code;
char const *name;
} const rerr_names[] = {
{ RERR_SYNTAX , "syntax or usage error" },
{ RERR_PROTOCOL , "protocol incompatibility" },
{ RERR_FILESELECT , "errors selecting input/output files, dirs" },
{ RERR_UNSUPPORTED, "requested action not supported" },
{ RERR_STARTCLIENT, "error starting client-server protocol" },
{ RERR_SOCKETIO , "error in socket IO" },
{ RERR_FILEIO , "error in file IO" },
{ RERR_STREAMIO , "error in rsync protocol data stream" },
{ RERR_MESSAGEIO , "errors with program diagnostics" },
{ RERR_IPC , "error in IPC code" },
{ RERR_CRASHED , "sibling process crashed" },
{ RERR_TERMINATED , "sibling process terminated abnormally" },
{ RERR_SIGNAL1 , "received SIGUSR1" },
{ RERR_SIGNAL , "received SIGINT, SIGTERM, or SIGHUP" },
{ RERR_WAITCHILD , "waitpid() failed" },
{ RERR_MALLOC , "error allocating core memory buffers" },
{ RERR_PARTIAL , "some files/attrs were not transferred (see previous errors)" },
{ RERR_VANISHED , "some files vanished before they could be transferred" },
{ RERR_DEL_LIMIT , "the --max-delete limit stopped deletions" },
{ RERR_TIMEOUT , "timeout in data send/receive" },
{ RERR_CONTIMEOUT , "timeout waiting for daemon connection" },
{ RERR_CMD_FAILED , "remote shell failed" },
{ RERR_CMD_KILLED , "remote shell killed" },
{ RERR_CMD_RUN , "remote command could not be run" },
{ RERR_CMD_NOTFOUND,"remote command not found" },
{ 0, NULL }
};
// NB: '22' and "Invalid argument" in the log are coming from EINVAL
// RERR_PARTIAL -- definition (23)
#line 43 errcode.h
/* If you change these, please also update the string mappings in log.c and
* the EXIT VALUES in rsync.yo. */
#define RERR_OK 0
#define RERR_SYNTAX 1 /* syntax or usage error */
#define RERR_PROTOCOL 2 /* protocol incompatibility */
#define RERR_FILESELECT 3 /* errors selecting input/output files, dirs */
#define RERR_UNSUPPORTED 4 /* requested action not supported */
#define RERR_STARTCLIENT 5 /* error starting client-server protocol */
#define RERR_SOCKETIO 10 /* error in socket IO */
#define RERR_FILEIO 11 /* error in file IO */
#define RERR_STREAMIO 12 /* error in rsync protocol data stream */
#define RERR_MESSAGEIO 13 /* errors with program diagnostics */
#define RERR_IPC 14 /* error in IPC code */
#define RERR_CRASHED 15 /* sibling crashed */
#define RERR_TERMINATED 16 /* sibling terminated abnormally */
#define RERR_SIGNAL1 19 /* status returned when sent SIGUSR1 */
#define RERR_SIGNAL 20 /* status returned when sent SIGINT, SIGTERM, SIGHUP */
#define RERR_WAITCHILD 21 /* some error returned by waitpid() */
#define RERR_MALLOC 22 /* error allocating core memory buffers */
#define RERR_PARTIAL 23 /* partial transfer */
#define RERR_VANISHED 24 /* file(s) vanished on sender side */
#define RERR_DEL_LIMIT 25 /* skipped some deletes due to --max-delete */
#define RERR_TIMEOUT 30 /* timeout in data send/receive */
#define RERR_CONTIMEOUT 35 /* timeout waiting for daemon connection */
//
// Ok, now let us follow 'file->flags' logic :
//
// 'file->flags' : definition
#line 704 rsync.h
struct file_struct {
const char *dirname; /* The dir info inside the transfer */
time_t modtime; /* When the item was last modified */
uint32 len32; /* Lowest 32 bits of the file's length */
uint16 mode; /* The item's type and permissions */
uint16 flags; /* The FLAG_* bits for this item */
const char basename[1]; /* The basename (AKA filename) follows */
};
// w-what does it say about symlinks?
#line 497 generator.c
void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statret,
stat_x *sxp, int32 iflags, uchar fnamecmp_type,
const char *xname)
{
if (statret >= 0) { /* A from-dest-dir statret can == 1! */
int keep_time = !preserve_times ? 0
: S_ISDIR(file->mode) ? preserve_times & PRESERVE_DIR_TIMES
: S_ISLNK(file->mode) ? preserve_times & PRESERVE_LINK_TIMES
: 1;
if (S_ISREG(file->mode) && F_LENGTH(file) != sxp->st.st_size)
iflags |= ITEM_REPORT_SIZE;
if (file->flags & FLAG_TIME_FAILED) { /* symlinks only */
if (iflags & ITEM_LOCAL_CHANGE)
iflags |= symlink_timeset_failed_flags;
} else if (keep_time
? cmp_time(file->modtime, sxp->st.st_mtime) != 0
: iflags & (ITEM_TRANSFER|ITEM_LOCAL_CHANGE) && !(iflags & ITEM_MATCHED)
&& (!(iflags & ITEM_XNAME_FOLLOWS) || *xname))
iflags |= ITEM_REPORT_TIME;
// 'symlink_timeset_failed_flags' -- declaration:
#line 109 generator.c
static int symlink_timeset_failed_flags;
// setting 'symlink_timeset_failed_flags' -- not too helpful
#line 2186 generator.c
void generate_files(int f_out, const char *local_name)
{
// ...
loopchk_limit = allowed_lull ? allowed_lull * 5 : 200;
symlink_timeset_failed_flags = ITEM_REPORT_TIME
| (protocol_version >= 30 || !am_server ? ITEM_REPORT_TIMEFAIL : 0);
implied_dirs_are_missing = relative_paths && !implied_dirs && protocol_version < 30;
//
// ... and these are all the references for 'symlink_timeset_failed_flags' ?
//
//
// probably it goes to the logs -- somthing like this:
//
$ grep -rn 'ITEM_REPORT_TIME' *
generator.c:502: iflags |= ITEM_REPORT_TIME;
generator.c:2186: symlink_timeset_failed_flags = ITEM_REPORT_TIME
generator.c:2187: | (protocol_version >= 30 || !am_server ? ITEM_REPORT_TIMEFAIL : 0);
log.c:708: c[4] = !(iflags & ITEM_REPORT_TIME) ? '.'
log.c:710: || (iflags & ITEM_REPORT_TIMEFAIL) ? 'T' : 't';
log.c:716: c[4] = !(iflags & ITEM_REPORT_TIME) ? '.'
rsync.h:187:#define ITEM_REPORT_TIMEFAIL (1<<2) /* symlinks only */
rsync.h:188:#define ITEM_REPORT_TIME (1<<3)
// man rsync :
o A t means the modification time is different
and is being updated to the sender’s value (requires --times).
An alternate value of T means that the modification
time will be set to the transfer time,
which happens when a file/symlink/device is
updated without --times and when a symlink is changed
and the receiver can’t set its time.
( Note: when using an rsync 3.0.0 client,
you might see the s flag combined with t
instead of the proper T flag for this time-setting failure. )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment