From dbe948ca3ebdad97f4f2096f6074623fc2a8e3c8 Mon Sep 17 00:00:00 2001 From: Russ Allbery Date: Fri, 5 Oct 2007 00:16:26 +0000 Subject: Pull the file writing code for the wallet client into a separate file so that the srvtab and keytab management can share it. Write atomically to a new file and then link and rename to do an atomic update. Leave a backup copy of any file that's replaced. --- client/file.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 client/file.c (limited to 'client/file.c') diff --git a/client/file.c b/client/file.c new file mode 100644 index 0000000..621b49d --- /dev/null +++ b/client/file.c @@ -0,0 +1,50 @@ +/* $Id$ +** +** File handling for the wallet client. +** +** Written by Russ Allbery +** Copyright 2007 Board of Trustees, Leland Stanford Jr. University +** +** See README for licensing terms. +*/ + +#include +#include + +#include + +#include +#include + +/* +** Given a filename, some data, and a length, write that data to the given +** file safely and atomically by creating file.new, writing the data, linking +** file to file.bak, and then renaming file.new to file. +*/ +void +write_file(const char *name, const void *data, size_t length) +{ + int fd; + ssize_t status; + char *temp, *backup; + + temp = concat(name, ".new", (char *) 0); + backup = concat(name, ".bak", (char *) 0); + fd = open(temp, O_WRONLY | O_CREAT | O_TRUNC, 0600); + if (fd < 0) + sysdie("open of %s failed", temp); + status = write(fd, data, length); + if (status < 0) + sysdie("write to %s failed", temp); + else if (status != (ssize_t) length) + die("write to %s truncated", temp); + if (close(fd) < 0) + sysdie("close of %s failed (file probably truncated)", temp); + if (access(name, F_OK) == 0) + if (link(name, backup) < 0) + sysdie("link of %s to %s failed", name, backup); + if (rename(temp, name) < 0) + sysdie("rename of %s to %s failed", temp, name); + free(temp); + free(backup); +} -- cgit v1.2.3