Skip to content

Commit

Permalink
File Stream API now writes sparse files
Browse files Browse the repository at this point in the history
The implementation is based on the previous protocol for `GET
<FILENAME>` requests that used sparse files.

Ticket: ENT-12414
Changelog: Title
Signed-off-by: Lars Erik Wik <[email protected]>
  • Loading branch information
larsewi committed Dec 3, 2024
1 parent 57d89f5 commit d3e76a3
Showing 1 changed file with 30 additions and 9 deletions.
39 changes: 30 additions & 9 deletions libcfnet/file_stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -840,8 +840,9 @@ static bool RecvDelta(
char in_buf[MESSAGE_SIZE * 2], out_buf[MESSAGE_SIZE];

/* Open/create the destination file */
FILE *new = safe_fopen_create_perms(dest, "wb", perms);
if (new == NULL)
int new = safe_open_create_perms(
dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL | O_BINARY, perms);
if (new == -1)
{
Log(LOG_LEVEL_ERR,
"Failed to open/create destination file '%s': %s",
Expand All @@ -865,6 +866,8 @@ static bool RecvDelta(
basis,
GetErrorStr());
FlushStream(conn);
close(new);
unlink(dest);
return false;
}

Expand All @@ -874,6 +877,9 @@ static bool RecvDelta(
{
Log(LOG_LEVEL_ERR, "Failed to begin job for patching");
FlushStream(conn);
close(new);
fclose(old);
unlink(dest);
return false;
}

Expand All @@ -882,6 +888,10 @@ static bool RecvDelta(
bufs.next_out = out_buf;
bufs.avail_out = sizeof(out_buf);

/* Sparse file specific */
bool last_write_made_hole = false;
size_t n_wrote_total = 0;

rs_result res;
do
{
Expand All @@ -900,9 +910,10 @@ static bool RecvDelta(
MESSAGE_SIZE);
FlushStream(conn);

fclose(new);
close(new);
fclose(old);
rs_job_free(job);
unlink(dest);
return false;
}

Expand All @@ -917,9 +928,10 @@ static bool RecvDelta(
if (!RecvMessage(conn, in_buf + bufs.avail_in, &n_bytes, &eof))
{
/* Error is already logged */
fclose(new);
close(new);
fclose(old);
rs_job_free(job);
unlink(dest);
return false;
}

Expand All @@ -939,18 +951,18 @@ static bool RecvDelta(
FlushStream(conn);
}

fclose(new);
close(new);
fclose(old);
rs_job_free(job);
unlink(dest);
return false;
}

/* Drain output buffer, if there is data */
size_t present = bufs.next_out - out_buf;
if (present > 0)
{
size_t n_bytes = fwrite(out_buf, 1 /* Byte */, present, new);
if (n_bytes == 0)
if (!FileSparseWrite(new, out_buf, present, &last_write_made_hole))
{
Log(LOG_LEVEL_ERR,
"Failed to write to destination file '%s' during file stream: %s",
Expand All @@ -961,21 +973,30 @@ static bool RecvDelta(
FlushStream(conn);
}

fclose(new);
close(new);
fclose(old);
rs_job_free(job);
unlink(dest);
return false;
}

n_wrote_total += present;
bufs.next_out = out_buf;
bufs.avail_out = sizeof(out_buf);
}
} while (res != RS_DONE);

fclose(new);
fclose(old);
rs_job_free(job);

if (!FileSparseClose(
new, dest, false, n_wrote_total, last_write_made_hole))
{
/* Error is already logged */
unlink(dest);
return false;
}

return true;
}

Expand Down

0 comments on commit d3e76a3

Please sign in to comment.