WvStreams
wvatomicfile.cc
1/*
2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2005 Net Integration Technologies, Inc.
4 *
5 * Wrapper class for WvFile for automic file creation. Any files that
6 * are guaranteed to be automic will completely write over any existing
7 * file on close.
8*/
9
10#include "wvatomicfile.h"
11#include "wvfileutils.h"
12#include "wvstrutils.h"
13#include <sys/stat.h>
14
15WvAtomicFile::WvAtomicFile(WvStringParm filename, int flags, mode_t create_mode)
16 : tmp_file(WvString::null)
17{
18 open(filename, flags, create_mode);
19}
20
21WvAtomicFile::~WvAtomicFile()
22{
23 close();
24}
25
26
27/* Mimics behaviour of wvfile except that it uses a tmp file and stores the
28 real name */
29bool WvAtomicFile::open(WvStringParm filename, int flags, mode_t create_mode)
30{
31 close();
32
33 atomic_file = filename;
34
35 // Ensure that if the file exists it is a regular file
36 struct stat st;
37 if (lstat(atomic_file, &st) == 0 && !S_ISREG(st.st_mode))
38 return false;
39
40 WvString new_tmp_file("%s/WvXXXXXX", getdirname(filename));
41
42 // Get the current umask and guarantee that mkstemp() creates
43 // a file with maximal restrictions
44 mode_t old_umask = ::umask(077);
45 int tmp_fd = ::mkstemp(new_tmp_file.edit());
46 if (tmp_fd < 0)
47 seterr(errno);
48 ::umask(old_umask);
49 if (tmp_fd < 0)
50 return false;
51
52 // Set the permissions as specified using the original umask
53 // We will only possibly be adding permissions here...
54 if (::fchmod(tmp_fd, create_mode & ~old_umask) != 0)
55 seterr(errno);
56
57 if (!WvFile::open(tmp_fd))
58 {
59 ::close(tmp_fd);
60 return false;
61 }
62
63 tmp_file = new_tmp_file;
64
65 return true;
66}
67
68
70{
72
73 if (tmp_file)
74 {
75 if (::rename(tmp_file, atomic_file) != 0)
76 ::unlink(tmp_file);
77
78 tmp_file = WvString::null;
79 }
80}
81
82
83bool WvAtomicFile::chmod(mode_t mode)
84{
85 if (getfd() == -1) return false;
86
87 if (fchmod(getfd(), mode) != 0)
88 {
89 seterr(errno);
90 return false;
91 }
92
93 return true;
94}
95
96
97bool WvAtomicFile::chown(uid_t owner, gid_t group)
98{
99 if (getfd() == -1) return false;
100
101 if (fchown(getfd(), owner, group) != 0)
102 {
103 seterr(errno);
104 return false;
105 }
106
107 return true;
108}
void close()
Closes the file descriptors.
A WvFastString acts exactly like a WvString, but can take (const char *) strings without needing to a...
int getfd() const
Returns the Unix file descriptor for reading and writing.
virtual void close()
Closes the file descriptors.
virtual void seterr(int _errnum)
Override seterr() from WvError so that it auto-closes the stream.
Definition wvstream.cc:451
WvString is an implementation of a simple and efficient printable-string class.