- if (@puts) {
- # Write ustar header and data for each file.
- put_scratch_file ($_->[0],
- defined $_->[1] ? $_->[1] : $_->[0])
- foreach @puts;
-
- # Write end-of-archive marker.
- write_fully ($disks{SCRATCH}{HANDLE}, $disks{SCRATCH}{FILE_NAME},
- "\0" x 1024);
+ return if !@gets && !@puts;
+
+ my ($p) = $parts{SCRATCH};
+ # Create temporary partition and write the files to put to it,
+ # then write an end-of-archive marker.
+ my ($part_handle, $part_fn) = tempfile (UNLINK => 1, SUFFIX => '.part');
+ put_scratch_file ($_->[0], defined $_->[1] ? $_->[1] : $_->[0],
+ $part_handle, $part_fn)
+ foreach @puts;
+ write_fully ($part_handle, $part_fn, "\0" x 1024);
+
+ # Make sure the scratch disk is big enough to get big files
+ # and at least as big as any requested size.
+ my ($size) = round_up (max (@gets * 1024 * 1024, $p->{BYTES} || 0), 512);
+ extend_file ($part_handle, $part_fn, $size);
+ close ($part_handle);
+
+ if (exists $p->{DISK}) {
+ # Copy the scratch partition to the disk.
+ die "$p->{DISK}: scratch partition too small\n"
+ if $p->{SECTORS} * 512 < $size;
+
+ my ($disk_handle);
+ open ($part_handle, '<', $part_fn) or die "$part_fn: open: $!\n";
+ open ($disk_handle, '+<', $p->{DISK}) or die "$p->{DISK}: open: $!\n";
+ my ($start) = $p->{START} * 512;
+ sysseek ($disk_handle, $start, SEEK_SET) == $start
+ or die "$p->{DISK}: seek: $!\n";
+ copy_file ($part_handle, $part_fn, $disk_handle, $p->{DISK}, $size);
+ close ($disk_handle) or die "$p->{DISK}: close: $!\n";
+ close ($part_handle) or die "$part_fn: close: $!\n";
+ } else {
+ # Set $part_fn as the source for the scratch partition.
+ do_set_part ('SCRATCH', 'file', $part_fn);