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