kdecore Library API Documentation

ksavefile.cpp

00001 /* 00002 This file is part of the KDE libraries 00003 Copyright (c) 1999 Waldo Bastian <bastian@kde.org> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License version 2 as published by the Free Software Foundation. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to 00016 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00017 Boston, MA 02111-1307, USA. 00018 */ 00019 00020 #include <config.h> 00021 00022 #include <sys/types.h> 00023 00024 #ifdef HAVE_SYS_STAT_H 00025 #include <sys/stat.h> 00026 #endif 00027 00028 #include <unistd.h> 00029 #include <fcntl.h> 00030 00031 #ifdef HAVE_TEST 00032 #include <test.h> 00033 #endif 00034 00035 #include <qdatetime.h> 00036 #include <qdir.h> 00037 00038 #include "kapplication.h" 00039 #include "ksavefile.h" 00040 00041 KSaveFile::KSaveFile(const QString &filename, int mode) 00042 : mTempFile(true) 00043 { 00044 00045 // follow symbolic link, if any 00046 QString real_filename = filename; 00047 00048 QFileInfo file_info(real_filename); 00049 int c=0; 00050 while(file_info.isSymLink() && ++c<6) { 00051 real_filename = file_info.readLink(); 00052 file_info.setFile( real_filename ); 00053 } 00054 00055 // we only check here if the directory can be written to 00056 // the actual filename isn't written to, but replaced later 00057 // with the contents of our tempfile 00058 if (!checkAccess(real_filename, W_OK)) 00059 { 00060 mTempFile.setError(EACCES); 00061 return; 00062 } 00063 00064 if (mTempFile.create(real_filename, QString::fromLatin1(".new"), mode)) 00065 { 00066 mFileName = real_filename; // Set filename upon success 00067 00068 // if we're overwriting an existing file, ensure temp file's 00069 // permissions are the same as existing file so the existing 00070 // file's permissions are preserved 00071 struct stat stat_buf; 00072 if ((stat(QFile::encodeName(real_filename), &stat_buf)==0) 00073 && (stat_buf.st_uid == getuid()) 00074 && (stat_buf.st_gid == getgid())) 00075 { 00076 fchmod(mTempFile.handle() , stat_buf.st_mode); 00077 } 00078 } 00079 return; 00080 } 00081 00082 KSaveFile::~KSaveFile() 00083 { 00084 if (mTempFile.bOpen) 00085 close(); // Close if we were still open 00086 } 00087 00088 QString 00089 KSaveFile::name() const 00090 { 00091 return mFileName; 00092 } 00093 00094 void 00095 KSaveFile::abort() 00096 { 00097 mTempFile.unlink(); 00098 mTempFile.close(); 00099 } 00100 00101 bool 00102 KSaveFile::close() 00103 { 00104 if (mTempFile.name().isEmpty()) 00105 return false; // Save was aborted already 00106 if (mTempFile.close()) 00107 { 00108 QDir dir; 00109 bool result = dir.rename( mTempFile.name(), mFileName); 00110 if ( result ) 00111 { 00112 return true; // Success! 00113 } 00114 mTempFile.setError(errno); 00115 } 00116 00117 // Something went wrong, make sure to delete the interim file. 00118 mTempFile.unlink(); 00119 return false; 00120 } 00121 00122 static int 00123 write_all(int fd, const char *buf, size_t len) 00124 { 00125 while (len > 0) 00126 { 00127 int written = write(fd, buf, len); 00128 if (written < 0) 00129 { 00130 if (errno == EINTR) 00131 continue; 00132 return -1; 00133 } 00134 buf += written; 00135 len -= written; 00136 } 00137 return 0; 00138 } 00139 00140 bool KSaveFile::backupFile( const QString& qFilename, const QString& backupDir, 00141 const QString& backupExtension) 00142 { 00143 QCString cFilename = QFile::encodeName(qFilename); 00144 const char *filename = cFilename.data(); 00145 00146 int fd = open( filename, O_RDONLY); 00147 if (fd < 0) 00148 return false; 00149 00150 struct stat buff; 00151 if ( fstat( fd, &buff) < 0 ) 00152 { 00153 ::close( fd ); 00154 return false; 00155 } 00156 00157 QCString cBackup; 00158 if ( backupDir.isEmpty() ) 00159 cBackup = cFilename; 00160 else 00161 { 00162 QCString nameOnly; 00163 int slash = cFilename.findRev('/'); 00164 if (slash < 0) 00165 nameOnly = cFilename; 00166 else 00167 nameOnly = cFilename.mid(slash + 1); 00168 cBackup = QFile::encodeName(backupDir); 00169 if ( backupDir[backupDir.length()-1] != '/' ) 00170 cBackup += '/'; 00171 cBackup += nameOnly; 00172 } 00173 cBackup += QFile::encodeName(backupExtension); 00174 const char *backup = cBackup.data(); 00175 int permissions = buff.st_mode & 07777; 00176 00177 if ( stat( backup, &buff) == 0) 00178 { 00179 if ( unlink( backup ) != 0 ) 00180 { 00181 ::close(fd); 00182 return false; 00183 } 00184 } 00185 00186 mode_t old_umask = umask(0); 00187 int fd2 = open( backup, O_WRONLY | O_CREAT | O_EXCL, permissions | S_IWUSR); 00188 umask(old_umask); 00189 00190 if ( fd2 < 0 ) 00191 { 00192 ::close(fd); 00193 return false; 00194 } 00195 00196 char buffer[ 32*1024 ]; 00197 00198 while( 1 ) 00199 { 00200 int n = ::read( fd, buffer, 32*1024 ); 00201 if (n == -1) 00202 { 00203 if (errno == EINTR) 00204 continue; 00205 ::close(fd); 00206 ::close(fd2); 00207 return false; 00208 } 00209 if (n == 0) 00210 break; // Finished 00211 00212 if (write_all( fd2, buffer, n)) 00213 { 00214 ::close(fd); 00215 ::close(fd2); 00216 return false; 00217 } 00218 } 00219 00220 ::close( fd ); 00221 00222 if (::close(fd2)) 00223 return false; 00224 return true; 00225 }
KDE Logo
This file is part of the documentation for kdecore Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Aug 20 09:48:26 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003