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//===----------------------------------------------------------------------===//
95460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <string>
105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <sys/types.h>
115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <sys/stat.h>
12f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <sys/mman.h>
13f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <dirent.h>
14affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <unistd.h>
155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <fcntl.h>
16f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <mcld/Support/FileHandle.h>
17f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <mcld/Support/Directory.h>
18f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <llvm/Support/ErrorHandling.h>
195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaonamespace mcld{
215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaonamespace sys{
225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaonamespace fs{
235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaonamespace detail{
245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostd::string static_library_extension = ".a";
265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostd::string shared_library_extension = ".so";
27f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesstd::string executable_extension     = "";
28f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesstd::string relocatable_extension    = ".o";
29f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesstd::string assembly_extension       = ".s";
30f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesstd::string bitcode_extension        = ".bc";
31f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
32f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//===----------------------------------------------------------------------===//
33f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// Helper Functions
34f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//===----------------------------------------------------------------------===//
35f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// read_dir - return true if we read one entry
36f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//  @return value -1: read error
37f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//                 0: read the end
38f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//                 1: success
39f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesstatic int read_dir(intptr_t& pDir, std::string& pOutFilename)
40f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
41f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  errno = 0;
42f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  dirent *cur_dir = ::readdir(reinterpret_cast<DIR*>(pDir));
43f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (0 == cur_dir && 0 != errno)
44f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return -1;
45f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
46f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // idx does not stay at the end, but all elements had beed put into cache.
47f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (NULL == cur_dir) {
48f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return 0;
49f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
50f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
51f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  llvm::StringRef name(cur_dir->d_name, strlen(cur_dir->d_name));
52f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if ((name.size() == 1 && name[0] == '.') ||
53f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      (name.size() == 2 && name[0] == '.' && name[1] == '.'))
54f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return read_dir(pDir, pOutFilename);
55f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
56f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // find a new directory
57f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  pOutFilename.append(name.data(), name.size());
58f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return 1;
59f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
60f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
61f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid open_dir(Directory& pDir)
62f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
63f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  pDir.m_Handler = reinterpret_cast<intptr_t>(opendir(pDir.path().c_str()));
64f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (0 == pDir.m_Handler) {
65f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    errno = 0; // opendir() will set errno if it failed to open directory.
66f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // set cache is full, then Directory::begin() can return end().
67f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    pDir.m_CacheFull = true;
68f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return;
69f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
70f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // read one entry for advance the end element of the cache.
71f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  std::string path(pDir.path().native());
72f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  switch (read_dir(pDir.m_Handler, path)) {
73f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  case 1: {
74f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // find a new directory
75f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    bool exist = false;
76f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    mcld::sys::fs::PathCache::entry_type* entry = pDir.m_Cache.insert(path, exist);
77f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (!exist)
78f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      entry->setValue(path);
79f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return;
80f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
81f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  case 0:
82f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // FIXME: a warning function
83f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    pDir.m_CacheFull = true;
84f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return;
85f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  default:
86f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  case -1:
87f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    llvm::report_fatal_error(std::string("Can't read directory: ")+
88f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                             pDir.path().native());
89f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
90f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
91f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
92f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid close_dir(Directory& pDir)
93f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
94f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pDir.m_Handler)
95f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    closedir(reinterpret_cast<DIR *>(pDir.m_Handler));
96f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  pDir.m_Handler = 0;
97f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
99affc150dc44fab1911775a49636d0ce85333b634Zonr Changint open(const Path& pPath, int pOFlag)
1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
101affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return ::open(pPath.native().c_str(), pOFlag);
1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
104affc150dc44fab1911775a49636d0ce85333b634Zonr Changint open(const Path& pPath, int pOFlag, int pPerm)
1055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
106f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  mode_t perm = 0;
107f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pPerm & FileHandle::ReadOwner)
108f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    perm |= S_IRUSR;
109f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pPerm & FileHandle::WriteOwner)
110f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    perm |= S_IWUSR;
111f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pPerm & FileHandle::ExeOwner)
112f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    perm |= S_IXUSR;
113f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pPerm & FileHandle::ReadGroup)
114f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    perm |= S_IRGRP;
115f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pPerm & FileHandle::WriteGroup)
116f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    perm |= S_IWGRP;
117f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pPerm & FileHandle::ExeGroup)
118f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    perm |= S_IXGRP;
119f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pPerm & FileHandle::ReadOther)
120f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    perm |= S_IROTH;
121f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pPerm & FileHandle::WriteOther)
122f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    perm |= S_IWOTH;
123f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pPerm & FileHandle::ExeOther)
124f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    perm |= S_IXOTH;
125f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
126f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return ::open(pPath.native().c_str(), pOFlag, perm);
1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
129f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesssize_t pread(int pFD, void* pBuf, size_t pCount, off_t pOffset)
1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
131affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return ::pread(pFD, pBuf, pCount, pOffset);
132affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
133affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
134f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesssize_t pwrite(int pFD, const void* pBuf, size_t pCount, off_t pOffset)
135affc150dc44fab1911775a49636d0ce85333b634Zonr Chang{
136affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return ::pwrite(pFD, pBuf, pCount, pOffset);
137affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
138affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
139affc150dc44fab1911775a49636d0ce85333b634Zonr Changint ftruncate(int pFD, size_t pLength)
140affc150dc44fab1911775a49636d0ce85333b634Zonr Chang{
141affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return ::ftruncate(pFD, pLength);
1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
144f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid get_pwd(Path& pPWD)
145f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
146f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  char* pwd = (char*)malloc(PATH_MAX);
147f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  pPWD.assign(getcwd(pwd, PATH_MAX));
148f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  free(pwd);
149f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
150f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} // namespace of detail
1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} // namespace of fs
1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} // namespace of sys
154f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
155f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//===----------------------------------------------------------------------===//
156f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// FileHandler
157f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//===----------------------------------------------------------------------===//
158f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesbool FileHandle::mmap(void*& pMemBuffer, size_t pStartOffset, size_t pLength)
159f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
160f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (!isOpened()) {
161f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    setState(BadBit);
162f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return false;
163f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
164f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
165f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (0 == pLength)
166f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return true;
167f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
168f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  int prot, flag;
169f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (isReadable() && !isWritable()) {
170f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // read-only
171f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    prot = PROT_READ;
172f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    flag = MAP_FILE | MAP_PRIVATE;
173f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
174f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  else if (!isReadable() && isWritable()) {
175f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // write-only
176f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    prot = PROT_WRITE;
177f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    flag = MAP_FILE | MAP_SHARED;
178f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
179f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  else if (isReadWrite()) {
180f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // read and write
181f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    prot = PROT_READ | PROT_WRITE;
182f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    flag = MAP_FILE | MAP_SHARED;
183f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
184f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  else {
185f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // can not read/write
186f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    setState(BadBit);
187f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return false;
188f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
189f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
190f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  pMemBuffer = ::mmap(NULL, pLength, prot, flag, m_Handler, pStartOffset);
191f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
192f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (MAP_FAILED == pMemBuffer) {
193f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    setState(FailBit);
194f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return false;
195f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
196f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
197f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return true;
198f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
199f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
200f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesbool FileHandle::munmap(void* pMemBuffer, size_t pLength)
201f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
202f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (!isOpened()) {
203f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    setState(BadBit);
204f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return false;
205f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
206f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
207f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (-1 == ::munmap(pMemBuffer, pLength)) {
208f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    setState(FailBit);
209f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return false;
210f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
211f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
212f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return true;
213f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
214f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
2155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} // namespace of mcld
2165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
217