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
125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <string>
1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines
1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <cstdlib>
15f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <io.h>
16f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <fcntl.h>
17f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <limits.h>
1837b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <sys/stat.h>
1937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <windows.h>
20f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
21f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#ifndef STDIN_FILENO
2237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#define STDIN_FILENO 0
23f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#endif
24f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#ifndef STDOUT_FILENO
2537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#define STDOUT_FILENO 1
26f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#endif
27f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#ifndef STDERR_FILENO
2837b74a387bb3993387029859c2d9d051c41c724eStephen Hines#define STDERR_FILENO 2
29f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#endif
305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
3237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace sys {
3337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace fs {
3437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace detail {
355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
36f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// FIXME: the extension depends on target machine, not host machine.
37f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesPath::StringType static_library_extension = ".a";
38f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesPath::StringType shared_library_extension = ".so";
3937b74a387bb3993387029859c2d9d051c41c724eStephen HinesPath::StringType executable_extension = ".exe";
4037b74a387bb3993387029859c2d9d051c41c724eStephen HinesPath::StringType relocatable_extension = ".o";
4137b74a387bb3993387029859c2d9d051c41c724eStephen HinesPath::StringType assembly_extension = ".s";
4237b74a387bb3993387029859c2d9d051c41c724eStephen HinesPath::StringType bitcode_extension = ".bc";
43f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
4437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid open_dir(Directory& pDir) {
45f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  fs::Path file_filter(pDir.path());
46f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  file_filter.append("*");
47f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
48f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  WIN32_FIND_DATA FindFileData;
49f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  HANDLE hFile = FindFirstFile(file_filter.c_str(), &FindFileData);
50f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  pDir.m_Handler = reinterpret_cast<intptr_t>(hFile);
51f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
52f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (INVALID_HANDLE_VALUE == hFile) {
53f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // set cache is full, then Directory::begin() can return end().
54f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    pDir.m_CacheFull = true;
55f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return;
56f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
57f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
58f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // find a new directory and file
59f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  bool exist = false;
60f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  std::string path(FindFileData.cFileName);
61f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  fs::PathCache::entry_type* entry = pDir.m_Cache.insert(path, exist);
62f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (!exist)
63f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    entry->setValue(path);
64f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
65f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
6637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid close_dir(Directory& pDir) {
67f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pDir.m_Handler)
68f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    FindClose(reinterpret_cast<HANDLE>(pDir.m_Handler));
69f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  pDir.m_Handler = 0;
70f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
71f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
7237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesint open(const Path& pPath, int pOFlag) {
73f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return ::_open(pPath.native().c_str(), pOFlag | _O_BINARY);
74f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
75f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
7637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesint open(const Path& pPath, int pOFlag, int pPerm) {
77f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  int perm = 0;
7837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (pPerm & FileHandle::ReadOwner || pPerm & FileHandle::ReadGroup ||
79f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      pPerm & FileHandle::ReadOther)
80f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    perm |= _S_IREAD;
81f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
8237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (pPerm & FileHandle::WriteOwner || pPerm & FileHandle::WriteGroup ||
83f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      pPerm & FileHandle::WriteOther)
84f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    perm |= _S_IWRITE;
85f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
86f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return ::_open(pPath.native().c_str(), pOFlag | _O_BINARY, perm);
87f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
88f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
8937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesssize_t pread(int pFD, void* pBuf, size_t pCount, off_t pOffset) {
90f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ssize_t ret;
91f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  off_t old_pos;
92f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (-1 == (old_pos = ::lseek(pFD, 0, SEEK_CUR)))
9337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    return -1;
94f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
95f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (-1 == ::lseek(pFD, pOffset, SEEK_SET))
96f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return -1;
97f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
98f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (-1 == (ret = ::read(pFD, pBuf, pCount))) {
99f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    int err = errno;
100f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    ::lseek(pFD, old_pos, SEEK_SET);
101f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    errno = err;
10237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    return -1;
103f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
105f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (-1 == ::lseek(pFD, old_pos, SEEK_SET))
106f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return -1;
107f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
108f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return ret;
109f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
110f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
11137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesssize_t pwrite(int pFD, const void* pBuf, size_t pCount, off_t pOffset) {
112f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ssize_t ret;
113f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  off_t old_pos;
114f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (-1 == (old_pos = ::lseek(pFD, 0, SEEK_CUR)))
115f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return -1;
116f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
117f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (-1 == ::lseek(pFD, pOffset, SEEK_SET))
118f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return -1;
119f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
120f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (-1 == (ret = ::write(pFD, pBuf, pCount))) {
121f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    int err = errno;
122f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    ::lseek(pFD, old_pos, SEEK_SET);
123f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    errno = err;
124f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return -1;
125f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
126f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
127f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (-1 == ::lseek(pFD, old_pos, SEEK_SET))
128f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return -1;
129f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
130f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return ret;
131f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
132f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
13337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesint ftruncate(int pFD, size_t pLength) {
134f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return ::_chsize(pFD, pLength);
135f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
136f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
13737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid get_pwd(Path& pPWD) {
138f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  char* pwd = (char*)malloc(PATH_MAX);
139f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  pPWD.assign(_getcwd(pwd, PATH_MAX));
140f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  free(pwd);
141f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
14337b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace detail
14437b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace fs
14537b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace sys
146f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
147f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//===----------------------------------------------------------------------===//
148f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// FileHandle
149f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//===----------------------------------------------------------------------===//
15037b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool FileHandle::mmap(void*& pMemBuffer, size_t pStartOffset, size_t pLength) {
151f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // FIXME: This implementation reduces mmap to read. Use Windows APIs.
152f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  pMemBuffer = (void*)::malloc(pLength);
153f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return read(pMemBuffer, pStartOffset, pLength);
154f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
155f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
15637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool FileHandle::munmap(void* pMemBuffer, size_t pLength) {
157f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // FIXME: This implementation reduces mmap to read. Use Windows APIs.
158f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  free(pMemBuffer);
159f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return true;
160f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
161f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
16237b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
163