author | llornkcor <llornkcor> | 2003-07-17 02:25:08 (UTC) |
---|---|---|
committer | llornkcor <llornkcor> | 2003-07-17 02:25:08 (UTC) |
commit | 6ca1d7605597f4b8a7559167e5cf3d6e093805cd (patch) (unidiff) | |
tree | 93096c3d0df0c0f02c75d2acc2f481120914945c | |
parent | 115e09bdeb2ee3c7c0b9344f95179e1d10e86e48 (diff) | |
download | opie-6ca1d7605597f4b8a7559167e5cf3d6e093805cd.zip opie-6ca1d7605597f4b8a7559167e5cf3d6e093805cd.tar.gz opie-6ca1d7605597f4b8a7559167e5cf3d6e093805cd.tar.bz2 |
fix filesaving when filename contains extended characters
-rw-r--r-- | library/filemanager.cpp | 167 | ||||
-rw-r--r-- | library/filemanager.h | 6 |
2 files changed, 121 insertions, 52 deletions
diff --git a/library/filemanager.cpp b/library/filemanager.cpp index 2b97846..cc657fa 100644 --- a/library/filemanager.cpp +++ b/library/filemanager.cpp | |||
@@ -28,6 +28,11 @@ | |||
28 | 28 | ||
29 | #include <errno.h> | 29 | #include <errno.h> |
30 | #include <stdlib.h> | 30 | #include <stdlib.h> |
31 | #include <unistd.h> | ||
32 | #include <sys/stat.h> | ||
33 | #include <dirent.h> | ||
34 | #include <sys/sendfile.h> | ||
35 | #include <fcntl.h> | ||
31 | 36 | ||
32 | /*! | 37 | /*! |
33 | \class FileManager | 38 | \class FileManager |
@@ -56,23 +61,25 @@ FileManager::~FileManager() | |||
56 | */ | 61 | */ |
57 | bool FileManager::saveFile( const DocLnk &f, const QByteArray &data ) | 62 | bool FileManager::saveFile( const DocLnk &f, const QByteArray &data ) |
58 | { | 63 | { |
59 | QString fn = f.file() + ".new"; | 64 | QString fn = f.file() + ".new"; |
60 | ensurePathExists( fn ); | 65 | ensurePathExists( fn ); |
61 | QFile fl( fn ); | 66 | QFile fl( fn ); |
62 | if ( !fl.open( IO_WriteOnly|IO_Raw ) ) | 67 | if ( !fl.open( IO_WriteOnly|IO_Raw ) ) { |
63 | return FALSE; | 68 | qWarning("open failed"); |
69 | return FALSE; | ||
70 | } | ||
64 | int total_written = fl.writeBlock( data ); | 71 | int total_written = fl.writeBlock( data ); |
65 | fl.close(); | 72 | fl.close(); |
66 | if ( total_written != int(data.size()) || !f.writeLink() ) { | 73 | if ( total_written != int(data.size()) || !f.writeLink() ) { |
67 | QFile::remove( fn ); | 74 | QFile::remove( fn ); |
68 | return FALSE; | 75 | return FALSE; |
69 | } | 76 | } |
77 | qDebug("total written %d out of %d", total_written, data.size()); | ||
70 | // else rename the file... | 78 | // else rename the file... |
71 | if ( ::rename( fn.latin1(), f.file().latin1() ) < 0 ) { | 79 | if ( !renameFile( fn.latin1(), f.file().latin1() ) ) { |
72 | qWarning( "problem renaming file %s to %s, errno: %d", fn.latin1(), | 80 | qWarning( "problem renaming file %s to %s, errno: %d", fn.latin1(), |
73 | f.file().latin1(), errno ); | 81 | f.file().latin1(), errno ); |
74 | // remove the file... | 82 | // remove the file... |
75 | QFile::remove( fn ); | ||
76 | } | 83 | } |
77 | return TRUE; | 84 | return TRUE; |
78 | } | 85 | } |
@@ -86,12 +93,12 @@ bool FileManager::saveFile( const DocLnk &f, const QByteArray &data ) | |||
86 | */ | 93 | */ |
87 | bool FileManager::saveFile( const DocLnk &f, const QString &text ) | 94 | bool FileManager::saveFile( const DocLnk &f, const QString &text ) |
88 | { | 95 | { |
89 | QString fn = f.file() + ".new"; | 96 | QString fn = f.file() + ".new"; |
90 | ensurePathExists( fn ); | 97 | ensurePathExists( fn ); |
91 | QFile fl( fn ); | 98 | QFile fl( fn ); |
92 | if ( !fl.open( IO_WriteOnly|IO_Raw ) ) { | 99 | if ( !fl.open( IO_WriteOnly|IO_Raw ) ) { |
93 | qDebug( "open failed: %s", fn.latin1() ); | 100 | qWarning("open failed"); |
94 | return FALSE; | 101 | return FALSE; |
95 | } | 102 | } |
96 | 103 | ||
97 | QCString cstr = text.utf8(); | 104 | QCString cstr = text.utf8(); |
@@ -99,15 +106,14 @@ bool FileManager::saveFile( const DocLnk &f, const QString &text ) | |||
99 | total_written = fl.writeBlock( cstr.data(), cstr.length() ); | 106 | total_written = fl.writeBlock( cstr.data(), cstr.length() ); |
100 | fl.close(); | 107 | fl.close(); |
101 | if ( total_written != int(cstr.length()) || !f.writeLink() ) { | 108 | if ( total_written != int(cstr.length()) || !f.writeLink() ) { |
102 | QFile::remove( fn ); | 109 | QFile::remove( fn ); |
103 | return FALSE; | 110 | return FALSE; |
104 | } | 111 | } |
105 | // okay now rename the file... | 112 | // okay now rename the file.. |
106 | if ( ::rename( fn.latin1(), f.file().latin1() ) < 0 ) { | 113 | if ( !renameFile( fn.latin1(), f.file().latin1() ) ) { |
107 | qWarning( "problem renaming file %s to %s, errno: %d", fn.latin1(), | 114 | qWarning( "problem renaming file %s to %s, errno: %d", fn.latin1(), |
108 | f.file().latin1(), errno ); | 115 | f.file().latin1(), errno ); |
109 | // remove the tmp file, otherwise, it will just lay around... | 116 | |
110 | QFile::remove( fn.latin1() ); | ||
111 | } | 117 | } |
112 | return TRUE; | 118 | return TRUE; |
113 | } | 119 | } |
@@ -125,7 +131,7 @@ bool FileManager::loadFile( const DocLnk &f, QString &text ) | |||
125 | QString fn = f.file(); | 131 | QString fn = f.file(); |
126 | QFile fl( fn ); | 132 | QFile fl( fn ); |
127 | if ( !fl.open( IO_ReadOnly ) ) | 133 | if ( !fl.open( IO_ReadOnly ) ) |
128 | return FALSE; | 134 | return FALSE; |
129 | QTextStream ts( &fl ); | 135 | QTextStream ts( &fl ); |
130 | #if QT_VERSION <= 230 && defined(QT_NO_CODECS) | 136 | #if QT_VERSION <= 230 && defined(QT_NO_CODECS) |
131 | // The below should work, but doesn't in Qt 2.3.0 | 137 | // The below should work, but doesn't in Qt 2.3.0 |
@@ -149,10 +155,10 @@ bool FileManager::loadFile( const DocLnk &f, QByteArray &ba ) | |||
149 | QString fn = f.file(); | 155 | QString fn = f.file(); |
150 | QFile fl( fn ); | 156 | QFile fl( fn ); |
151 | if ( !fl.open( IO_ReadOnly ) ) | 157 | if ( !fl.open( IO_ReadOnly ) ) |
152 | return FALSE; | 158 | return FALSE; |
153 | ba.resize( fl.size() ); | 159 | ba.resize( fl.size() ); |
154 | if ( fl.size() > 0 ) | 160 | if ( fl.size() > 0 ) |
155 | fl.readBlock( ba.data(), fl.size() ); | 161 | fl.readBlock( ba.data(), fl.size() ); |
156 | fl.close(); | 162 | fl.close(); |
157 | return TRUE; | 163 | return TRUE; |
158 | } | 164 | } |
@@ -167,49 +173,110 @@ bool FileManager::copyFile( const AppLnk &src, const AppLnk &dest ) | |||
167 | { | 173 | { |
168 | QFile sf( src.file() ); | 174 | QFile sf( src.file() ); |
169 | if ( !sf.open( IO_ReadOnly ) ) | 175 | if ( !sf.open( IO_ReadOnly ) ) |
170 | return FALSE; | 176 | return FALSE; |
171 | 177 | ||
172 | QString fn = dest.file() + ".new"; | 178 | QString fn = dest.file() + ".new"; |
173 | ensurePathExists( fn ); | 179 | ensurePathExists( fn ); |
174 | QFile df( fn ); | 180 | QFile df( fn ); |
175 | if ( !df.open( IO_WriteOnly|IO_Raw ) ) | 181 | if ( !df.open( IO_WriteOnly|IO_Raw ) ) |
176 | return FALSE; | 182 | return FALSE; |
177 | 183 | ||
178 | const int bufsize = 16384; | 184 | const int bufsize = 16384; |
179 | char buffer[bufsize]; | 185 | char buffer[bufsize]; |
180 | bool ok = TRUE; | 186 | bool ok = TRUE; |
181 | int bytesRead = 0; | 187 | int bytesRead = 0; |
182 | while ( ok && !sf.atEnd() ) { | 188 | while ( ok && !sf.atEnd() ) { |
183 | bytesRead = sf.readBlock( buffer, bufsize ); | 189 | bytesRead = sf.readBlock( buffer, bufsize ); |
184 | if ( bytesRead < 0 ) | 190 | if ( bytesRead < 0 ) |
185 | ok = FALSE; | 191 | ok = FALSE; |
186 | while ( ok && bytesRead > 0 ) { | 192 | while ( ok && bytesRead > 0 ) { |
187 | int bytesWritten = df.writeBlock( buffer, bytesRead ); | 193 | int bytesWritten = df.writeBlock( buffer, bytesRead ); |
188 | if ( bytesWritten < 0 ) | 194 | if ( bytesWritten < 0 ) |
189 | ok = FALSE; | 195 | ok = FALSE; |
190 | else | 196 | else |
191 | bytesRead -= bytesWritten; | 197 | bytesRead -= bytesWritten; |
192 | } | 198 | } |
193 | } | 199 | } |
194 | 200 | ||
195 | if ( ok ) | 201 | if ( ok ) |
196 | ok = dest.writeLink(); | 202 | ok = dest.writeLink(); |
197 | 203 | ||
198 | if ( ok ) { | 204 | if ( ok ) { |
199 | // okay now rename the file... | 205 | // okay now rename the file... |
200 | if ( ::rename( fn.latin1(), dest.file().latin1() ) < 0 ) { | 206 | if ( !renameFile( fn.latin1(), dest.file().latin1() ) ) { |
201 | qWarning( "problem renaming file %s to %s, errno: %d", fn.latin1(), | 207 | qWarning( "problem renaming file %s to %s, errno: %d", fn.latin1(), |
202 | dest.file().latin1(), errno ); | 208 | dest.file().latin1(), errno ); |
203 | // remove the tmp file, otherwise, it will just lay around... | 209 | // remove the tmp file, otherwise, it will just lay around... |
204 | QFile::remove( fn.latin1() ); | 210 | QFile::remove( fn.latin1() ); |
205 | } | 211 | } |
206 | } else { | 212 | } else { |
207 | QFile::remove( fn.latin1() ); | 213 | QFile::remove( fn.latin1() ); |
208 | } | 214 | } |
209 | 215 | ||
210 | return ok; | 216 | return ok; |
211 | } | 217 | } |
212 | 218 | ||
219 | bool FileManager::copyFile( const QString & src, const QString & dest ) { | ||
220 | bool success = true; | ||
221 | struct stat status; | ||
222 | int read_fd=0; | ||
223 | int write_fd=0; | ||
224 | struct stat stat_buf; | ||
225 | off_t offset = 0; | ||
226 | QFile srcFile(src); | ||
227 | QFile destFile(dest); | ||
228 | |||
229 | if(!srcFile.open( IO_ReadOnly|IO_Raw)) { | ||
230 | return success = false; | ||
231 | } | ||
232 | read_fd = srcFile.handle(); | ||
233 | if(read_fd != -1) { | ||
234 | fstat (read_fd, &stat_buf); | ||
235 | if( !destFile.open( IO_WriteOnly|IO_Raw ) ) | ||
236 | return success = false; | ||
237 | write_fd = destFile.handle(); | ||
238 | if(write_fd != -1) { | ||
239 | int err=0; | ||
240 | QString msg; | ||
241 | err = sendfile(write_fd, read_fd, &offset, stat_buf.st_size); | ||
242 | if( err == -1) { | ||
243 | switch(err) { | ||
244 | case EBADF : msg = "The input file was not opened for reading or the output file was not opened for writing. "; | ||
245 | case EINVAL: msg = "Descriptor is not valid or locked. "; | ||
246 | case ENOMEM: msg = "Insufficient memory to read from in_fd."; | ||
247 | case EIO: msg = "Unspecified error while reading from in_fd."; | ||
248 | }; | ||
249 | success = false; | ||
250 | } | ||
251 | } else { | ||
252 | qWarning("open write failed %s, %s",src.latin1(), dest.latin1()); | ||
253 | success = false; | ||
254 | } | ||
255 | } else { | ||
256 | qWarning("open read failed %s, %s",src.latin1(), dest.latin1()); | ||
257 | success = false; | ||
258 | } | ||
259 | srcFile.close(); | ||
260 | destFile.close(); | ||
261 | // Set file permissions | ||
262 | if( stat( (const char *) src, &status ) == 0 ) { | ||
263 | chmod( (const char *) dest, status.st_mode ); | ||
264 | } | ||
265 | |||
266 | return success; | ||
267 | } | ||
268 | |||
269 | |||
270 | bool FileManager::renameFile( const QString & src, const QString & dest ) { | ||
271 | if(copyFile( src, dest )) { | ||
272 | if(QFile::remove(src) ) { | ||
273 | return true; | ||
274 | } | ||
275 | } | ||
276 | return false; | ||
277 | } | ||
278 | |||
279 | |||
213 | /*! | 280 | /*! |
214 | Opens the document specified by \a f as a readable QIODevice. | 281 | Opens the document specified by \a f as a readable QIODevice. |
215 | The caller must delete the return value. | 282 | The caller must delete the return value. |
@@ -221,7 +288,7 @@ QIODevice* FileManager::openFile( const DocLnk& f ) | |||
221 | QString fn = f.file(); | 288 | QString fn = f.file(); |
222 | QFile* fl = new QFile( fn ); | 289 | QFile* fl = new QFile( fn ); |
223 | if ( !fl->open( IO_ReadOnly ) ) { | 290 | if ( !fl->open( IO_ReadOnly ) ) { |
224 | delete fl; | 291 | delete fl; |
225 | fl = 0; | 292 | fl = 0; |
226 | } | 293 | } |
227 | return fl; | 294 | return fl; |
@@ -239,9 +306,9 @@ QIODevice* FileManager::saveFile( const DocLnk& f ) | |||
239 | ensurePathExists( fn ); | 306 | ensurePathExists( fn ); |
240 | QFile* fl = new QFile( fn ); | 307 | QFile* fl = new QFile( fn ); |
241 | if ( fl->open( IO_WriteOnly ) ) { | 308 | if ( fl->open( IO_WriteOnly ) ) { |
242 | f.writeLink(); | 309 | f.writeLink(); |
243 | } else { | 310 | } else { |
244 | delete fl; | 311 | delete fl; |
245 | fl = 0; | 312 | fl = 0; |
246 | } | 313 | } |
247 | return fl; | 314 | return fl; |
@@ -266,8 +333,8 @@ bool FileManager::ensurePathExists( const QString &fn ) | |||
266 | QFileInfo fi(fn); | 333 | QFileInfo fi(fn); |
267 | fi.setFile( fi.dirPath(TRUE) ); | 334 | fi.setFile( fi.dirPath(TRUE) ); |
268 | if ( !fi.exists() ) { | 335 | if ( !fi.exists() ) { |
269 | if ( system(("mkdir -p "+fi.filePath())) ) | 336 | if ( system(("mkdir -p "+fi.filePath())) ) |
270 | return FALSE; | 337 | return FALSE; |
271 | } | 338 | } |
272 | 339 | ||
273 | return TRUE; | 340 | return TRUE; |
diff --git a/library/filemanager.h b/library/filemanager.h index f8d9425..61a3341 100644 --- a/library/filemanager.h +++ b/library/filemanager.h | |||
@@ -38,8 +38,10 @@ public: | |||
38 | bool loadFile( const DocLnk&, QByteArray &data ); | 38 | bool loadFile( const DocLnk&, QByteArray &data ); |
39 | bool loadFile( const DocLnk&, QString &text ); | 39 | bool loadFile( const DocLnk&, QString &text ); |
40 | bool copyFile( const AppLnk &src, const AppLnk &dest ); | 40 | bool copyFile( const AppLnk &src, const AppLnk &dest ); |
41 | 41 | bool copyFile( const QString & src, const QString & dest ); | |
42 | // The caller must delete the return values. | 42 | bool renameFile( const QString &, const QString &); |
43 | |||
44 | // The caller must delete the return values. | ||
43 | QIODevice* openFile( const DocLnk& ); | 45 | QIODevice* openFile( const DocLnk& ); |
44 | QIODevice* saveFile( const DocLnk& ); | 46 | QIODevice* saveFile( const DocLnk& ); |
45 | 47 | ||