1 //===- FileHandle.cpp -----------------------------------------------------===//
2 //
3 // The MCLinker Project
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 #include <mcld/Support/FileHandle.h>
10 #include <mcld/Support/FileSystem.h>
11 #include <errno.h>
12 #include <fcntl.h>
13 #include <sys/stat.h>
14 #include <sys/mman.h>
15
16 using namespace mcld;
17
18 //===----------------------------------------------------------------------===//
19 // FileHandle
FileHandle()20 FileHandle::FileHandle()
21 : m_Path(),
22 m_Handler(-1),
23 m_Size(0),
24 m_State(GoodBit),
25 m_OpenMode(NotOpen) {
26 }
27
~FileHandle()28 FileHandle::~FileHandle()
29 {
30 if (isOpened())
31 close();
32 }
33
oflag(FileHandle::OpenMode pMode)34 inline static int oflag(FileHandle::OpenMode pMode)
35 {
36 int result = 0x0;
37 if (FileHandle::Unknown == pMode)
38 return result;
39
40 if (FileHandle::ReadWrite == (pMode & FileHandle::ReadWrite))
41 result |= O_RDWR;
42 else if (pMode & FileHandle::ReadOnly)
43 result |= O_RDONLY;
44 else if (pMode & FileHandle::WriteOnly)
45 result |= O_WRONLY;
46
47 if (pMode & FileHandle::Append)
48 result |= O_APPEND;
49
50 if (pMode & FileHandle::Create)
51 result |= O_CREAT;
52
53 if (pMode & FileHandle::Truncate)
54 result |= O_TRUNC;
55
56 return result;
57 }
58
get_size(int pHandler,unsigned int & pSize)59 inline static bool get_size(int pHandler, unsigned int &pSize)
60 {
61 struct ::stat file_stat;
62 if (-1 == ::fstat(pHandler, &file_stat)) {
63 pSize = 0;
64 return false;
65 }
66 pSize = file_stat.st_size;
67 return true;
68 }
69
open(const sys::fs::Path & pPath,FileHandle::OpenMode pMode)70 bool FileHandle::open(const sys::fs::Path& pPath,
71 FileHandle::OpenMode pMode)
72 {
73 if (isOpened() || Unknown == pMode) {
74 setState(BadBit);
75 return false;
76 }
77
78 m_OpenMode = pMode;
79 m_Handler = ::open(pPath.native().c_str(), oflag(pMode));
80 m_Path = pPath;
81 if (-1 == m_Handler) {
82 m_OpenMode = NotOpen;
83 setState(FailBit);
84 return false;
85 }
86
87 if (!get_size(m_Handler, m_Size)) {
88 setState(FailBit);
89 return false;
90 }
91
92 return true;
93 }
94
open(const sys::fs::Path & pPath,FileHandle::OpenMode pMode,FileHandle::Permission pPerm)95 bool FileHandle::open(const sys::fs::Path& pPath,
96 FileHandle::OpenMode pMode,
97 FileHandle::Permission pPerm)
98 {
99 if (isOpened() || Unknown == pMode) {
100 setState(BadBit);
101 return false;
102 }
103
104 m_OpenMode = pMode;
105 m_Handler = sys::fs::detail::open(pPath, oflag(pMode), (int)pPerm);
106 m_Path = pPath;
107 if (-1 == m_Handler) {
108 m_OpenMode = NotOpen;
109 setState(FailBit);
110 return false;
111 }
112
113 if (!get_size(m_Handler, m_Size)) {
114 setState(FailBit);
115 return false;
116 }
117
118 return true;
119 }
120
delegate(int pFD,FileHandle::OpenMode pMode)121 bool FileHandle::delegate(int pFD, FileHandle::OpenMode pMode)
122 {
123 if (isOpened()) {
124 setState(BadBit);
125 return false;
126 }
127
128 m_Handler = pFD;
129 m_OpenMode = pMode;
130 m_State = GoodBit;
131
132 if (!get_size(m_Handler, m_Size)) {
133 setState(FailBit);
134 return false;
135 }
136
137 return true;
138 }
139
close()140 bool FileHandle::close()
141 {
142 if (!isOpened()) {
143 setState(BadBit);
144 return false;
145 }
146
147 if (-1 == ::close(m_Handler)) {
148 setState(FailBit);
149 return false;
150 }
151
152 m_Path.native().clear();
153 m_Size = 0;
154 m_OpenMode = NotOpen;
155 cleanState();
156 return true;
157 }
158
truncate(size_t pSize)159 bool FileHandle::truncate(size_t pSize)
160 {
161 if (!isOpened() || !isWritable()) {
162 setState(BadBit);
163 return false;
164 }
165
166 if (-1 == sys::fs::detail::ftruncate(m_Handler, pSize)) {
167 setState(FailBit);
168 return false;
169 }
170
171 m_Size = pSize;
172 return true;
173 }
174
read(void * pMemBuffer,size_t pStartOffset,size_t pLength)175 bool FileHandle::read(void* pMemBuffer, size_t pStartOffset, size_t pLength)
176 {
177 if (!isOpened() || !isReadable()) {
178 setState(BadBit);
179 return false;
180 }
181
182 if (0 == pLength)
183 return true;
184
185 ssize_t read_bytes = sys::fs::detail::pread(m_Handler,
186 pMemBuffer,
187 pLength,
188 pStartOffset);
189
190 if (-1 == read_bytes) {
191 setState(FailBit);
192 return false;
193 }
194
195 return true;
196 }
197
write(const void * pMemBuffer,size_t pStartOffset,size_t pLength)198 bool FileHandle::write(const void* pMemBuffer, size_t pStartOffset, size_t pLength)
199 {
200 if (!isOpened() || !isWritable()) {
201 setState(BadBit);
202 return false;
203 }
204
205 if (0 == pLength)
206 return true;
207
208
209 ssize_t write_bytes = sys::fs::detail::pwrite(m_Handler,
210 pMemBuffer,
211 pLength,
212 pStartOffset);
213
214 if (-1 == write_bytes) {
215 setState(FailBit);
216 return false;
217 }
218
219 return true;
220 }
221
mmap(void * & pMemBuffer,size_t pStartOffset,size_t pLength)222 bool FileHandle::mmap(void*& pMemBuffer, size_t pStartOffset, size_t pLength)
223 {
224 if (!isOpened()) {
225 setState(BadBit);
226 return false;
227 }
228
229 if (0 == pLength)
230 return true;
231
232 int prot, flag;
233 if (isReadable() && !isWritable()) {
234 // read-only
235 prot = PROT_READ;
236 flag = MAP_FILE | MAP_PRIVATE;
237 }
238 else if (!isReadable() && isWritable()) {
239 // write-only
240 prot = PROT_WRITE;
241 flag = MAP_FILE | MAP_SHARED;
242 }
243 else if (isReadWrite()) {
244 // read and write
245 prot = PROT_READ | PROT_WRITE;
246 flag = MAP_FILE | MAP_SHARED;
247 }
248 else {
249 // can not read/write
250 setState(BadBit);
251 return false;
252 }
253
254 pMemBuffer = ::mmap(NULL, pLength, prot, flag, m_Handler, pStartOffset);
255
256 if (MAP_FAILED == pMemBuffer) {
257 setState(FailBit);
258 return false;
259 }
260
261 return true;
262 }
263
munmap(void * pMemBuffer,size_t pLength)264 bool FileHandle::munmap(void* pMemBuffer, size_t pLength)
265 {
266 if (!isOpened()) {
267 setState(BadBit);
268 return false;
269 }
270
271 if (-1 == ::munmap(pMemBuffer, pLength)) {
272 setState(FailBit);
273 return false;
274 }
275
276 return true;
277 }
278
setState(FileHandle::IOState pState)279 void FileHandle::setState(FileHandle::IOState pState)
280 {
281 m_State |= pState;
282 }
283
cleanState(FileHandle::IOState pState)284 void FileHandle::cleanState(FileHandle::IOState pState)
285 {
286 m_State = pState;
287 }
288
isOpened() const289 bool FileHandle::isOpened() const
290 {
291 if (-1 != m_Handler && m_OpenMode != NotOpen && isGood())
292 return true;
293
294 return false;
295 }
296
297 // Assume Unknown OpenMode is readable
isReadable() const298 bool FileHandle::isReadable() const
299 {
300 return (m_OpenMode & ReadOnly);
301 }
302
303 // Assume Unknown OpenMode is writable
isWritable() const304 bool FileHandle::isWritable() const
305 {
306 return (m_OpenMode & WriteOnly);
307 }
308
309 // Assume Unknown OpenMode is both readable and writable
isReadWrite() const310 bool FileHandle::isReadWrite() const
311 {
312 return (FileHandle::ReadWrite == (m_OpenMode & FileHandle::ReadWrite));
313 }
314
isGood() const315 bool FileHandle::isGood() const
316 {
317 return !(m_State & (BadBit | FailBit));
318 }
319
isBad() const320 bool FileHandle::isBad() const
321 {
322 return (m_State & BadBit);
323 }
324
isFailed() const325 bool FileHandle::isFailed() const
326 {
327 return (m_State & (BadBit | FailBit));
328 }
329
330