blob: 11f8f6d6b1824b3dc59533908968ff4eae158979 [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 }
49 return st.st_mtime;
50}
Shinichiro Hamaji94d6f2a2015-07-05 05:32:25 +090051
52int RunCommand(const string& shell, const string& cmd, bool redirect_stderr,
53 string* s) {
54 int pipefd[2];
55 if (pipe(pipefd) != 0)
56 PERROR("pipe failed");
57 int pid;
58 if ((pid = vfork())) {
59 int status;
60 close(pipefd[1]);
61 while (true) {
62 int result = waitpid(pid, &status, WNOHANG);
63 if (result < 0)
64 PERROR("waitpid failed");
65
66 while (true) {
67 char buf[4096];
68 ssize_t r = read(pipefd[0], buf, 4096);
69 if (r < 0)
70 PERROR("read failed");
71 if (r == 0)
72 break;
73 s->append(buf, buf+r);
74 }
75
76 if (result != 0) {
77 break;
78 }
79 }
80 close(pipefd[0]);
81
82 return status;
83 } else {
84 close(pipefd[0]);
85 if (redirect_stderr) {
86 if (dup2(pipefd[1], 2) < 0)
87 PERROR("dup2 failed");
88 }
89 if (dup2(pipefd[1], 1) < 0)
90 PERROR("dup2 failed");
91 close(pipefd[1]);
92
93 const char* argv[] = {
94 shell.c_str(), "-c", cmd.c_str(), NULL
95 };
96 execvp(argv[0], const_cast<char**>(argv));
97 }
98 abort();
99}
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900100
Shinichiro Hamajib58bb4b2015-07-30 18:02:51 +0900101void GetExecutablePath(string* path) {
102#if defined(__linux__)
103 char mypath[PATH_MAX + 1];
104 ssize_t l = readlink("/proc/self/exe", mypath, PATH_MAX);
105 if (l < 0) {
106 PERROR("readlink for /proc/self/exe");
107 }
108 mypath[l] = '\0';
109 *path = mypath;
110#elif defined(__APPLE__)
111 char mypath[PATH_MAX + 1];
112 if (_NSGetExecutablePath(mypath, PATH_MAX) != 0) {
113 ERROR("_NSGetExecutablePath failed");
114 }
115 *path = mypath;
116#else
117#error "Unsupported OS"
118#endif
119}
120
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900121namespace {
122
123class GlobCache {
124 public:
125 ~GlobCache() {
Shinichiro Hamajia09ed282015-07-31 12:21:54 +0900126 Clear();
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900127 }
128
129 void Get(const char* pat, vector<string>** files) {
130 auto p = cache_.emplace(pat, nullptr);
131 if (p.second) {
132 vector<string>* files = p.first->second = new vector<string>;
133 if (strcspn(pat, "?*[\\") != strlen(pat)) {
134 glob_t gl;
135 glob(pat, GLOB_NOSORT, NULL, &gl);
136 for (size_t i = 0; i < gl.gl_pathc; i++) {
137 files->push_back(gl.gl_pathv[i]);
138 }
139 globfree(&gl);
140 } else {
141 if (Exists(pat))
142 files->push_back(pat);
143 }
144 }
145 *files = p.first->second;
146 }
147
Shinichiro Hamajia09ed282015-07-31 12:21:54 +0900148 const unordered_map<string, vector<string>*>& GetAll() const {
149 return cache_;
150 }
151
152 void Clear() {
153 for (auto& p : cache_) {
154 delete p.second;
155 }
156 cache_.clear();
157 }
158
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900159 private:
160 unordered_map<string, vector<string>*> cache_;
161};
162
Shinichiro Hamajia09ed282015-07-31 12:21:54 +0900163static GlobCache g_gc;
164
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900165} // namespace
166
167void Glob(const char* pat, vector<string>** files) {
Shinichiro Hamajia09ed282015-07-31 12:21:54 +0900168 g_gc.Get(pat, files);
169}
170
171const unordered_map<string, vector<string>*>& GetAllGlobCache() {
172 return g_gc.GetAll();
173}
174
175void ClearGlobCache() {
176 g_gc.Clear();
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900177}