blob: 86d66e0ac4d2cd2bbac1c6a3c25eea7bf1668b5a [file] [log] [blame]
Shinichiro Hamaji1d545aa2015-06-23 15:29:13 +09001// Copyright 2015 Google Inc. All rights reserved
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +090015// +build ignore
16
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090017#include "fileutil.h"
18
19#include <errno.h>
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +090020#include <glob.h>
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090021#include <limits.h>
22#include <sys/stat.h>
Shinichiro Hamaji94d6f2a2015-07-05 05:32:25 +090023#include <sys/types.h>
24#include <sys/wait.h>
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090025#include <unistd.h>
Shinichiro Hamajib58bb4b2015-07-30 18:02:51 +090026#if defined(__APPLE__)
27#include <mach-o/dyld.h>
28#endif
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090029
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +090030#include <unordered_map>
31
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090032#include "log.h"
33
34bool Exists(StringPiece filename) {
35 CHECK(filename.size() < PATH_MAX);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090036 struct stat st;
Shinichiro Hamajifda79432015-07-05 03:17:34 +090037 if (stat(filename.as_string().c_str(), &st) < 0) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090038 return false;
39 }
40 return true;
41}
Shinichiro Hamajifda79432015-07-05 03:17:34 +090042
43double GetTimestamp(StringPiece filename) {
44 CHECK(filename.size() < PATH_MAX);
45 struct stat st;
46 if (stat(filename.as_string().c_str(), &st) < 0) {
47 return -2.0;
48 }
Shinichiro Hamaji36eeb752015-07-31 15:12:04 +090049#if defined(__linux__)
50 return st.st_mtime + st.st_mtim.tv_nsec * 0.001 * 0.001 * 0.001;
51#else
Shinichiro Hamajifda79432015-07-05 03:17:34 +090052 return st.st_mtime;
Shinichiro Hamaji36eeb752015-07-31 15:12:04 +090053#endif
Shinichiro Hamajifda79432015-07-05 03:17:34 +090054}
Shinichiro Hamaji94d6f2a2015-07-05 05:32:25 +090055
56int RunCommand(const string& shell, const string& cmd, bool redirect_stderr,
57 string* s) {
58 int pipefd[2];
59 if (pipe(pipefd) != 0)
60 PERROR("pipe failed");
61 int pid;
62 if ((pid = vfork())) {
63 int status;
64 close(pipefd[1]);
65 while (true) {
66 int result = waitpid(pid, &status, WNOHANG);
67 if (result < 0)
68 PERROR("waitpid failed");
69
70 while (true) {
71 char buf[4096];
72 ssize_t r = read(pipefd[0], buf, 4096);
73 if (r < 0)
74 PERROR("read failed");
75 if (r == 0)
76 break;
77 s->append(buf, buf+r);
78 }
79
80 if (result != 0) {
81 break;
82 }
83 }
84 close(pipefd[0]);
85
86 return status;
87 } else {
88 close(pipefd[0]);
89 if (redirect_stderr) {
90 if (dup2(pipefd[1], 2) < 0)
91 PERROR("dup2 failed");
92 }
93 if (dup2(pipefd[1], 1) < 0)
94 PERROR("dup2 failed");
95 close(pipefd[1]);
96
97 const char* argv[] = {
98 shell.c_str(), "-c", cmd.c_str(), NULL
99 };
100 execvp(argv[0], const_cast<char**>(argv));
101 }
102 abort();
103}
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900104
Shinichiro Hamajib58bb4b2015-07-30 18:02:51 +0900105void GetExecutablePath(string* path) {
106#if defined(__linux__)
107 char mypath[PATH_MAX + 1];
108 ssize_t l = readlink("/proc/self/exe", mypath, PATH_MAX);
109 if (l < 0) {
110 PERROR("readlink for /proc/self/exe");
111 }
112 mypath[l] = '\0';
113 *path = mypath;
114#elif defined(__APPLE__)
115 char mypath[PATH_MAX + 1];
Shinichiro Hamajie6ec1182015-07-31 15:02:35 +0900116 uint32_t size = PATH_MAX;
117 if (_NSGetExecutablePath(mypath, &size) != 0) {
Shinichiro Hamajib58bb4b2015-07-30 18:02:51 +0900118 ERROR("_NSGetExecutablePath failed");
119 }
Shinichiro Hamajie6ec1182015-07-31 15:02:35 +0900120 mypath[size] = 0;
Shinichiro Hamajib58bb4b2015-07-30 18:02:51 +0900121 *path = mypath;
122#else
123#error "Unsupported OS"
124#endif
125}
126
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900127namespace {
128
129class GlobCache {
130 public:
131 ~GlobCache() {
Shinichiro Hamajia09ed282015-07-31 12:21:54 +0900132 Clear();
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900133 }
134
135 void Get(const char* pat, vector<string>** files) {
136 auto p = cache_.emplace(pat, nullptr);
137 if (p.second) {
138 vector<string>* files = p.first->second = new vector<string>;
139 if (strcspn(pat, "?*[\\") != strlen(pat)) {
140 glob_t gl;
141 glob(pat, GLOB_NOSORT, NULL, &gl);
142 for (size_t i = 0; i < gl.gl_pathc; i++) {
143 files->push_back(gl.gl_pathv[i]);
144 }
145 globfree(&gl);
146 } else {
147 if (Exists(pat))
148 files->push_back(pat);
149 }
150 }
151 *files = p.first->second;
152 }
153
Shinichiro Hamajia09ed282015-07-31 12:21:54 +0900154 const unordered_map<string, vector<string>*>& GetAll() const {
155 return cache_;
156 }
157
158 void Clear() {
159 for (auto& p : cache_) {
160 delete p.second;
161 }
162 cache_.clear();
163 }
164
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900165 private:
166 unordered_map<string, vector<string>*> cache_;
167};
168
Shinichiro Hamajia09ed282015-07-31 12:21:54 +0900169static GlobCache g_gc;
170
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900171} // namespace
172
173void Glob(const char* pat, vector<string>** files) {
Shinichiro Hamajia09ed282015-07-31 12:21:54 +0900174 g_gc.Get(pat, files);
175}
176
177const unordered_map<string, vector<string>*>& GetAllGlobCache() {
178 return g_gc.GetAll();
179}
180
181void ClearGlobCache() {
182 g_gc.Clear();
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900183}