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