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 #include <sys/stat.h> 00015 00016 WvAtomicFile::WvAtomicFile(WvStringParm filename, int flags, mode_t create_mode) 00017 : tmp_file(WvString::null) 00018 { 00019 open(filename, flags, create_mode); 00020 } 00021 00022 WvAtomicFile::~WvAtomicFile() 00023 { 00024 close(); 00025 } 00026 00027 00028 /* Mimics behaviour of wvfile except that it uses a tmp file and stores the 00029 real name */ 00030 bool WvAtomicFile::open(WvStringParm filename, int flags, mode_t create_mode) 00031 { 00032 close(); 00033 00034 atomic_file = filename; 00035 00036 // Ensure that if the file exists it is a regular file 00037 struct stat st; 00038 if (lstat(atomic_file, &st) == 0 && !S_ISREG(st.st_mode)) 00039 return false; 00040 00041 WvString new_tmp_file("%s/WvXXXXXX", getdirname(filename)); 00042 00043 // Get the current umask and guarantee that mkstemp() creates 00044 // a file with maximal restrictions 00045 mode_t old_umask = ::umask(077); 00046 int tmp_fd = ::mkstemp(new_tmp_file.edit()); 00047 if (tmp_fd < 0) 00048 seterr(errno); 00049 ::umask(old_umask); 00050 if (tmp_fd < 0) 00051 return false; 00052 00053 // Set the permissions as specified using the original umask 00054 // We will only possibly be adding permissions here... 00055 if (::fchmod(tmp_fd, create_mode & ~old_umask) != 0) 00056 seterr(errno); 00057 00058 if (!WvFile::open(tmp_fd)) 00059 { 00060 ::close(tmp_fd); 00061 return false; 00062 } 00063 00064 tmp_file = new_tmp_file; 00065 00066 return true; 00067 } 00068 00069 00070 void WvAtomicFile::close() 00071 { 00072 WvFdStream::close(); 00073 00074 if (tmp_file) 00075 { 00076 if (::rename(tmp_file, atomic_file) != 0) 00077 ::unlink(tmp_file); 00078 00079 tmp_file = WvString::null; 00080 } 00081 } 00082 00083 00084 bool WvAtomicFile::chmod(mode_t mode) 00085 { 00086 if (getfd() == -1) return false; 00087 00088 if (fchmod(getfd(), mode) != 0) 00089 { 00090 seterr(errno); 00091 return false; 00092 } 00093 00094 return true; 00095 } 00096 00097 00098 bool WvAtomicFile::chown(uid_t owner, gid_t group) 00099 { 00100 if (getfd() == -1) return false; 00101 00102 if (fchown(getfd(), owner, group) != 0) 00103 { 00104 seterr(errno); 00105 return false; 00106 } 00107 00108 return true; 00109 }