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/Config/Config.h"
10 #include <mcld/Support/FileHandle.h>
11 #include <mcld/Support/FileSystem.h>
12 #include <errno.h>
13 
14 #if defined(HAVE_UNISTD_H)
15 # include <unistd.h>
16 #endif
17 #if defined(HAVE_FCNTL_H)
18 # include <fcntl.h>
19 #endif
20 
21 #include <sys/stat.h>
22 
23 using namespace mcld;
24 
25 //===----------------------------------------------------------------------===//
26 // FileHandle
27 //===----------------------------------------------------------------------===//
FileHandle()28 FileHandle::FileHandle()
29   : m_Path(),
30     m_Handler(-1),
31     m_Size(0),
32     m_State(GoodBit),
33     m_OpenMode(NotOpen) {
34 }
35 
~FileHandle()36 FileHandle::~FileHandle()
37 {
38   if (isOpened())
39     close();
40 }
41 
oflag(FileHandle::OpenMode pMode)42 inline static int oflag(FileHandle::OpenMode pMode)
43 {
44   int result = 0x0;
45   if (FileHandle::Unknown == pMode)
46     return result;
47 
48   if (FileHandle::ReadWrite == (pMode & FileHandle::ReadWrite))
49     result |= O_RDWR;
50   else if (FileHandle::ReadOnly == (pMode & FileHandle::ReadOnly))
51     result |= O_RDONLY;
52   else if (FileHandle::WriteOnly == (pMode & FileHandle::WriteOnly))
53     result |= O_WRONLY;
54 
55   if (FileHandle::Append == (pMode & FileHandle::Append))
56     result |= O_APPEND;
57 
58   if (FileHandle::Create == (pMode & FileHandle::Create))
59     result |= O_CREAT;
60 
61   if (FileHandle::Truncate == (pMode & FileHandle::Truncate))
62     result |= O_TRUNC;
63 
64   return result;
65 }
66 
get_size(int pHandler,unsigned int & pSize)67 inline static bool get_size(int pHandler, unsigned int &pSize)
68 {
69   struct ::stat file_stat;
70   if (-1 == ::fstat(pHandler, &file_stat)) {
71     pSize = 0;
72     return false;
73   }
74   pSize = file_stat.st_size;
75   return true;
76 }
77 
open(const sys::fs::Path & pPath,FileHandle::OpenMode pMode,FileHandle::Permission pPerm)78 bool FileHandle::open(const sys::fs::Path& pPath,
79                       FileHandle::OpenMode pMode,
80                       FileHandle::Permission pPerm)
81 {
82   if (isOpened() || Unknown == pMode) {
83     setState(BadBit);
84     return false;
85   }
86 
87   m_OpenMode = pMode;
88   if (System == pPerm)
89     m_Handler = sys::fs::detail::open(pPath, oflag(pMode));
90   else
91     m_Handler = sys::fs::detail::open(pPath, oflag(pMode), (int)pPerm);
92 
93   m_Path = pPath;
94   if (-1 == m_Handler) {
95     m_OpenMode = NotOpen;
96     setState(FailBit);
97     return false;
98   }
99 
100   if (!get_size(m_Handler, m_Size)) {
101     setState(FailBit);
102     return false;
103   }
104 
105   return true;
106 }
107 
delegate(int pFD,FileHandle::OpenMode pMode)108 bool FileHandle::delegate(int pFD, FileHandle::OpenMode pMode)
109 {
110   if (isOpened()) {
111     setState(BadBit);
112     return false;
113   }
114 
115   m_Handler = pFD;
116   m_OpenMode = pMode;
117   m_State = (GoodBit | DeputedBit);
118 
119   if (!get_size(m_Handler, m_Size)) {
120     setState(FailBit);
121     return false;
122   }
123 
124   return true;
125 }
126 
close()127 bool FileHandle::close()
128 {
129   if (!isOpened()) {
130     setState(BadBit);
131     return false;
132   }
133 
134   if (isOwned()) {
135     if (-1 == ::close(m_Handler)) {
136       setState(FailBit);
137       return false;
138     }
139   }
140 
141   m_Path.native().clear();
142   m_Size = 0;
143   m_OpenMode = NotOpen;
144   cleanState();
145   return true;
146 }
147 
truncate(size_t pSize)148 bool FileHandle::truncate(size_t pSize)
149 {
150   if (!isOpened() || !isWritable()) {
151     setState(BadBit);
152     return false;
153   }
154 
155   if (-1 == sys::fs::detail::ftruncate(m_Handler, pSize)) {
156     setState(FailBit);
157     return false;
158   }
159 
160   m_Size = pSize;
161   return true;
162 }
163 
read(void * pMemBuffer,size_t pStartOffset,size_t pLength)164 bool FileHandle::read(void* pMemBuffer, size_t pStartOffset, size_t pLength)
165 {
166   if (!isOpened() || !isReadable()) {
167     setState(BadBit);
168     return false;
169   }
170 
171   if (0 == pLength)
172     return true;
173 
174   ssize_t read_bytes = sys::fs::detail::pread(m_Handler,
175                                               pMemBuffer,
176                                               pLength,
177                                               pStartOffset);
178 
179   if (-1 == read_bytes) {
180     setState(FailBit);
181     return false;
182   }
183 
184   return true;
185 }
186 
write(const void * pMemBuffer,size_t pStartOffset,size_t pLength)187 bool FileHandle::write(const void* pMemBuffer, size_t pStartOffset, size_t pLength)
188 {
189   if (!isOpened() || !isWritable()) {
190     setState(BadBit);
191     return false;
192   }
193 
194   if (0 == pLength)
195     return true;
196 
197 
198   ssize_t write_bytes = sys::fs::detail::pwrite(m_Handler,
199                                                 pMemBuffer,
200                                                 pLength,
201                                                 pStartOffset);
202 
203   if (-1 == write_bytes) {
204     setState(FailBit);
205     return false;
206   }
207 
208   return true;
209 }
210 
setState(FileHandle::IOState pState)211 void FileHandle::setState(FileHandle::IOState pState)
212 {
213   m_State |= pState;
214 }
215 
cleanState(FileHandle::IOState pState)216 void FileHandle::cleanState(FileHandle::IOState pState)
217 {
218   m_State = pState;
219 }
220 
isOpened() const221 bool FileHandle::isOpened() const
222 {
223   if (-1 != m_Handler && m_OpenMode != NotOpen && isGood())
224     return true;
225 
226   return false;
227 }
228 
229 // Assume Unknown OpenMode is readable
isReadable() const230 bool FileHandle::isReadable() const
231 {
232   return (m_OpenMode & ReadOnly);
233 }
234 
235 // Assume Unknown OpenMode is writable
isWritable() const236 bool FileHandle::isWritable() const
237 {
238   return (m_OpenMode & WriteOnly);
239 }
240 
241 // Assume Unknown OpenMode is both readable and writable
isReadWrite() const242 bool FileHandle::isReadWrite() const
243 {
244   return (FileHandle::ReadWrite == (m_OpenMode & FileHandle::ReadWrite));
245 }
246 
isGood() const247 bool FileHandle::isGood() const
248 {
249   return !(m_State & (BadBit | FailBit));
250 }
251 
isBad() const252 bool FileHandle::isBad() const
253 {
254   return (m_State & BadBit);
255 }
256 
isFailed() const257 bool FileHandle::isFailed() const
258 {
259   return (m_State & (BadBit | FailBit));
260 }
261 
isOwned() const262 bool FileHandle::isOwned() const
263 {
264   return !(m_State & DeputedBit);
265 }
266 
267