summaryrefslogtreecommitdiffstats
path: root/akregator/src/mk4storage/metakit/src/fileio.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'akregator/src/mk4storage/metakit/src/fileio.cpp')
-rw-r--r--akregator/src/mk4storage/metakit/src/fileio.cpp434
1 files changed, 434 insertions, 0 deletions
diff --git a/akregator/src/mk4storage/metakit/src/fileio.cpp b/akregator/src/mk4storage/metakit/src/fileio.cpp
new file mode 100644
index 000000000..28ff7dca0
--- /dev/null
+++ b/akregator/src/mk4storage/metakit/src/fileio.cpp
@@ -0,0 +1,434 @@
+// fileio.cpp --
+// $Id$
+// This is part of Metakit, see http://www.equi4.com/metakit/
+
+/** @file
+ * Implementation of c4_FileStrategy and c4_FileStream
+ */
+
+#include "header.h"
+#include "mk4io.h"
+
+#if q4_WIN32
+#if q4_MSVC && !q4_STRICT
+#pragma warning(disable: 4201) // nonstandard extension used : ...
+#endif
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#if !defined (q4_WINCE)
+#include <io.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#endif
+#endif
+
+#if q4_UNIX && HAVE_MMAP
+#include <sys/types.h>
+#include <sys/mman.h>
+#endif
+
+#if q4_UNIX
+#include <unistd.h>
+#include <fcntl.h>
+#endif
+
+#if q4_WINCE
+#define _get_osfhandle(x) x
+#endif
+
+#ifndef _O_NOINHERIT
+#define _O_NOINHERIT 0
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// The "Carbon" version of a build on Macintosh supports running under
+// either MacOS 7..9 (which has no mmap), or MacOS X (which has mmap).
+// The logic below was adapted from a contribution by Paul Snively, it
+// decides at run time which case it is, and switches I/O calls to match.
+
+#if defined (q4_CARBON) && q4_CARBON
+//#if q4_MAC && !defined (__MACH__) && (!q4_MWCW || __MWERKS__ >= 0x3000)
+#undef HAVE_MMAP
+#define HAVE_MMAP 1
+
+#include <CFBundle.h>
+#include <Folders.h>
+
+#define PROT_NONE 0x00
+#define PROT_READ 0x01
+#define PROT_WRITE 0x02
+#define PROT_EXEC 0x04
+
+#define MAP_SHARED 0x0001
+#define MAP_PRIVATE 0x0002
+
+#define MAP_FIXED 0x0010
+#define MAP_RENAME 0x0020
+#define MAP_NORESERVE 0x0040
+#define MAP_INHERIT 0x0080
+#define MAP_NOEXTEND 0x0100
+#define MAP_HASSEMAPHORE 0x0200
+
+typedef unsigned long t4_u32;
+
+static t4_u32 sfwRefCount = 0;
+static CFBundleRef systemFramework = NULL;
+
+static char* fake_mmap(char*, t4_u32, int, int, int, long long)
+ { return (char*) -1L; }
+static int fake_munmap(char*, t4_u32)
+ { return 0; }
+
+static FILE* (*my_fopen)(const char*,const char*) = fopen;
+static int (*my_fclose)(FILE*) = fclose;
+static long (*my_ftell)(FILE*) = ftell;
+static int (*my_fseek)(FILE*,long,int) = fseek;
+static t4_u32 (*my_fread)(void* ptr,t4_u32,t4_u32,FILE*) = fread;
+static t4_u32 (*my_fwrite)(const void* ptr,t4_u32,t4_u32,FILE*) = fwrite;
+static int (*my_ferror)(FILE*) = ferror;
+static int (*my_fflush)(FILE*) = fflush;
+static int (*my_fileno)(FILE*) = fileno;
+static char* (*my_mmap)(char*,t4_u32,int,int,int,long long) = fake_mmap;
+static int (*my_munmap)(char*,t4_u32) = fake_munmap;
+
+static void InitializeIO()
+{
+ if (sfwRefCount++) return; // race condition, infinitesimal risk
+
+ FSRef theRef;
+ if (FSFindFolder(kOnAppropriateDisk, kFrameworksFolderType,
+ false, &theRef) == noErr) {
+ CFURLRef fw = CFURLCreateFromFSRef(kCFAllocatorSystemDefault, &theRef);
+ if (fw) {
+ CFURLRef bd =
+ CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault,
+ fw, CFSTR("System.framework"), false);
+ CFRelease(fw);
+ if (bd) {
+ systemFramework = CFBundleCreate(kCFAllocatorSystemDefault, bd);
+ CFRelease(bd);
+ }
+ }
+ if (!systemFramework || !CFBundleLoadExecutable(systemFramework))
+ return;
+#define F(x) CFBundleGetFunctionPointerForName(systemFramework, CFSTR(#x))
+ my_fopen = (FILE* (*)(const char*,const char*)) F(fopen);
+ my_fclose = (int (*)(FILE*)) F(fclose);
+ my_ftell = (long (*)(FILE*)) F(ftell);
+ my_fseek = (int (*)(FILE*,long,int)) F(fseek);
+ my_fread = (t4_u32 (*)(void* ptr,t4_u32,t4_u32,FILE*)) F(fread);
+ my_fwrite = (t4_u32 (*)(const void* ptr,t4_u32,t4_u32,FILE*)) F(fwrite);
+ my_ferror = (int (*)(FILE*)) F(ferror);
+ my_fflush = (int (*)(FILE*)) F(fflush);
+ my_fileno = (int (*)(FILE*)) F(fileno);
+ my_mmap = (char* (*)(char*,t4_u32,int,int,int,long long)) F(mmap);
+ my_munmap = (int (*)(char*,t4_u32)) F(munmap);
+#undef F
+ d4_assert(my_fopen && my_fclose && my_ftell && my_fseek &&
+ my_fread && my_fwrite && my_ferror && my_fflush &&
+ my_fileno && my_mmap && my_munmap);
+ }
+}
+
+static void FinalizeIO()
+{
+ if (--sfwRefCount) return; // race condition, infinitesimal risk
+
+ if (systemFramework) {
+ CFBundleUnloadExecutable(systemFramework);
+ CFRelease(systemFramework);
+ systemFramework = 0;
+ }
+}
+
+#define fopen my_fopen
+#define fclose my_fclose
+#define ftell my_ftell
+#define fseek my_fseek
+#define fread my_fread
+#define fwrite my_fwrite
+#define ferror my_ferror
+#define fflush my_fflush
+#define fileno my_fileno
+#define mmap my_mmap
+#define munmap my_munmap
+
+#else
+
+#define InitializeIO()
+#define FinalizeIO()
+
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+
+#if q4_CHECK
+#include <stdlib.h>
+
+void f4_AssertionFailed(const char* cond_, const char* file_, int line_)
+{
+ fprintf(stderr, "Assertion failed: %s (file %s, line %d)\n",
+ cond_, file_, line_);
+ abort();
+}
+
+#endif //q4_CHECK
+
+/////////////////////////////////////////////////////////////////////////////
+// c4_FileStream
+
+c4_FileStream::c4_FileStream (FILE* stream_, bool owned_)
+ : _stream (stream_), _owned (owned_)
+{
+}
+
+c4_FileStream::~c4_FileStream ()
+{
+ if (_owned)
+ fclose(_stream);
+}
+
+int c4_FileStream::Read(void* buffer_, int length_)
+{
+ d4_assert(_stream != 0);
+
+ return (int) fread(buffer_, 1, length_, _stream);
+}
+
+bool c4_FileStream::Write(const void* buffer_, int length_)
+{
+ d4_assert(_stream != 0);
+
+ return (int) fwrite(buffer_, 1, length_, _stream) == length_;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// c4_FileStrategy
+
+c4_FileStrategy::c4_FileStrategy (FILE* file_)
+ : _file (file_), _cleanup (0)
+{
+ InitializeIO();
+ ResetFileMapping();
+}
+
+c4_FileStrategy::~c4_FileStrategy ()
+{
+ _file = 0;
+ ResetFileMapping();
+
+ if (_cleanup)
+ fclose(_cleanup);
+
+ d4_assert(_mapStart == 0);
+ FinalizeIO();
+}
+
+bool c4_FileStrategy::IsValid() const
+{
+ return _file != 0;
+}
+
+t4_i32 c4_FileStrategy::FileSize()
+{
+ d4_assert(_file != 0);
+
+ long size = -1;
+
+ long old = ftell(_file);
+ if (old >= 0 && fseek(_file, 0, 2) == 0) {
+ long pos = ftell(_file);
+ if (fseek(_file, old, 0) == 0)
+ size = pos;
+ }
+
+ if (size < 0)
+ _failure = ferror(_file);
+
+ return size;
+}
+
+t4_i32 c4_FileStrategy::FreshGeneration()
+{
+ d4_assert(false);
+ return 0;
+}
+
+void c4_FileStrategy::ResetFileMapping()
+{
+#if q4_WIN32
+ if (_mapStart != 0) {
+ _mapStart -= _baseOffset;
+ d4_dbgdef(BOOL g =)
+ ::UnmapViewOfFile((char*) _mapStart);
+ d4_assert(g);
+ _mapStart = 0;
+ _dataSize = 0;
+ }
+
+ if (_file != 0) {
+ t4_i32 len = FileSize();
+
+ if (len > 0) {
+ FlushFileBuffers((HANDLE) _get_osfhandle(_fileno(_file)));
+ HANDLE h = ::CreateFileMapping((HANDLE) _get_osfhandle(_fileno(_file)),
+ 0, PAGE_READONLY, 0, len, 0);
+ d4_assert(h); // check for errors, but can continue without mapping
+
+ if (h) {
+ _mapStart = (t4_byte*) ::MapViewOfFile(h, FILE_MAP_READ, 0, 0, len);
+ d4_assert(_mapStart != 0);
+
+ if (_mapStart != 0) {
+ _mapStart += _baseOffset;
+ _dataSize = len - _baseOffset;
+ }
+
+ d4_dbgdef(BOOL f =)
+ ::CloseHandle(h);
+ d4_assert(f);
+ }
+ }
+ }
+#elif HAVE_MMAP
+ if (_mapStart != 0) {
+ _mapStart -= _baseOffset;
+ munmap((char*) _mapStart, _baseOffset + _dataSize); // also loses const
+ _mapStart = 0;
+ _dataSize = 0;
+ }
+
+ if (_file != 0) {
+ t4_i32 len = FileSize();
+
+ if (len > 0) {
+ _mapStart = (const t4_byte*) mmap(0, len, PROT_READ, MAP_SHARED,
+ fileno(_file), 0);
+ if (_mapStart != (void*) -1L) {
+ _mapStart += _baseOffset;
+ _dataSize = len - _baseOffset;
+ } else
+ _mapStart = 0;
+ }
+ }
+#endif
+}
+
+bool c4_FileStrategy::DataOpen(const char* fname_, int mode_)
+{
+ d4_assert(!_file);
+
+#if q4_WIN32 && !q4_BORC && !q4_WINCE
+ int flags = _O_BINARY | _O_NOINHERIT | (mode_ > 0 ? _O_RDWR : _O_RDONLY);
+ int fd = _open(fname_, flags);
+ if (fd != -1)
+ _cleanup = _file = _fdopen(fd, mode_ > 0 ? "r+b" : "rb");
+#else
+ _cleanup = _file = fopen(fname_, mode_ > 0 ? "r+b" : "rb");
+#if q4_UNIX
+ if (_file != 0)
+ fcntl(fileno(_file), F_SETFD, FD_CLOEXEC);
+#endif //q4_UNIX
+#endif //q4_WIN32 && !q4_BORC && !q4_WINCE
+
+ if (_file != 0) {
+ ResetFileMapping();
+ return true;
+ }
+
+ if (mode_ > 0) {
+#if q4_WIN32 && !q4_BORC && !q4_WINCE
+ fd = _open(fname_, flags | _O_CREAT, _S_IREAD | _S_IWRITE);
+ if (fd != -1)
+ _cleanup = _file = _fdopen(fd, "w+b");
+#else
+ _cleanup = _file = fopen(fname_, "w+b");
+#if q4_UNIX
+ if (_file != 0)
+ fcntl(fileno(_file), F_SETFD, FD_CLOEXEC);
+#endif //q4_UNIX
+#endif //q4_WIN32 && !q4_BORC && !q4_WINCE
+ }
+
+ //d4_assert(_file != 0);
+ return false;
+}
+
+int c4_FileStrategy::DataRead(t4_i32 pos_, void* buf_, int len_)
+{
+ d4_assert(_baseOffset + pos_ >= 0);
+ d4_assert(_file != 0);
+
+ //printf("DataRead at %d len %d\n", pos_, len_);
+ return fseek(_file, _baseOffset + pos_, 0) != 0 ? -1 :
+ (int) fread(buf_, 1, len_, _file);
+}
+
+void c4_FileStrategy::DataWrite(t4_i32 pos_, const void* buf_, int len_)
+{
+ d4_assert(_baseOffset + pos_ >= 0);
+ d4_assert(_file != 0);
+#if 0
+ if (_mapStart <= buf_ && buf_ < _mapStart + _dataSize) {
+ printf("DataWrite %08x at %d len %d (map %d)\n", buf_, pos_, len_,
+ (const t4_byte*) buf_ - _mapStart + _baseOffset);
+ } else {
+ printf("DataWrite %08x at %d len %d\n", buf_, pos_, len_);
+ }
+ fprintf(stderr, " _mapStart %08x _dataSize %d buf_ %08x len_ %d _baseOffset %d\n",
+ _mapStart, _dataSize, buf_, len_, _baseOffset);
+ printf(" _mapStart %08x _dataSize %d buf_ %08x len_ %d _baseOffset %d\n",
+ _mapStart, _dataSize, buf_, len_, _baseOffset);
+ fflush(stdout);
+#endif
+
+#if q4_WIN32 || __hpux || __MACH__
+// if (buf_ >= _mapStart && buf_ <= _mapLimit - len_)
+
+ // a horrendous hack to allow file mapping for Win95 on network drive
+ // must use a temp buf to avoid write from mapped file to same file
+ //
+ // 6-Feb-1999 -- this workaround is not thread safe
+ // 30-Nov-2001 -- changed to use the stack so now it is
+ // 28-Oct-2002 -- added HP/UX to the mix, to avoid hard lockup
+ char tempBuf [4096];
+ d4_assert(len_ <= sizeof tempBuf);
+ buf_ = memcpy(tempBuf, buf_, len_);
+#endif
+
+ if (fseek(_file, _baseOffset + pos_, 0) != 0 ||
+ (int) fwrite(buf_, 1, len_, _file) != len_) {
+ _failure = ferror(_file);
+ d4_assert(_failure != 0);
+ d4_assert(true); // always force an assertion failure in debug mode
+ }
+}
+
+void c4_FileStrategy::DataCommit(t4_i32 limit_)
+{
+ d4_assert(_file != 0);
+
+ if (fflush(_file) < 0) {
+ _failure = ferror(_file);
+ d4_assert(_failure != 0);
+ d4_assert(true); // always force an assertion failure in debug mode
+ return;
+ }
+
+ if (limit_ > 0) {
+#if 0 // can't truncate file in a portable way!
+ // unmap the file first, WinNT is more picky about this than Win95
+ FILE* save = _file;
+
+ _file = 0;
+ ResetFileMapping();
+ _file = save;
+
+ _file->SetLength(limit_); // now we can resize the file
+#endif
+ ResetFileMapping(); // remap, since file length may have changed
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////