summaryrefslogtreecommitdiff
authorllornkcor <llornkcor>2003-07-17 02:25:08 (UTC)
committer llornkcor <llornkcor>2003-07-17 02:25:08 (UTC)
commit6ca1d7605597f4b8a7559167e5cf3d6e093805cd (patch) (unidiff)
tree93096c3d0df0c0f02c75d2acc2f481120914945c
parent115e09bdeb2ee3c7c0b9344f95179e1d10e86e48 (diff)
downloadopie-6ca1d7605597f4b8a7559167e5cf3d6e093805cd.zip
opie-6ca1d7605597f4b8a7559167e5cf3d6e093805cd.tar.gz
opie-6ca1d7605597f4b8a7559167e5cf3d6e093805cd.tar.bz2
fix filesaving when filename contains extended characters
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--library/filemanager.cpp167
-rw-r--r--library/filemanager.h6
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
@@ -27,8 +27,13 @@
27#include <qtextcodec.h> 27#include <qtextcodec.h>
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
34 \brief The FileManager class assists with AppLnk input/output. 39 \brief The FileManager class assists with AppLnk input/output.
@@ -55,25 +60,27 @@ FileManager::~FileManager()
55 Returns whether the operation succeeded. 60 Returns whether the operation succeeded.
56*/ 61*/
57bool FileManager::saveFile( const DocLnk &f, const QByteArray &data ) 62bool 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}
79 86
@@ -85,30 +92,29 @@ bool FileManager::saveFile( const DocLnk &f, const QByteArray &data )
85 Returns whether the operation succeeded. 92 Returns whether the operation succeeded.
86*/ 93*/
87bool FileManager::saveFile( const DocLnk &f, const QString &text ) 94bool 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();
98 int total_written; 105 int total_written;
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}
114 120
@@ -124,9 +130,9 @@ bool FileManager::loadFile( const DocLnk &f, QString &text )
124{ 130{
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
132 ts.setCodec( QTextCodec::codecForMib( 106 ) ); 138 ts.setCodec( QTextCodec::codecForMib( 106 ) );
@@ -148,12 +154,12 @@ bool FileManager::loadFile( const DocLnk &f, QByteArray &ba )
148{ 154{
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}
159 165
@@ -166,51 +172,112 @@ bool FileManager::loadFile( const DocLnk &f, QByteArray &ba )
166bool FileManager::copyFile( const AppLnk &src, const AppLnk &dest ) 172bool 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
219bool 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
270bool 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.
216 283
@@ -220,9 +287,9 @@ QIODevice* FileManager::openFile( const DocLnk& f )
220{ 287{
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;
228} 295}
@@ -238,11 +305,11 @@ QIODevice* FileManager::saveFile( const DocLnk& f )
238 QString fn = f.file(); 305 QString fn = f.file();
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;
248} 315}
@@ -265,10 +332,10 @@ bool FileManager::ensurePathExists( const QString &fn )
265{ 332{
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;
274} 341}
diff --git a/library/filemanager.h b/library/filemanager.h
index f8d9425..61a3341 100644
--- a/library/filemanager.h
+++ b/library/filemanager.h
@@ -37,10 +37,12 @@ public:
37 bool saveFile( const DocLnk&, const QString &text ); 37 bool saveFile( const DocLnk&, const QString &text );
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
46 bool exists( const DocLnk& ); 48 bool exists( const DocLnk& );