FileHandle.cpp revision 22add6ff3426df1a85089fe6a6e1597ee3b6f300
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 13#if defined(HAVE_UNISTD_H) 14# include <unistd.h> 15#endif 16#if defined(HAVE_FCNTL_H) 17# include <fcntl.h> 18#endif 19 20#include <sys/stat.h> 21#include <sys/mman.h> 22 23#if defined(_MSC_VER) 24#include <io.h> 25#include <fcntl.h> 26#ifndef STDIN_FILENO 27# define STDIN_FILENO 0 28#endif 29#ifndef STDOUT_FILENO 30# define STDOUT_FILENO 1 31#endif 32#ifndef STDERR_FILENO 33# define STDERR_FILENO 2 34#endif 35#endif 36 37using namespace mcld; 38 39//===----------------------------------------------------------------------===// 40// FileHandle 41FileHandle::FileHandle() 42 : m_Path(), 43 m_Handler(-1), 44 m_Size(0), 45 m_State(GoodBit), 46 m_OpenMode(NotOpen) { 47} 48 49FileHandle::~FileHandle() 50{ 51 if (isOpened()) 52 close(); 53} 54 55inline static int oflag(FileHandle::OpenMode pMode) 56{ 57 int result = 0x0; 58 if (FileHandle::Unknown == pMode) 59 return result; 60 61 if (FileHandle::ReadWrite == (pMode & FileHandle::ReadWrite)) 62 result |= O_RDWR; 63 else if (FileHandle::ReadOnly == (pMode & FileHandle::ReadOnly)) 64 result |= O_RDONLY; 65 else if (FileHandle::WriteOnly == (pMode & FileHandle::WriteOnly)) 66 result |= O_WRONLY; 67 68 if (FileHandle::Append == (pMode & FileHandle::Append)) 69 result |= O_APPEND; 70 71 if (FileHandle::Create == (pMode & FileHandle::Create)) 72 result |= O_CREAT; 73 74 if (FileHandle::Truncate == (pMode & FileHandle::Truncate)) 75 result |= O_TRUNC; 76 77 return result; 78} 79 80inline static bool get_size(int pHandler, unsigned int &pSize) 81{ 82 struct ::stat file_stat; 83 if (-1 == ::fstat(pHandler, &file_stat)) { 84 pSize = 0; 85 return false; 86 } 87 pSize = file_stat.st_size; 88 return true; 89} 90 91bool FileHandle::open(const sys::fs::Path& pPath, 92 FileHandle::OpenMode pMode, 93 FileHandle::Permission pPerm) 94{ 95 if (isOpened() || Unknown == pMode) { 96 setState(BadBit); 97 return false; 98 } 99 100 m_OpenMode = pMode; 101 if (System == pPerm) 102 m_Handler = sys::fs::detail::open(pPath, oflag(pMode)); 103 else 104 m_Handler = sys::fs::detail::open(pPath, oflag(pMode), (int)pPerm); 105 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 222bool FileHandle::mmap(void*& pMemBuffer, size_t pStartOffset, size_t pLength) 223{ 224 if (!isOpened()) { 225 setState(BadBit); 226 return false; 227 } 228 229 if (0 == pLength) 230 return true; 231 232 int prot, flag; 233 if (isReadable() && !isWritable()) { 234 // read-only 235 prot = PROT_READ; 236 flag = MAP_FILE | MAP_PRIVATE; 237 } 238 else if (!isReadable() && isWritable()) { 239 // write-only 240 prot = PROT_WRITE; 241 flag = MAP_FILE | MAP_SHARED; 242 } 243 else if (isReadWrite()) { 244 // read and write 245 prot = PROT_READ | PROT_WRITE; 246 flag = MAP_FILE | MAP_SHARED; 247 } 248 else { 249 // can not read/write 250 setState(BadBit); 251 return false; 252 } 253 254 pMemBuffer = ::mmap(NULL, pLength, prot, flag, m_Handler, pStartOffset); 255 256 if (MAP_FAILED == pMemBuffer) { 257 setState(FailBit); 258 return false; 259 } 260 261 return true; 262} 263 264bool FileHandle::munmap(void* pMemBuffer, size_t pLength) 265{ 266 if (!isOpened()) { 267 setState(BadBit); 268 return false; 269 } 270 271 if (-1 == ::munmap(pMemBuffer, pLength)) { 272 setState(FailBit); 273 return false; 274 } 275 276 return true; 277} 278 279void FileHandle::setState(FileHandle::IOState pState) 280{ 281 m_State |= pState; 282} 283 284void FileHandle::cleanState(FileHandle::IOState pState) 285{ 286 m_State = pState; 287} 288 289bool FileHandle::isOpened() const 290{ 291 if (-1 != m_Handler && m_OpenMode != NotOpen && isGood()) 292 return true; 293 294 return false; 295} 296 297// Assume Unknown OpenMode is readable 298bool FileHandle::isReadable() const 299{ 300 return (m_OpenMode & ReadOnly); 301} 302 303// Assume Unknown OpenMode is writable 304bool FileHandle::isWritable() const 305{ 306 return (m_OpenMode & WriteOnly); 307} 308 309// Assume Unknown OpenMode is both readable and writable 310bool FileHandle::isReadWrite() const 311{ 312 return (FileHandle::ReadWrite == (m_OpenMode & FileHandle::ReadWrite)); 313} 314 315bool FileHandle::isGood() const 316{ 317 return !(m_State & (BadBit | FailBit)); 318} 319 320bool FileHandle::isBad() const 321{ 322 return (m_State & BadBit); 323} 324 325bool FileHandle::isFailed() const 326{ 327 return (m_State & (BadBit | FailBit)); 328} 329 330