| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/file_util.h" | 5 #include "base/file_util.h" |
| 6 | 6 |
| 7 #include <dirent.h> | 7 #include <dirent.h> |
| 8 #include <errno.h> | 8 #include <errno.h> |
| 9 #include <fcntl.h> | 9 #include <fcntl.h> |
| 10 #include <fnmatch.h> | 10 #include <fnmatch.h> |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 88 *real_path = FilePath(buf); | 88 *real_path = FilePath(buf); |
| 89 return true; | 89 return true; |
| 90 } | 90 } |
| 91 | 91 |
| 92 // Helper for VerifyPathControlledByUser. | 92 // Helper for VerifyPathControlledByUser. |
| 93 bool VerifySpecificPathControlledByUser(const FilePath& path, | 93 bool VerifySpecificPathControlledByUser(const FilePath& path, |
| 94 uid_t owner_uid, | 94 uid_t owner_uid, |
| 95 const std::set<gid_t>& group_gids) { | 95 const std::set<gid_t>& group_gids) { |
| 96 stat_wrapper_t stat_info; | 96 stat_wrapper_t stat_info; |
| 97 if (CallLstat(path.value().c_str(), &stat_info) != 0) { | 97 if (CallLstat(path.value().c_str(), &stat_info) != 0) { |
| 98 PLOG(ERROR) << "Failed to get information on path " | 98 DPLOG(ERROR) << "Failed to get information on path " |
| 99 << path.value(); | 99 << path.value(); |
| 100 return false; | 100 return false; |
| 101 } | 101 } |
| 102 | 102 |
| 103 if (S_ISLNK(stat_info.st_mode)) { | 103 if (S_ISLNK(stat_info.st_mode)) { |
| 104 LOG(ERROR) << "Path " << path.value() | 104 DLOG(ERROR) << "Path " << path.value() |
| 105 << " is a symbolic link."; | 105 << " is a symbolic link."; |
| 106 return false; | 106 return false; |
| 107 } | 107 } |
| 108 | 108 |
| 109 if (stat_info.st_uid != owner_uid) { | 109 if (stat_info.st_uid != owner_uid) { |
| 110 LOG(ERROR) << "Path " << path.value() | 110 DLOG(ERROR) << "Path " << path.value() |
| 111 << " is owned by the wrong user."; | 111 << " is owned by the wrong user."; |
| 112 return false; | 112 return false; |
| 113 } | 113 } |
| 114 | 114 |
| 115 if ((stat_info.st_mode & S_IWGRP) && | 115 if ((stat_info.st_mode & S_IWGRP) && |
| 116 !ContainsKey(group_gids, stat_info.st_gid)) { | 116 !ContainsKey(group_gids, stat_info.st_gid)) { |
| 117 LOG(ERROR) << "Path " << path.value() | 117 DLOG(ERROR) << "Path " << path.value() |
| 118 << " is writable by an unprivileged group."; | 118 << " is writable by an unprivileged group."; |
| 119 return false; | 119 return false; |
| 120 } | 120 } |
| 121 | 121 |
| 122 if (stat_info.st_mode & S_IWOTH) { | 122 if (stat_info.st_mode & S_IWOTH) { |
| 123 LOG(ERROR) << "Path " << path.value() | 123 DLOG(ERROR) << "Path " << path.value() |
| 124 << " is writable by any user."; | 124 << " is writable by any user."; |
| 125 return false; | 125 return false; |
| 126 } | 126 } |
| 127 | 127 |
| 128 return true; | 128 return true; |
| 129 } | 129 } |
| 130 | 130 |
| 131 } // namespace | 131 } // namespace |
| 132 | 132 |
| 133 static std::string TempFileName() { | 133 static std::string TempFileName() { |
| 134 #if defined(OS_MACOSX) | 134 #if defined(OS_MACOSX) |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 struct dirent ent_buf; | 166 struct dirent ent_buf; |
| 167 struct dirent* ent; | 167 struct dirent* ent; |
| 168 while (readdir_r(dir, &ent_buf, &ent) == 0 && ent) { | 168 while (readdir_r(dir, &ent_buf, &ent) == 0 && ent) { |
| 169 if ((strcmp(ent->d_name, ".") == 0) || | 169 if ((strcmp(ent->d_name, ".") == 0) || |
| 170 (strcmp(ent->d_name, "..") == 0)) | 170 (strcmp(ent->d_name, "..") == 0)) |
| 171 continue; | 171 continue; |
| 172 | 172 |
| 173 stat_wrapper_t st; | 173 stat_wrapper_t st; |
| 174 int test = CallStat(path.Append(ent->d_name).value().c_str(), &st); | 174 int test = CallStat(path.Append(ent->d_name).value().c_str(), &st); |
| 175 if (test != 0) { | 175 if (test != 0) { |
| 176 PLOG(ERROR) << "stat64 failed"; | 176 DPLOG(ERROR) << "stat64 failed"; |
| 177 continue; | 177 continue; |
| 178 } | 178 } |
| 179 // Here, we use Time::TimeT(), which discards microseconds. This | 179 // Here, we use Time::TimeT(), which discards microseconds. This |
| 180 // means that files which are newer than |comparison_time| may | 180 // means that files which are newer than |comparison_time| may |
| 181 // be considered older. If we don't discard microseconds, it | 181 // be considered older. If we don't discard microseconds, it |
| 182 // introduces another issue. Suppose the following case: | 182 // introduces another issue. Suppose the following case: |
| 183 // | 183 // |
| 184 // 1. Get |comparison_time| by Time::Now() and the value is 10.1 (secs). | 184 // 1. Get |comparison_time| by Time::Now() and the value is 10.1 (secs). |
| 185 // 2. Create a file and the current time is 10.3 (secs). | 185 // 2. Create a file and the current time is 10.3 (secs). |
| 186 // | 186 // |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 315 if (recursive) | 315 if (recursive) |
| 316 traverse_type = static_cast<FileEnumerator::FileType>( | 316 traverse_type = static_cast<FileEnumerator::FileType>( |
| 317 traverse_type | FileEnumerator::DIRECTORIES); | 317 traverse_type | FileEnumerator::DIRECTORIES); |
| 318 FileEnumerator traversal(from_path, recursive, traverse_type); | 318 FileEnumerator traversal(from_path, recursive, traverse_type); |
| 319 | 319 |
| 320 // We have to mimic windows behavior here. |to_path| may not exist yet, | 320 // We have to mimic windows behavior here. |to_path| may not exist yet, |
| 321 // start the loop with |to_path|. | 321 // start the loop with |to_path|. |
| 322 FileEnumerator::FindInfo info; | 322 FileEnumerator::FindInfo info; |
| 323 FilePath current = from_path; | 323 FilePath current = from_path; |
| 324 if (stat(from_path.value().c_str(), &info.stat) < 0) { | 324 if (stat(from_path.value().c_str(), &info.stat) < 0) { |
| 325 LOG(ERROR) << "CopyDirectory() couldn't stat source directory: " << | 325 DLOG(ERROR) << "CopyDirectory() couldn't stat source directory: " |
| 326 from_path.value() << " errno = " << errno; | 326 << from_path.value() << " errno = " << errno; |
| 327 success = false; | 327 success = false; |
| 328 } | 328 } |
| 329 struct stat to_path_stat; | 329 struct stat to_path_stat; |
| 330 FilePath from_path_base = from_path; | 330 FilePath from_path_base = from_path; |
| 331 if (recursive && stat(to_path.value().c_str(), &to_path_stat) == 0 && | 331 if (recursive && stat(to_path.value().c_str(), &to_path_stat) == 0 && |
| 332 S_ISDIR(to_path_stat.st_mode)) { | 332 S_ISDIR(to_path_stat.st_mode)) { |
| 333 // If the destination already exists and is a directory, then the | 333 // If the destination already exists and is a directory, then the |
| 334 // top level of source needs to be copied. | 334 // top level of source needs to be copied. |
| 335 from_path_base = from_path.DirName(); | 335 from_path_base = from_path.DirName(); |
| 336 } | 336 } |
| 337 | 337 |
| 338 // The Windows version of this function assumes that non-recursive calls | 338 // The Windows version of this function assumes that non-recursive calls |
| 339 // will always have a directory for from_path. | 339 // will always have a directory for from_path. |
| 340 DCHECK(recursive || S_ISDIR(info.stat.st_mode)); | 340 DCHECK(recursive || S_ISDIR(info.stat.st_mode)); |
| 341 | 341 |
| 342 while (success && !current.empty()) { | 342 while (success && !current.empty()) { |
| 343 // current is the source path, including from_path, so paste | 343 // current is the source path, including from_path, so paste |
| 344 // the suffix after from_path onto to_path to create the target_path. | 344 // the suffix after from_path onto to_path to create the target_path. |
| 345 std::string suffix(¤t.value().c_str()[from_path_base.value().size()]); | 345 std::string suffix(¤t.value().c_str()[from_path_base.value().size()]); |
| 346 // Strip the leading '/' (if any). | 346 // Strip the leading '/' (if any). |
| 347 if (!suffix.empty()) { | 347 if (!suffix.empty()) { |
| 348 DCHECK_EQ('/', suffix[0]); | 348 DCHECK_EQ('/', suffix[0]); |
| 349 suffix.erase(0, 1); | 349 suffix.erase(0, 1); |
| 350 } | 350 } |
| 351 const FilePath target_path = to_path.Append(suffix); | 351 const FilePath target_path = to_path.Append(suffix); |
| 352 | 352 |
| 353 if (S_ISDIR(info.stat.st_mode)) { | 353 if (S_ISDIR(info.stat.st_mode)) { |
| 354 if (mkdir(target_path.value().c_str(), info.stat.st_mode & 01777) != 0 && | 354 if (mkdir(target_path.value().c_str(), info.stat.st_mode & 01777) != 0 && |
| 355 errno != EEXIST) { | 355 errno != EEXIST) { |
| 356 LOG(ERROR) << "CopyDirectory() couldn't create directory: " << | 356 DLOG(ERROR) << "CopyDirectory() couldn't create directory: " |
| 357 target_path.value() << " errno = " << errno; | 357 << target_path.value() << " errno = " << errno; |
| 358 success = false; | 358 success = false; |
| 359 } | 359 } |
| 360 } else if (S_ISREG(info.stat.st_mode)) { | 360 } else if (S_ISREG(info.stat.st_mode)) { |
| 361 if (!CopyFile(current, target_path)) { | 361 if (!CopyFile(current, target_path)) { |
| 362 LOG(ERROR) << "CopyDirectory() couldn't create file: " << | 362 DLOG(ERROR) << "CopyDirectory() couldn't create file: " |
| 363 target_path.value(); | 363 << target_path.value(); |
| 364 success = false; | 364 success = false; |
| 365 } | 365 } |
| 366 } else { | 366 } else { |
| 367 LOG(WARNING) << "CopyDirectory() skipping non-regular file: " << | 367 DLOG(WARNING) << "CopyDirectory() skipping non-regular file: " |
| 368 current.value(); | 368 << current.value(); |
| 369 } | 369 } |
| 370 | 370 |
| 371 current = traversal.Next(); | 371 current = traversal.Next(); |
| 372 traversal.GetFindInfo(&info); | 372 traversal.GetFindInfo(&info); |
| 373 } | 373 } |
| 374 | 374 |
| 375 return success; | 375 return success; |
| 376 } | 376 } |
| 377 | 377 |
| 378 bool PathExists(const FilePath& path) { | 378 bool PathExists(const FilePath& path) { |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 504 bool CreateTemporaryFileInDir(const FilePath& dir, FilePath* temp_file) { | 504 bool CreateTemporaryFileInDir(const FilePath& dir, FilePath* temp_file) { |
| 505 base::ThreadRestrictions::AssertIOAllowed(); // For call to close(). | 505 base::ThreadRestrictions::AssertIOAllowed(); // For call to close(). |
| 506 int fd = CreateAndOpenFdForTemporaryFile(dir, temp_file); | 506 int fd = CreateAndOpenFdForTemporaryFile(dir, temp_file); |
| 507 return ((fd >= 0) && !HANDLE_EINTR(close(fd))); | 507 return ((fd >= 0) && !HANDLE_EINTR(close(fd))); |
| 508 } | 508 } |
| 509 | 509 |
| 510 static bool CreateTemporaryDirInDirImpl(const FilePath& base_dir, | 510 static bool CreateTemporaryDirInDirImpl(const FilePath& base_dir, |
| 511 const FilePath::StringType& name_tmpl, | 511 const FilePath::StringType& name_tmpl, |
| 512 FilePath* new_dir) { | 512 FilePath* new_dir) { |
| 513 base::ThreadRestrictions::AssertIOAllowed(); // For call to mkdtemp(). | 513 base::ThreadRestrictions::AssertIOAllowed(); // For call to mkdtemp(). |
| 514 CHECK(name_tmpl.find("XXXXXX") != FilePath::StringType::npos) | 514 DCHECK(name_tmpl.find("XXXXXX") != FilePath::StringType::npos) |
| 515 << "Directory name template must contain \"XXXXXX\"."; | 515 << "Directory name template must contain \"XXXXXX\"."; |
| 516 | 516 |
| 517 FilePath sub_dir = base_dir.Append(name_tmpl); | 517 FilePath sub_dir = base_dir.Append(name_tmpl); |
| 518 std::string sub_dir_string = sub_dir.value(); | 518 std::string sub_dir_string = sub_dir.value(); |
| 519 | 519 |
| 520 // this should be OK since mkdtemp just replaces characters in place | 520 // this should be OK since mkdtemp just replaces characters in place |
| 521 char* buffer = const_cast<char*>(sub_dir_string.c_str()); | 521 char* buffer = const_cast<char*>(sub_dir_string.c_str()); |
| 522 char* dtemp = mkdtemp(buffer); | 522 char* dtemp = mkdtemp(buffer); |
| 523 if (!dtemp) { | 523 if (!dtemp) { |
| 524 DPLOG(ERROR) << "mkdtemp"; | 524 DPLOG(ERROR) << "mkdtemp"; |
| 525 return false; | 525 return false; |
| (...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 816 FilePath full_name = source.Append(dent->d_name); | 816 FilePath full_name = source.Append(dent->d_name); |
| 817 int ret; | 817 int ret; |
| 818 if (show_links) | 818 if (show_links) |
| 819 ret = lstat(full_name.value().c_str(), &info.stat); | 819 ret = lstat(full_name.value().c_str(), &info.stat); |
| 820 else | 820 else |
| 821 ret = stat(full_name.value().c_str(), &info.stat); | 821 ret = stat(full_name.value().c_str(), &info.stat); |
| 822 if (ret < 0) { | 822 if (ret < 0) { |
| 823 // Print the stat() error message unless it was ENOENT and we're | 823 // Print the stat() error message unless it was ENOENT and we're |
| 824 // following symlinks. | 824 // following symlinks. |
| 825 if (!(errno == ENOENT && !show_links)) { | 825 if (!(errno == ENOENT && !show_links)) { |
| 826 PLOG(ERROR) << "Couldn't stat " | 826 DPLOG(ERROR) << "Couldn't stat " |
| 827 << source.Append(dent->d_name).value(); | 827 << source.Append(dent->d_name).value(); |
| 828 } | 828 } |
| 829 memset(&info.stat, 0, sizeof(info.stat)); | 829 memset(&info.stat, 0, sizeof(info.stat)); |
| 830 } | 830 } |
| 831 entries->push_back(info); | 831 entries->push_back(info); |
| 832 } | 832 } |
| 833 | 833 |
| 834 closedir(dir); | 834 closedir(dir); |
| 835 return true; | 835 return true; |
| 836 } | 836 } |
| 837 | 837 |
| 838 /////////////////////////////////////////////// | 838 /////////////////////////////////////////////// |
| 839 // MemoryMappedFile | 839 // MemoryMappedFile |
| 840 | 840 |
| 841 MemoryMappedFile::MemoryMappedFile() | 841 MemoryMappedFile::MemoryMappedFile() |
| 842 : file_(base::kInvalidPlatformFileValue), | 842 : file_(base::kInvalidPlatformFileValue), |
| 843 data_(NULL), | 843 data_(NULL), |
| 844 length_(0) { | 844 length_(0) { |
| 845 } | 845 } |
| 846 | 846 |
| 847 bool MemoryMappedFile::MapFileToMemoryInternal() { | 847 bool MemoryMappedFile::MapFileToMemoryInternal() { |
| 848 base::ThreadRestrictions::AssertIOAllowed(); | 848 base::ThreadRestrictions::AssertIOAllowed(); |
| 849 | 849 |
| 850 struct stat file_stat; | 850 struct stat file_stat; |
| 851 if (fstat(file_, &file_stat) == base::kInvalidPlatformFileValue) { | 851 if (fstat(file_, &file_stat) == base::kInvalidPlatformFileValue) { |
| 852 LOG(ERROR) << "Couldn't fstat " << file_ << ", errno " << errno; | 852 DLOG(ERROR) << "Couldn't fstat " << file_ << ", errno " << errno; |
| 853 return false; | 853 return false; |
| 854 } | 854 } |
| 855 length_ = file_stat.st_size; | 855 length_ = file_stat.st_size; |
| 856 | 856 |
| 857 data_ = static_cast<uint8*>( | 857 data_ = static_cast<uint8*>( |
| 858 mmap(NULL, length_, PROT_READ, MAP_SHARED, file_, 0)); | 858 mmap(NULL, length_, PROT_READ, MAP_SHARED, file_, 0)); |
| 859 if (data_ == MAP_FAILED) | 859 if (data_ == MAP_FAILED) |
| 860 LOG(ERROR) << "Couldn't mmap " << file_ << ", errno " << errno; | 860 DLOG(ERROR) << "Couldn't mmap " << file_ << ", errno " << errno; |
| 861 | 861 |
| 862 return data_ != MAP_FAILED; | 862 return data_ != MAP_FAILED; |
| 863 } | 863 } |
| 864 | 864 |
| 865 void MemoryMappedFile::CloseHandles() { | 865 void MemoryMappedFile::CloseHandles() { |
| 866 base::ThreadRestrictions::AssertIOAllowed(); | 866 base::ThreadRestrictions::AssertIOAllowed(); |
| 867 | 867 |
| 868 if (data_ != NULL) | 868 if (data_ != NULL) |
| 869 munmap(data_, length_); | 869 munmap(data_, length_); |
| 870 if (file_ != base::kInvalidPlatformFileValue) | 870 if (file_ != base::kInvalidPlatformFileValue) |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 916 return true; | 916 return true; |
| 917 } | 917 } |
| 918 #endif | 918 #endif |
| 919 | 919 |
| 920 FilePath GetHomeDir() { | 920 FilePath GetHomeDir() { |
| 921 const char* home_dir = getenv("HOME"); | 921 const char* home_dir = getenv("HOME"); |
| 922 if (home_dir && home_dir[0]) | 922 if (home_dir && home_dir[0]) |
| 923 return FilePath(home_dir); | 923 return FilePath(home_dir); |
| 924 | 924 |
| 925 #if defined(OS_ANDROID) | 925 #if defined(OS_ANDROID) |
| 926 LOG(WARNING) << "OS_ANDROID: Home directory lookup not yet implemented."; | 926 DLOG(WARNING) << "OS_ANDROID: Home directory lookup not yet implemented."; |
| 927 #else | 927 #else |
| 928 // g_get_home_dir calls getpwent, which can fall through to LDAP calls. | 928 // g_get_home_dir calls getpwent, which can fall through to LDAP calls. |
| 929 base::ThreadRestrictions::AssertIOAllowed(); | 929 base::ThreadRestrictions::AssertIOAllowed(); |
| 930 | 930 |
| 931 home_dir = g_get_home_dir(); | 931 home_dir = g_get_home_dir(); |
| 932 if (home_dir && home_dir[0]) | 932 if (home_dir && home_dir[0]) |
| 933 return FilePath(home_dir); | 933 return FilePath(home_dir); |
| 934 #endif | 934 #endif |
| 935 | 935 |
| 936 FilePath rv; | 936 FilePath rv; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 987 | 987 |
| 988 return result; | 988 return result; |
| 989 } | 989 } |
| 990 #endif // defined(OS_MACOSX) | 990 #endif // defined(OS_MACOSX) |
| 991 | 991 |
| 992 bool VerifyPathControlledByUser(const FilePath& base, | 992 bool VerifyPathControlledByUser(const FilePath& base, |
| 993 const FilePath& path, | 993 const FilePath& path, |
| 994 uid_t owner_uid, | 994 uid_t owner_uid, |
| 995 const std::set<gid_t>& group_gids) { | 995 const std::set<gid_t>& group_gids) { |
| 996 if (base != path && !base.IsParent(path)) { | 996 if (base != path && !base.IsParent(path)) { |
| 997 LOG(ERROR) << "|base| must be a subdirectory of |path|. base = \"" | 997 DLOG(ERROR) << "|base| must be a subdirectory of |path|. base = \"" |
| 998 << base.value() << "\", path = \"" << path.value() << "\""; | 998 << base.value() << "\", path = \"" << path.value() << "\""; |
| 999 return false; | 999 return false; |
| 1000 } | 1000 } |
| 1001 | 1001 |
| 1002 std::vector<FilePath::StringType> base_components; | 1002 std::vector<FilePath::StringType> base_components; |
| 1003 std::vector<FilePath::StringType> path_components; | 1003 std::vector<FilePath::StringType> path_components; |
| 1004 | 1004 |
| 1005 base.GetComponents(&base_components); | 1005 base.GetComponents(&base_components); |
| 1006 path.GetComponents(&path_components); | 1006 path.GetComponents(&path_components); |
| 1007 | 1007 |
| 1008 std::vector<FilePath::StringType>::const_iterator ib, ip; | 1008 std::vector<FilePath::StringType>::const_iterator ib, ip; |
| 1009 for (ib = base_components.begin(), ip = path_components.begin(); | 1009 for (ib = base_components.begin(), ip = path_components.begin(); |
| 1010 ib != base_components.end(); ++ib, ++ip) { | 1010 ib != base_components.end(); ++ib, ++ip) { |
| 1011 // |base| must be a subpath of |path|, so all components should match. | 1011 // |base| must be a subpath of |path|, so all components should match. |
| 1012 // If these CHECKs fail, look at the test that base is a parent of | 1012 // If these CHECKs fail, look at the test that base is a parent of |
| 1013 // path at the top of this function. | 1013 // path at the top of this function. |
| 1014 CHECK(ip != path_components.end()); | 1014 DCHECK(ip != path_components.end()); |
| 1015 CHECK(*ip == *ib); | 1015 DCHECK(*ip == *ib); |
| 1016 } | 1016 } |
| 1017 | 1017 |
| 1018 FilePath current_path = base; | 1018 FilePath current_path = base; |
| 1019 if (!VerifySpecificPathControlledByUser(current_path, owner_uid, group_gids)) | 1019 if (!VerifySpecificPathControlledByUser(current_path, owner_uid, group_gids)) |
| 1020 return false; | 1020 return false; |
| 1021 | 1021 |
| 1022 for (; ip != path_components.end(); ++ip) { | 1022 for (; ip != path_components.end(); ++ip) { |
| 1023 current_path = current_path.Append(*ip); | 1023 current_path = current_path.Append(*ip); |
| 1024 if (!VerifySpecificPathControlledByUser( | 1024 if (!VerifySpecificPathControlledByUser( |
| 1025 current_path, owner_uid, group_gids)) | 1025 current_path, owner_uid, group_gids)) |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1039 "wheel" | 1039 "wheel" |
| 1040 }; | 1040 }; |
| 1041 | 1041 |
| 1042 // Reading the groups database may touch the file system. | 1042 // Reading the groups database may touch the file system. |
| 1043 base::ThreadRestrictions::AssertIOAllowed(); | 1043 base::ThreadRestrictions::AssertIOAllowed(); |
| 1044 | 1044 |
| 1045 std::set<gid_t> allowed_group_ids; | 1045 std::set<gid_t> allowed_group_ids; |
| 1046 for (int i = 0, ie = arraysize(kAdminGroupNames); i < ie; ++i) { | 1046 for (int i = 0, ie = arraysize(kAdminGroupNames); i < ie; ++i) { |
| 1047 struct group *group_record = getgrnam(kAdminGroupNames[i]); | 1047 struct group *group_record = getgrnam(kAdminGroupNames[i]); |
| 1048 if (!group_record) { | 1048 if (!group_record) { |
| 1049 PLOG(ERROR) << "Could not get the group ID of group \"" | 1049 DPLOG(ERROR) << "Could not get the group ID of group \"" |
| 1050 << kAdminGroupNames[i] << "\"."; | 1050 << kAdminGroupNames[i] << "\"."; |
| 1051 continue; | 1051 continue; |
| 1052 } | 1052 } |
| 1053 | 1053 |
| 1054 allowed_group_ids.insert(group_record->gr_gid); | 1054 allowed_group_ids.insert(group_record->gr_gid); |
| 1055 } | 1055 } |
| 1056 | 1056 |
| 1057 return VerifyPathControlledByUser( | 1057 return VerifyPathControlledByUser( |
| 1058 kFileSystemRoot, path, kRootUid, allowed_group_ids); | 1058 kFileSystemRoot, path, kRootUid, allowed_group_ids); |
| 1059 } | 1059 } |
| 1060 #endif // defined(OS_MACOSX) | 1060 #endif // defined(OS_MACOSX) |
| 1061 | 1061 |
| 1062 } // namespace file_util | 1062 } // namespace file_util |
| OLD | NEW |