Skip to content

Commit

Permalink
Atomic copy_from in files promise
Browse files Browse the repository at this point in the history
Changes to `files` promise in `copy_from` attribute:

- The new file (i.e., `<FILENAME>.cfnew`) is now created with correct
  permission during remote copy. Previously it would be created with
  default permissions.
- The destination file (`<FILENAME>`) is no longer deleted on backup
  during file copy.  Previously it would be renamed to
  <FILENAME>.cfsaved, causing the original file to dissappear. Now an
  actual copy of the original file with the same permissions is created
  instead.

As a result, there will no longer be a brief moment where the original
file is inaccessible.

Ticket: ENT-11988
Changelog: Commit
Signed-off-by: Lars Erik Wik <[email protected]>
  • Loading branch information
larsewi committed Oct 9, 2024
1 parent 8334505 commit 359f9b8
Show file tree
Hide file tree
Showing 3 changed files with 5 additions and 5 deletions.
4 changes: 2 additions & 2 deletions cf-agent/verify_files_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -1552,7 +1552,7 @@ bool CopyRegularFile(EvalContext *ctx, const char *source, const char *dest, con
}

if (!CopyRegularFileNet(source, ToChangesPath(new),
sstat->st_size, attr->copy.encrypt, conn))
sstat->st_size, attr->copy.encrypt, conn, sstat->st_mode))
{
RecordFailure(ctx, pp, attr, "Failed to copy file '%s' from '%s'",
source, conn->remoteip);
Expand Down Expand Up @@ -1712,7 +1712,7 @@ bool CopyRegularFile(EvalContext *ctx, const char *source, const char *dest, con
}
}

if (rename(dest, changes_backup) == 0)
if (FileCopyKeepPerms(dest, changes_backup))
{
RecordChange(ctx, pp, attr, "Backed up '%s' as '%s'", dest, backup);
*result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE);
Expand Down
4 changes: 2 additions & 2 deletions libcfnet/client_code.c
Original file line number Diff line number Diff line change
Expand Up @@ -750,7 +750,7 @@ static void FlushFileStream(int sd, int toget)
/* TODO finalise socket or TLS session in all cases that this function fails
* and the transaction protocol is out of sync. */
bool CopyRegularFileNet(const char *source, const char *dest, off_t size,
bool encrypt, AgentConnection *conn)
bool encrypt, AgentConnection *conn, mode_t mode)
{
char *buf, workbuf[CF_BUFSIZE], cfchangedstr[265];
const int buf_size = 2048;
Expand All @@ -774,7 +774,7 @@ bool CopyRegularFileNet(const char *source, const char *dest, off_t size,

unlink(dest); /* To avoid link attacks */

int dd = safe_open_create_perms(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL | O_BINARY, CF_PERMS_DEFAULT);
int dd = safe_open_create_perms(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL | O_BINARY, mode);
if (dd == -1)
{
Log(LOG_LEVEL_ERR,
Expand Down
2 changes: 1 addition & 1 deletion libcfnet/client_code.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ void DisconnectServer(AgentConnection *conn);

bool CompareHashNet(const char *file1, const char *file2, bool encrypt, AgentConnection *conn);
bool CopyRegularFileNet(const char *source, const char *dest, off_t size,
bool encrypt, AgentConnection *conn);
bool encrypt, AgentConnection *conn, mode_t mode);
Item *RemoteDirList(const char *dirname, bool encrypt, AgentConnection *conn);

int TLSConnectCallCollect(ConnectionInfo *conn_info, const char *username);
Expand Down

0 comments on commit 359f9b8

Please sign in to comment.