1//===- FileSystem.inc -----------------------------------------------------===//
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/Support/FileHandle.h"
10#include "mcld/Support/Directory.h"
11
12#include <string>
13
14#include <cstdlib>
15#include <io.h>
16#include <fcntl.h>
17#include <limits.h>
18#include <sys/stat.h>
19#include <windows.h>
20
21#ifndef STDIN_FILENO
22#define STDIN_FILENO 0
23#endif
24#ifndef STDOUT_FILENO
25#define STDOUT_FILENO 1
26#endif
27#ifndef STDERR_FILENO
28#define STDERR_FILENO 2
29#endif
30
31namespace mcld {
32namespace sys {
33namespace fs {
34namespace detail {
35
36// FIXME: the extension depends on target machine, not host machine.
37Path::StringType static_library_extension = ".a";
38Path::StringType shared_library_extension = ".so";
39Path::StringType executable_extension = ".exe";
40Path::StringType relocatable_extension = ".o";
41Path::StringType assembly_extension = ".s";
42Path::StringType bitcode_extension = ".bc";
43
44void open_dir(Directory& pDir) {
45  fs::Path file_filter(pDir.path());
46  file_filter.append("*");
47
48  WIN32_FIND_DATA FindFileData;
49  HANDLE hFile = FindFirstFile(file_filter.c_str(), &FindFileData);
50  pDir.m_Handler = reinterpret_cast<intptr_t>(hFile);
51
52  if (INVALID_HANDLE_VALUE == hFile) {
53    // set cache is full, then Directory::begin() can return end().
54    pDir.m_CacheFull = true;
55    return;
56  }
57
58  // find a new directory and file
59  bool exist = false;
60  std::string path(FindFileData.cFileName);
61  fs::PathCache::entry_type* entry = pDir.m_Cache.insert(path, exist);
62  if (!exist)
63    entry->setValue(path);
64}
65
66void close_dir(Directory& pDir) {
67  if (pDir.m_Handler)
68    FindClose(reinterpret_cast<HANDLE>(pDir.m_Handler));
69  pDir.m_Handler = 0;
70}
71
72int open(const Path& pPath, int pOFlag) {
73  return ::_open(pPath.native().c_str(), pOFlag | _O_BINARY);
74}
75
76int open(const Path& pPath, int pOFlag, int pPerm) {
77  int perm = 0;
78  if (pPerm & FileHandle::ReadOwner || pPerm & FileHandle::ReadGroup ||
79      pPerm & FileHandle::ReadOther)
80    perm |= _S_IREAD;
81
82  if (pPerm & FileHandle::WriteOwner || pPerm & FileHandle::WriteGroup ||
83      pPerm & FileHandle::WriteOther)
84    perm |= _S_IWRITE;
85
86  return ::_open(pPath.native().c_str(), pOFlag | _O_BINARY, perm);
87}
88
89ssize_t pread(int pFD, void* pBuf, size_t pCount, off_t pOffset) {
90  ssize_t ret;
91  off_t old_pos;
92  if (-1 == (old_pos = ::lseek(pFD, 0, SEEK_CUR)))
93    return -1;
94
95  if (-1 == ::lseek(pFD, pOffset, SEEK_SET))
96    return -1;
97
98  if (-1 == (ret = ::read(pFD, pBuf, pCount))) {
99    int err = errno;
100    ::lseek(pFD, old_pos, SEEK_SET);
101    errno = err;
102    return -1;
103  }
104
105  if (-1 == ::lseek(pFD, old_pos, SEEK_SET))
106    return -1;
107
108  return ret;
109}
110
111ssize_t pwrite(int pFD, const void* pBuf, size_t pCount, off_t pOffset) {
112  ssize_t ret;
113  off_t old_pos;
114  if (-1 == (old_pos = ::lseek(pFD, 0, SEEK_CUR)))
115    return -1;
116
117  if (-1 == ::lseek(pFD, pOffset, SEEK_SET))
118    return -1;
119
120  if (-1 == (ret = ::write(pFD, pBuf, pCount))) {
121    int err = errno;
122    ::lseek(pFD, old_pos, SEEK_SET);
123    errno = err;
124    return -1;
125  }
126
127  if (-1 == ::lseek(pFD, old_pos, SEEK_SET))
128    return -1;
129
130  return ret;
131}
132
133int ftruncate(int pFD, size_t pLength) {
134  return ::_chsize(pFD, pLength);
135}
136
137void get_pwd(Path& pPWD) {
138  char* pwd = (char*)malloc(PATH_MAX);
139  pPWD.assign(_getcwd(pwd, PATH_MAX));
140  free(pwd);
141}
142
143}  // namespace detail
144}  // namespace fs
145}  // namespace sys
146
147//===----------------------------------------------------------------------===//
148// FileHandle
149//===----------------------------------------------------------------------===//
150bool FileHandle::mmap(void*& pMemBuffer, size_t pStartOffset, size_t pLength) {
151  // FIXME: This implementation reduces mmap to read. Use Windows APIs.
152  pMemBuffer = (void*)::malloc(pLength);
153  return read(pMemBuffer, pStartOffset, pLength);
154}
155
156bool FileHandle::munmap(void* pMemBuffer, size_t pLength) {
157  // FIXME: This implementation reduces mmap to read. Use Windows APIs.
158  free(pMemBuffer);
159  return true;
160}
161
162}  // namespace mcld
163