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 
14 #include <sys/stat.h>
15 
16 WvAtomicFile::WvAtomicFile(WvStringParm filename, int flags, mode_t create_mode)
17  : tmp_file(WvString::null)
18 {
19  open(filename, flags, create_mode);
20 }
21 
22 WvAtomicFile::~WvAtomicFile()
23 {
24  close();
25 }
26 
27 
28 /* Mimics behaviour of wvfile except that it uses a tmp file and stores the
29  real name */
30 bool WvAtomicFile::open(WvStringParm filename, int flags, mode_t create_mode)
31 {
32  close();
33 
34  atomic_file = filename;
35 
36  // Ensure that if the file exists it is a regular file
37  struct stat st;
38  if (lstat(atomic_file, &st) == 0 && !S_ISREG(st.st_mode))
39  return false;
40 
41  WvString new_tmp_file("%s/WvXXXXXX", getdirname(filename));
42 
43  // Get the current umask and guarantee that mkstemp() creates
44  // a file with maximal restrictions
45  mode_t old_umask = ::umask(077);
46  int tmp_fd = ::mkstemp(new_tmp_file.edit());
47  if (tmp_fd < 0)
48  seterr(errno);
49  ::umask(old_umask);
50  if (tmp_fd < 0)
51  return false;
52 
53  // Set the permissions as specified using the original umask
54  // We will only possibly be adding permissions here...
55  if (::fchmod(tmp_fd, create_mode & ~old_umask) != 0)
56  seterr(errno);
57 
58  if (!WvFile::open(tmp_fd))
59  {
60  ::close(tmp_fd);
61  return false;
62  }
63 
64  tmp_file = new_tmp_file;
65 
66  return true;
67 }
68 
69 
71 {
73 
74  if (tmp_file)
75  {
76  if (::rename(tmp_file, atomic_file) != 0)
77  ::unlink(tmp_file);
78 
79  tmp_file = WvString::null;
80  }
81 }
82 
83 
84 bool WvAtomicFile::chmod(mode_t mode)
85 {
86  if (getfd() == -1) return false;
87 
88  if (fchmod(getfd(), mode) != 0)
89  {
90  seterr(errno);
91  return false;
92  }
93 
94  return true;
95 }
96 
97 
98 bool WvAtomicFile::chown(uid_t owner, gid_t group)
99 {
100  if (getfd() == -1) return false;
101 
102  if (fchown(getfd(), owner, group) != 0)
103  {
104  seterr(errno);
105  return false;
106  }
107 
108  return true;
109 }
WvAtomicFile::close
void close()
Closes the file descriptors.
Definition: wvatomicfile.cc:70
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:329
group
Definition: argp-parse.c:204
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