FileHandle.cpp revision affc150dc44fab1911775a49636d0ce85333b634
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 16using namespace mcld; 17 18//===----------------------------------------------------------------------===// 19// FileHandle 20FileHandle::FileHandle() 21 : m_Path(), 22 m_Handler(-1), 23 m_Size(0), 24 m_State(GoodBit), 25 m_OpenMode(NotOpen) { 26} 27 28FileHandle::~FileHandle() 29{ 30 if (isOpened()) 31 close(); 32} 33 34inline 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 59inline 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 70bool 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 95bool 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 121bool 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 140bool 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 159bool 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 175bool 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 198bool 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 222#include <iostream> 223using namespace std; 224 225bool FileHandle::mmap(void*& pMemBuffer, size_t pStartOffset, size_t pLength) 226{ 227 if (!isOpened()) { 228 setState(BadBit); 229 return false; 230 } 231 232 if (0 == pLength) 233 return true; 234 235 int prot, flag; 236 if (isReadable() && !isWritable()) { 237 // read-only 238 prot = PROT_READ; 239 flag = MAP_FILE | MAP_PRIVATE; 240 } 241 else if (!isReadable() && isWritable()) { 242 // write-only 243 prot = PROT_WRITE; 244 flag = MAP_FILE | MAP_SHARED; 245 } 246 else if (isReadWrite()) { 247 // read and write 248 prot = PROT_READ | PROT_WRITE; 249 flag = MAP_FILE | MAP_SHARED; 250 } 251 else { 252 // can not read/write 253 setState(BadBit); 254 return false; 255 } 256 257 pMemBuffer = ::mmap(NULL, pLength, prot, flag, m_Handler, pStartOffset); 258 259 if (MAP_FAILED == pMemBuffer) { 260 setState(FailBit); 261 return false; 262 } 263 264 return true; 265} 266 267bool FileHandle::munmap(void* pMemBuffer, size_t pLength) 268{ 269 if (!isOpened()) { 270 setState(BadBit); 271 return false; 272 } 273 274 if (-1 == ::munmap(pMemBuffer, pLength)) { 275 setState(FailBit); 276 return false; 277 } 278 279 return true; 280} 281 282void FileHandle::setState(FileHandle::IOState pState) 283{ 284 m_State |= pState; 285} 286 287void FileHandle::cleanState(FileHandle::IOState pState) 288{ 289 m_State = pState; 290} 291 292bool FileHandle::isOpened() const 293{ 294 if (-1 != m_Handler && m_OpenMode != NotOpen && isGood()) 295 return true; 296 297 return false; 298} 299 300// Assume Unknown OpenMode is readable 301bool FileHandle::isReadable() const 302{ 303 return (m_OpenMode & ReadOnly); 304} 305 306// Assume Unknown OpenMode is writable 307bool FileHandle::isWritable() const 308{ 309 return (m_OpenMode & WriteOnly); 310} 311 312// Assume Unknown OpenMode is both readable and writable 313bool FileHandle::isReadWrite() const 314{ 315 return (FileHandle::ReadWrite == (m_OpenMode & FileHandle::ReadWrite)); 316} 317 318bool FileHandle::isGood() const 319{ 320 return !(m_State & (BadBit | FailBit)); 321} 322 323bool FileHandle::isBad() const 324{ 325 return (m_State & BadBit); 326} 327 328bool FileHandle::isFailed() const 329{ 330 return (m_State & (BadBit | FailBit)); 331} 332 333