-#ifdef WIN32
+#ifndef WIN32
+#define _LARGEFILE64_SOURCE
+#include <cerrno>
+#include <unistd.h>
+#else
#include <windows.h>
#endif
-#include <stdexcept>
+#include <msp/core/systemerror.h>
+#include <msp/strings/format.h>
+#include "handle.h"
+#include "handle_private.h"
#include "seekable.h"
using namespace std;
-namespace Msp {
-namespace IO {
+namespace {
+
+using namespace Msp::IO;
int sys_seek_type(SeekType st)
{
throw invalid_argument("sys_seek_type");
}
+} // namespace
+
+
+namespace Msp {
+namespace IO {
+
+bad_seek::bad_seek(SeekOffset offset, SeekType type):
+ runtime_error(type==S_BEG ? lexical_cast<string>(offset) :
+ type==S_CUR ? format("CUR%+d", offset) :
+ type==S_END ? format("END%+d", offset) :
+ format("SeekType(%d)", type))
+{ }
+
+
+SeekOffset sys_seek(Handle &handle, SeekOffset offset, SeekType type)
+{
+#ifdef WIN32
+ LONG high = offset>>32;
+ DWORD ret = SetFilePointer(*handle, offset, &high, sys_seek_type(type));
+ if(ret==INVALID_SET_FILE_POINTER)
+ {
+ DWORD err = GetLastError();
+ if(err!=NO_ERROR)
+ throw system_error("SetFilePointer");
+ }
+
+ return (SeekOffset(high)<<32) | ret;
+#else
+ off64_t ret = lseek64(*handle, offset, sys_seek_type(type));
+ if(ret==(off64_t)-1)
+ {
+ if(errno==EINVAL)
+ throw bad_seek(offset, type);
+ else
+ throw system_error("lseek64");
+ }
+
+ return ret;
+#endif
+}
+
} // namespace IO
} // namespace Msp