Rara data corruption with --sparse

David Taylor davidt-rsync at yadt.co.uk
Sat Sep 14 21:58:58 CEST 2013


In fileio.c, function write_sparse() there is a bug that can lead
to corrupt copies if the write() call only completes partially.

        for (l1 = 0; l1 < len && buf[l1] == 0; l1++) {}
        for (l2 = 0; l2 < len-l1 && buf[len-(l2+1)] == 0; l2++) {}

        sparse_seek += l1;

        if (l1 == len)
                return len;

        if (sparse_seek)
                do_lseek(f, sparse_seek, SEEK_CUR);
        sparse_seek = l2;

After first calculating l1 (zero-prefix len) and l2 (zero-suffic len),
the code adds l1 to sparse_seek, seeks l1 bytes and resets sparse_seek
to l2, ready for the next call.

        while ((ret = write(f, buf + l1, len - (l1+l2))) <= 0) {
                if (ret < 0 && errno == EINTR)
                return ret;

        if (ret != (int)(len - (l1+l2)))
                return l1+ret;

If the write() then returns an unexpected count (other than len - (l1+l2)),
the return value is recalculated, but sparse_seek is left unchanged.

On the next call to write_sparse() buf will correctly be set to the
next byte to be written, but sparse_seek will be non-zero and a spurious
hole will be created in the file.

A simple fix is to add 'sparse_seek = 0;' before 'return l1+ret;'.

David Taylor

More information about the rsync mailing list