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 }