• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright (C) 2016 The Android Open Source Project
3   *
4   * Licensed under the Apache License, Version 2.0 (the "License");
5   * you may not use this file except in compliance with the License.
6   * You may obtain a copy of the License at
7   *
8   *      http://www.apache.org/licenses/LICENSE-2.0
9   *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  #include <err.h>
18  #include <fcntl.h>
19  #include <fts.h>
20  #include <sys/stat.h>
21  #include <sys/types.h>
22  #include <unistd.h>
23  
24  #include <memory>
25  #include <string>
26  
27  #include <android-base/unique_fd.h>
28  #include <llvm/ADT/IntrusiveRefCntPtr.h>
29  #include <llvm/Support/MemoryBuffer.h>
30  #include <llvm/Support/VirtualFileSystem.h>
31  
32  #include "Utils.h"
33  
34  using android::base::unique_fd;
35  using namespace llvm::vfs;
36  
addDirectoryToVFS(InMemoryFileSystem * vfs,const std::string & path)37  static void addDirectoryToVFS(InMemoryFileSystem* vfs, const std::string& path) {
38    char* paths[] = { const_cast<char*>(path.c_str()), nullptr };
39    std::unique_ptr<FTS, decltype(&fts_close)> fts(
40        fts_open(paths, FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOCHDIR, nullptr), fts_close);
41  
42    if (!fts) {
43      err(1, "failed to open directory %s", path.c_str());
44    }
45  
46    while (FTSENT* ent = fts_read(fts.get())) {
47      if ((ent->fts_info & FTS_F) == 0) {
48        continue;
49      }
50  
51      const char* file_path = ent->fts_accpath;
52      unique_fd fd(open(file_path, O_RDONLY | O_CLOEXEC));
53      if (fd == -1) {
54        err(1, "failed to open header '%s'", file_path);
55      }
56  
57      auto buffer_opt = llvm::MemoryBuffer::getOpenFile(fd, file_path, -1, false, false);
58      if (!buffer_opt) {
59        errx(1, "failed to map header '%s'", file_path);
60      }
61  
62      if (!vfs->addFile(file_path, ent->fts_statp->st_mtime, std::move(buffer_opt.get()))) {
63        errx(1, "failed to add file '%s'", file_path);
64      }
65    }
66  }
67  
createCommonVFS(const std::string & header_dir,const std::string & dependency_dir,bool add_versioning_header)68  llvm::IntrusiveRefCntPtr<FileSystem> createCommonVFS(const std::string& header_dir,
69                                                       const std::string& dependency_dir,
70                                                       bool add_versioning_header) {
71    auto vfs = std::make_unique<InMemoryFileSystem>();
72    addDirectoryToVFS(vfs.get(), header_dir);
73    if (!dependency_dir.empty()) {
74      addDirectoryToVFS(vfs.get(), dependency_dir);
75    }
76  
77    if (add_versioning_header) {
78      const char* top = getenv("ANDROID_BUILD_TOP");
79      if (!top) {
80        errx(1, "-i passed, but ANDROID_BUILD_TOP is unset");
81      }
82  
83      std::string header_path = std::string(top) + "/bionic/libc/include/android/versioning.h";
84      auto buffer_opt = llvm::MemoryBuffer::getFile(header_path);
85      if (!buffer_opt) {
86        err(1, "failed to open %s", header_path.c_str());
87      }
88      vfs->addFile("android/versioning.h", 0, std::move(buffer_opt.get()));
89    }
90  
91    return llvm::IntrusiveRefCntPtr<FileSystem>(vfs.release());
92  }
93