| 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 |