1affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===- FileHandle.cpp -----------------------------------------------------===//
2affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//
3affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//                     The MCLinker Project
4affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//
5affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// This file is distributed under the University of Illinois Open Source
6affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// License. See LICENSE.TXT for details.
7affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//
8affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===----------------------------------------------------------------------===//
96f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include "mcld/Config/Config.h"
1037b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/FileHandle.h"
1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/FileSystem.h"
1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines
13affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <errno.h>
1422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#if defined(HAVE_UNISTD_H)
1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <unistd.h>
1722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#endif
1822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#if defined(HAVE_FCNTL_H)
1937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <fcntl.h>
2022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#endif
2122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
22affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <sys/stat.h>
2322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
2437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
25affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
26affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===----------------------------------------------------------------------===//
27affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// FileHandle
28f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//===----------------------------------------------------------------------===//
29affc150dc44fab1911775a49636d0ce85333b634Zonr ChangFileHandle::FileHandle()
3037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : m_Path(),
3137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_Handler(-1),
3237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_Size(0),
3337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_State(GoodBit),
3437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_OpenMode(NotOpen) {
35affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
36affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
3737b74a387bb3993387029859c2d9d051c41c724eStephen HinesFileHandle::~FileHandle() {
38affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (isOpened())
39affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    close();
40affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
41affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
4237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesinline static int oflag(FileHandle::OpenMode pMode) {
43affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  int result = 0x0;
44affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (FileHandle::Unknown == pMode)
45affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return result;
46affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
47affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (FileHandle::ReadWrite == (pMode & FileHandle::ReadWrite))
48affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    result |= O_RDWR;
4922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else if (FileHandle::ReadOnly == (pMode & FileHandle::ReadOnly))
50affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    result |= O_RDONLY;
5122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else if (FileHandle::WriteOnly == (pMode & FileHandle::WriteOnly))
52affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    result |= O_WRONLY;
53affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
5422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (FileHandle::Append == (pMode & FileHandle::Append))
55affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    result |= O_APPEND;
56affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
5722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (FileHandle::Create == (pMode & FileHandle::Create))
58affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    result |= O_CREAT;
59affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
6022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (FileHandle::Truncate == (pMode & FileHandle::Truncate))
61affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    result |= O_TRUNC;
62affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
63affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return result;
64affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
65affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
6637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesinline static bool get_size(int pHandler, unsigned int& pSize) {
67affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  struct ::stat file_stat;
68affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (-1 == ::fstat(pHandler, &file_stat)) {
69affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pSize = 0;
70affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return false;
71affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
72affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  pSize = file_stat.st_size;
73affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return true;
74affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
75affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
76affc150dc44fab1911775a49636d0ce85333b634Zonr Changbool FileHandle::open(const sys::fs::Path& pPath,
77affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                      FileHandle::OpenMode pMode,
7837b74a387bb3993387029859c2d9d051c41c724eStephen Hines                      FileHandle::Permission pPerm) {
79affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (isOpened() || Unknown == pMode) {
80affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    setState(BadBit);
81affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return false;
82affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
83affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
84affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  m_OpenMode = pMode;
8522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (System == pPerm)
8622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    m_Handler = sys::fs::detail::open(pPath, oflag(pMode));
8722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else
8837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    m_Handler = sys::fs::detail::open(pPath, oflag(pMode),
8937b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      static_cast<int>(pPerm));
9022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
91affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  m_Path = pPath;
9237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (m_Handler == -1) {
9337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    m_OpenMode = OpenMode(NotOpen);
94affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    setState(FailBit);
95affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return false;
96affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
97affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
98affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!get_size(m_Handler, m_Size)) {
99affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    setState(FailBit);
100affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return false;
101affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
102affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
103affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return true;
104affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
105affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
10637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool FileHandle::delegate(int pFD, FileHandle::OpenModeEnum pMode) {
107affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (isOpened()) {
108affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    setState(BadBit);
109affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return false;
110affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
111affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
112affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  m_Handler = pFD;
11337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  m_OpenMode = OpenMode(pMode);
1146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  m_State = (GoodBit | DeputedBit);
115affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
116affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!get_size(m_Handler, m_Size)) {
117affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    setState(FailBit);
118affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return false;
119affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
120affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
121affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return true;
122affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
123affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
12437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool FileHandle::close() {
125affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!isOpened()) {
126affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    setState(BadBit);
127affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return false;
128affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
129affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
1306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (isOwned()) {
13137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (::close(m_Handler) == -1) {
1326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      setState(FailBit);
1336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      return false;
1346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
135affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
136affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
137affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  m_Path.native().clear();
138affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  m_Size = 0;
13937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  m_OpenMode = OpenMode(NotOpen);
140affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  cleanState();
141affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return true;
142affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
143affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
14437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool FileHandle::truncate(size_t pSize) {
145affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!isOpened() || !isWritable()) {
146affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    setState(BadBit);
147affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return false;
148affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
149affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
15037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (sys::fs::detail::ftruncate(m_Handler, pSize) == -1) {
151affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    setState(FailBit);
152affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return false;
153affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
154affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
155affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  m_Size = pSize;
156affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return true;
157affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
158affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
15937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool FileHandle::read(void* pMemBuffer, size_t pStartOffset, size_t pLength) {
160affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!isOpened() || !isReadable()) {
161affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    setState(BadBit);
162affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return false;
163affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
164affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
16537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (pLength == 0)
166affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return true;
167affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
16837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  ssize_t read_bytes =
16937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      sys::fs::detail::pread(m_Handler, pMemBuffer, pLength, pStartOffset);
170affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
17137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (read_bytes == -1) {
172affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    setState(FailBit);
173affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return false;
174affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
175affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
176affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return true;
177affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
178affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
17937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool FileHandle::write(const void* pMemBuffer,
18037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                       size_t pStartOffset,
18137b74a387bb3993387029859c2d9d051c41c724eStephen Hines                       size_t pLength) {
182affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!isOpened() || !isWritable()) {
183affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    setState(BadBit);
184affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return false;
185affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
186affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
18737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (pLength == 0)
188affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return true;
189affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
19037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  ssize_t write_bytes =
19137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      sys::fs::detail::pwrite(m_Handler, pMemBuffer, pLength, pStartOffset);
192affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
19337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (write_bytes == -1) {
194affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    setState(FailBit);
195affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return false;
196affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
197affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
198affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return true;
199affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
200affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
20137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid FileHandle::setState(FileHandle::IOState pState) {
202affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  m_State |= pState;
203affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
204affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
20537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid FileHandle::cleanState(FileHandle::IOState pState) {
206affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  m_State = pState;
207affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
208affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
20937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool FileHandle::isOpened() const {
21037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (m_Handler != -1 && m_OpenMode != NotOpen && isGood())
211affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return true;
212affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
213affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return false;
214affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
215affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
216affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// Assume Unknown OpenMode is readable
21737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool FileHandle::isReadable() const {
218affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return (m_OpenMode & ReadOnly);
219affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
220affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
221affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// Assume Unknown OpenMode is writable
22237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool FileHandle::isWritable() const {
223affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return (m_OpenMode & WriteOnly);
224affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
225affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
226affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// Assume Unknown OpenMode is both readable and writable
22737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool FileHandle::isReadWrite() const {
228affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return (FileHandle::ReadWrite == (m_OpenMode & FileHandle::ReadWrite));
229affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
230affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
23137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool FileHandle::isGood() const {
232affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return !(m_State & (BadBit | FailBit));
233affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
234affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
23537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool FileHandle::isBad() const {
236affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return (m_State & BadBit);
237affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
238affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
23937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool FileHandle::isFailed() const {
240affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return (m_State & (BadBit | FailBit));
241affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
242affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
24337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool FileHandle::isOwned() const {
2446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return !(m_State & DeputedBit);
2456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
2466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
24737b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
248