Make file saving transactional
git-svn-id: https://svn.code.sf.net/p/keepassx/code/trunk@361 b624d157-de02-0410-bad0-e51aec6abb33
This commit is contained in:
parent
2f159db165
commit
0d44be7a68
|
@ -518,12 +518,6 @@ bool Kdb3Database::load(QString identifier, bool readOnly){
|
|||
return false;
|
||||
|
||||
bool Kdb3Database::loadReal(QString filename, bool readOnly, bool differentEncoding) {
|
||||
unsigned long total_size,crypto_size;
|
||||
quint32 Signature1,Signature2,Version,NumGroups,NumEntries,Flags;
|
||||
quint8 FinalRandomSeed[16];
|
||||
quint8 ContentsHash[32];
|
||||
quint8 EncryptionIV[16];
|
||||
|
||||
File = new QFile(filename);
|
||||
if (readOnly) {
|
||||
if(!File->open(QIODevice::ReadOnly)){
|
||||
|
@ -547,6 +541,14 @@ bool Kdb3Database::loadReal(QString filename, bool readOnly, bool differentEncod
|
|||
}
|
||||
}
|
||||
|
||||
openedReadOnly = readOnly;
|
||||
|
||||
unsigned long total_size,crypto_size;
|
||||
quint32 Signature1,Signature2,Version,NumGroups,NumEntries,Flags;
|
||||
quint8 FinalRandomSeed[16];
|
||||
quint8 ContentsHash[32];
|
||||
quint8 EncryptionIV[16];
|
||||
|
||||
total_size=File->size();
|
||||
char* buffer = new char[total_size];
|
||||
File->read(buffer,total_size);
|
||||
|
@ -1352,6 +1354,18 @@ bool Kdb3Database::save(){
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!File->isOpen()) {
|
||||
if(!File->open(QIODevice::ReadWrite)){
|
||||
error=tr("Could not open file.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!(File->openMode() & QIODevice::WriteOnly)){
|
||||
error = tr("The database has been opened read-only.");
|
||||
return false;
|
||||
}
|
||||
|
||||
//Delete old backup entries
|
||||
if (config->backup() && config->backupDelete() && config->backupDeleteAfter()>0 && backupGroup()){
|
||||
QDateTime time = QDateTime::currentDateTime().addDays(-config->backupDeleteAfter());
|
||||
|
@ -1367,11 +1381,6 @@ bool Kdb3Database::save(){
|
|||
quint8 ContentsHash[32];
|
||||
quint8 EncryptionIV[16];
|
||||
|
||||
if(!(File->openMode() & QIODevice::WriteOnly)){
|
||||
error = tr("The database has been opened read-only.");
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int FileSize;
|
||||
|
||||
QList<StdEntry> MetaStreams;
|
||||
|
@ -1488,31 +1497,53 @@ bool Kdb3Database::save(){
|
|||
|
||||
int size = EncryptedPartSize+DB_HEADER_SIZE;
|
||||
|
||||
if (!File->resize(size)){
|
||||
// only recreate file if the new database is smaller
|
||||
if (File->size() > size) {
|
||||
qDebug("Unable to resize, trying to recreate file");
|
||||
if (!File->remove() || !File->open(QIODevice::ReadWrite)) {
|
||||
delete [] buffer;
|
||||
error=decodeFileError(File->error());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
File->seek(0);
|
||||
if (File->write(buffer,size)!=size){
|
||||
delete [] buffer;
|
||||
if (!saveFileTransactional(buffer, size)) {
|
||||
error=decodeFileError(File->error());
|
||||
delete [] buffer;
|
||||
return false;
|
||||
}
|
||||
if (!syncFile(File))
|
||||
qWarning("Unable to flush file to disk");
|
||||
|
||||
delete [] buffer;
|
||||
//if(SearchGroupID!=-1)Groups.push_back(SearchGroup);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Kdb3Database::saveFileTransactional(char* buffer, int size) {
|
||||
QString orgFilename = File->fileName();
|
||||
QFile* tmpFile = new QFile(orgFilename + ".tmp");
|
||||
if (!tmpFile->open(QIODevice::WriteOnly|QIODevice::Truncate)) {
|
||||
tmpFile->remove();
|
||||
delete tmpFile;
|
||||
return false;
|
||||
}
|
||||
if (tmpFile->write(buffer,size) != size) {
|
||||
tmpFile->remove();
|
||||
delete tmpFile;
|
||||
return false;
|
||||
}
|
||||
if (!syncFile(tmpFile))
|
||||
qWarning("Unable to flush file to disk");
|
||||
tmpFile->close();
|
||||
if (!File->remove()) {
|
||||
delete tmpFile;
|
||||
return false;
|
||||
}
|
||||
delete File;
|
||||
File = NULL;
|
||||
if (!tmpFile->rename(orgFilename)) {
|
||||
delete tmpFile;
|
||||
File = new QFile(orgFilename);
|
||||
return false;
|
||||
}
|
||||
File = tmpFile;
|
||||
if (!tmpFile->open(QIODevice::ReadWrite)) {
|
||||
delete tmpFile;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Kdb3Database::createCustomIconsMetaStream(StdEntry* e){
|
||||
/* Rev 3 */
|
||||
e->BinaryDesc="bin-stream";
|
||||
|
|
|
@ -138,6 +138,7 @@ public:
|
|||
virtual ~Kdb3Database(){};
|
||||
virtual bool load(QString identifier, bool readOnly);
|
||||
virtual bool save();
|
||||
virtual bool saveFileTransactional(char* buffer, int size);
|
||||
virtual bool close();
|
||||
virtual void create();
|
||||
virtual int numEntries();
|
||||
|
@ -236,6 +237,7 @@ private:
|
|||
StdGroup RootGroup;
|
||||
QList<QPixmap>CustomIcons;
|
||||
QFile* File;
|
||||
bool openedReadOnly;
|
||||
QString error;
|
||||
bool KeyError;
|
||||
bool PotentialEncodingIssueLatin1;
|
||||
|
|
Loading…
Reference in New Issue