int io_error;
static struct file_struct null_file;
+static char empty_sum[MD4_SUM_LENGTH];
static void clean_flist(struct file_list *flist, int strip_root, int no_dups);
}
}
+/* These vars are used by both send_file_entry() and receive_file_entry()
+ * (but just one at a time). They have been placed outside these functions
+ * so that we can reset the values when the batch-processing wants to make
+ * extra use of these functions (which needs to start from a known state). */
+static time_t modtime;
+static mode_t mode;
+static DEV64_T rdev; /* just high bytes in p28 onward */
+static uid_t uid;
+static gid_t gid;
+static DEV64_T dev;
+static char lastname[MAXPATHLEN];
+
+void reset_file_entry_vars(void)
+{
+ modtime = 0;
+ mode = 0;
+ rdev = 0;
+ uid = 0;
+ gid = 0;
+ dev = 0;
+ *lastname = '\0';
+}
-static void send_file_entry(struct file_struct *file, int f,
- unsigned short base_flags)
+void send_file_entry(struct file_struct *file, int f, unsigned short base_flags)
{
unsigned short flags;
- static time_t modtime;
- static mode_t mode;
- static DEV64_T last_rdev;
- static uid_t uid;
- static gid_t gid;
- static DEV64_T dev;
- static char lastname[MAXPATHLEN];
char *fname, fbuf[MAXPATHLEN];
int l1, l2;
mode = file->mode;
if (preserve_devices) {
if (protocol_version < 28) {
- if (IS_DEVICE(mode) && file->rdev == last_rdev) {
+ if (IS_DEVICE(mode) && file->rdev == rdev) {
/* Set both flags so that the test when
* writing the data is simpler. */
flags |= SAME_RDEV_pre28|SAME_HIGH_RDEV;
}
else
- last_rdev = file->rdev;
+ rdev = file->rdev;
}
else if (IS_DEVICE(mode)) {
- if ((file->rdev & ~0xFF) == last_rdev)
+ if ((file->rdev & ~0xFF) == rdev)
flags |= SAME_HIGH_RDEV;
else
- last_rdev = file->rdev & ~0xFF;
+ rdev = file->rdev & ~0xFF;
}
}
if (file->uid == uid)
write_int(f, gid);
}
if (preserve_devices && IS_DEVICE(mode)) {
- /* If SAME_HIGH_RDEV is off, SAME_RDEV_pre28 is also off. */
+ /* If SAME_HIGH_RDEV is off, SAME_RDEV_pre28 is also off.
+ * Also, avoid using "rdev" because it may be incomplete. */
if (!(flags & SAME_HIGH_RDEV))
write_int(f, file->rdev);
else if (protocol_version >= 28)
}
#endif
- if (always_checksum) {
- if (protocol_version < 21)
- write_buf(f, file->sum, 2);
- else
- write_buf(f, file->sum, MD4_SUM_LENGTH);
+ if (always_checksum && (protocol_version < 28 || S_ISREG(mode))) {
+ char *sum = file->sum? file->sum : empty_sum;
+ write_buf(f, sum, protocol_version < 21? 2
+ : MD4_SUM_LENGTH);
}
strlcpy(lastname, fname, MAXPATHLEN);
-static void receive_file_entry(struct file_struct **fptr,
- unsigned short flags, int f)
+void receive_file_entry(struct file_struct **fptr, unsigned short flags, int f)
{
- static time_t modtime;
- static mode_t mode;
- static DEV64_T rdev;
- static uid_t uid;
- static gid_t gid;
- static DEV64_T dev;
- static char lastname[MAXPATHLEN];
char thisname[MAXPATHLEN];
unsigned int l1 = 0, l2 = 0;
char *p;
file->rdev = (DEV64_T)read_int(f);
rdev = file->rdev & ~0xFF;
} else
- file->rdev = (DEV64_T)(rdev | read_byte(f));
+ file->rdev = rdev | (DEV64_T)read_byte(f);
}
}
#endif
if (always_checksum) {
- file->sum = new_array(char, MD4_SUM_LENGTH);
- if (!file->sum)
- out_of_memory("md4 sum");
- if (protocol_version < 21)
- read_buf(f, file->sum, 2);
- else
- read_buf(f, file->sum, MD4_SUM_LENGTH);
+ char *sum;
+ if (S_ISREG(mode)) {
+ sum = file->sum = new_array(char, MD4_SUM_LENGTH);
+ if (!sum)
+ out_of_memory("md4 sum");
+ } else if (protocol_version < 28) {
+ /* Prior to 28, we get a useless set of nulls. */
+ sum = empty_sum;
+ } else
+ sum = NULL;
+ if (sum) {
+ read_buf(f, sum, protocol_version < 21? 2
+ : MD4_SUM_LENGTH);
+ }
}
if (!preserve_perms) {
extern int orig_umask;
/* set an appropriate set of permissions based on original
- permissions and umask. This emulates what GNU cp does */
+ * permissions and umask. This emulates what GNU cp does */
file->mode &= ~orig_umask;
}
}
file->link = STRDUP(ap, linkbuf);
#endif
- if (always_checksum) {
- file->sum = (char *) MALLOC(ap, MD4_SUM_LENGTH);
+ if (always_checksum && S_ISREG(st.st_mode)) {
+ file->sum = (char*)MALLOC(ap, MD4_SUM_LENGTH);
if (!file->sum)
out_of_memory("md4 sum");
- /* drat. we have to provide a null checksum for non-regular
- files in order to be compatible with earlier versions
- of rsync */
- if (S_ISREG(st.st_mode)) {
- file_checksum(fname, file->sum, st.st_size);
- } else {
- memset(file->sum, 0, MD4_SUM_LENGTH);
- }
+ file_checksum(fname, file->sum, st.st_size);
}
if (flist_dir) {