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 <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 <kde_file.h>
00039
#include "kapplication.h"
00040
#include "ksavefile.h"
00041
#include "kstandarddirs.h"
00042
00043 KSaveFile::KSaveFile(
const QString &filename,
int mode)
00044 : mTempFile(true)
00045 {
00046
00047
QString real_filename = KStandardDirs::realFilePath(filename);
00048
00049
00050
00051
00052
if (!checkAccess(real_filename, W_OK))
00053 {
00054 mTempFile.
setError(EACCES);
00055
return;
00056 }
00057
00058
if (mTempFile.
create(real_filename, QString::fromLatin1(
".new"), mode))
00059 {
00060 mFileName = real_filename;
00061
00062
00063
00064
00065 KDE_struct_stat stat_buf;
00066
if (KDE_stat(QFile::encodeName(real_filename), &stat_buf)==0)
00067 {
00068
00069
if (stat_buf.st_uid == getuid())
00070 {
00071
bool changePermission =
true;
00072
if (stat_buf.st_gid != getgid())
00073 {
00074
if (fchown(mTempFile.
handle(), (uid_t) -1, stat_buf.st_gid) != 0)
00075 {
00076
00077 changePermission =
false;
00078 }
00079 }
00080
if (changePermission)
00081 fchmod(mTempFile.
handle(), stat_buf.st_mode);
00082 }
00083 }
00084 }
00085 }
00086
00087 KSaveFile::~KSaveFile()
00088 {
00089
if (mTempFile.
bOpen)
00090
close();
00091 }
00092
00093
QString
00094 KSaveFile::name()
const
00095
{
00096
return mFileName;
00097 }
00098
00099
void
00100 KSaveFile::abort()
00101 {
00102 mTempFile.
unlink();
00103 mTempFile.
close();
00104 }
00105
00106
bool
00107 KSaveFile::close()
00108 {
00109
if (mTempFile.
name().isEmpty() || mTempFile.
handle()==-1)
00110
return false;
00111
if (!mTempFile.
sync())
00112 {
00113
abort();
00114
return false;
00115 }
00116
if (mTempFile.
close())
00117 {
00118
if (0==KDE_rename(QFile::encodeName(mTempFile.
name()), QFile::encodeName(mFileName)))
00119
return true;
00120 mTempFile.
setError(errno);
00121 }
00122
00123 mTempFile.
unlink();
00124
return false;
00125 }
00126
00127
static int
00128 write_all(
int fd,
const char *buf, size_t len)
00129 {
00130
while (len > 0)
00131 {
00132
int written = write(fd, buf, len);
00133
if (written < 0)
00134 {
00135
if (errno == EINTR)
00136
continue;
00137
return -1;
00138 }
00139 buf += written;
00140 len -= written;
00141 }
00142
return 0;
00143 }
00144
00145 bool KSaveFile::backupFile(
const QString& qFilename,
const QString& backupDir,
00146
const QString& backupExtension)
00147 {
00148
QCString cFilename = QFile::encodeName(qFilename);
00149
const char *filename = cFilename.data();
00150
00151
int fd = KDE_open( filename, O_RDONLY );
00152
if (fd < 0)
00153
return false;
00154
00155 KDE_struct_stat buff;
00156
if ( KDE_fstat( fd, &buff) < 0 )
00157 {
00158 ::close( fd );
00159
return false;
00160 }
00161
00162
QCString cBackup;
00163
if ( backupDir.isEmpty() )
00164 cBackup = cFilename;
00165
else
00166 {
00167
QCString nameOnly;
00168
int slash = cFilename.findRev(
'/');
00169
if (slash < 0)
00170 nameOnly = cFilename;
00171
else
00172 nameOnly = cFilename.mid(slash + 1);
00173 cBackup = QFile::encodeName(backupDir);
00174
if ( backupDir[backupDir.length()-1] !=
'/' )
00175 cBackup +=
'/';
00176 cBackup += nameOnly;
00177 }
00178 cBackup += QFile::encodeName(backupExtension);
00179
const char *backup = cBackup.data();
00180
int permissions = buff.st_mode & 07777;
00181
00182
if ( KDE_stat( backup, &buff) == 0)
00183 {
00184
if ( unlink( backup ) != 0 )
00185 {
00186 ::close(fd);
00187
return false;
00188 }
00189 }
00190
00191 mode_t old_umask = umask(0);
00192
int fd2 = KDE_open( backup, O_WRONLY | O_CREAT | O_EXCL, permissions | S_IWUSR);
00193 umask(old_umask);
00194
00195
if ( fd2 < 0 )
00196 {
00197 ::close(fd);
00198
return false;
00199 }
00200
00201
char buffer[ 32*1024 ];
00202
00203
while( 1 )
00204 {
00205
int n = ::read( fd, buffer, 32*1024 );
00206
if (n == -1)
00207 {
00208
if (errno == EINTR)
00209
continue;
00210 ::close(fd);
00211 ::close(fd2);
00212
return false;
00213 }
00214
if (n == 0)
00215
break;
00216
00217
if (write_all( fd2, buffer, n))
00218 {
00219 ::close(fd);
00220 ::close(fd2);
00221
return false;
00222 }
00223 }
00224
00225 ::close( fd );
00226
00227
if (::close(fd2))
00228
return false;
00229
return true;
00230 }