ksavefile.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #include <stdlib.h>
00023 #include <sys/types.h>
00024
00025 #ifdef HAVE_SYS_STAT_H
00026 #include <sys/stat.h>
00027 #endif
00028
00029 #include <sys/param.h>
00030 #include <unistd.h>
00031 #include <fcntl.h>
00032
00033 #ifdef HAVE_TEST
00034 #include <test.h>
00035 #endif
00036
00037 #include <qdatetime.h>
00038 #include <qdir.h>
00039
00040 #include "kapplication.h"
00041 #include "ksavefile.h"
00042 #include "kstandarddirs.h"
00043
00044 static QString realFilePath(const QString &filename)
00045 {
00046 char realpath_buffer[MAXPATHLEN + 1];
00047 memset(realpath_buffer, 0, MAXPATHLEN + 1);
00048
00049
00050 if (realpath( QFile::encodeName(filename).data(), realpath_buffer) != 0) {
00051
00052 return QFile::decodeName(realpath_buffer);
00053 }
00054
00055 return filename;
00056 }
00057
00058
00059 KSaveFile::KSaveFile(const QString &filename, int mode)
00060 : mTempFile(true)
00061 {
00062
00063 QString real_filename = realFilePath(filename);
00064
00065
00066
00067
00068 if (!checkAccess(real_filename, W_OK))
00069 {
00070 mTempFile.setError(EACCES);
00071 return;
00072 }
00073
00074 if (mTempFile.create(real_filename, QString::fromLatin1(".new"), mode))
00075 {
00076 mFileName = real_filename;
00077
00078
00079
00080
00081 struct stat stat_buf;
00082 if (stat(QFile::encodeName(real_filename), &stat_buf)==0)
00083 {
00084
00085 if (stat_buf.st_uid == getuid())
00086 {
00087 bool changePermission = true;
00088 if (stat_buf.st_gid != getgid())
00089 {
00090 if (fchown(mTempFile.handle(), (uid_t) -1, stat_buf.st_gid) != 0)
00091 {
00092
00093 changePermission = false;
00094 }
00095 }
00096 if (changePermission)
00097 fchmod(mTempFile.handle(), stat_buf.st_mode);
00098 }
00099 }
00100 }
00101 return;
00102 }
00103
00104 KSaveFile::~KSaveFile()
00105 {
00106 if (mTempFile.bOpen)
00107 close();
00108 }
00109
00110 QString
00111 KSaveFile::name() const
00112 {
00113 return mFileName;
00114 }
00115
00116 void
00117 KSaveFile::abort()
00118 {
00119 mTempFile.unlink();
00120 mTempFile.close();
00121 }
00122
00123 bool
00124 KSaveFile::close()
00125 {
00126 if (mTempFile.name().isEmpty())
00127 return false;
00128 if (!mTempFile.sync())
00129 {
00130 abort();
00131 return false;
00132 }
00133 if (mTempFile.close())
00134 {
00135 QDir dir;
00136 bool result = dir.rename( mTempFile.name(), mFileName);
00137 if ( result )
00138 {
00139 return true;
00140 }
00141 mTempFile.setError(errno);
00142 }
00143
00144
00145 mTempFile.unlink();
00146 return false;
00147 }
00148
00149 static int
00150 write_all(int fd, const char *buf, size_t len)
00151 {
00152 while (len > 0)
00153 {
00154 int written = write(fd, buf, len);
00155 if (written < 0)
00156 {
00157 if (errno == EINTR)
00158 continue;
00159 return -1;
00160 }
00161 buf += written;
00162 len -= written;
00163 }
00164 return 0;
00165 }
00166
00167 bool KSaveFile::backupFile( const QString& qFilename, const QString& backupDir,
00168 const QString& backupExtension)
00169 {
00170 QCString cFilename = QFile::encodeName(qFilename);
00171 const char *filename = cFilename.data();
00172
00173 int fd = open( filename, O_RDONLY);
00174 if (fd < 0)
00175 return false;
00176
00177 struct stat buff;
00178 if ( fstat( fd, &buff) < 0 )
00179 {
00180 ::close( fd );
00181 return false;
00182 }
00183
00184 QCString cBackup;
00185 if ( backupDir.isEmpty() )
00186 cBackup = cFilename;
00187 else
00188 {
00189 QCString nameOnly;
00190 int slash = cFilename.findRev('/');
00191 if (slash < 0)
00192 nameOnly = cFilename;
00193 else
00194 nameOnly = cFilename.mid(slash + 1);
00195 cBackup = QFile::encodeName(backupDir);
00196 if ( backupDir[backupDir.length()-1] != '/' )
00197 cBackup += '/';
00198 cBackup += nameOnly;
00199 }
00200 cBackup += QFile::encodeName(backupExtension);
00201 const char *backup = cBackup.data();
00202 int permissions = buff.st_mode & 07777;
00203
00204 if ( stat( backup, &buff) == 0)
00205 {
00206 if ( unlink( backup ) != 0 )
00207 {
00208 ::close(fd);
00209 return false;
00210 }
00211 }
00212
00213 mode_t old_umask = umask(0);
00214 int fd2 = open( backup, O_WRONLY | O_CREAT | O_EXCL, permissions | S_IWUSR);
00215 umask(old_umask);
00216
00217 if ( fd2 < 0 )
00218 {
00219 ::close(fd);
00220 return false;
00221 }
00222
00223 char buffer[ 32*1024 ];
00224
00225 while( 1 )
00226 {
00227 int n = ::read( fd, buffer, 32*1024 );
00228 if (n == -1)
00229 {
00230 if (errno == EINTR)
00231 continue;
00232 ::close(fd);
00233 ::close(fd2);
00234 return false;
00235 }
00236 if (n == 0)
00237 break;
00238
00239 if (write_all( fd2, buffer, n))
00240 {
00241 ::close(fd);
00242 ::close(fd2);
00243 return false;
00244 }
00245 }
00246
00247 ::close( fd );
00248
00249 if (::close(fd2))
00250 return false;
00251 return true;
00252 }
This file is part of the documentation for kdecore Library Version 3.3.2.