WvStreams
|
00001 /* 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 1997-2005 Net Integration Technologies, Inc. 00004 * 00005 * Wrapper class for WvFile for automic file creation. Any files that 00006 * are guaranteed to be automic will completely write over any existing 00007 * file on close. 00008 */ 00009 00010 #include "wvatomicfile.h" 00011 #include "wvfileutils.h" 00012 #include "wvstrutils.h" 00013 00014 WvAtomicFile::WvAtomicFile(WvStringParm filename, int flags, mode_t create_mode) 00015 : tmp_file(WvString::null) 00016 { 00017 open(filename, flags, create_mode); 00018 } 00019 00020 WvAtomicFile::~WvAtomicFile() 00021 { 00022 close(); 00023 } 00024 00025 00026 /* Mimics behaviour of wvfile except that it uses a tmp file and stores the 00027 real name */ 00028 bool WvAtomicFile::open(WvStringParm filename, int flags, mode_t create_mode) 00029 { 00030 close(); 00031 00032 atomic_file = filename; 00033 00034 // Ensure that if the file exists it is a regular file 00035 struct stat st; 00036 if (lstat(atomic_file, &st) == 0 && !S_ISREG(st.st_mode)) 00037 return false; 00038 00039 WvString new_tmp_file("%s/WvXXXXXX", getdirname(filename)); 00040 00041 // Get the current umask and guarantee that mkstemp() creates 00042 // a file with maximal restrictions 00043 mode_t old_umask = ::umask(077); 00044 int tmp_fd = ::mkstemp(new_tmp_file.edit()); 00045 if (tmp_fd < 0) 00046 seterr(errno); 00047 ::umask(old_umask); 00048 if (tmp_fd < 0) 00049 return false; 00050 00051 // Set the permissions as specified using the original umask 00052 // We will only possibly be adding permissions here... 00053 if (::fchmod(tmp_fd, create_mode & ~old_umask) != 0) 00054 seterr(errno); 00055 00056 if (!WvFile::open(tmp_fd)) 00057 { 00058 ::close(tmp_fd); 00059 return false; 00060 } 00061 00062 tmp_file = new_tmp_file; 00063 00064 return true; 00065 } 00066 00067 00068 void WvAtomicFile::close() 00069 { 00070 WvFdStream::close(); 00071 00072 if (tmp_file) 00073 { 00074 if (::rename(tmp_file, atomic_file) != 0) 00075 ::unlink(tmp_file); 00076 00077 tmp_file = WvString::null; 00078 } 00079 } 00080 00081 00082 bool WvAtomicFile::chmod(mode_t mode) 00083 { 00084 if (getfd() == -1) return false; 00085 00086 if (fchmod(getfd(), mode) != 0) 00087 { 00088 seterr(errno); 00089 return false; 00090 } 00091 00092 return true; 00093 } 00094 00095 00096 bool WvAtomicFile::chown(uid_t owner, gid_t group) 00097 { 00098 if (getfd() == -1) return false; 00099 00100 if (fchown(getfd(), owner, group) != 0) 00101 { 00102 seterr(errno); 00103 return false; 00104 } 00105 00106 return true; 00107 }