1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker *
4*6dbdd20aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker *
8*6dbdd20aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker *
10*6dbdd20aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker * limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker */
16*6dbdd20aSAndroid Build Coastguard Worker
17*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/file_utils.h"
18*6dbdd20aSAndroid Build Coastguard Worker
19*6dbdd20aSAndroid Build Coastguard Worker #include <sys/stat.h>
20*6dbdd20aSAndroid Build Coastguard Worker #include <sys/types.h>
21*6dbdd20aSAndroid Build Coastguard Worker
22*6dbdd20aSAndroid Build Coastguard Worker #include <algorithm>
23*6dbdd20aSAndroid Build Coastguard Worker #include <deque>
24*6dbdd20aSAndroid Build Coastguard Worker #include <optional>
25*6dbdd20aSAndroid Build Coastguard Worker #include <string>
26*6dbdd20aSAndroid Build Coastguard Worker #include <vector>
27*6dbdd20aSAndroid Build Coastguard Worker
28*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/build_config.h"
29*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/compiler.h"
30*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/logging.h"
31*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/platform_handle.h"
32*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/status.h"
33*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/platform.h"
34*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/scoped_file.h"
35*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/string_utils.h"
36*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/utils.h"
37*6dbdd20aSAndroid Build Coastguard Worker
38*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
39*6dbdd20aSAndroid Build Coastguard Worker #include <Windows.h>
40*6dbdd20aSAndroid Build Coastguard Worker #include <direct.h>
41*6dbdd20aSAndroid Build Coastguard Worker #include <io.h>
42*6dbdd20aSAndroid Build Coastguard Worker #include <stringapiset.h>
43*6dbdd20aSAndroid Build Coastguard Worker #else
44*6dbdd20aSAndroid Build Coastguard Worker #include <dirent.h>
45*6dbdd20aSAndroid Build Coastguard Worker #include <unistd.h>
46*6dbdd20aSAndroid Build Coastguard Worker #endif
47*6dbdd20aSAndroid Build Coastguard Worker
48*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
49*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
50*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
51*6dbdd20aSAndroid Build Coastguard Worker #define PERFETTO_SET_FILE_PERMISSIONS
52*6dbdd20aSAndroid Build Coastguard Worker #include <fcntl.h>
53*6dbdd20aSAndroid Build Coastguard Worker #include <grp.h>
54*6dbdd20aSAndroid Build Coastguard Worker #include <sys/stat.h>
55*6dbdd20aSAndroid Build Coastguard Worker #include <sys/types.h>
56*6dbdd20aSAndroid Build Coastguard Worker #include <unistd.h>
57*6dbdd20aSAndroid Build Coastguard Worker #endif
58*6dbdd20aSAndroid Build Coastguard Worker
59*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto {
60*6dbdd20aSAndroid Build Coastguard Worker namespace base {
61*6dbdd20aSAndroid Build Coastguard Worker namespace {
62*6dbdd20aSAndroid Build Coastguard Worker constexpr size_t kBufSize = 2048;
63*6dbdd20aSAndroid Build Coastguard Worker
64*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
65*6dbdd20aSAndroid Build Coastguard Worker // Wrap FindClose to: (1) make the return unix-style; (2) deal with stdcall.
CloseFindHandle(HANDLE h)66*6dbdd20aSAndroid Build Coastguard Worker int CloseFindHandle(HANDLE h) {
67*6dbdd20aSAndroid Build Coastguard Worker return FindClose(h) ? 0 : -1;
68*6dbdd20aSAndroid Build Coastguard Worker }
69*6dbdd20aSAndroid Build Coastguard Worker
ToUtf16(const std::string str)70*6dbdd20aSAndroid Build Coastguard Worker std::optional<std::wstring> ToUtf16(const std::string str) {
71*6dbdd20aSAndroid Build Coastguard Worker int len = MultiByteToWideChar(CP_UTF8, 0, str.data(),
72*6dbdd20aSAndroid Build Coastguard Worker static_cast<int>(str.size()), nullptr, 0);
73*6dbdd20aSAndroid Build Coastguard Worker if (len < 0) {
74*6dbdd20aSAndroid Build Coastguard Worker return std::nullopt;
75*6dbdd20aSAndroid Build Coastguard Worker }
76*6dbdd20aSAndroid Build Coastguard Worker std::vector<wchar_t> tmp;
77*6dbdd20aSAndroid Build Coastguard Worker tmp.resize(static_cast<std::vector<wchar_t>::size_type>(len));
78*6dbdd20aSAndroid Build Coastguard Worker len =
79*6dbdd20aSAndroid Build Coastguard Worker MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast<int>(str.size()),
80*6dbdd20aSAndroid Build Coastguard Worker tmp.data(), static_cast<int>(tmp.size()));
81*6dbdd20aSAndroid Build Coastguard Worker if (len < 0) {
82*6dbdd20aSAndroid Build Coastguard Worker return std::nullopt;
83*6dbdd20aSAndroid Build Coastguard Worker }
84*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_CHECK(static_cast<std::vector<wchar_t>::size_type>(len) ==
85*6dbdd20aSAndroid Build Coastguard Worker tmp.size());
86*6dbdd20aSAndroid Build Coastguard Worker return std::wstring(tmp.data(), tmp.size());
87*6dbdd20aSAndroid Build Coastguard Worker }
88*6dbdd20aSAndroid Build Coastguard Worker
89*6dbdd20aSAndroid Build Coastguard Worker #endif
90*6dbdd20aSAndroid Build Coastguard Worker
91*6dbdd20aSAndroid Build Coastguard Worker } // namespace
92*6dbdd20aSAndroid Build Coastguard Worker
Read(int fd,void * dst,size_t dst_size)93*6dbdd20aSAndroid Build Coastguard Worker ssize_t Read(int fd, void* dst, size_t dst_size) {
94*6dbdd20aSAndroid Build Coastguard Worker ssize_t ret;
95*6dbdd20aSAndroid Build Coastguard Worker platform::BeforeMaybeBlockingSyscall();
96*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
97*6dbdd20aSAndroid Build Coastguard Worker ret = _read(fd, dst, static_cast<unsigned>(dst_size));
98*6dbdd20aSAndroid Build Coastguard Worker #else
99*6dbdd20aSAndroid Build Coastguard Worker ret = PERFETTO_EINTR(read(fd, dst, dst_size));
100*6dbdd20aSAndroid Build Coastguard Worker #endif
101*6dbdd20aSAndroid Build Coastguard Worker platform::AfterMaybeBlockingSyscall();
102*6dbdd20aSAndroid Build Coastguard Worker return ret;
103*6dbdd20aSAndroid Build Coastguard Worker }
104*6dbdd20aSAndroid Build Coastguard Worker
ReadFileDescriptor(int fd,std::string * out)105*6dbdd20aSAndroid Build Coastguard Worker bool ReadFileDescriptor(int fd, std::string* out) {
106*6dbdd20aSAndroid Build Coastguard Worker // Do not override existing data in string.
107*6dbdd20aSAndroid Build Coastguard Worker size_t i = out->size();
108*6dbdd20aSAndroid Build Coastguard Worker
109*6dbdd20aSAndroid Build Coastguard Worker struct stat buf {};
110*6dbdd20aSAndroid Build Coastguard Worker if (fstat(fd, &buf) != -1) {
111*6dbdd20aSAndroid Build Coastguard Worker if (buf.st_size > 0)
112*6dbdd20aSAndroid Build Coastguard Worker out->resize(i + static_cast<size_t>(buf.st_size));
113*6dbdd20aSAndroid Build Coastguard Worker }
114*6dbdd20aSAndroid Build Coastguard Worker
115*6dbdd20aSAndroid Build Coastguard Worker ssize_t bytes_read;
116*6dbdd20aSAndroid Build Coastguard Worker for (;;) {
117*6dbdd20aSAndroid Build Coastguard Worker if (out->size() < i + kBufSize)
118*6dbdd20aSAndroid Build Coastguard Worker out->resize(out->size() + kBufSize);
119*6dbdd20aSAndroid Build Coastguard Worker
120*6dbdd20aSAndroid Build Coastguard Worker bytes_read = Read(fd, &((*out)[i]), kBufSize);
121*6dbdd20aSAndroid Build Coastguard Worker if (bytes_read > 0) {
122*6dbdd20aSAndroid Build Coastguard Worker i += static_cast<size_t>(bytes_read);
123*6dbdd20aSAndroid Build Coastguard Worker } else {
124*6dbdd20aSAndroid Build Coastguard Worker out->resize(i);
125*6dbdd20aSAndroid Build Coastguard Worker return bytes_read == 0;
126*6dbdd20aSAndroid Build Coastguard Worker }
127*6dbdd20aSAndroid Build Coastguard Worker }
128*6dbdd20aSAndroid Build Coastguard Worker }
129*6dbdd20aSAndroid Build Coastguard Worker
ReadPlatformHandle(PlatformHandle h,std::string * out)130*6dbdd20aSAndroid Build Coastguard Worker bool ReadPlatformHandle(PlatformHandle h, std::string* out) {
131*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
132*6dbdd20aSAndroid Build Coastguard Worker // Do not override existing data in string.
133*6dbdd20aSAndroid Build Coastguard Worker size_t i = out->size();
134*6dbdd20aSAndroid Build Coastguard Worker
135*6dbdd20aSAndroid Build Coastguard Worker for (;;) {
136*6dbdd20aSAndroid Build Coastguard Worker if (out->size() < i + kBufSize)
137*6dbdd20aSAndroid Build Coastguard Worker out->resize(out->size() + kBufSize);
138*6dbdd20aSAndroid Build Coastguard Worker DWORD bytes_read = 0;
139*6dbdd20aSAndroid Build Coastguard Worker auto res = ::ReadFile(h, &((*out)[i]), kBufSize, &bytes_read, nullptr);
140*6dbdd20aSAndroid Build Coastguard Worker if (res && bytes_read > 0) {
141*6dbdd20aSAndroid Build Coastguard Worker i += static_cast<size_t>(bytes_read);
142*6dbdd20aSAndroid Build Coastguard Worker } else {
143*6dbdd20aSAndroid Build Coastguard Worker out->resize(i);
144*6dbdd20aSAndroid Build Coastguard Worker const bool is_eof = res && bytes_read == 0;
145*6dbdd20aSAndroid Build Coastguard Worker auto err = res ? 0 : GetLastError();
146*6dbdd20aSAndroid Build Coastguard Worker // The "Broken pipe" error on Windows is slighly different than Unix:
147*6dbdd20aSAndroid Build Coastguard Worker // On Unix: a "broken pipe" error can happen only on the writer side. On
148*6dbdd20aSAndroid Build Coastguard Worker // the reader there is no broken pipe, just a EOF.
149*6dbdd20aSAndroid Build Coastguard Worker // On windows: the reader also sees a broken pipe error.
150*6dbdd20aSAndroid Build Coastguard Worker // Here we normalize on the Unix behavior, treating broken pipe as EOF.
151*6dbdd20aSAndroid Build Coastguard Worker return is_eof || err == ERROR_BROKEN_PIPE;
152*6dbdd20aSAndroid Build Coastguard Worker }
153*6dbdd20aSAndroid Build Coastguard Worker }
154*6dbdd20aSAndroid Build Coastguard Worker #else
155*6dbdd20aSAndroid Build Coastguard Worker return ReadFileDescriptor(h, out);
156*6dbdd20aSAndroid Build Coastguard Worker #endif
157*6dbdd20aSAndroid Build Coastguard Worker }
158*6dbdd20aSAndroid Build Coastguard Worker
ReadFileStream(FILE * f,std::string * out)159*6dbdd20aSAndroid Build Coastguard Worker bool ReadFileStream(FILE* f, std::string* out) {
160*6dbdd20aSAndroid Build Coastguard Worker return ReadFileDescriptor(fileno(f), out);
161*6dbdd20aSAndroid Build Coastguard Worker }
162*6dbdd20aSAndroid Build Coastguard Worker
ReadFile(const std::string & path,std::string * out)163*6dbdd20aSAndroid Build Coastguard Worker bool ReadFile(const std::string& path, std::string* out) {
164*6dbdd20aSAndroid Build Coastguard Worker base::ScopedFile fd = base::OpenFile(path, O_RDONLY);
165*6dbdd20aSAndroid Build Coastguard Worker if (!fd)
166*6dbdd20aSAndroid Build Coastguard Worker return false;
167*6dbdd20aSAndroid Build Coastguard Worker
168*6dbdd20aSAndroid Build Coastguard Worker return ReadFileDescriptor(*fd, out);
169*6dbdd20aSAndroid Build Coastguard Worker }
170*6dbdd20aSAndroid Build Coastguard Worker
WriteAll(int fd,const void * buf,size_t count)171*6dbdd20aSAndroid Build Coastguard Worker ssize_t WriteAll(int fd, const void* buf, size_t count) {
172*6dbdd20aSAndroid Build Coastguard Worker size_t written = 0;
173*6dbdd20aSAndroid Build Coastguard Worker while (written < count) {
174*6dbdd20aSAndroid Build Coastguard Worker // write() on windows takes an unsigned int size.
175*6dbdd20aSAndroid Build Coastguard Worker uint32_t bytes_left = static_cast<uint32_t>(
176*6dbdd20aSAndroid Build Coastguard Worker std::min(count - written, static_cast<size_t>(UINT32_MAX)));
177*6dbdd20aSAndroid Build Coastguard Worker platform::BeforeMaybeBlockingSyscall();
178*6dbdd20aSAndroid Build Coastguard Worker ssize_t wr = PERFETTO_EINTR(
179*6dbdd20aSAndroid Build Coastguard Worker write(fd, static_cast<const char*>(buf) + written, bytes_left));
180*6dbdd20aSAndroid Build Coastguard Worker platform::AfterMaybeBlockingSyscall();
181*6dbdd20aSAndroid Build Coastguard Worker if (wr == 0)
182*6dbdd20aSAndroid Build Coastguard Worker break;
183*6dbdd20aSAndroid Build Coastguard Worker if (wr < 0)
184*6dbdd20aSAndroid Build Coastguard Worker return wr;
185*6dbdd20aSAndroid Build Coastguard Worker written += static_cast<size_t>(wr);
186*6dbdd20aSAndroid Build Coastguard Worker }
187*6dbdd20aSAndroid Build Coastguard Worker return static_cast<ssize_t>(written);
188*6dbdd20aSAndroid Build Coastguard Worker }
189*6dbdd20aSAndroid Build Coastguard Worker
WriteAllHandle(PlatformHandle h,const void * buf,size_t count)190*6dbdd20aSAndroid Build Coastguard Worker ssize_t WriteAllHandle(PlatformHandle h, const void* buf, size_t count) {
191*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
192*6dbdd20aSAndroid Build Coastguard Worker DWORD wsize = 0;
193*6dbdd20aSAndroid Build Coastguard Worker if (::WriteFile(h, buf, static_cast<DWORD>(count), &wsize, nullptr)) {
194*6dbdd20aSAndroid Build Coastguard Worker return wsize;
195*6dbdd20aSAndroid Build Coastguard Worker } else {
196*6dbdd20aSAndroid Build Coastguard Worker return -1;
197*6dbdd20aSAndroid Build Coastguard Worker }
198*6dbdd20aSAndroid Build Coastguard Worker #else
199*6dbdd20aSAndroid Build Coastguard Worker return WriteAll(h, buf, count);
200*6dbdd20aSAndroid Build Coastguard Worker #endif
201*6dbdd20aSAndroid Build Coastguard Worker }
202*6dbdd20aSAndroid Build Coastguard Worker
FlushFile(int fd)203*6dbdd20aSAndroid Build Coastguard Worker bool FlushFile(int fd) {
204*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_DCHECK(fd != 0);
205*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
206*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
207*6dbdd20aSAndroid Build Coastguard Worker return !PERFETTO_EINTR(fdatasync(fd));
208*6dbdd20aSAndroid Build Coastguard Worker #elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
209*6dbdd20aSAndroid Build Coastguard Worker return !PERFETTO_EINTR(_commit(fd));
210*6dbdd20aSAndroid Build Coastguard Worker #else
211*6dbdd20aSAndroid Build Coastguard Worker return !PERFETTO_EINTR(fsync(fd));
212*6dbdd20aSAndroid Build Coastguard Worker #endif
213*6dbdd20aSAndroid Build Coastguard Worker }
214*6dbdd20aSAndroid Build Coastguard Worker
Mkdir(const std::string & path)215*6dbdd20aSAndroid Build Coastguard Worker bool Mkdir(const std::string& path) {
216*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
217*6dbdd20aSAndroid Build Coastguard Worker return _mkdir(path.c_str()) == 0;
218*6dbdd20aSAndroid Build Coastguard Worker #else
219*6dbdd20aSAndroid Build Coastguard Worker return mkdir(path.c_str(), 0755) == 0;
220*6dbdd20aSAndroid Build Coastguard Worker #endif
221*6dbdd20aSAndroid Build Coastguard Worker }
222*6dbdd20aSAndroid Build Coastguard Worker
Rmdir(const std::string & path)223*6dbdd20aSAndroid Build Coastguard Worker bool Rmdir(const std::string& path) {
224*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
225*6dbdd20aSAndroid Build Coastguard Worker return _rmdir(path.c_str()) == 0;
226*6dbdd20aSAndroid Build Coastguard Worker #else
227*6dbdd20aSAndroid Build Coastguard Worker return rmdir(path.c_str()) == 0;
228*6dbdd20aSAndroid Build Coastguard Worker #endif
229*6dbdd20aSAndroid Build Coastguard Worker }
230*6dbdd20aSAndroid Build Coastguard Worker
CloseFile(int fd)231*6dbdd20aSAndroid Build Coastguard Worker int CloseFile(int fd) {
232*6dbdd20aSAndroid Build Coastguard Worker return close(fd);
233*6dbdd20aSAndroid Build Coastguard Worker }
234*6dbdd20aSAndroid Build Coastguard Worker
OpenFile(const std::string & path,int flags,FileOpenMode mode)235*6dbdd20aSAndroid Build Coastguard Worker ScopedFile OpenFile(const std::string& path, int flags, FileOpenMode mode) {
236*6dbdd20aSAndroid Build Coastguard Worker // If a new file might be created, ensure that the permissions for the new
237*6dbdd20aSAndroid Build Coastguard Worker // file are explicitly specified.
238*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_CHECK((flags & O_CREAT) == 0 || mode != kFileModeInvalid);
239*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
240*6dbdd20aSAndroid Build Coastguard Worker // Always use O_BINARY on Windows, to avoid silly EOL translations.
241*6dbdd20aSAndroid Build Coastguard Worker ScopedFile fd(_open(path.c_str(), flags | O_BINARY, mode));
242*6dbdd20aSAndroid Build Coastguard Worker #else
243*6dbdd20aSAndroid Build Coastguard Worker // Always open a ScopedFile with O_CLOEXEC so we can safely fork and exec.
244*6dbdd20aSAndroid Build Coastguard Worker ScopedFile fd(open(path.c_str(), flags | O_CLOEXEC, mode));
245*6dbdd20aSAndroid Build Coastguard Worker #endif
246*6dbdd20aSAndroid Build Coastguard Worker return fd;
247*6dbdd20aSAndroid Build Coastguard Worker }
248*6dbdd20aSAndroid Build Coastguard Worker
OpenFstream(const char * path,const char * mode)249*6dbdd20aSAndroid Build Coastguard Worker ScopedFstream OpenFstream(const char* path, const char* mode) {
250*6dbdd20aSAndroid Build Coastguard Worker ScopedFstream file;
251*6dbdd20aSAndroid Build Coastguard Worker // On Windows fopen interprets filename using the ANSI or OEM codepage but
252*6dbdd20aSAndroid Build Coastguard Worker // sqlite3_value_text returns a UTF-8 string. To make sure we interpret the
253*6dbdd20aSAndroid Build Coastguard Worker // filename correctly we use _wfopen and a UTF-16 string on windows.
254*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
255*6dbdd20aSAndroid Build Coastguard Worker auto w_path = ToUtf16(path);
256*6dbdd20aSAndroid Build Coastguard Worker auto w_mode = ToUtf16(mode);
257*6dbdd20aSAndroid Build Coastguard Worker if (w_path && w_mode) {
258*6dbdd20aSAndroid Build Coastguard Worker file.reset(_wfopen(w_path->c_str(), w_mode->c_str()));
259*6dbdd20aSAndroid Build Coastguard Worker }
260*6dbdd20aSAndroid Build Coastguard Worker #else
261*6dbdd20aSAndroid Build Coastguard Worker file.reset(fopen(path, mode));
262*6dbdd20aSAndroid Build Coastguard Worker #endif
263*6dbdd20aSAndroid Build Coastguard Worker return file;
264*6dbdd20aSAndroid Build Coastguard Worker }
265*6dbdd20aSAndroid Build Coastguard Worker
FileExists(const std::string & path)266*6dbdd20aSAndroid Build Coastguard Worker bool FileExists(const std::string& path) {
267*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
268*6dbdd20aSAndroid Build Coastguard Worker return _access(path.c_str(), 0) == 0;
269*6dbdd20aSAndroid Build Coastguard Worker #else
270*6dbdd20aSAndroid Build Coastguard Worker return access(path.c_str(), F_OK) == 0;
271*6dbdd20aSAndroid Build Coastguard Worker #endif
272*6dbdd20aSAndroid Build Coastguard Worker }
273*6dbdd20aSAndroid Build Coastguard Worker
274*6dbdd20aSAndroid Build Coastguard Worker // Declared in base/platform_handle.h.
ClosePlatformHandle(PlatformHandle handle)275*6dbdd20aSAndroid Build Coastguard Worker int ClosePlatformHandle(PlatformHandle handle) {
276*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
277*6dbdd20aSAndroid Build Coastguard Worker // Make the return value UNIX-style.
278*6dbdd20aSAndroid Build Coastguard Worker return CloseHandle(handle) ? 0 : -1;
279*6dbdd20aSAndroid Build Coastguard Worker #else
280*6dbdd20aSAndroid Build Coastguard Worker return close(handle);
281*6dbdd20aSAndroid Build Coastguard Worker #endif
282*6dbdd20aSAndroid Build Coastguard Worker }
283*6dbdd20aSAndroid Build Coastguard Worker
ListFilesRecursive(const std::string & dir_path,std::vector<std::string> & output)284*6dbdd20aSAndroid Build Coastguard Worker base::Status ListFilesRecursive(const std::string& dir_path,
285*6dbdd20aSAndroid Build Coastguard Worker std::vector<std::string>& output) {
286*6dbdd20aSAndroid Build Coastguard Worker std::string root_dir_path = dir_path;
287*6dbdd20aSAndroid Build Coastguard Worker if (root_dir_path.back() == '\\') {
288*6dbdd20aSAndroid Build Coastguard Worker root_dir_path.back() = '/';
289*6dbdd20aSAndroid Build Coastguard Worker } else if (root_dir_path.back() != '/') {
290*6dbdd20aSAndroid Build Coastguard Worker root_dir_path.push_back('/');
291*6dbdd20aSAndroid Build Coastguard Worker }
292*6dbdd20aSAndroid Build Coastguard Worker
293*6dbdd20aSAndroid Build Coastguard Worker // dir_queue contains full paths to the directories. The paths include the
294*6dbdd20aSAndroid Build Coastguard Worker // root_dir_path at the beginning and the trailing slash at the end.
295*6dbdd20aSAndroid Build Coastguard Worker std::deque<std::string> dir_queue;
296*6dbdd20aSAndroid Build Coastguard Worker dir_queue.push_back(root_dir_path);
297*6dbdd20aSAndroid Build Coastguard Worker
298*6dbdd20aSAndroid Build Coastguard Worker while (!dir_queue.empty()) {
299*6dbdd20aSAndroid Build Coastguard Worker const std::string cur_dir = std::move(dir_queue.front());
300*6dbdd20aSAndroid Build Coastguard Worker dir_queue.pop_front();
301*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
302*6dbdd20aSAndroid Build Coastguard Worker return base::ErrStatus("ListFilesRecursive not supported yet");
303*6dbdd20aSAndroid Build Coastguard Worker #elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
304*6dbdd20aSAndroid Build Coastguard Worker std::string glob_path = cur_dir + "*";
305*6dbdd20aSAndroid Build Coastguard Worker // + 1 because we also have to count the NULL terminator.
306*6dbdd20aSAndroid Build Coastguard Worker if (glob_path.length() + 1 > MAX_PATH)
307*6dbdd20aSAndroid Build Coastguard Worker return base::ErrStatus("Directory path %s is too long", dir_path.c_str());
308*6dbdd20aSAndroid Build Coastguard Worker WIN32_FIND_DATAA ffd;
309*6dbdd20aSAndroid Build Coastguard Worker
310*6dbdd20aSAndroid Build Coastguard Worker base::ScopedResource<HANDLE, CloseFindHandle, nullptr, false,
311*6dbdd20aSAndroid Build Coastguard Worker base::PlatformHandleChecker>
312*6dbdd20aSAndroid Build Coastguard Worker hFind(FindFirstFileA(glob_path.c_str(), &ffd));
313*6dbdd20aSAndroid Build Coastguard Worker if (!hFind) {
314*6dbdd20aSAndroid Build Coastguard Worker // For empty directories, there should be at least one entry '.'.
315*6dbdd20aSAndroid Build Coastguard Worker // If FindFirstFileA returns INVALID_HANDLE_VALUE, this means directory
316*6dbdd20aSAndroid Build Coastguard Worker // couldn't be accessed.
317*6dbdd20aSAndroid Build Coastguard Worker return base::ErrStatus("Failed to open directory %s", cur_dir.c_str());
318*6dbdd20aSAndroid Build Coastguard Worker }
319*6dbdd20aSAndroid Build Coastguard Worker do {
320*6dbdd20aSAndroid Build Coastguard Worker if (strcmp(ffd.cFileName, ".") == 0 || strcmp(ffd.cFileName, "..") == 0)
321*6dbdd20aSAndroid Build Coastguard Worker continue;
322*6dbdd20aSAndroid Build Coastguard Worker if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
323*6dbdd20aSAndroid Build Coastguard Worker std::string subdir_path = cur_dir + ffd.cFileName + '/';
324*6dbdd20aSAndroid Build Coastguard Worker dir_queue.push_back(subdir_path);
325*6dbdd20aSAndroid Build Coastguard Worker } else {
326*6dbdd20aSAndroid Build Coastguard Worker const std::string full_path = cur_dir + ffd.cFileName;
327*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_CHECK(full_path.length() > root_dir_path.length());
328*6dbdd20aSAndroid Build Coastguard Worker output.push_back(full_path.substr(root_dir_path.length()));
329*6dbdd20aSAndroid Build Coastguard Worker }
330*6dbdd20aSAndroid Build Coastguard Worker } while (FindNextFileA(*hFind, &ffd));
331*6dbdd20aSAndroid Build Coastguard Worker #else
332*6dbdd20aSAndroid Build Coastguard Worker ScopedDir dir = ScopedDir(opendir(cur_dir.c_str()));
333*6dbdd20aSAndroid Build Coastguard Worker if (!dir) {
334*6dbdd20aSAndroid Build Coastguard Worker return base::ErrStatus("Failed to open directory %s", cur_dir.c_str());
335*6dbdd20aSAndroid Build Coastguard Worker }
336*6dbdd20aSAndroid Build Coastguard Worker for (auto* dirent = readdir(dir.get()); dirent != nullptr;
337*6dbdd20aSAndroid Build Coastguard Worker dirent = readdir(dir.get())) {
338*6dbdd20aSAndroid Build Coastguard Worker if (strcmp(dirent->d_name, ".") == 0 ||
339*6dbdd20aSAndroid Build Coastguard Worker strcmp(dirent->d_name, "..") == 0) {
340*6dbdd20aSAndroid Build Coastguard Worker continue;
341*6dbdd20aSAndroid Build Coastguard Worker }
342*6dbdd20aSAndroid Build Coastguard Worker if (dirent->d_type == DT_DIR) {
343*6dbdd20aSAndroid Build Coastguard Worker dir_queue.push_back(cur_dir + dirent->d_name + '/');
344*6dbdd20aSAndroid Build Coastguard Worker } else if (dirent->d_type == DT_REG) {
345*6dbdd20aSAndroid Build Coastguard Worker const std::string full_path = cur_dir + dirent->d_name;
346*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_CHECK(full_path.length() > root_dir_path.length());
347*6dbdd20aSAndroid Build Coastguard Worker output.push_back(full_path.substr(root_dir_path.length()));
348*6dbdd20aSAndroid Build Coastguard Worker }
349*6dbdd20aSAndroid Build Coastguard Worker }
350*6dbdd20aSAndroid Build Coastguard Worker #endif
351*6dbdd20aSAndroid Build Coastguard Worker }
352*6dbdd20aSAndroid Build Coastguard Worker return base::OkStatus();
353*6dbdd20aSAndroid Build Coastguard Worker }
354*6dbdd20aSAndroid Build Coastguard Worker
GetFileExtension(const std::string & filename)355*6dbdd20aSAndroid Build Coastguard Worker std::string GetFileExtension(const std::string& filename) {
356*6dbdd20aSAndroid Build Coastguard Worker auto ext_idx = filename.rfind('.');
357*6dbdd20aSAndroid Build Coastguard Worker if (ext_idx == std::string::npos)
358*6dbdd20aSAndroid Build Coastguard Worker return std::string();
359*6dbdd20aSAndroid Build Coastguard Worker return filename.substr(ext_idx);
360*6dbdd20aSAndroid Build Coastguard Worker }
361*6dbdd20aSAndroid Build Coastguard Worker
SetFilePermissions(const std::string & file_path,const std::string & group_name_or_id,const std::string & mode_bits)362*6dbdd20aSAndroid Build Coastguard Worker base::Status SetFilePermissions(const std::string& file_path,
363*6dbdd20aSAndroid Build Coastguard Worker const std::string& group_name_or_id,
364*6dbdd20aSAndroid Build Coastguard Worker const std::string& mode_bits) {
365*6dbdd20aSAndroid Build Coastguard Worker #ifdef PERFETTO_SET_FILE_PERMISSIONS
366*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_CHECK(!file_path.empty());
367*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_CHECK(!group_name_or_id.empty());
368*6dbdd20aSAndroid Build Coastguard Worker
369*6dbdd20aSAndroid Build Coastguard Worker // Default |group_id| to -1 for not changing the group ownership.
370*6dbdd20aSAndroid Build Coastguard Worker gid_t group_id = static_cast<gid_t>(-1);
371*6dbdd20aSAndroid Build Coastguard Worker auto maybe_group_id = base::StringToUInt32(group_name_or_id);
372*6dbdd20aSAndroid Build Coastguard Worker if (maybe_group_id) { // A numerical group ID.
373*6dbdd20aSAndroid Build Coastguard Worker group_id = *maybe_group_id;
374*6dbdd20aSAndroid Build Coastguard Worker } else { // A group name.
375*6dbdd20aSAndroid Build Coastguard Worker struct group* file_group = nullptr;
376*6dbdd20aSAndroid Build Coastguard Worker // Query the group ID of |group|.
377*6dbdd20aSAndroid Build Coastguard Worker do {
378*6dbdd20aSAndroid Build Coastguard Worker file_group = getgrnam(group_name_or_id.c_str());
379*6dbdd20aSAndroid Build Coastguard Worker } while (file_group == nullptr && errno == EINTR);
380*6dbdd20aSAndroid Build Coastguard Worker if (file_group == nullptr) {
381*6dbdd20aSAndroid Build Coastguard Worker return base::ErrStatus("Failed to get group information of %s ",
382*6dbdd20aSAndroid Build Coastguard Worker group_name_or_id.c_str());
383*6dbdd20aSAndroid Build Coastguard Worker }
384*6dbdd20aSAndroid Build Coastguard Worker group_id = file_group->gr_gid;
385*6dbdd20aSAndroid Build Coastguard Worker }
386*6dbdd20aSAndroid Build Coastguard Worker
387*6dbdd20aSAndroid Build Coastguard Worker if (PERFETTO_EINTR(chown(file_path.c_str(), geteuid(), group_id))) {
388*6dbdd20aSAndroid Build Coastguard Worker return base::ErrStatus("Failed to chown %s ", file_path.c_str());
389*6dbdd20aSAndroid Build Coastguard Worker }
390*6dbdd20aSAndroid Build Coastguard Worker
391*6dbdd20aSAndroid Build Coastguard Worker // |mode| accepts values like "0660" as "rw-rw----" mode bits.
392*6dbdd20aSAndroid Build Coastguard Worker auto mode_value = base::StringToInt32(mode_bits, 8);
393*6dbdd20aSAndroid Build Coastguard Worker if (!(mode_bits.size() == 4 && mode_value.has_value())) {
394*6dbdd20aSAndroid Build Coastguard Worker return base::ErrStatus(
395*6dbdd20aSAndroid Build Coastguard Worker "The chmod mode bits must be a 4-digit octal number, e.g. 0660");
396*6dbdd20aSAndroid Build Coastguard Worker }
397*6dbdd20aSAndroid Build Coastguard Worker if (PERFETTO_EINTR(
398*6dbdd20aSAndroid Build Coastguard Worker chmod(file_path.c_str(), static_cast<mode_t>(mode_value.value())))) {
399*6dbdd20aSAndroid Build Coastguard Worker return base::ErrStatus("Failed to chmod %s", file_path.c_str());
400*6dbdd20aSAndroid Build Coastguard Worker }
401*6dbdd20aSAndroid Build Coastguard Worker return base::OkStatus();
402*6dbdd20aSAndroid Build Coastguard Worker #else
403*6dbdd20aSAndroid Build Coastguard Worker base::ignore_result(file_path);
404*6dbdd20aSAndroid Build Coastguard Worker base::ignore_result(group_name_or_id);
405*6dbdd20aSAndroid Build Coastguard Worker base::ignore_result(mode_bits);
406*6dbdd20aSAndroid Build Coastguard Worker return base::ErrStatus(
407*6dbdd20aSAndroid Build Coastguard Worker "Setting file permissions is not supported on this platform");
408*6dbdd20aSAndroid Build Coastguard Worker #endif
409*6dbdd20aSAndroid Build Coastguard Worker }
410*6dbdd20aSAndroid Build Coastguard Worker
GetFileSize(const std::string & file_path)411*6dbdd20aSAndroid Build Coastguard Worker std::optional<uint64_t> GetFileSize(const std::string& file_path) {
412*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
413*6dbdd20aSAndroid Build Coastguard Worker // This does not use base::OpenFile to avoid getting an exclusive lock.
414*6dbdd20aSAndroid Build Coastguard Worker base::ScopedPlatformHandle fd(
415*6dbdd20aSAndroid Build Coastguard Worker CreateFileA(file_path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr,
416*6dbdd20aSAndroid Build Coastguard Worker OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr));
417*6dbdd20aSAndroid Build Coastguard Worker #else
418*6dbdd20aSAndroid Build Coastguard Worker base::ScopedFile fd(base::OpenFile(file_path, O_RDONLY | O_CLOEXEC));
419*6dbdd20aSAndroid Build Coastguard Worker #endif
420*6dbdd20aSAndroid Build Coastguard Worker if (!fd) {
421*6dbdd20aSAndroid Build Coastguard Worker return std::nullopt;
422*6dbdd20aSAndroid Build Coastguard Worker }
423*6dbdd20aSAndroid Build Coastguard Worker return GetFileSize(*fd);
424*6dbdd20aSAndroid Build Coastguard Worker }
425*6dbdd20aSAndroid Build Coastguard Worker
GetFileSize(PlatformHandle fd)426*6dbdd20aSAndroid Build Coastguard Worker std::optional<uint64_t> GetFileSize(PlatformHandle fd) {
427*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
428*6dbdd20aSAndroid Build Coastguard Worker LARGE_INTEGER file_size;
429*6dbdd20aSAndroid Build Coastguard Worker file_size.QuadPart = 0;
430*6dbdd20aSAndroid Build Coastguard Worker if (!GetFileSizeEx(fd, &file_size)) {
431*6dbdd20aSAndroid Build Coastguard Worker return std::nullopt;
432*6dbdd20aSAndroid Build Coastguard Worker }
433*6dbdd20aSAndroid Build Coastguard Worker static_assert(sizeof(decltype(file_size.QuadPart)) <= sizeof(uint64_t));
434*6dbdd20aSAndroid Build Coastguard Worker return static_cast<uint64_t>(file_size.QuadPart);
435*6dbdd20aSAndroid Build Coastguard Worker #else
436*6dbdd20aSAndroid Build Coastguard Worker struct stat buf {};
437*6dbdd20aSAndroid Build Coastguard Worker if (fstat(fd, &buf) == -1) {
438*6dbdd20aSAndroid Build Coastguard Worker return std::nullopt;
439*6dbdd20aSAndroid Build Coastguard Worker }
440*6dbdd20aSAndroid Build Coastguard Worker static_assert(sizeof(decltype(buf.st_size)) <= sizeof(uint64_t));
441*6dbdd20aSAndroid Build Coastguard Worker return static_cast<uint64_t>(buf.st_size);
442*6dbdd20aSAndroid Build Coastguard Worker #endif
443*6dbdd20aSAndroid Build Coastguard Worker }
444*6dbdd20aSAndroid Build Coastguard Worker
445*6dbdd20aSAndroid Build Coastguard Worker } // namespace base
446*6dbdd20aSAndroid Build Coastguard Worker } // namespace perfetto
447