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 23using namespace mcld; 24 25//===----------------------------------------------------------------------===// 26// FileHandle 27//===----------------------------------------------------------------------===// 28FileHandle::FileHandle() 29 : m_Path(), 30 m_Handler(-1), 31 m_Size(0), 32 m_State(GoodBit), 33 m_OpenMode(NotOpen) { 34} 35 36FileHandle::~FileHandle() 37{ 38 if (isOpened()) 39 close(); 40} 41 42inline static int oflag(FileHandle::OpenMode pMode) 43{ 44 int result = 0x0; 45 if (FileHandle::Unknown == pMode) 46 return result; 47 48 if (FileHandle::ReadWrite == (pMode & FileHandle::ReadWrite)) 49 result |= O_RDWR; 50 else if (FileHandle::ReadOnly == (pMode & FileHandle::ReadOnly)) 51 result |= O_RDONLY; 52 else if (FileHandle::WriteOnly == (pMode & FileHandle::WriteOnly)) 53 result |= O_WRONLY; 54 55 if (FileHandle::Append == (pMode & FileHandle::Append)) 56 result |= O_APPEND; 57 58 if (FileHandle::Create == (pMode & FileHandle::Create)) 59 result |= O_CREAT; 60 61 if (FileHandle::Truncate == (pMode & FileHandle::Truncate)) 62 result |= O_TRUNC; 63 64 return result; 65} 66 67inline static bool get_size(int pHandler, unsigned int &pSize) 68{ 69 struct ::stat file_stat; 70 if (-1 == ::fstat(pHandler, &file_stat)) { 71 pSize = 0; 72 return false; 73 } 74 pSize = file_stat.st_size; 75 return true; 76} 77 78bool FileHandle::open(const sys::fs::Path& pPath, 79 FileHandle::OpenMode pMode, 80 FileHandle::Permission pPerm) 81{ 82 if (isOpened() || Unknown == pMode) { 83 setState(BadBit); 84 return false; 85 } 86 87 m_OpenMode = pMode; 88 if (System == pPerm) 89 m_Handler = sys::fs::detail::open(pPath, oflag(pMode)); 90 else 91 m_Handler = sys::fs::detail::open(pPath, oflag(pMode), (int)pPerm); 92 93 m_Path = pPath; 94 if (-1 == m_Handler) { 95 m_OpenMode = NotOpen; 96 setState(FailBit); 97 return false; 98 } 99 100 if (!get_size(m_Handler, m_Size)) { 101 setState(FailBit); 102 return false; 103 } 104 105 return true; 106} 107 108bool FileHandle::delegate(int pFD, FileHandle::OpenMode pMode) 109{ 110 if (isOpened()) { 111 setState(BadBit); 112 return false; 113 } 114 115 m_Handler = pFD; 116 m_OpenMode = pMode; 117 m_State = (GoodBit | DeputedBit); 118 119 if (!get_size(m_Handler, m_Size)) { 120 setState(FailBit); 121 return false; 122 } 123 124 return true; 125} 126 127bool FileHandle::close() 128{ 129 if (!isOpened()) { 130 setState(BadBit); 131 return false; 132 } 133 134 if (isOwned()) { 135 if (-1 == ::close(m_Handler)) { 136 setState(FailBit); 137 return false; 138 } 139 } 140 141 m_Path.native().clear(); 142 m_Size = 0; 143 m_OpenMode = NotOpen; 144 cleanState(); 145 return true; 146} 147 148bool FileHandle::truncate(size_t pSize) 149{ 150 if (!isOpened() || !isWritable()) { 151 setState(BadBit); 152 return false; 153 } 154 155 if (-1 == sys::fs::detail::ftruncate(m_Handler, pSize)) { 156 setState(FailBit); 157 return false; 158 } 159 160 m_Size = pSize; 161 return true; 162} 163 164bool FileHandle::read(void* pMemBuffer, size_t pStartOffset, size_t pLength) 165{ 166 if (!isOpened() || !isReadable()) { 167 setState(BadBit); 168 return false; 169 } 170 171 if (0 == pLength) 172 return true; 173 174 ssize_t read_bytes = sys::fs::detail::pread(m_Handler, 175 pMemBuffer, 176 pLength, 177 pStartOffset); 178 179 if (-1 == read_bytes) { 180 setState(FailBit); 181 return false; 182 } 183 184 return true; 185} 186 187bool FileHandle::write(const void* pMemBuffer, size_t pStartOffset, size_t pLength) 188{ 189 if (!isOpened() || !isWritable()) { 190 setState(BadBit); 191 return false; 192 } 193 194 if (0 == pLength) 195 return true; 196 197 198 ssize_t write_bytes = sys::fs::detail::pwrite(m_Handler, 199 pMemBuffer, 200 pLength, 201 pStartOffset); 202 203 if (-1 == write_bytes) { 204 setState(FailBit); 205 return false; 206 } 207 208 return true; 209} 210 211void FileHandle::setState(FileHandle::IOState pState) 212{ 213 m_State |= pState; 214} 215 216void FileHandle::cleanState(FileHandle::IOState pState) 217{ 218 m_State = pState; 219} 220 221bool FileHandle::isOpened() const 222{ 223 if (-1 != m_Handler && m_OpenMode != NotOpen && isGood()) 224 return true; 225 226 return false; 227} 228 229// Assume Unknown OpenMode is readable 230bool FileHandle::isReadable() const 231{ 232 return (m_OpenMode & ReadOnly); 233} 234 235// Assume Unknown OpenMode is writable 236bool FileHandle::isWritable() const 237{ 238 return (m_OpenMode & WriteOnly); 239} 240 241// Assume Unknown OpenMode is both readable and writable 242bool FileHandle::isReadWrite() const 243{ 244 return (FileHandle::ReadWrite == (m_OpenMode & FileHandle::ReadWrite)); 245} 246 247bool FileHandle::isGood() const 248{ 249 return !(m_State & (BadBit | FailBit)); 250} 251 252bool FileHandle::isBad() const 253{ 254 return (m_State & BadBit); 255} 256 257bool FileHandle::isFailed() const 258{ 259 return (m_State & (BadBit | FailBit)); 260} 261 262bool FileHandle::isOwned() const 263{ 264 return !(m_State & DeputedBit); 265} 266 267