• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdecore
 

tdecore

  • tdecore
ksavefile.cpp
1/*
2 This file is part of the KDE libraries
3 Copyright (c) 1999 Waldo Bastian <bastian@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License version 2 as published by the Free Software Foundation.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18*/
19
20#include <config.h>
21
22#include <sys/types.h>
23
24#ifdef HAVE_SYS_STAT_H
25#include <sys/stat.h>
26#endif
27
28#include <unistd.h>
29#include <fcntl.h>
30
31#ifdef HAVE_TEST
32#include <test.h>
33#endif
34
35#include <tqdatetime.h>
36#include <tqdir.h>
37
38#include <kde_file.h>
39#include "tdeapplication.h"
40#include "ksavefile.h"
41#include "tdestandarddirs.h"
42
43KSaveFile::KSaveFile(const TQString &filename, int mode)
44 : mTempFile(true)
45{
46 // follow symbolic link, if any
47 TQString real_filename = TDEStandardDirs::realFilePath(filename);
48
49 // we only check here if the directory can be written to
50 // the actual filename isn't written to, but replaced later
51 // with the contents of our tempfile
52 if (!checkAccess(real_filename, W_OK))
53 {
54 mTempFile.setError(EACCES);
55 return;
56 }
57
58 if (mTempFile.create(real_filename, TQString::fromLatin1(".new"), mode))
59 {
60 mFileName = real_filename; // Set filename upon success
61
62 // if we're overwriting an existing file, ensure temp file's
63 // permissions are the same as existing file so the existing
64 // file's permissions are preserved
65 KDE_struct_stat stat_buf;
66 if (KDE_stat(TQFile::encodeName(real_filename), &stat_buf)==0)
67 {
68 // But only if we own the existing file
69 if (stat_buf.st_uid == getuid())
70 {
71 bool changePermission = true;
72 if (stat_buf.st_gid != getgid())
73 {
74 if (fchown(mTempFile.handle(), (uid_t) -1, stat_buf.st_gid) != 0)
75 {
76 // Use standard permission if we can't set the group
77 changePermission = false;
78 }
79 }
80 if (changePermission)
81 fchmod(mTempFile.handle(), stat_buf.st_mode);
82 }
83 }
84 }
85}
86
87KSaveFile::~KSaveFile()
88{
89 if (mTempFile.bOpen)
90 close(); // Close if we were still open
91}
92
93TQString
94KSaveFile::name() const
95{
96 return mFileName;
97}
98
99void
100KSaveFile::abort()
101{
102 mTempFile.close();
103 mTempFile.unlink();
104}
105
106bool
107KSaveFile::close()
108{
109 if (mTempFile.name().isEmpty() || mTempFile.handle()==-1)
110 return false; // Save was aborted already
111 if (!mTempFile.sync())
112 {
113 abort();
114 return false;
115 }
116 if (mTempFile.close())
117 {
118 if (0==KDE_rename(TQFile::encodeName(mTempFile.name()), TQFile::encodeName(mFileName)))
119 return true; // Success!
120 mTempFile.setError(errno);
121 }
122 // Something went wrong, make sure to delete the interim file.
123 mTempFile.unlink();
124 return false;
125}
126
127static int
128write_all(int fd, const char *buf, size_t len)
129{
130 while (len > 0)
131 {
132 int written = write(fd, buf, len);
133 if (written < 0)
134 {
135 if (errno == EINTR)
136 continue;
137 return -1;
138 }
139 buf += written;
140 len -= written;
141 }
142 return 0;
143}
144
145bool KSaveFile::backupFile( const TQString& qFilename, const TQString& backupDir,
146 const TQString& backupExtension)
147{
148 TQCString cFilename = TQFile::encodeName(qFilename);
149 const char *filename = cFilename.data();
150
151 int fd = KDE_open( filename, O_RDONLY );
152 if (fd < 0)
153 return false;
154
155 KDE_struct_stat buff;
156 if ( KDE_fstat( fd, &buff) < 0 )
157 {
158 ::close( fd );
159 return false;
160 }
161
162 TQCString cBackup;
163 if ( backupDir.isEmpty() )
164 cBackup = cFilename;
165 else
166 {
167 TQCString nameOnly;
168 int slash = cFilename.findRev('/');
169 if (slash < 0)
170 nameOnly = cFilename;
171 else
172 nameOnly = cFilename.mid(slash + 1);
173 cBackup = TQFile::encodeName(backupDir);
174 if ( backupDir[backupDir.length()-1] != (TQChar)'/' )
175 cBackup += '/';
176 cBackup += nameOnly;
177 }
178 cBackup += TQFile::encodeName(backupExtension);
179 const char *backup = cBackup.data();
180 int permissions = buff.st_mode & 07777;
181
182 if ( KDE_stat( backup, &buff) == 0)
183 {
184 if ( unlink( backup ) != 0 )
185 {
186 ::close(fd);
187 return false;
188 }
189 }
190
191 mode_t old_umask = umask(0);
192 int fd2 = KDE_open( backup, O_WRONLY | O_CREAT | O_EXCL, permissions | S_IWUSR);
193 umask(old_umask);
194
195 if ( fd2 < 0 )
196 {
197 ::close(fd);
198 return false;
199 }
200
201 char buffer[ 32*1024 ];
202
203 while( 1 )
204 {
205 int n = ::read( fd, buffer, 32*1024 );
206 if (n == -1)
207 {
208 if (errno == EINTR)
209 continue;
210 ::close(fd);
211 ::close(fd2);
212 return false;
213 }
214 if (n == 0)
215 break; // Finished
216
217 if (write_all( fd2, buffer, n))
218 {
219 ::close(fd);
220 ::close(fd2);
221 return false;
222 }
223 }
224
225 ::close( fd );
226
227 if (::close(fd2))
228 return false;
229 return true;
230}
KSaveFile::name
TQString name() const
The name of the file as passed to the constructor.
Definition: ksavefile.cpp:94
KSaveFile::~KSaveFile
~KSaveFile()
The destructor closes the file.
Definition: ksavefile.cpp:87
KSaveFile::KSaveFile
KSaveFile(const TQString &filename, int mode=0666)
Creates a new KSaveFile with the given file name.
Definition: ksavefile.cpp:43
KSaveFile::close
bool close()
Closes the file and makes the changes definitive.
Definition: ksavefile.cpp:107
KSaveFile::abort
void abort()
Aborts the write operation and removes any intermediate files This implies a close.
Definition: ksavefile.cpp:100
KSaveFile::backupFile
static bool backupFile(const TQString &filename, const TQString &backupDir=TQString::null, const TQString &backupExtension=TQString::fromLatin1("~"))
Static method to create a backup file before saving.
Definition: ksavefile.cpp:145
KTempFile::handle
int handle() const
An integer file descriptor open for writing to the file.
Definition: tdetempfile.cpp:153
KTempFile::close
bool close()
Closes the file.
Definition: tdetempfile.cpp:257
KTempFile::sync
bool sync()
Flushes file to disk (fsync).
Definition: tdetempfile.cpp:220
KTempFile::unlink
void unlink()
Unlinks the file from the directory.
Definition: tdetempfile.cpp:206
KTempFile::name
TQString name() const
Returns the full path and name of the file.
Definition: tdetempfile.cpp:147
TDEStandardDirs::realFilePath
static TQString realFilePath(const TQString &filename)
Expands all symbolic links and resolves references to '/.
Definition: tdestandarddirs.cpp:707

tdecore

Skip menu "tdecore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

tdecore

Skip menu "tdecore"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdecore by doxygen 1.9.4
This website is maintained by Timothy Pearson.