static int FSWrite(const char *destination, int dd, const char *buf, size_t n_write) { const void *cur = buf; const void *end = buf + n_write; while (cur < end) { const void *skip_span = MemSpan(cur, 0, end - cur); if (skip_span > cur) { if (lseek(dd, skip_span - cur, SEEK_CUR) < 0) { Log(LOG_LEVEL_ERR, "Copy failed (no space?) while copying to '%s' from network '%s'", destination, GetErrorStr()); return false; } cur = skip_span; } const void *copy_span = MemSpanInverse(cur, 0, end - cur); if (copy_span > cur) { if (FullWrite(dd, cur, copy_span - cur) < 0) { Log(LOG_LEVEL_ERR, "Copy failed (no space?) while copying to '%s' from network '%s'", destination, GetErrorStr()); return false; } cur = copy_span; } } return true; }
/* * Copy data jumping over areas filled by '\0', so files automatically become sparse if possible. */ static bool CopyData(const char *source, int sd, const char *destination, int dd, char *buf, size_t buf_size) { off_t n_read_total = 0; while (true) { ssize_t n_read = read(sd, buf, buf_size); if (n_read == -1) { if (errno == EINTR) { continue; } CfOut(OUTPUT_LEVEL_ERROR, "read", "Unable to read source file while doing %s to %s", source, destination); return false; } if (n_read == 0) { /* * As the tail of file may contain of bytes '\0' (and hence * lseek(2)ed on destination instead of being written), do a * ftruncate(2) here to ensure the whole file is written to the * disc. */ if (ftruncate(dd, n_read_total) < 0) { CfOut(OUTPUT_LEVEL_ERROR, "ftruncate", "Copy failed (no space?) while doing %s to %s", source, destination); return false; } return true; } n_read_total += n_read; /* Copy/seek */ void *cur = buf; void *end = buf + n_read; while (cur < end) { void *skip_span = MemSpan(cur, 0, end - cur); if (skip_span > cur) { if (lseek(dd, skip_span - cur, SEEK_CUR) < 0) { CfOut(OUTPUT_LEVEL_ERROR, "lseek", "Copy failed (no space?) while doing %s to %s", source, destination); return false; } cur = skip_span; } void *copy_span = MemSpanInverse(cur, 0, end - cur); if (copy_span > cur) { if (FullWrite(dd, cur, copy_span - cur) < 0) { CfOut(OUTPUT_LEVEL_ERROR, "write", "Copy failed (no space?) while doing %s to %s", source, destination); return false; } cur = copy_span; } } } }