blob: 42e81a2aca140cae5e3752375b0d3a2e3de9bf7c [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 Hamajic9b0aca2015-07-31 16:47:56 +090020#include <fcntl.h>
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +090021#include <glob.h>
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090022#include <limits.h>
Shinichiro Hamaji7cf19352016-01-26 15:32:44 +090023#include <signal.h>
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090024#include <sys/stat.h>
Shinichiro Hamaji94d6f2a2015-07-05 05:32:25 +090025#include <sys/types.h>
26#include <sys/wait.h>
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090027#include <unistd.h>
Shinichiro Hamajib58bb4b2015-07-30 18:02:51 +090028#if defined(__APPLE__)
29#include <mach-o/dyld.h>
30#endif
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090031
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +090032#include <unordered_map>
33
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090034#include "log.h"
35
36bool Exists(StringPiece filename) {
37 CHECK(filename.size() < PATH_MAX);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090038 struct stat st;
Shinichiro Hamajifda79432015-07-05 03:17:34 +090039 if (stat(filename.as_string().c_str(), &st) < 0) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090040 return false;
41 }
42 return true;
43}
Shinichiro Hamajifda79432015-07-05 03:17:34 +090044
Shinichiro Hamaji6ce977d2015-10-15 16:01:16 +090045double GetTimestampFromStat(const struct stat& st) {
46#if defined(__linux__)
47 return st.st_mtime + st.st_mtim.tv_nsec * 0.001 * 0.001 * 0.001;
48#else
49 return st.st_mtime;
50#endif
51}
52
Shinichiro Hamajifda79432015-07-05 03:17:34 +090053double GetTimestamp(StringPiece filename) {
54 CHECK(filename.size() < PATH_MAX);
55 struct stat st;
56 if (stat(filename.as_string().c_str(), &st) < 0) {
57 return -2.0;
58 }
Shinichiro Hamaji6ce977d2015-10-15 16:01:16 +090059 return GetTimestampFromStat(st);
Shinichiro Hamajifda79432015-07-05 03:17:34 +090060}
Shinichiro Hamaji94d6f2a2015-07-05 05:32:25 +090061
Shinichiro Hamajic9b0aca2015-07-31 16:47:56 +090062int RunCommand(const string& shell, const string& cmd,
63 RedirectStderr redirect_stderr,
Shinichiro Hamaji94d6f2a2015-07-05 05:32:25 +090064 string* s) {
65 int pipefd[2];
66 if (pipe(pipefd) != 0)
67 PERROR("pipe failed");
68 int pid;
69 if ((pid = vfork())) {
70 int status;
71 close(pipefd[1]);
72 while (true) {
73 int result = waitpid(pid, &status, WNOHANG);
74 if (result < 0)
75 PERROR("waitpid failed");
76
77 while (true) {
78 char buf[4096];
79 ssize_t r = read(pipefd[0], buf, 4096);
80 if (r < 0)
81 PERROR("read failed");
82 if (r == 0)
83 break;
84 s->append(buf, buf+r);
85 }
86
87 if (result != 0) {
88 break;
89 }
90 }
91 close(pipefd[0]);
92
93 return status;
94 } else {
95 close(pipefd[0]);
Shinichiro Hamajic9b0aca2015-07-31 16:47:56 +090096 if (redirect_stderr == RedirectStderr::STDOUT) {
Shinichiro Hamaji94d6f2a2015-07-05 05:32:25 +090097 if (dup2(pipefd[1], 2) < 0)
98 PERROR("dup2 failed");
Shinichiro Hamajic9b0aca2015-07-31 16:47:56 +090099 } else if (redirect_stderr == RedirectStderr::DEV_NULL) {
100 int fd = open("/dev/null", O_WRONLY);
101 if (dup2(fd, 2) < 0)
102 PERROR("dup2 failed");
103 close(fd);
Shinichiro Hamaji94d6f2a2015-07-05 05:32:25 +0900104 }
105 if (dup2(pipefd[1], 1) < 0)
106 PERROR("dup2 failed");
107 close(pipefd[1]);
108
109 const char* argv[] = {
110 shell.c_str(), "-c", cmd.c_str(), NULL
111 };
112 execvp(argv[0], const_cast<char**>(argv));
Shinichiro Hamaji7cf19352016-01-26 15:32:44 +0900113 PLOG("execvp for %s failed", argv[0]);
114 kill(getppid(), SIGTERM);
115 _exit(1);
Shinichiro Hamaji94d6f2a2015-07-05 05:32:25 +0900116 }
Shinichiro Hamaji94d6f2a2015-07-05 05:32:25 +0900117}
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900118
Shinichiro Hamajib58bb4b2015-07-30 18:02:51 +0900119void GetExecutablePath(string* path) {
120#if defined(__linux__)
121 char mypath[PATH_MAX + 1];
122 ssize_t l = readlink("/proc/self/exe", mypath, PATH_MAX);
123 if (l < 0) {
124 PERROR("readlink for /proc/self/exe");
125 }
126 mypath[l] = '\0';
127 *path = mypath;
128#elif defined(__APPLE__)
129 char mypath[PATH_MAX + 1];
Shinichiro Hamajie6ec1182015-07-31 15:02:35 +0900130 uint32_t size = PATH_MAX;
131 if (_NSGetExecutablePath(mypath, &size) != 0) {
Shinichiro Hamajib58bb4b2015-07-30 18:02:51 +0900132 ERROR("_NSGetExecutablePath failed");
133 }
Shinichiro Hamajie6ec1182015-07-31 15:02:35 +0900134 mypath[size] = 0;
Shinichiro Hamajib58bb4b2015-07-30 18:02:51 +0900135 *path = mypath;
136#else
137#error "Unsupported OS"
138#endif
139}
140
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900141namespace {
142
143class GlobCache {
144 public:
145 ~GlobCache() {
Shinichiro Hamajia09ed282015-07-31 12:21:54 +0900146 Clear();
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900147 }
148
149 void Get(const char* pat, vector<string>** files) {
150 auto p = cache_.emplace(pat, nullptr);
151 if (p.second) {
152 vector<string>* files = p.first->second = new vector<string>;
153 if (strcspn(pat, "?*[\\") != strlen(pat)) {
154 glob_t gl;
155 glob(pat, GLOB_NOSORT, NULL, &gl);
156 for (size_t i = 0; i < gl.gl_pathc; i++) {
157 files->push_back(gl.gl_pathv[i]);
158 }
159 globfree(&gl);
160 } else {
161 if (Exists(pat))
162 files->push_back(pat);
163 }
164 }
165 *files = p.first->second;
166 }
167
Shinichiro Hamajia09ed282015-07-31 12:21:54 +0900168 const unordered_map<string, vector<string>*>& GetAll() const {
169 return cache_;
170 }
171
172 void Clear() {
173 for (auto& p : cache_) {
174 delete p.second;
175 }
176 cache_.clear();
177 }
178
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900179 private:
180 unordered_map<string, vector<string>*> cache_;
181};
182
Shinichiro Hamajia09ed282015-07-31 12:21:54 +0900183static GlobCache g_gc;
184
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900185} // namespace
186
187void Glob(const char* pat, vector<string>** files) {
Shinichiro Hamajia09ed282015-07-31 12:21:54 +0900188 g_gc.Get(pat, files);
189}
190
191const unordered_map<string, vector<string>*>& GetAllGlobCache() {
192 return g_gc.GetAll();
193}
194
195void ClearGlobCache() {
196 g_gc.Clear();
Shinichiro Hamaji0e3873a2015-07-05 15:48:28 +0900197}