OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #include "webrtc/base/unixfilesystem.h" | |
12 | |
13 #include <errno.h> | |
14 #include <fcntl.h> | |
15 #include <stdlib.h> | |
16 #include <sys/stat.h> | |
17 #include <unistd.h> | |
18 | |
19 #if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) | |
20 #include <CoreServices/CoreServices.h> | |
21 #include <IOKit/IOCFBundle.h> | |
22 #include <sys/statvfs.h> | |
23 #include "webrtc/base/macutils.h" | |
24 #endif // WEBRTC_MAC && !defined(WEBRTC_IOS) | |
25 | |
26 #if defined(WEBRTC_POSIX) && !defined(WEBRTC_MAC) || defined(WEBRTC_IOS) | |
27 #include <sys/types.h> | |
28 #if defined(WEBRTC_ANDROID) | |
29 #include <sys/statfs.h> | |
30 #elif !defined(__native_client__) | |
31 #include <sys/statvfs.h> | |
32 #endif // !defined(__native_client__) | |
33 #include <limits.h> | |
34 #include <pwd.h> | |
35 #include <stdio.h> | |
36 #endif // WEBRTC_POSIX && !WEBRTC_MAC || WEBRTC_IOS | |
37 | |
38 #if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID) | |
39 #include <ctype.h> | |
40 #include <algorithm> | |
41 #endif | |
42 | |
43 #if defined(__native_client__) && !defined(__GLIBC__) | |
44 #include <sys/syslimits.h> | |
45 #endif | |
46 | |
47 #include "webrtc/base/arraysize.h" | |
48 #include "webrtc/base/checks.h" | |
49 #include "webrtc/base/fileutils.h" | |
50 #include "webrtc/base/pathutils.h" | |
51 #include "webrtc/base/stream.h" | |
52 #include "webrtc/base/stringutils.h" | |
53 | |
54 #if defined(WEBRTC_MAC) | |
55 // Defined in applefilesystem.mm. No header file to discourage use | |
56 // elsewhere; other places should use GetApp{Data,Temp}Folder() in | |
57 // this file. Don't copy/paste. I mean it. | |
58 char* AppleDataDirectory(); | |
59 char* AppleTempDirectory(); | |
60 void AppleAppName(rtc::Pathname* path); | |
61 #endif | |
62 | |
63 namespace rtc { | |
64 | |
65 #if !defined(WEBRTC_ANDROID) && !defined(WEBRTC_MAC) | |
66 char* UnixFilesystem::app_temp_path_ = nullptr; | |
67 #else | |
68 char* UnixFilesystem::provided_app_data_folder_ = nullptr; | |
69 char* UnixFilesystem::provided_app_temp_folder_ = nullptr; | |
70 | |
71 void UnixFilesystem::SetAppDataFolder(const std::string& folder) { | |
72 delete [] provided_app_data_folder_; | |
73 provided_app_data_folder_ = CopyString(folder); | |
74 } | |
75 | |
76 void UnixFilesystem::SetAppTempFolder(const std::string& folder) { | |
77 delete [] provided_app_temp_folder_; | |
78 provided_app_temp_folder_ = CopyString(folder); | |
79 } | |
80 #endif | |
81 | |
82 UnixFilesystem::UnixFilesystem() { | |
83 #if defined(WEBRTC_MAC) | |
84 if (!provided_app_data_folder_) | |
85 provided_app_data_folder_ = AppleDataDirectory(); | |
86 if (!provided_app_temp_folder_) | |
87 provided_app_temp_folder_ = AppleTempDirectory(); | |
88 #endif | |
89 } | |
90 | |
91 UnixFilesystem::~UnixFilesystem() {} | |
92 | |
93 bool UnixFilesystem::CreateFolder(const Pathname &path, mode_t mode) { | |
94 std::string pathname(path.pathname()); | |
95 int len = pathname.length(); | |
96 if ((len == 0) || (pathname[len - 1] != '/')) | |
97 return false; | |
98 | |
99 struct stat st; | |
100 int res = ::stat(pathname.c_str(), &st); | |
101 if (res == 0) { | |
102 // Something exists at this location, check if it is a directory | |
103 return S_ISDIR(st.st_mode) != 0; | |
104 } else if (errno != ENOENT) { | |
105 // Unexpected error | |
106 return false; | |
107 } | |
108 | |
109 // Directory doesn't exist, look up one directory level | |
110 do { | |
111 --len; | |
112 } while ((len > 0) && (pathname[len - 1] != '/')); | |
113 | |
114 if (!CreateFolder(Pathname(pathname.substr(0, len)), mode)) { | |
115 return false; | |
116 } | |
117 | |
118 LOG(LS_INFO) << "Creating folder: " << pathname; | |
119 return (0 == ::mkdir(pathname.c_str(), mode)); | |
120 } | |
121 | |
122 bool UnixFilesystem::CreateFolder(const Pathname &path) { | |
123 return CreateFolder(path, 0755); | |
124 } | |
125 | |
126 bool UnixFilesystem::DeleteFile(const Pathname &filename) { | |
127 LOG(LS_INFO) << "Deleting file:" << filename.pathname(); | |
128 | |
129 if (!IsFile(filename)) { | |
130 RTC_DCHECK(IsFile(filename)); | |
131 return false; | |
132 } | |
133 return ::unlink(filename.pathname().c_str()) == 0; | |
134 } | |
135 | |
136 bool UnixFilesystem::GetTemporaryFolder(Pathname &pathname, bool create, | |
137 const std::string *append) { | |
138 #if defined(WEBRTC_ANDROID) || defined(WEBRTC_MAC) | |
139 RTC_DCHECK(provided_app_temp_folder_ != nullptr); | |
140 pathname.SetPathname(provided_app_temp_folder_, ""); | |
141 #else | |
142 if (const char* tmpdir = getenv("TMPDIR")) { | |
143 pathname.SetPathname(tmpdir, ""); | |
144 } else if (const char* tmp = getenv("TMP")) { | |
145 pathname.SetPathname(tmp, ""); | |
146 } else { | |
147 #ifdef P_tmpdir | |
148 pathname.SetPathname(P_tmpdir, ""); | |
149 #else // !P_tmpdir | |
150 pathname.SetPathname("/tmp/", ""); | |
151 #endif // !P_tmpdir | |
152 } | |
153 #endif // defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS) | |
154 if (append) { | |
155 RTC_DCHECK(!append->empty()); | |
156 pathname.AppendFolder(*append); | |
157 } | |
158 return !create || CreateFolder(pathname); | |
159 } | |
160 | |
161 std::string UnixFilesystem::TempFilename(const Pathname &dir, | |
162 const std::string &prefix) { | |
163 int len = dir.pathname().size() + prefix.size() + 2 + 6; | |
164 char *tempname = new char[len]; | |
165 | |
166 snprintf(tempname, len, "%s/%sXXXXXX", dir.pathname().c_str(), | |
167 prefix.c_str()); | |
168 int fd = ::mkstemp(tempname); | |
169 if (fd != -1) | |
170 ::close(fd); | |
171 std::string ret(tempname); | |
172 delete[] tempname; | |
173 | |
174 return ret; | |
175 } | |
176 | |
177 bool UnixFilesystem::MoveFile(const Pathname &old_path, | |
178 const Pathname &new_path) { | |
179 if (!IsFile(old_path)) { | |
180 RTC_DCHECK(IsFile(old_path)); | |
181 return false; | |
182 } | |
183 LOG(LS_VERBOSE) << "Moving " << old_path.pathname() | |
184 << " to " << new_path.pathname(); | |
185 if (rename(old_path.pathname().c_str(), new_path.pathname().c_str()) != 0) { | |
186 return false; | |
187 } | |
188 return true; | |
189 } | |
190 | |
191 bool UnixFilesystem::IsFolder(const Pathname &path) { | |
192 struct stat st; | |
193 if (stat(path.pathname().c_str(), &st) < 0) | |
194 return false; | |
195 return S_ISDIR(st.st_mode); | |
196 } | |
197 | |
198 bool UnixFilesystem::IsFile(const Pathname& pathname) { | |
199 struct stat st; | |
200 int res = ::stat(pathname.pathname().c_str(), &st); | |
201 // Treat symlinks, named pipes, etc. all as files. | |
202 return res == 0 && !S_ISDIR(st.st_mode); | |
203 } | |
204 | |
205 bool UnixFilesystem::IsAbsent(const Pathname& pathname) { | |
206 struct stat st; | |
207 int res = ::stat(pathname.pathname().c_str(), &st); | |
208 // Note: we specifically maintain ENOTDIR as an error, because that implies | |
209 // that you could not call CreateFolder(pathname). | |
210 return res != 0 && ENOENT == errno; | |
211 } | |
212 | |
213 bool UnixFilesystem::GetFileSize(const Pathname& pathname, size_t *size) { | |
214 struct stat st; | |
215 if (::stat(pathname.pathname().c_str(), &st) != 0) | |
216 return false; | |
217 *size = st.st_size; | |
218 return true; | |
219 } | |
220 | |
221 char* UnixFilesystem::CopyString(const std::string& str) { | |
222 size_t size = str.length() + 1; | |
223 | |
224 char* buf = new char[size]; | |
225 if (!buf) { | |
226 return nullptr; | |
227 } | |
228 | |
229 strcpyn(buf, size, str.c_str()); | |
230 return buf; | |
231 } | |
232 | |
233 } // namespace rtc | |
234 | |
235 #if defined(__native_client__) | |
236 extern "C" int __attribute__((weak)) | |
237 link(const char* oldpath, const char* newpath) { | |
238 errno = EACCES; | |
239 return -1; | |
240 } | |
241 #endif | |
OLD | NEW |