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;
|
return false;
|
||||||
|
|
||||||
bool Kdb3Database::loadReal(QString filename, bool readOnly, bool differentEncoding) {
|
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);
|
File = new QFile(filename);
|
||||||
if (readOnly) {
|
if (readOnly) {
|
||||||
if(!File->open(QIODevice::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();
|
total_size=File->size();
|
||||||
char* buffer = new char[total_size];
|
char* buffer = new char[total_size];
|
||||||
File->read(buffer,total_size);
|
File->read(buffer,total_size);
|
||||||
|
@ -1352,6 +1354,18 @@ bool Kdb3Database::save(){
|
||||||
return false;
|
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
|
//Delete old backup entries
|
||||||
if (config->backup() && config->backupDelete() && config->backupDeleteAfter()>0 && backupGroup()){
|
if (config->backup() && config->backupDelete() && config->backupDeleteAfter()>0 && backupGroup()){
|
||||||
QDateTime time = QDateTime::currentDateTime().addDays(-config->backupDeleteAfter());
|
QDateTime time = QDateTime::currentDateTime().addDays(-config->backupDeleteAfter());
|
||||||
|
@ -1367,11 +1381,6 @@ bool Kdb3Database::save(){
|
||||||
quint8 ContentsHash[32];
|
quint8 ContentsHash[32];
|
||||||
quint8 EncryptionIV[16];
|
quint8 EncryptionIV[16];
|
||||||
|
|
||||||
if(!(File->openMode() & QIODevice::WriteOnly)){
|
|
||||||
error = tr("The database has been opened read-only.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int FileSize;
|
unsigned int FileSize;
|
||||||
|
|
||||||
QList<StdEntry> MetaStreams;
|
QList<StdEntry> MetaStreams;
|
||||||
|
@ -1488,31 +1497,53 @@ bool Kdb3Database::save(){
|
||||||
|
|
||||||
int size = EncryptedPartSize+DB_HEADER_SIZE;
|
int size = EncryptedPartSize+DB_HEADER_SIZE;
|
||||||
|
|
||||||
if (!File->resize(size)){
|
if (!saveFileTransactional(buffer, 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;
|
|
||||||
error=decodeFileError(File->error());
|
error=decodeFileError(File->error());
|
||||||
|
delete [] buffer;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!syncFile(File))
|
|
||||||
qWarning("Unable to flush file to disk");
|
|
||||||
|
|
||||||
delete [] buffer;
|
delete [] buffer;
|
||||||
//if(SearchGroupID!=-1)Groups.push_back(SearchGroup);
|
//if(SearchGroupID!=-1)Groups.push_back(SearchGroup);
|
||||||
return true;
|
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){
|
void Kdb3Database::createCustomIconsMetaStream(StdEntry* e){
|
||||||
/* Rev 3 */
|
/* Rev 3 */
|
||||||
e->BinaryDesc="bin-stream";
|
e->BinaryDesc="bin-stream";
|
||||||
|
|
|
@ -138,6 +138,7 @@ public:
|
||||||
virtual ~Kdb3Database(){};
|
virtual ~Kdb3Database(){};
|
||||||
virtual bool load(QString identifier, bool readOnly);
|
virtual bool load(QString identifier, bool readOnly);
|
||||||
virtual bool save();
|
virtual bool save();
|
||||||
|
virtual bool saveFileTransactional(char* buffer, int size);
|
||||||
virtual bool close();
|
virtual bool close();
|
||||||
virtual void create();
|
virtual void create();
|
||||||
virtual int numEntries();
|
virtual int numEntries();
|
||||||
|
@ -236,6 +237,7 @@ private:
|
||||||
StdGroup RootGroup;
|
StdGroup RootGroup;
|
||||||
QList<QPixmap>CustomIcons;
|
QList<QPixmap>CustomIcons;
|
||||||
QFile* File;
|
QFile* File;
|
||||||
|
bool openedReadOnly;
|
||||||
QString error;
|
QString error;
|
||||||
bool KeyError;
|
bool KeyError;
|
||||||
bool PotentialEncodingIssueLatin1;
|
bool PotentialEncodingIssueLatin1;
|
||||||
|
|
Loading…
Reference in New Issue