diff options
Diffstat (limited to 'lib/libUPnP/Neptune/Source/System/StdC/NptStdcFile.cpp')
-rw-r--r-- | lib/libUPnP/Neptune/Source/System/StdC/NptStdcFile.cpp | 509 |
1 files changed, 509 insertions, 0 deletions
diff --git a/lib/libUPnP/Neptune/Source/System/StdC/NptStdcFile.cpp b/lib/libUPnP/Neptune/Source/System/StdC/NptStdcFile.cpp new file mode 100644 index 0000000..cc549c3 --- /dev/null +++ b/lib/libUPnP/Neptune/Source/System/StdC/NptStdcFile.cpp @@ -0,0 +1,509 @@ +/***************************************************************** +| +| Neptune - Files :: Standard C Implementation +| +| (c) 2001-2008 Gilles Boccon-Gibod +| Author: Gilles Boccon-Gibod (bok@bok.net) +| + ****************************************************************/ + +/*---------------------------------------------------------------------- +| includes ++---------------------------------------------------------------------*/ +#define _LARGEFILE_SOURCE +#define _LARGEFILE_SOURCE64 +#define _LARGEFILE64_SOURCE +#define _FILE_OFFSET_BITS 64 + +#include <stdio.h> +#if !defined(_WIN32_WCE) +#include <string.h> +#include <sys/stat.h> +#include <errno.h> +#else +#include <stdio.h> +#define errno GetLastError() +#endif + +#include "NptConfig.h" +#include "NptUtils.h" +#include "NptFile.h" +#include "NptThreads.h" +#include "NptInterfaces.h" +#include "NptStrings.h" +#include "NptDebug.h" + +#if defined(NPT_CONFIG_HAVE_SHARE_H) +#include <share.h> +#endif + +#if defined(_WIN32) +extern FILE *NPT_fsopen_utf8(const char* path, const char* mode, int sh_flags); +extern FILE *NPT_fopen_utf8(const char* path, const char* mode); +#define fopen NPT_fopen_utf8 +#define fopen_s NPT_fopen_s_utf8 +#define _fsopen NPT_fsopen_utf8 +#endif + +/*---------------------------------------------------------------------- +| compatibility wrappers ++---------------------------------------------------------------------*/ +#if !defined(NPT_CONFIG_HAVE_FOPEN_S) +static int fopen_s(FILE** file, + const char* filename, + const char* mode) +{ + *file = fopen(filename, mode); + +#if defined(_WIN32_WCE) + if (*file == NULL) return ENOENT; +#else + if (*file == NULL) return errno; +#endif + return 0; +} +#endif // defined(NPT_CONFIG_HAVE_FOPEN_S + +/*---------------------------------------------------------------------- +| MapErrno ++---------------------------------------------------------------------*/ +static NPT_Result +MapErrno(int err) { + switch (err) { + case EACCES: return NPT_ERROR_PERMISSION_DENIED; + case EPERM: return NPT_ERROR_PERMISSION_DENIED; + case ENOENT: return NPT_ERROR_NO_SUCH_FILE; +#if defined(ENAMETOOLONG) + case ENAMETOOLONG: return NPT_ERROR_INVALID_PARAMETERS; +#endif + case EBUSY: return NPT_ERROR_FILE_BUSY; + case EROFS: return NPT_ERROR_FILE_NOT_WRITABLE; + case ENOTDIR: return NPT_ERROR_FILE_NOT_DIRECTORY; + default: return NPT_ERROR_ERRNO(err); + } +} + +/*---------------------------------------------------------------------- +| NPT_StdcFileWrapper ++---------------------------------------------------------------------*/ +class NPT_StdcFileWrapper +{ +public: + // constructors and destructor + NPT_StdcFileWrapper(FILE* file, const char* name) : m_File(file), m_Name(name) {} + ~NPT_StdcFileWrapper() { + if (m_File != NULL && + m_File != stdin && + m_File != stdout && + m_File != stderr) { + fclose(m_File); + } + } + + // members + FILE* m_File; + NPT_String m_Name; +}; + +typedef NPT_Reference<NPT_StdcFileWrapper> NPT_StdcFileReference; + +/*---------------------------------------------------------------------- +| NPT_StdcFileStream ++---------------------------------------------------------------------*/ +class NPT_StdcFileStream +{ +public: + // constructors and destructor + NPT_StdcFileStream(NPT_StdcFileReference file) : + m_FileReference(file) {} + + // NPT_FileInterface methods + NPT_Result Seek(NPT_Position offset); + NPT_Result Tell(NPT_Position& offset); + NPT_Result Flush(); + +protected: + // constructors and destructors + virtual ~NPT_StdcFileStream() {} + + // members + NPT_StdcFileReference m_FileReference; +}; + +/*---------------------------------------------------------------------- +| NPT_StdcFileStream::Seek ++---------------------------------------------------------------------*/ +NPT_Result +NPT_StdcFileStream::Seek(NPT_Position offset) +{ + size_t result; + + result = NPT_fseek(m_FileReference->m_File, offset, SEEK_SET); + if (result == 0) { + return NPT_SUCCESS; + } else { + return NPT_FAILURE; + } +} + +/*---------------------------------------------------------------------- +| NPT_StdcFileStream::Tell ++---------------------------------------------------------------------*/ +NPT_Result +NPT_StdcFileStream::Tell(NPT_Position& offset) +{ + offset = 0; + + NPT_Int64 pos = NPT_ftell(m_FileReference->m_File); + if (pos < 0) return NPT_FAILURE; + + offset = pos; + return NPT_SUCCESS; +} + +/*---------------------------------------------------------------------- +| NPT_StdcFileStream::Flush ++---------------------------------------------------------------------*/ +NPT_Result +NPT_StdcFileStream::Flush() +{ + fflush(m_FileReference->m_File); + return NPT_SUCCESS; +} + +/*---------------------------------------------------------------------- +| NPT_StdcFileInputStream ++---------------------------------------------------------------------*/ +class NPT_StdcFileInputStream : public NPT_InputStream, + private NPT_StdcFileStream + +{ +public: + // constructors and destructor + NPT_StdcFileInputStream(NPT_StdcFileReference& file) : + NPT_StdcFileStream(file) {} + + // NPT_InputStream methods + NPT_Result Read(void* buffer, + NPT_Size bytes_to_read, + NPT_Size* bytes_read); + NPT_Result Seek(NPT_Position offset) { + return NPT_StdcFileStream::Seek(offset); + } + NPT_Result Tell(NPT_Position& offset) { + return NPT_StdcFileStream::Tell(offset); + } + NPT_Result GetSize(NPT_LargeSize& size); + NPT_Result GetAvailable(NPT_LargeSize& available); +}; + +/*---------------------------------------------------------------------- +| NPT_StdcFileInputStream::Read ++---------------------------------------------------------------------*/ +NPT_Result +NPT_StdcFileInputStream::Read(void* buffer, + NPT_Size bytes_to_read, + NPT_Size* bytes_read) +{ + size_t nb_read; + + // check the parameters + if (buffer == NULL) { + return NPT_ERROR_INVALID_PARAMETERS; + } + + // read from the file + nb_read = fread(buffer, 1, bytes_to_read, m_FileReference->m_File); + if (nb_read > 0) { + if (bytes_read) *bytes_read = (NPT_Size)nb_read; + return NPT_SUCCESS; + } else if (feof(m_FileReference->m_File)) { + if (bytes_read) *bytes_read = 0; + return NPT_ERROR_EOS; + } else { + if (bytes_read) *bytes_read = 0; + return MapErrno(errno); + } +} + +/*---------------------------------------------------------------------- +| NPT_StdcFileInputStream::GetSize ++---------------------------------------------------------------------*/ +NPT_Result +NPT_StdcFileInputStream::GetSize(NPT_LargeSize& size) +{ + NPT_FileInfo file_info; + NPT_Result result = NPT_File::GetInfo(m_FileReference->m_Name, &file_info); + if (NPT_FAILED(result)) return result; + size = file_info.m_Size; + + return NPT_SUCCESS; +} + +/*---------------------------------------------------------------------- +| NPT_StdcFileInputStream::GetAvailable ++---------------------------------------------------------------------*/ +NPT_Result +NPT_StdcFileInputStream::GetAvailable(NPT_LargeSize& available) +{ + NPT_Int64 offset = NPT_ftell(m_FileReference->m_File); + NPT_LargeSize size = 0; + + if (NPT_SUCCEEDED(GetSize(size)) && offset >= 0 && (NPT_LargeSize)offset <= size) { + available = size - offset; + return NPT_SUCCESS; + } else { + available = 0; + return NPT_FAILURE; + } +} + +/*---------------------------------------------------------------------- +| NPT_StdcFileOutputStream ++---------------------------------------------------------------------*/ +class NPT_StdcFileOutputStream : public NPT_OutputStream, + private NPT_StdcFileStream +{ +public: + // constructors and destructor + NPT_StdcFileOutputStream(NPT_StdcFileReference& file) : + NPT_StdcFileStream(file) {} + + // NPT_InputStream methods + NPT_Result Write(const void* buffer, + NPT_Size bytes_to_write, + NPT_Size* bytes_written); + NPT_Result Seek(NPT_Position offset) { + return NPT_StdcFileStream::Seek(offset); + } + NPT_Result Tell(NPT_Position& offset) { + return NPT_StdcFileStream::Tell(offset); + } + NPT_Result Flush() { + return NPT_StdcFileStream::Flush(); + } +}; + +/*---------------------------------------------------------------------- +| NPT_StdcFileOutputStream::Write ++---------------------------------------------------------------------*/ +NPT_Result +NPT_StdcFileOutputStream::Write(const void* buffer, + NPT_Size bytes_to_write, + NPT_Size* bytes_written) +{ + size_t nb_written; + + nb_written = fwrite(buffer, 1, bytes_to_write, m_FileReference->m_File); + + if (nb_written > 0) { + if (bytes_written) *bytes_written = (NPT_Size)nb_written; + return NPT_SUCCESS; + } else { + if (bytes_written) *bytes_written = 0; + return NPT_ERROR_WRITE_FAILED; + } +} + +/*---------------------------------------------------------------------- +| NPT_StdcFile ++---------------------------------------------------------------------*/ +class NPT_StdcFile: public NPT_FileInterface +{ +public: + // constructors and destructor + NPT_StdcFile(NPT_File& delegator); + ~NPT_StdcFile(); + + // NPT_FileInterface methods + NPT_Result Open(OpenMode mode); + NPT_Result Close(); + NPT_Result GetInputStream(NPT_InputStreamReference& stream); + NPT_Result GetOutputStream(NPT_OutputStreamReference& stream); + +private: + // members + NPT_File& m_Delegator; + OpenMode m_Mode; + NPT_StdcFileReference m_FileReference; +}; + +/*---------------------------------------------------------------------- +| NPT_StdcFile::NPT_StdcFile ++---------------------------------------------------------------------*/ +NPT_StdcFile::NPT_StdcFile(NPT_File& delegator) : + m_Delegator(delegator), + m_Mode(0) +{ +} + +/*---------------------------------------------------------------------- +| NPT_StdcFile::~NPT_StdcFile ++---------------------------------------------------------------------*/ +NPT_StdcFile::~NPT_StdcFile() +{ + Close(); +} + +/*---------------------------------------------------------------------- +| NPT_StdcFile::Open ++---------------------------------------------------------------------*/ +NPT_Result +NPT_StdcFile::Open(NPT_File::OpenMode mode) +{ + FILE* file = NULL; + + // check if we're already open + if (!m_FileReference.IsNull()) { + return NPT_ERROR_FILE_ALREADY_OPEN; + } + + // store the mode + m_Mode = mode; + + // check for special names + const char* name = (const char*)m_Delegator.GetPath(); + if (NPT_StringsEqual(name, NPT_FILE_STANDARD_INPUT)) { + file = stdin; + } else if (NPT_StringsEqual(name, NPT_FILE_STANDARD_OUTPUT)) { + file = stdout; + } else if (NPT_StringsEqual(name, NPT_FILE_STANDARD_ERROR)) { + file = stderr; + } else { + // compute mode + const char* fmode = ""; + if (mode & NPT_FILE_OPEN_MODE_WRITE) { + if (mode & NPT_FILE_OPEN_MODE_APPEND) { + /* write, read, create, append */ + /* (append implies create) */ + fmode = "a+b"; + } else { + if ((mode & NPT_FILE_OPEN_MODE_CREATE) || (mode & NPT_FILE_OPEN_MODE_TRUNCATE)) { + /* write, read, create, truncate */ + /* (truncate implies create, create implies truncate) */ + fmode = "w+b"; + } else { + /* write, read */ + fmode = "r+b"; + } + } + } else { + /* read only */ + fmode = "rb"; + } + + // open the file +#if defined(NPT_CONFIG_HAVE_FSOPEN) + file = _fsopen(name, fmode, _SH_DENYNO); + int open_result = file == NULL ? ENOENT : 0; +#else + int open_result = fopen_s(&file, name, fmode); +#endif + + // test the result of the open + if (open_result != 0) return MapErrno(open_result); + } + + // unbuffer the file if needed + if ((mode & NPT_FILE_OPEN_MODE_UNBUFFERED) && file != NULL) { +#if !defined(_WIN32_WCE) + setvbuf(file, NULL, _IONBF, 0); +#endif + } + + // create a reference to the FILE object + m_FileReference = new NPT_StdcFileWrapper(file, name); + + return NPT_SUCCESS; +} + +/*---------------------------------------------------------------------- +| NPT_StdcFile::Close ++---------------------------------------------------------------------*/ +NPT_Result +NPT_StdcFile::Close() +{ + // release the file reference + m_FileReference = NULL; + + // reset the mode + m_Mode = 0; + + return NPT_SUCCESS; +} + +/*---------------------------------------------------------------------- +| NPT_StdcFile::GetInputStream ++---------------------------------------------------------------------*/ +NPT_Result +NPT_StdcFile::GetInputStream(NPT_InputStreamReference& stream) +{ + // default value + stream = NULL; + + // check that the file is open + if (m_FileReference.IsNull()) return NPT_ERROR_FILE_NOT_OPEN; + + // check that the mode is compatible + if (!(m_Mode & NPT_FILE_OPEN_MODE_READ)) { + return NPT_ERROR_FILE_NOT_READABLE; + } + + // create a stream + stream = new NPT_StdcFileInputStream(m_FileReference); + + return NPT_SUCCESS; +} + +/*---------------------------------------------------------------------- +| NPT_StdcFile::GetOutputStream ++---------------------------------------------------------------------*/ +NPT_Result +NPT_StdcFile::GetOutputStream(NPT_OutputStreamReference& stream) +{ + // default value + stream = NULL; + + // check that the file is open + if (m_FileReference.IsNull()) return NPT_ERROR_FILE_NOT_OPEN; + + // check that the mode is compatible + if (!(m_Mode & NPT_FILE_OPEN_MODE_WRITE)) { + return NPT_ERROR_FILE_NOT_WRITABLE; + } + + // create a stream + stream = new NPT_StdcFileOutputStream(m_FileReference); + + return NPT_SUCCESS; +} + +/*---------------------------------------------------------------------- +| NPT_File::NPT_File ++---------------------------------------------------------------------*/ +NPT_File::NPT_File(const char* path) : m_Path(path), m_IsSpecial(false) +{ + m_Delegate = new NPT_StdcFile(*this); + + if (NPT_StringsEqual(path, NPT_FILE_STANDARD_INPUT) || + NPT_StringsEqual(path, NPT_FILE_STANDARD_OUTPUT) || + NPT_StringsEqual(path, NPT_FILE_STANDARD_ERROR)) { + m_IsSpecial = true; + } +} + +/*---------------------------------------------------------------------- +| NPT_File::operator= ++---------------------------------------------------------------------*/ +NPT_File& +NPT_File::operator=(const NPT_File& file) +{ + if (this != &file) { + delete m_Delegate; + m_Path = file.m_Path; + m_IsSpecial = file.m_IsSpecial; + m_Delegate = new NPT_StdcFile(*this); + } + return *this; +} + |