FileHandle.cpp revision 6f75755c9204b1d8817ae5a65a2f7e5af0ec3f70
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#include <sys/mman.h> 23 24#if defined(_MSC_VER) 25#include <io.h> 26#include <fcntl.h> 27#ifndef STDIN_FILENO 28# define STDIN_FILENO 0 29#endif 30#ifndef STDOUT_FILENO 31# define STDOUT_FILENO 1 32#endif 33#ifndef STDERR_FILENO 34# define STDERR_FILENO 2 35#endif 36#endif 37 38using namespace mcld; 39 40//===----------------------------------------------------------------------===// 41// FileHandle 42FileHandle::FileHandle() 43 : m_Path(), 44 m_Handler(-1), 45 m_Size(0), 46 m_State(GoodBit), 47 m_OpenMode(NotOpen) { 48} 49 50FileHandle::~FileHandle() 51{ 52 if (isOpened()) 53 close(); 54} 55 56inline static int oflag(FileHandle::OpenMode pMode) 57{ 58 int result = 0x0; 59 if (FileHandle::Unknown == pMode) 60 return result; 61 62 if (FileHandle::ReadWrite == (pMode & FileHandle::ReadWrite)) 63 result |= O_RDWR; 64 else if (FileHandle::ReadOnly == (pMode & FileHandle::ReadOnly)) 65 result |= O_RDONLY; 66 else if (FileHandle::WriteOnly == (pMode & FileHandle::WriteOnly)) 67 result |= O_WRONLY; 68 69 if (FileHandle::Append == (pMode & FileHandle::Append)) 70 result |= O_APPEND; 71 72 if (FileHandle::Create == (pMode & FileHandle::Create)) 73 result |= O_CREAT; 74 75 if (FileHandle::Truncate == (pMode & FileHandle::Truncate)) 76 result |= O_TRUNC; 77 78 return result; 79} 80 81inline static bool get_size(int pHandler, unsigned int &pSize) 82{ 83 struct ::stat file_stat; 84 if (-1 == ::fstat(pHandler, &file_stat)) { 85 pSize = 0; 86 return false; 87 } 88 pSize = file_stat.st_size; 89 return true; 90} 91 92bool FileHandle::open(const sys::fs::Path& pPath, 93 FileHandle::OpenMode pMode, 94 FileHandle::Permission pPerm) 95{ 96 if (isOpened() || Unknown == pMode) { 97 setState(BadBit); 98 return false; 99 } 100 101 m_OpenMode = pMode; 102 if (System == pPerm) 103 m_Handler = sys::fs::detail::open(pPath, oflag(pMode)); 104 else 105 m_Handler = sys::fs::detail::open(pPath, oflag(pMode), (int)pPerm); 106 107 m_Path = pPath; 108 if (-1 == m_Handler) { 109 m_OpenMode = NotOpen; 110 setState(FailBit); 111 return false; 112 } 113 114 if (!get_size(m_Handler, m_Size)) { 115 setState(FailBit); 116 return false; 117 } 118 119 return true; 120} 121 122bool FileHandle::delegate(int pFD, FileHandle::OpenMode pMode) 123{ 124 if (isOpened()) { 125 setState(BadBit); 126 return false; 127 } 128 129 m_Handler = pFD; 130 m_OpenMode = pMode; 131 m_State = (GoodBit | DeputedBit); 132 133 if (!get_size(m_Handler, m_Size)) { 134 setState(FailBit); 135 return false; 136 } 137 138 return true; 139} 140 141bool FileHandle::close() 142{ 143 if (!isOpened()) { 144 setState(BadBit); 145 return false; 146 } 147 148 if (isOwned()) { 149 if (-1 == ::close(m_Handler)) { 150 setState(FailBit); 151 return false; 152 } 153 } 154 155 m_Path.native().clear(); 156 m_Size = 0; 157 m_OpenMode = NotOpen; 158 cleanState(); 159 return true; 160} 161 162bool FileHandle::truncate(size_t pSize) 163{ 164 if (!isOpened() || !isWritable()) { 165 setState(BadBit); 166 return false; 167 } 168 169 if (-1 == sys::fs::detail::ftruncate(m_Handler, pSize)) { 170 setState(FailBit); 171 return false; 172 } 173 174 m_Size = pSize; 175 return true; 176} 177 178bool FileHandle::read(void* pMemBuffer, size_t pStartOffset, size_t pLength) 179{ 180 if (!isOpened() || !isReadable()) { 181 setState(BadBit); 182 return false; 183 } 184 185 if (0 == pLength) 186 return true; 187 188 ssize_t read_bytes = sys::fs::detail::pread(m_Handler, 189 pMemBuffer, 190 pLength, 191 pStartOffset); 192 193 if (-1 == read_bytes) { 194 setState(FailBit); 195 return false; 196 } 197 198 return true; 199} 200 201bool FileHandle::write(const void* pMemBuffer, size_t pStartOffset, size_t pLength) 202{ 203 if (!isOpened() || !isWritable()) { 204 setState(BadBit); 205 return false; 206 } 207 208 if (0 == pLength) 209 return true; 210 211 212 ssize_t write_bytes = sys::fs::detail::pwrite(m_Handler, 213 pMemBuffer, 214 pLength, 215 pStartOffset); 216 217 if (-1 == write_bytes) { 218 setState(FailBit); 219 return false; 220 } 221 222 return true; 223} 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 333bool FileHandle::isOwned() const 334{ 335 return !(m_State & DeputedBit); 336} 337 338