Close files before calling FileIo::size() (which uses stat). This is necessary on Win32 it seems. Fixes bug #428. Changed default mode of FileIo::open to "rb" and added FileIo::switchMode. Fixes bug #429. Added a hack to make test output of exiv2-test.sh more readable on MinGW.
This commit is contained in:
parent
b8e809195c
commit
1b41ce9931
@ -45,6 +45,7 @@ EXIV2_RCSID("@(#) $Id$");
|
||||
#include "error.hpp"
|
||||
|
||||
// + standard includes
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <cstdio> // for remove()
|
||||
#include <sys/types.h> // for stat()
|
||||
@ -94,33 +95,65 @@ namespace Exiv2 {
|
||||
return basicIo;
|
||||
}
|
||||
|
||||
long FileIo::write(const byte* data, long wcount )
|
||||
int FileIo::switchMode(OpMode opMode)
|
||||
{
|
||||
assert(fp_ != 0);
|
||||
if (opMode_ == opMode) return 0;
|
||||
|
||||
// ANSI C requires a flush or seek when switching
|
||||
// between read and write modes.
|
||||
if (opMode_ == opRead) {
|
||||
// on msvcrt fflush does not do the job
|
||||
fseek(fp_, 0, SEEK_CUR);
|
||||
bool reopen = true;
|
||||
std::string mode = "r+b";
|
||||
|
||||
switch(opMode) {
|
||||
case opRead:
|
||||
// Flush if current mode allows reading, else reopen (in mode "r+b"
|
||||
// as in this case we know that we can write to the file)
|
||||
if ( openMode_[0] == 'r'
|
||||
|| openMode_.substr(0, 2) == "w+"
|
||||
|| openMode_.substr(0, 2) == "a+") reopen = false;
|
||||
break;
|
||||
case opWrite:
|
||||
// Flush if current mode allows writing, else reopen
|
||||
if ( openMode_.substr(0, 2) == "r+"
|
||||
|| openMode_[0] == 'w'
|
||||
|| openMode_[0] == 'a') reopen = false;
|
||||
break;
|
||||
case opSeek:
|
||||
reopen = false;
|
||||
break;
|
||||
}
|
||||
opMode_ = opWrite;
|
||||
|
||||
if (!reopen) {
|
||||
// Don't do anything when switching _from_ opSeek mode; we
|
||||
// flush when switching _to_ opSeek.
|
||||
if (opMode_ == opSeek) return 0;
|
||||
|
||||
// Flush. On msvcrt fflush does not do the job
|
||||
fseek(fp_, 0, SEEK_CUR);
|
||||
opMode_ = opMode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Reopen the file
|
||||
long offset = ftell(fp_);
|
||||
if (offset == -1) return -1;
|
||||
if (open(mode) != 0) return 1;
|
||||
opMode_ = opMode;
|
||||
return fseek(fp_, offset, SEEK_SET);
|
||||
}
|
||||
|
||||
long FileIo::write(const byte* data, long wcount)
|
||||
{
|
||||
assert(fp_ != 0);
|
||||
if (switchMode(opWrite) != 0) return 0;
|
||||
return (long)fwrite(data, 1, wcount, fp_);
|
||||
}
|
||||
|
||||
long FileIo::write(BasicIo& src)
|
||||
{
|
||||
assert(fp_ != 0);
|
||||
if (static_cast<BasicIo*>(this)==&src) return 0;
|
||||
if (static_cast<BasicIo*>(this) == &src) return 0;
|
||||
if (!src.isopen()) return 0;
|
||||
|
||||
// ANSI C requires a flush or seek when switching
|
||||
// between read and write modes.
|
||||
if (opMode_ == opRead) {
|
||||
// on msvcrt fflush does not do the job
|
||||
fseek(fp_, 0, SEEK_CUR);
|
||||
}
|
||||
opMode_ = opWrite;
|
||||
if (switchMode(opWrite) != 0) return 0;
|
||||
|
||||
byte buf[4096];
|
||||
long readCount = 0;
|
||||
@ -182,11 +215,7 @@ namespace Exiv2 {
|
||||
int FileIo::putb(byte data)
|
||||
{
|
||||
assert(fp_ != 0);
|
||||
if (opMode_ == opRead) {
|
||||
// on msvcrt fflush does not do the job
|
||||
fseek(fp_, 0, SEEK_CUR);
|
||||
}
|
||||
opMode_ = opWrite;
|
||||
if (switchMode(opWrite) != 0) return EOF;
|
||||
return putc(data, fp_);
|
||||
}
|
||||
|
||||
@ -218,6 +247,10 @@ namespace Exiv2 {
|
||||
|
||||
long FileIo::size() const
|
||||
{
|
||||
#if defined WIN32 && !defined __CYGWIN__
|
||||
// On msvcrt stat only works if the file is not open, or so it seems
|
||||
assert(fp_ == 0);
|
||||
#endif
|
||||
if (fp_ != 0) {
|
||||
fflush(fp_);
|
||||
}
|
||||
@ -230,8 +263,8 @@ namespace Exiv2 {
|
||||
|
||||
int FileIo::open()
|
||||
{
|
||||
// Default open is in read-write binary mode
|
||||
return open("r+b");
|
||||
// Default open is in read-only binary mode
|
||||
return open("rb");
|
||||
}
|
||||
|
||||
int FileIo::open(const std::string& mode)
|
||||
@ -273,24 +306,14 @@ namespace Exiv2 {
|
||||
long FileIo::read(byte* buf, long rcount)
|
||||
{
|
||||
assert(fp_ != 0);
|
||||
|
||||
if (opMode_ == opWrite) {
|
||||
// on msvcrt fflush does not do the job
|
||||
fseek(fp_, 0, SEEK_CUR);
|
||||
}
|
||||
opMode_ = opRead;
|
||||
if (switchMode(opRead) != 0) return 0;
|
||||
return (long)fread(buf, 1, rcount, fp_);
|
||||
}
|
||||
|
||||
int FileIo::getb()
|
||||
{
|
||||
assert(fp_ != 0);
|
||||
|
||||
if (opMode_ == opWrite) {
|
||||
// on msvcrt fflush does not do the job
|
||||
fseek(fp_, 0, SEEK_CUR);
|
||||
}
|
||||
opMode_ = opRead;
|
||||
if (switchMode(opRead) != 0) return EOF;
|
||||
return getc(fp_);
|
||||
}
|
||||
|
||||
|
||||
@ -295,7 +295,7 @@ namespace Exiv2 {
|
||||
*/
|
||||
int open(const std::string& mode);
|
||||
/*!
|
||||
@brief Open the file using using the default access mode of "r+b".
|
||||
@brief Open the file using using the default access mode of "rb".
|
||||
This method can also be used to "reopen" a file which will flush
|
||||
any unwritten data and reset the IO position to the start.
|
||||
@return 0 if successful;<BR>
|
||||
@ -406,6 +406,8 @@ namespace Exiv2 {
|
||||
/*!
|
||||
@brief Flush any buffered writes and get the current file size
|
||||
in bytes.
|
||||
@note On Win32 systems the file must be closed prior to calling this
|
||||
function.
|
||||
@return Size of the file in bytes;<BR>
|
||||
-1 if failure;
|
||||
*/
|
||||
@ -445,6 +447,16 @@ namespace Exiv2 {
|
||||
std::string openMode_;
|
||||
FILE *fp_;
|
||||
OpMode opMode_;
|
||||
|
||||
// METHODS
|
||||
/*!
|
||||
@brief Switch to a new access mode, reopening the file if needed.
|
||||
Optimized to only reopen the file when it is really necessary.
|
||||
@param opMode The mode to switch to.
|
||||
@return 0 if successful
|
||||
*/
|
||||
int switchMode(OpMode opMode);
|
||||
|
||||
}; // class FileIo
|
||||
|
||||
/*!
|
||||
@ -622,7 +634,7 @@ namespace Exiv2 {
|
||||
ByteVector data_;
|
||||
ByteVector::size_type idx_;
|
||||
|
||||
//METHODS
|
||||
// METHODS
|
||||
void checkSize(long wcount);
|
||||
}; // class MemIo
|
||||
} // namespace Exiv2
|
||||
|
||||
@ -73,6 +73,11 @@ try {
|
||||
memIo1.seek(0, BasicIo::beg);
|
||||
fileOut1.write(memIo1);
|
||||
|
||||
// On Win32 files must be closed before stat
|
||||
memIo1.close();
|
||||
fileIn.close();
|
||||
fileOut1.close();
|
||||
|
||||
// Make sure they are all the same size
|
||||
if(fileIn.size() != memIo1.size() || memIo1.size() != fileOut1.size()) {
|
||||
std::cerr << argv[0] <<
|
||||
@ -97,7 +102,10 @@ try {
|
||||
if (rc != 0) return rc;
|
||||
|
||||
// Another test of reading and writing
|
||||
fileOut1.seek(0, BasicIo::beg);
|
||||
if (fileOut1.open() != 0) {
|
||||
throw Error(9, fileOut1.path(), strError());
|
||||
}
|
||||
|
||||
memIo2.seek(0, BasicIo::beg);
|
||||
FileIo fileOut2(argv[3]);
|
||||
if (fileOut2.open("w+b") != 0) {
|
||||
@ -146,13 +154,18 @@ int WriteReadSeek(BasicIo &io)
|
||||
std::cerr << ": WRS initial write failed\n";
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
// On Win32 files must be closed before stat
|
||||
io.close();
|
||||
|
||||
if (io.size() != len1) {
|
||||
std::cerr << ": WRS size is not " << len1 << "\n";
|
||||
return 2;
|
||||
}
|
||||
|
||||
io.seek(-len1, BasicIo::cur);
|
||||
if (io.open() != 0) {
|
||||
throw Error(9, io.path(), strError());
|
||||
}
|
||||
|
||||
int c = EOF;
|
||||
memset(buf, -1, sizeof(buf));
|
||||
|
||||
@ -93,6 +93,12 @@ diff iii kkk
|
||||
|
||||
) > $results 2>&1
|
||||
|
||||
if [ `../config/config.guess` = "i686-pc-mingw32" ] ; then
|
||||
sed 's,\\,/,g' $results > ${results}-new
|
||||
mv -f ${results}-new $results
|
||||
unix2dos -q $results
|
||||
fi
|
||||
|
||||
diff -q -w $diffargs $results $good
|
||||
rc=$?
|
||||
if [ $rc -eq 0 ] ; then
|
||||
|
||||
Loading…
Reference in New Issue
Block a user