15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- FileSystem.inc -----------------------------------------------------===//
25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//                     The MCLinker Project
45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// This file is distributed under the University of Illinois Open Source
65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// License. See LICENSE.TXT for details.
75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/FileHandle.h"
1037b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/Directory.h"
1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines
1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <llvm/Support/ErrorHandling.h>
1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines
145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <string>
1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines
1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <dirent.h>
1737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <fcntl.h>
185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <sys/types.h>
195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <sys/stat.h>
20f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <sys/mman.h>
21affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <unistd.h>
225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
2437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace sys {
2537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace fs {
2637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace detail {
275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostd::string static_library_extension = ".a";
295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostd::string shared_library_extension = ".so";
3037b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstd::string executable_extension = "";
3137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstd::string relocatable_extension = ".o";
3237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstd::string assembly_extension = ".s";
3337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstd::string bitcode_extension = ".bc";
34f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
35f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//===----------------------------------------------------------------------===//
36f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// Helper Functions
37f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//===----------------------------------------------------------------------===//
38f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// read_dir - return true if we read one entry
39f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//  @return value -1: read error
40f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//                 0: read the end
41f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//                 1: success
4237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic int read_dir(intptr_t& pDir, std::string& pOutFilename) {
43f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  errno = 0;
4437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  dirent* cur_dir = ::readdir(reinterpret_cast<DIR*>(pDir));
45f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (0 == cur_dir && 0 != errno)
46f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return -1;
47f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
48f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // idx does not stay at the end, but all elements had beed put into cache.
49f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (NULL == cur_dir) {
50f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return 0;
51f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
52f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
53f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  llvm::StringRef name(cur_dir->d_name, strlen(cur_dir->d_name));
54f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if ((name.size() == 1 && name[0] == '.') ||
55f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      (name.size() == 2 && name[0] == '.' && name[1] == '.'))
56f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return read_dir(pDir, pOutFilename);
57f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
58f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // find a new directory
59f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  pOutFilename.append(name.data(), name.size());
60f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return 1;
61f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
62f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
6337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid open_dir(Directory& pDir) {
64f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  pDir.m_Handler = reinterpret_cast<intptr_t>(opendir(pDir.path().c_str()));
65f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (0 == pDir.m_Handler) {
6637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    errno = 0;  // opendir() will set errno if it failed to open directory.
67f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // set cache is full, then Directory::begin() can return end().
68f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    pDir.m_CacheFull = true;
69f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return;
70f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
71f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // read one entry for advance the end element of the cache.
72f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  std::string path(pDir.path().native());
73f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  switch (read_dir(pDir.m_Handler, path)) {
7437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case 1: {
7537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      // find a new directory
7637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      bool exist = false;
7737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      mcld::sys::fs::PathCache::entry_type* entry =
7837b74a387bb3993387029859c2d9d051c41c724eStephen Hines          pDir.m_Cache.insert(path, exist);
7937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      if (!exist)
8037b74a387bb3993387029859c2d9d051c41c724eStephen Hines        entry->setValue(sys::fs::Path(path));
8137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      return;
8237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    }
8337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case 0:
8437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      // FIXME: a warning function
8537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pDir.m_CacheFull = true;
8637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      return;
8737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    default:
8837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case -1:
8937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::report_fatal_error(std::string("Can't read directory: ") +
9037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                               pDir.path().native());
91f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
92f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
93f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
9437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid close_dir(Directory& pDir) {
95f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pDir.m_Handler)
9637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    closedir(reinterpret_cast<DIR*>(pDir.m_Handler));
97f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  pDir.m_Handler = 0;
98f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
10037b74a387bb3993387029859c2d9d051c41c724eStephen Hinesint open(const Path& pPath, int pOFlag) {
101affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return ::open(pPath.native().c_str(), pOFlag);
1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
10437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesint open(const Path& pPath, int pOFlag, int pPerm) {
105f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  mode_t perm = 0;
106f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pPerm & FileHandle::ReadOwner)
107f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    perm |= S_IRUSR;
108f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pPerm & FileHandle::WriteOwner)
109f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    perm |= S_IWUSR;
110f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pPerm & FileHandle::ExeOwner)
111f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    perm |= S_IXUSR;
112f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pPerm & FileHandle::ReadGroup)
113f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    perm |= S_IRGRP;
114f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pPerm & FileHandle::WriteGroup)
115f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    perm |= S_IWGRP;
116f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pPerm & FileHandle::ExeGroup)
117f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    perm |= S_IXGRP;
118f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pPerm & FileHandle::ReadOther)
119f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    perm |= S_IROTH;
120f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pPerm & FileHandle::WriteOther)
121f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    perm |= S_IWOTH;
122f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pPerm & FileHandle::ExeOther)
123f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    perm |= S_IXOTH;
124f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
125f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return ::open(pPath.native().c_str(), pOFlag, perm);
1265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
12837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesssize_t pread(int pFD, void* pBuf, size_t pCount, off_t pOffset) {
129affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return ::pread(pFD, pBuf, pCount, pOffset);
130affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
131affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
13237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesssize_t pwrite(int pFD, const void* pBuf, size_t pCount, off_t pOffset) {
133affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return ::pwrite(pFD, pBuf, pCount, pOffset);
134affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
135affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
13637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesint ftruncate(int pFD, size_t pLength) {
137affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return ::ftruncate(pFD, pLength);
1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
14037b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid get_pwd(Path& pPWD) {
141f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  char* pwd = (char*)malloc(PATH_MAX);
142f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  pPWD.assign(getcwd(pwd, PATH_MAX));
143f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  free(pwd);
144f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
145f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
14637b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace detail
14737b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace fs
14837b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace sys
149f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
150f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//===----------------------------------------------------------------------===//
151f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// FileHandler
152f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//===----------------------------------------------------------------------===//
15337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool FileHandle::mmap(void*& pMemBuffer, size_t pStartOffset, size_t pLength) {
154f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (!isOpened()) {
155f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    setState(BadBit);
156f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return false;
157f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
158f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
159f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (0 == pLength)
160f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return true;
161f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
162f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  int prot, flag;
163f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (isReadable() && !isWritable()) {
164f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // read-only
165f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    prot = PROT_READ;
166f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    flag = MAP_FILE | MAP_PRIVATE;
16737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else if (!isReadable() && isWritable()) {
168f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // write-only
169f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    prot = PROT_WRITE;
170f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    flag = MAP_FILE | MAP_SHARED;
17137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else if (isReadWrite()) {
172f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // read and write
173f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    prot = PROT_READ | PROT_WRITE;
174f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    flag = MAP_FILE | MAP_SHARED;
17537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
176f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // can not read/write
177f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    setState(BadBit);
178f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return false;
179f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
180f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
181f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  pMemBuffer = ::mmap(NULL, pLength, prot, flag, m_Handler, pStartOffset);
182f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
183f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (MAP_FAILED == pMemBuffer) {
184f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    setState(FailBit);
185f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return false;
186f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
187f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
188f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return true;
189f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
190f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
19137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool FileHandle::munmap(void* pMemBuffer, size_t pLength) {
192f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (!isOpened()) {
193f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    setState(BadBit);
194f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return false;
195f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
196f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
197f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (-1 == ::munmap(pMemBuffer, pLength)) {
198f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    setState(FailBit);
199f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return false;
200f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
201f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
202f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return true;
203f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
204f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
20537b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
206