| # kdecore Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# 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 <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    // follow symbolic link, if any
    00047    QString real_filename = KStandardDirs::realFilePath(filename);
    00048
    00049    // we only check here if the directory can be written to
    00050    // the actual filename isn't written to, but replaced later
    00051    // with the contents of our tempfile
    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; // Set filename upon success
    00061
    00062       // if we're overwriting an existing file, ensure temp file's
    00063       // permissions are the same as existing file so the existing
    00064       // file's permissions are preserved
    00065       KDE_struct_stat stat_buf;
    00066       if (KDE_stat(QFile::encodeName(real_filename), &stat_buf)==0)
    00067       {
    00068          // But only if we own the existing file
    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                   // Use standard permission if we can't set the group
    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(); // Close if we were still open
    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; // Save was aborted already
    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; // Success!
    00120       mTempFile.setError(errno);
    00121    }
    00122    // Something went wrong, make sure to delete the interim file.
    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; // Finished
    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 }

This file is part of the documentation for kdecore Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:18:10 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003