@@ -21,23 +21,10 @@ #ifdef HAVE_FCNTL_H # include #endif #include "unistd_wrapper.h" -#include "platform.h" - -#ifdef OF_WII -# define BOOL OGC_BOOL -# include -# undef BOOL -#endif - -#ifdef OF_NINTENDO_DS -# include -# include -#endif - #import "OFFile.h" #import "OFString.h" #import "OFLocalization.h" #import "OFInitializationFailedException.h" @@ -49,17 +36,43 @@ #import "OFWriteFailedException.h" #ifdef OF_WINDOWS # include #endif + +#if defined(OF_MORPHOS) && !defined(OF_IXEMUL) +# define BOOL EXEC_BOOL +# include +# undef BOOL +# define INVALID_FD 0 +# define close(fd) Close(fd) +#endif + +#ifdef OF_WII +# define BOOL OGC_BOOL +# include +# undef BOOL +#endif + +#ifdef OF_NINTENDO_DS +# include +# include +#endif + +#ifndef INVALID_FD +# define INVALID_FD -1 +#endif #ifndef O_BINARY # define O_BINARY 0 #endif #ifndef O_CLOEXEC # define O_CLOEXEC 0 #endif +#ifndef O_EXCL +# define O_EXCL 0 +#endif #ifndef O_EXLOCK # define O_EXLOCK 0 #endif #ifndef S_IRGRP @@ -75,10 +88,11 @@ # define S_IWOTH 0 #endif #define DEFAULT_MODE S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH +#if !defined(OF_MORPHOS) || defined(OF_IXEMUL) static int parseMode(const char *mode) { if (strcmp(mode, "r") == 0) return O_RDONLY; @@ -111,10 +125,56 @@ if (strcmp(mode, "ab+") == 0 || strcmp(mode, "a+b") == 0) return O_RDWR | O_CREAT | O_APPEND | O_BINARY; return -1; } +#else +static int +parseMode(const char *mode, bool *append) +{ + if (strcmp(mode, "r") == 0) + return MODE_OLDFILE; + if (strcmp(mode, "w") == 0) + return MODE_NEWFILE; + if (strcmp(mode, "wx") == 0) + return MODE_NEWFILE; + if (strcmp(mode, "a") == 0) { + *append = true; + return MODE_READWRITE; + } + if (strcmp(mode, "rb") == 0) + return MODE_OLDFILE; + if (strcmp(mode, "wb") == 0) + return MODE_NEWFILE; + if (strcmp(mode, "wbx") == 0) + return MODE_NEWFILE; + if (strcmp(mode, "ab") == 0) { + *append = true; + return MODE_READWRITE; + } + if (strcmp(mode, "r+") == 0) + return MODE_OLDFILE; + if (strcmp(mode, "w+") == 0) + return MODE_NEWFILE; + if (strcmp(mode, "a+") == 0) { + *append = true; + return MODE_READWRITE; + } + if (strcmp(mode, "r+b") == 0 || strcmp(mode, "rb+") == 0) + return MODE_OLDFILE; + if (strcmp(mode, "w+b") == 0 || strcmp(mode, "wb+") == 0) + return MODE_NEWFILE; + if (strcmp(mode, "w+bx") == 0 || strcmp(mode, "wb+x") == 0) + return MODE_NEWFILE; + if (strcmp(mode, "ab+") == 0 || strcmp(mode, "a+b") == 0) { + *append = true; + return MODE_READWRITE; + } + + return -1; +} +#endif @implementation OFFile + (void)initialize { if (self != [OFFile class]) @@ -157,29 +217,47 @@ self = [super init]; @try { int flags; +#if !defined(OF_MORPHOS) || defined(OF_IXEMUL) if ((flags = parseMode([mode UTF8String])) == -1) @throw [OFInvalidArgumentException exception]; flags |= O_CLOEXEC; -#if defined(OF_WINDOWS) +# if defined(OF_WINDOWS) if ((_fd = _wopen([path UTF16String], flags, DEFAULT_MODE)) == -1) -#elif defined(OF_HAVE_OFF64_T) +# elif defined(OF_HAVE_OFF64_T) if ((_fd = open64([path cStringWithEncoding: [OFLocalization encoding]], flags, DEFAULT_MODE)) == -1) -#else +# else if ((_fd = open([path cStringWithEncoding: [OFLocalization encoding]], flags, DEFAULT_MODE)) == -1) -#endif +# endif @throw [OFOpenItemFailedException exceptionWithPath: path mode: mode errNo: errno]; +#else + if ((flags = parseMode([mode UTF8String], &_append)) == -1) + @throw [OFInvalidArgumentException exception]; + + if ((_fd = Open([path cStringWithEncoding: + [OFLocalization encoding]], flags)) == INVALID_FD) + @throw [OFOpenItemFailedException + exceptionWithPath: path + mode: mode]; + + if (_append) { + if (Seek64(_fd, 0, OFFSET_END) == -1) + @throw [OFOpenItemFailedException + exceptionWithPath: path + mode: mode]; + } +#endif } @catch (id e) { [self release]; @throw e; } @@ -195,11 +273,11 @@ return self; } - (bool)lowlevelIsAtEndOfStream { - if (_fd == -1) + if (_fd == INVALID_FD) return true; return _atEndOfStream; } @@ -206,26 +284,33 @@ - (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length { ssize_t ret; - if (_fd == -1 || _atEndOfStream) + if (_fd == INVALID_FD || _atEndOfStream) @throw [OFReadFailedException exceptionWithObject: self requestedLength: length]; -#ifndef OF_WINDOWS - if ((ret = read(_fd, buffer, length)) < 0) - @throw [OFReadFailedException exceptionWithObject: self - requestedLength: length - errNo: errno]; -#else +#if defined(OF_WINDOWS) if (length > UINT_MAX) @throw [OFOutOfRangeException exception]; if ((ret = read(_fd, buffer, (unsigned int)length)) < 0) @throw [OFReadFailedException exceptionWithObject: self requestedLength: length + errNo: errno]; +#elif defined(OF_MORPHOS) && !defined(OF_IXEMUL) + if (length > LONG_MAX) + @throw [OFOutOfRangeException exception]; + + if ((ret = Read(_fd, buffer, length)) < 0) + @throw [OFReadFailedException exceptionWithObject: self + requestedLength: length]; +#else + if ((ret = read(_fd, buffer, length)) < 0) + @throw [OFReadFailedException exceptionWithObject: self + requestedLength: length errNo: errno]; #endif if (ret == 0) _atEndOfStream = true; @@ -234,78 +319,123 @@ } - (void)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length { - if (_fd == -1 || _atEndOfStream) + if (_fd == INVALID_FD || _atEndOfStream) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length]; -#ifndef OF_WINDOWS - if (length > SSIZE_MAX) - @throw [OFOutOfRangeException exception]; - - if (write(_fd, buffer, length) != (ssize_t)length) - @throw [OFWriteFailedException exceptionWithObject: self - requestedLength: length - errNo: errno]; -#else +#if defined(OF_WINDOWS) if (length > INT_MAX) @throw [OFOutOfRangeException exception]; if (write(_fd, buffer, (int)length) != (int)length) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length + errNo: errno]; +#elif defined(OF_MORPHOS) && !defined(OF_IXEMUL) + if (length > LONG_MAX) + @throw [OFOutOfRangeException exception]; + + if (_append) { + if (Seek64(_fd, 0, OFFSET_END) == -1) + @throw [OFWriteFailedException + exceptionWithObject: self + requestedLength: length]; + } + + if (Write(_fd, (void *)buffer, length) != (LONG)length) + @throw [OFWriteFailedException exceptionWithObject: self + requestedLength: length]; +#else + if (length > SSIZE_MAX) + @throw [OFOutOfRangeException exception]; + + if (write(_fd, buffer, length) != (ssize_t)length) + @throw [OFWriteFailedException exceptionWithObject: self + requestedLength: length errNo: errno]; #endif } - (of_offset_t)lowlevelSeekToOffset: (of_offset_t)offset whence: (int)whence { -#if defined(OF_WINDOWS) - of_offset_t ret = _lseeki64(_fd, offset, whence); -#elif defined(OF_HAVE_OFF64_T) - of_offset_t ret = lseek64(_fd, offset, whence); -#else - of_offset_t ret = lseek(_fd, offset, whence); -#endif + of_offset_t ret; + + if (_fd == INVALID_FD) + @throw [OFSeekFailedException exceptionWithStream: self + offset: offset + whence: whence]; + +#if !defined(OF_MORPHOS) || defined(OF_IXEMUL) +# if defined(OF_WINDOWS) + ret = _lseeki64(_fd, offset, whence); +# elif defined(OF_HAVE_OFF64_T) + ret = lseek64(_fd, offset, whence); +# else + ret = lseek(_fd, offset, whence); +# endif if (ret == -1) @throw [OFSeekFailedException exceptionWithStream: self offset: offset whence: whence errNo: errno]; +#else + switch (whence) { + case SEEK_SET: + ret = Seek64(_fd, offset, OFFSET_BEGINNING); + break; + case SEEK_CUR: + ret = Seek64(_fd, offset, OFFSET_CURRENT); + break; + case SEEK_END: + ret = Seek64(_fd, offset, OFFSET_END); + break; + default: + ret = -1; + break; + } + + if (ret == -1) + @throw [OFSeekFailedException exceptionWithStream: self + offset: offset + whence: whence]; +#endif _atEndOfStream = false; return ret; } +#if !defined(OF_WINDOWS) && (!defined(OF_MORPHOS) || defined(OF_IXEMUL)) - (int)fileDescriptorForReading { return _fd; } - (int)fileDescriptorForWriting { return _fd; } +#endif - (void)close { - if (_fd != -1) + if (_fd != INVALID_FD) close(_fd); - _fd = -1; + _fd = INVALID_FD; [super close]; } - (void)dealloc { - if (_fd != -1) + if (_fd != INVALID_FD) close(_fd); [super dealloc]; } @end