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