• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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