Commit e4ee1392 authored by Albert Astals Cid's avatar Albert Astals Cid

Error out on save if file has changed since we opened it

In poppler we keep the fd of the file open so the XRef+FileStream can
locate objects. This is good since we save lots of memory for not having
everything on memory all the time, but that means that when we want to
save we need the file to be exactly the same as it was when we created
the XRef otherwise we're going to be reading from the wrong part of the
"new" file.

Bug #103793
parent f1035912
......@@ -19,7 +19,7 @@
// Copyright (C) 2006 Kristian Høgsberg <krh@redhat.com>
// Copyright (C) 2008 Adam Batkin <adam@batkin.net>
// Copyright (C) 2008, 2010, 2012, 2013 Hib Eris <hib@hiberis.nl>
// Copyright (C) 2009, 2012, 2014 Albert Astals Cid <aacid@kde.org>
// Copyright (C) 2009, 2012, 2014, 2017 Albert Astals Cid <aacid@kde.org>
// Copyright (C) 2009 Kovid Goyal <kovid@kovidgoyal.net>
// Copyright (C) 2013 Adam Reichold <adamreichold@myopera.com>
// Copyright (C) 2013, 2017 Adrian Johnson <ajohnson@redneon.com>
......@@ -670,6 +670,22 @@ GooFile* GooFile::open(const GooString *fileName) {
return fd < 0 ? NULL : new GooFile(fd);
}
GooFile::GooFile(int fdA)
: fd(fdA)
{
struct stat statbuf;
fstat(fd, &statbuf);
modifiedTimeOnOpen = statbuf.st_mtim;
}
bool GooFile::modificationTimeChangedSinceOpen() const
{
struct stat statbuf;
fstat(fd, &statbuf);
return modifiedTimeOnOpen.tv_sec != statbuf.st_mtim.tv_sec || modifiedTimeOnOpen.tv_nsec != statbuf.st_mtim.tv_nsec;
}
#endif // _WIN32
//------------------------------------------------------------------------
......
......@@ -16,7 +16,7 @@
// under GPL version 2 or later
//
// Copyright (C) 2006 Kristian Høgsberg <krh@redhat.com>
// Copyright (C) 2009, 2011, 2012 Albert Astals Cid <aacid@kde.org>
// Copyright (C) 2009, 2011, 2012, 2017 Albert Astals Cid <aacid@kde.org>
// Copyright (C) 2009 Kovid Goyal <kovid@kovidgoyal.net>
// Copyright (C) 2013 Adam Reichold <adamreichold@myopera.com>
// Copyright (C) 2013, 2017 Adrian Johnson <ajohnson@redneon.com>
......@@ -146,15 +146,21 @@ public:
~GooFile() { CloseHandle(handle); }
// Asuming than on windows you can't change files that are already open
bool modificationTimeChangedSinceOpen() const { return false; };
private:
GooFile(HANDLE handleA): handle(handleA) {}
HANDLE handle;
#else
~GooFile() { close(fd); }
bool modificationTimeChangedSinceOpen() const;
private:
GooFile(int fdA) : fd(fdA) {}
GooFile(int fdA);
int fd;
struct timespec modifiedTimeOnOpen;
#endif // _WIN32
};
......
......@@ -6,6 +6,20 @@
//
//========================================================================
//========================================================================
//
// Modified under the Poppler project - http://poppler.freedesktop.org
//
// All changes made under the Poppler project to this file are licensed
// under GPL version 2 or later
//
// Copyright (C) 2017 Albert Astals Cid <aacid@kde.org>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
//
//========================================================================
#ifndef ERRORCODES_H
#define ERRORCODES_H
......@@ -33,4 +47,6 @@
#define errFileIO 10 // file I/O error
#define errFileChangedSinceOpen 11 // file has changed since opening and save can't be done
#endif
......@@ -730,6 +730,11 @@ int PDFDoc::savePageAs(GooString *name, int pageNo)
FILE *f;
OutStream *outStr;
XRef *yRef, *countRef;
if (file && file->modificationTimeChangedSinceOpen())
return errFileChangedSinceOpen;
int rootNum = getXRef()->getNumObjects() + 1;
// Make sure that special flags are set, because we are going to read
......@@ -901,6 +906,9 @@ int PDFDoc::saveAs(GooString *name, PDFWriteMode mode) {
}
int PDFDoc::saveAs(OutStream *outStr, PDFWriteMode mode) {
if (file && file->modificationTimeChangedSinceOpen())
return errFileChangedSinceOpen;
if (!xref->isModified() && mode == writeStandard) {
// simply copy the original file
saveWithoutChangesAs (outStr);
......@@ -935,6 +943,9 @@ int PDFDoc::saveWithoutChangesAs(GooString *name) {
int PDFDoc::saveWithoutChangesAs(OutStream *outStr) {
int c;
if (file && file->modificationTimeChangedSinceOpen())
return errFileChangedSinceOpen;
BaseStream *copyStr = str->copy();
copyStr->reset();
while ((c = copyStr->getChar()) != EOF) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment