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