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 
15 WvAtomicFile::WvAtomicFile(WvStringParm filename, int flags, mode_t create_mode)
16  : tmp_file(WvString::null)
17 {
18  open(filename, flags, create_mode);
19 }
20 
21 WvAtomicFile::~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 */
29 bool 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 
83 bool 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 
97 bool 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 }
WvAtomicFile::close
void close()
Closes the file descriptors.
Definition: wvatomicfile.cc:69
WvStream::seterr
virtual void seterr(int _errnum)
Override seterr() from WvError so that it auto-closes the stream.
Definition: wvstream.cc:451
WvString
WvString is an implementation of a simple and efficient printable-string class.
Definition: wvstring.h:330
group
Definition: argp-parse.c:205
wvstrutils.h
WvFdStream::getfd
int getfd() const
Returns the Unix file descriptor for reading and writing.
Definition: wvfdstream.h:81
WvFdStream::close
virtual void close()
Closes the file descriptors.
Definition: wvfdstream.cc:117
WvFastString
A WvFastString acts exactly like a WvString, but can take (const char *) strings without needing to a...
Definition: wvstring.h:94