1 | /* |
2 | --------------------------------------------------------------------------- |
3 | Open Asset Import Library (assimp) |
4 | --------------------------------------------------------------------------- |
5 | |
6 | Copyright (c) 2006-2017, assimp team |
7 | |
8 | |
9 | All rights reserved. |
10 | |
11 | Redistribution and use of this software in source and binary forms, |
12 | with or without modification, are permitted provided that the following |
13 | conditions are met: |
14 | |
15 | * Redistributions of source code must retain the above |
16 | copyright notice, this list of conditions and the |
17 | following disclaimer. |
18 | |
19 | * Redistributions in binary form must reproduce the above |
20 | copyright notice, this list of conditions and the |
21 | following disclaimer in the documentation and/or other |
22 | materials provided with the distribution. |
23 | |
24 | * Neither the name of the assimp team, nor the names of its |
25 | contributors may be used to endorse or promote products |
26 | derived from this software without specific prior |
27 | written permission of the assimp team. |
28 | |
29 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
30 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
31 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
32 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
33 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
34 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
35 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
36 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
37 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
38 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
39 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
40 | --------------------------------------------------------------------------- |
41 | */ |
42 | /** @file DefaultIOStream.cpp |
43 | * @brief Default File I/O implementation for #Importer |
44 | */ |
45 | |
46 | |
47 | #include <assimp/ai_assert.h> |
48 | #include <assimp/DefaultIOStream.h> |
49 | #include <sys/types.h> |
50 | #include <sys/stat.h> |
51 | |
52 | using namespace Assimp; |
53 | |
54 | // ---------------------------------------------------------------------------------- |
55 | DefaultIOStream::~DefaultIOStream() |
56 | { |
57 | if (mFile) { |
58 | ::fclose(mFile); |
59 | mFile = nullptr; |
60 | } |
61 | } |
62 | |
63 | // ---------------------------------------------------------------------------------- |
64 | size_t DefaultIOStream::Read(void* pvBuffer, |
65 | size_t pSize, |
66 | size_t pCount) |
67 | { |
68 | ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount); |
69 | return (mFile ? ::fread(pvBuffer, pSize, pCount, mFile) : 0); |
70 | } |
71 | |
72 | // ---------------------------------------------------------------------------------- |
73 | size_t DefaultIOStream::Write(const void* pvBuffer, |
74 | size_t pSize, |
75 | size_t pCount) |
76 | { |
77 | ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount); |
78 | return (mFile ? ::fwrite(pvBuffer, pSize, pCount, mFile) : 0); |
79 | } |
80 | |
81 | // ---------------------------------------------------------------------------------- |
82 | aiReturn DefaultIOStream::Seek(size_t pOffset, |
83 | aiOrigin pOrigin) |
84 | { |
85 | if (!mFile) { |
86 | return AI_FAILURE; |
87 | } |
88 | |
89 | // Just to check whether our enum maps one to one with the CRT constants |
90 | static_assert(aiOrigin_CUR == SEEK_CUR && |
91 | aiOrigin_END == SEEK_END && aiOrigin_SET == SEEK_SET, "aiOrigin_CUR == SEEK_CUR && \ |
92 | aiOrigin_END == SEEK_END && aiOrigin_SET == SEEK_SET" ); |
93 | |
94 | // do the seek |
95 | return (0 == ::fseek(mFile, (long)pOffset,(int)pOrigin) ? AI_SUCCESS : AI_FAILURE); |
96 | } |
97 | |
98 | // ---------------------------------------------------------------------------------- |
99 | size_t DefaultIOStream::Tell() const |
100 | { |
101 | if (!mFile) { |
102 | return 0; |
103 | } |
104 | return ::ftell(mFile); |
105 | } |
106 | |
107 | // ---------------------------------------------------------------------------------- |
108 | size_t DefaultIOStream::FileSize() const |
109 | { |
110 | if (! mFile || mFilename.empty()) { |
111 | return 0; |
112 | } |
113 | |
114 | if (SIZE_MAX == mCachedSize ) { |
115 | |
116 | // Although fseek/ftell would allow us to reuse the existing file handle here, |
117 | // it is generally unsafe because: |
118 | // - For binary streams, it is not technically well-defined |
119 | // - For text files the results are meaningless |
120 | // That's why we use the safer variant fstat here. |
121 | // |
122 | // See here for details: |
123 | // https://www.securecoding.cert.org/confluence/display/seccode/FIO19-C.+Do+not+use+fseek()+and+ftell()+to+compute+the+size+of+a+regular+file |
124 | #if defined _WIN32 && (!defined __GNUC__ || __MSVCRT_VERSION__ >= 0x0601) |
125 | struct __stat64 fileStat; |
126 | int err = _stat64( mFilename.c_str(), &fileStat ); |
127 | if (0 != err) |
128 | return 0; |
129 | mCachedSize = (size_t) (fileStat.st_size); |
130 | #elif defined __GNUC__ || defined __APPLE__ || defined __MACH__ || defined __FreeBSD__ |
131 | struct stat fileStat; |
132 | int err = stat(mFilename.c_str(), &fileStat ); |
133 | if (0 != err) |
134 | return 0; |
135 | const unsigned long long cachedSize = fileStat.st_size; |
136 | mCachedSize = static_cast< size_t >( cachedSize ); |
137 | #else |
138 | # error "Unknown platform" |
139 | #endif |
140 | } |
141 | return mCachedSize; |
142 | } |
143 | |
144 | // ---------------------------------------------------------------------------------- |
145 | void DefaultIOStream::Flush() |
146 | { |
147 | if (mFile) { |
148 | ::fflush(mFile); |
149 | } |
150 | } |
151 | |
152 | // ---------------------------------------------------------------------------------- |
153 | |