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 24namespace mcld { 25 26//===----------------------------------------------------------------------===// 27// FileHandle 28//===----------------------------------------------------------------------===// 29FileHandle::FileHandle() 30 : m_Path(), 31 m_Handler(-1), 32 m_Size(0), 33 m_State(GoodBit), 34 m_OpenMode(NotOpen) { 35} 36 37FileHandle::~FileHandle() { 38 if (isOpened()) 39 close(); 40} 41 42inline 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 66inline 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 76bool 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 106bool 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 124bool 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 144bool 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 159bool 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 179bool 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 201void FileHandle::setState(FileHandle::IOState pState) { 202 m_State |= pState; 203} 204 205void FileHandle::cleanState(FileHandle::IOState pState) { 206 m_State = pState; 207} 208 209bool 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 217bool FileHandle::isReadable() const { 218 return (m_OpenMode & ReadOnly); 219} 220 221// Assume Unknown OpenMode is writable 222bool FileHandle::isWritable() const { 223 return (m_OpenMode & WriteOnly); 224} 225 226// Assume Unknown OpenMode is both readable and writable 227bool FileHandle::isReadWrite() const { 228 return (FileHandle::ReadWrite == (m_OpenMode & FileHandle::ReadWrite)); 229} 230 231bool FileHandle::isGood() const { 232 return !(m_State & (BadBit | FailBit)); 233} 234 235bool FileHandle::isBad() const { 236 return (m_State & BadBit); 237} 238 239bool FileHandle::isFailed() const { 240 return (m_State & (BadBit | FailBit)); 241} 242 243bool FileHandle::isOwned() const { 244 return !(m_State & DeputedBit); 245} 246 247} // namespace mcld 248