Avoid splitting a multi-byte character when trimming a name.
[rsync/rsync.git] / receiver.c
index fc3e40c..0bc6517 100644 (file)
@@ -129,6 +129,14 @@ int get_tmpname(char *fnametmp, const char *fname, BOOL make_unique)
                added = maxname - 1;
        suf = fnametmp + length + added;
 
+       /* Trim any dangling high-bit chars if the first-trimmed char (if any) is
+        * also a high-bit char, just in case we cut into a multi-byte sequence.
+        * We are guaranteed to stop because of the leading '.' we added. */
+       if ((int)f[added] & 0x80) {
+               while ((int)suf[-1] & 0x80)
+                       suf--;
+       }
+
        if (make_unique) {
                static unsigned counter_limit;
                unsigned counter;
@@ -322,8 +330,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
                goto report_write_error;
 
 #ifdef HAVE_FTRUNCATE
-       if (inplace && fd != -1
-        && ftruncate(fd, offset) < 0) {
+       if (inplace && fd != -1 && do_ftruncate(fd, offset) < 0) {
                rsyserr(FERROR_XFER, errno, "ftruncate failed on %s",
                        full_fname(fname));
        }
@@ -332,7 +339,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
        if (INFO_GTE(PROGRESS, 1))
                end_progress(total_size);
 
-       if (fd != -1 && offset > 0 && sparse_end(fd) != 0) {
+       if (fd != -1 && offset > 0 && sparse_end(fd, offset) != 0) {
            report_write_error:
                rsyserr(FERROR_XFER, errno, "write failed on %s",
                        full_fname(fname));