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 23 using namespace mcld; 24 25 //===----------------------------------------------------------------------===// 26 // FileHandle 27 //===----------------------------------------------------------------------===// 28 FileHandle::FileHandle() 29 : m_Path(), 30 m_Handler(-1), 31 m_Size(0), 32 m_State(GoodBit), 33 m_OpenMode(NotOpen) { 34 } 35 36 FileHandle::~FileHandle() 37 { 38 if (isOpened()) 39 close(); 40 } 41 42 inline 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 67 inline 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 78 bool 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 108 bool 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 127 bool 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 148 bool 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 164 bool 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 187 bool 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 211 void FileHandle::setState(FileHandle::IOState pState) 212 { 213 m_State |= pState; 214 } 215 216 void FileHandle::cleanState(FileHandle::IOState pState) 217 { 218 m_State = pState; 219 } 220 221 bool 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 230 bool FileHandle::isReadable() const 231 { 232 return (m_OpenMode & ReadOnly); 233 } 234 235 // Assume Unknown OpenMode is writable 236 bool FileHandle::isWritable() const 237 { 238 return (m_OpenMode & WriteOnly); 239 } 240 241 // Assume Unknown OpenMode is both readable and writable 242 bool FileHandle::isReadWrite() const 243 { 244 return (FileHandle::ReadWrite == (m_OpenMode & FileHandle::ReadWrite)); 245 } 246 247 bool FileHandle::isGood() const 248 { 249 return !(m_State & (BadBit | FailBit)); 250 } 251 252 bool FileHandle::isBad() const 253 { 254 return (m_State & BadBit); 255 } 256 257 bool FileHandle::isFailed() const 258 { 259 return (m_State & (BadBit | FailBit)); 260 } 261 262 bool FileHandle::isOwned() const 263 { 264 return !(m_State & DeputedBit); 265 } 266 267