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