void shfs_arch_read_flush(shfs_arch_t *arch) { size_t status; /* result from system call */ /* Clear the count of errors. This only applies to a single call to flush_read. */ while (1) { status = shfs_arch_buffer_read(arch->archive, record_start->buffer, arch->record_size); if (status == arch->record_size) { arch->records_read++; return; } /* The condition below used to include || (status > 0 && !read_full_records) This is incorrect since even if new_volume() succeeds, the subsequent call to rmtread will overwrite the chunk of data already read in the buffer, so the processing will fail */ if (status == SAFE_READ_ERROR) { continue; } break; } short_read(arch, status); }
/** * Copy thread code. This copies one segment in parallel with the other * segments. It is copied in reads and writes of several k-bytes at a time. * * @param[in] arg the file_seg_t pointer describing the segment to copy. */ static void * do_copy(void * arg) { file_seg_t * fseg = arg; size_t const readlim = pc_min(fseg->end - fseg->start, OPT_VALUE_MAX_CHUNK); copy_start(fseg); for (;;) { ssize_t rdlen = fseg->end - fseg->start; if (rdlen > readlim) rdlen = readlim; ssize_t rdct = read(fseg->fdin, fseg->buffer, rdlen); if (rdct <= 0) short_read(fseg, rdlen, rdct); rdlen = write(fseg->fdout, fseg->buffer, rdct); if (rdlen != rdct) fserr(PCOPY_EXIT_FS_ERR_OUT, "write", fseg->dname); fseg->start += rdlen; if (fseg->start >= fseg->end) break; copy_progress(fseg); } copy_wrap(fseg); free(arg); pthread_exit(0); }
/* Simple flush read (no multi-volume or label extensions) */ static void simple_flush_read(shfs_arch_t *arch) { size_t status; /* result from system call */ /* Clear the count of errors. This only applies to a single call to flush_read. */ for (;;) { status = shfs_arch_buffer_read(arch->archive, record_start->buffer, arch->record_size); if (status == arch->record_size) { arch->records_read++; return; } if (status == SAFE_READ_ERROR) { continue; /* try again */ } break; } short_read(arch, status); }