Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(576)

Side by Side Diff: base/file_util_posix.cc

Issue 93263002: Move some more file utils to the base namespace. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/file_util_mac.mm ('k') | base/file_util_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 <libgen.h> 10 #include <libgen.h>
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 return StringPrintf(".%s.XXXXXX", base::mac::BaseBundleID()); 143 return StringPrintf(".%s.XXXXXX", base::mac::BaseBundleID());
144 #endif 144 #endif
145 145
146 #if defined(GOOGLE_CHROME_BUILD) 146 #if defined(GOOGLE_CHROME_BUILD)
147 return std::string(".com.google.Chrome.XXXXXX"); 147 return std::string(".com.google.Chrome.XXXXXX");
148 #else 148 #else
149 return std::string(".org.chromium.Chromium.XXXXXX"); 149 return std::string(".org.chromium.Chromium.XXXXXX");
150 #endif 150 #endif
151 } 151 }
152 152
153 // Creates and opens a temporary file in |directory|, returning the
154 // file descriptor. |path| is set to the temporary file path.
155 // This function does NOT unlink() the file.
156 int CreateAndOpenFdForTemporaryFile(FilePath directory, FilePath* path) {
157 ThreadRestrictions::AssertIOAllowed(); // For call to mkstemp().
158 *path = directory.Append(base::TempFileName());
159 const std::string& tmpdir_string = path->value();
160 // this should be OK since mkstemp just replaces characters in place
161 char* buffer = const_cast<char*>(tmpdir_string.c_str());
162
163 return HANDLE_EINTR(mkstemp(buffer));
164 }
165
166 #if defined(OS_LINUX)
167 // Determine if /dev/shm files can be mapped and then mprotect'd PROT_EXEC.
168 // This depends on the mount options used for /dev/shm, which vary among
169 // different Linux distributions and possibly local configuration. It also
170 // depends on details of kernel--ChromeOS uses the noexec option for /dev/shm
171 // but its kernel allows mprotect with PROT_EXEC anyway.
172 bool DetermineDevShmExecutable() {
173 bool result = false;
174 FilePath path;
175 int fd = CreateAndOpenFdForTemporaryFile(FilePath("/dev/shm"), &path);
176 if (fd >= 0) {
177 file_util::ScopedFD shm_fd_closer(&fd);
178 DeleteFile(path, false);
179 long sysconf_result = sysconf(_SC_PAGESIZE);
180 CHECK_GE(sysconf_result, 0);
181 size_t pagesize = static_cast<size_t>(sysconf_result);
182 CHECK_GE(sizeof(pagesize), sizeof(sysconf_result));
183 void *mapping = mmap(NULL, pagesize, PROT_READ, MAP_SHARED, fd, 0);
184 if (mapping != MAP_FAILED) {
185 if (mprotect(mapping, pagesize, PROT_READ | PROT_EXEC) == 0)
186 result = true;
187 munmap(mapping, pagesize);
188 }
189 }
190 return result;
191 }
192 #endif // defined(OS_LINUX)
193
153 } // namespace 194 } // namespace
154 195
155 FilePath MakeAbsoluteFilePath(const FilePath& input) { 196 FilePath MakeAbsoluteFilePath(const FilePath& input) {
156 ThreadRestrictions::AssertIOAllowed(); 197 ThreadRestrictions::AssertIOAllowed();
157 char full_path[PATH_MAX]; 198 char full_path[PATH_MAX];
158 if (realpath(input.value().c_str(), full_path) == NULL) 199 if (realpath(input.value().c_str(), full_path) == NULL)
159 return FilePath(); 200 return FilePath();
160 return FilePath(full_path); 201 return FilePath(full_path);
161 } 202 }
162 203
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 // Clears the existing permission bits, and adds the new ones. 439 // Clears the existing permission bits, and adds the new ones.
399 mode_t updated_mode_bits = stat_buf.st_mode & ~FILE_PERMISSION_MASK; 440 mode_t updated_mode_bits = stat_buf.st_mode & ~FILE_PERMISSION_MASK;
400 updated_mode_bits |= mode & FILE_PERMISSION_MASK; 441 updated_mode_bits |= mode & FILE_PERMISSION_MASK;
401 442
402 if (HANDLE_EINTR(chmod(path.value().c_str(), updated_mode_bits)) != 0) 443 if (HANDLE_EINTR(chmod(path.value().c_str(), updated_mode_bits)) != 0)
403 return false; 444 return false;
404 445
405 return true; 446 return true;
406 } 447 }
407 448
449 #if !defined(OS_MACOSX)
450 // This is implemented in file_util_mac.mm for Mac.
451 bool GetTempDir(FilePath* path) {
452 const char* tmp = getenv("TMPDIR");
453 if (tmp) {
454 *path = FilePath(tmp);
455 } else {
456 #if defined(OS_ANDROID)
457 return PathService::Get(base::DIR_CACHE, path);
458 #else
459 *path = FilePath("/tmp");
460 #endif
461 }
462 return true;
463 }
464 #endif // !defined(OS_MACOSX)
465
466 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
467 // This is implemented in file_util_mac.mm and file_util_android.cc for those
468 // platforms.
469 bool GetShmemTempDir(bool executable, FilePath* path) {
470 #if defined(OS_LINUX)
471 bool use_dev_shm = true;
472 if (executable) {
473 static const bool s_dev_shm_executable = DetermineDevShmExecutable();
474 use_dev_shm = s_dev_shm_executable;
475 }
476 if (use_dev_shm) {
477 *path = FilePath("/dev/shm");
478 return true;
479 }
480 #endif
481 return GetTempDir(path);
482 }
483 #endif // !defined(OS_MACOSX) && !defined(OS_ANDROID)
484
485 #if !defined(OS_MACOSX)
486 FilePath GetHomeDir() {
487 #if defined(OS_CHROMEOS)
488 if (SysInfo::IsRunningOnChromeOS())
489 return FilePath("/home/chronos/user");
490 #endif
491
492 const char* home_dir = getenv("HOME");
493 if (home_dir && home_dir[0])
494 return FilePath(home_dir);
495
496 #if defined(OS_ANDROID)
497 DLOG(WARNING) << "OS_ANDROID: Home directory lookup not yet implemented.";
498 #elif defined(USE_GLIB) && !defined(OS_CHROMEOS)
499 // g_get_home_dir calls getpwent, which can fall through to LDAP calls.
500 ThreadRestrictions::AssertIOAllowed();
501
502 home_dir = g_get_home_dir();
503 if (home_dir && home_dir[0])
504 return FilePath(home_dir);
505 #endif
506
507 FilePath rv;
508 if (GetTempDir(&rv))
509 return rv;
510
511 // Last resort.
512 return FilePath("/tmp");
513 }
514 #endif // !defined(OS_MACOSX)
515
408 } // namespace base 516 } // namespace base
409 517
410 // ----------------------------------------------------------------------------- 518 // -----------------------------------------------------------------------------
411 519
412 namespace file_util { 520 namespace file_util {
413 521
414 using base::stat_wrapper_t; 522 using base::stat_wrapper_t;
415 using base::CallStat; 523 using base::CallStat;
416 using base::CallLstat; 524 using base::CallLstat;
525 using base::CreateAndOpenFdForTemporaryFile;
417 using base::DirectoryExists; 526 using base::DirectoryExists;
418 using base::FileEnumerator; 527 using base::FileEnumerator;
419 using base::FilePath; 528 using base::FilePath;
420 using base::MakeAbsoluteFilePath; 529 using base::MakeAbsoluteFilePath;
421 using base::RealPath; 530 using base::RealPath;
422 using base::VerifySpecificPathControlledByUser; 531 using base::VerifySpecificPathControlledByUser;
423 532
424 // Creates and opens a temporary file in |directory|, returning the
425 // file descriptor. |path| is set to the temporary file path.
426 // This function does NOT unlink() the file.
427 int CreateAndOpenFdForTemporaryFile(FilePath directory, FilePath* path) {
428 base::ThreadRestrictions::AssertIOAllowed(); // For call to mkstemp().
429 *path = directory.Append(base::TempFileName());
430 const std::string& tmpdir_string = path->value();
431 // this should be OK since mkstemp just replaces characters in place
432 char* buffer = const_cast<char*>(tmpdir_string.c_str());
433
434 return HANDLE_EINTR(mkstemp(buffer));
435 }
436
437 bool CreateTemporaryFile(FilePath* path) { 533 bool CreateTemporaryFile(FilePath* path) {
438 base::ThreadRestrictions::AssertIOAllowed(); // For call to close(). 534 base::ThreadRestrictions::AssertIOAllowed(); // For call to close().
439 FilePath directory; 535 FilePath directory;
440 if (!GetTempDir(&directory)) 536 if (!GetTempDir(&directory))
441 return false; 537 return false;
442 int fd = CreateAndOpenFdForTemporaryFile(directory, path); 538 int fd = CreateAndOpenFdForTemporaryFile(directory, path);
443 if (fd < 0) 539 if (fd < 0)
444 return false; 540 return false;
445 ignore_result(HANDLE_EINTR(close(fd))); 541 ignore_result(HANDLE_EINTR(close(fd)));
446 return true; 542 return true;
447 } 543 }
448 544
449 FILE* CreateAndOpenTemporaryShmemFile(FilePath* path, bool executable) { 545 FILE* CreateAndOpenTemporaryShmemFile(FilePath* path, bool executable) {
450 FilePath directory; 546 FilePath directory;
451 if (!GetShmemTempDir(&directory, executable)) 547 if (!GetShmemTempDir(executable, &directory))
452 return NULL; 548 return NULL;
453 549
454 return CreateAndOpenTemporaryFileInDir(directory, path); 550 return CreateAndOpenTemporaryFileInDir(directory, path);
455 } 551 }
456 552
457 FILE* CreateAndOpenTemporaryFileInDir(const FilePath& dir, FilePath* path) { 553 FILE* CreateAndOpenTemporaryFileInDir(const FilePath& dir, FilePath* path) {
458 int fd = CreateAndOpenFdForTemporaryFile(dir, path); 554 int fd = CreateAndOpenFdForTemporaryFile(dir, path);
459 if (fd < 0) 555 if (fd < 0)
460 return NULL; 556 return NULL;
461 557
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
718 // directory. 814 // directory.
719 stat_wrapper_t file_info; 815 stat_wrapper_t file_info;
720 if (CallStat(real_path_result.value().c_str(), &file_info) != 0 || 816 if (CallStat(real_path_result.value().c_str(), &file_info) != 0 ||
721 S_ISDIR(file_info.st_mode)) 817 S_ISDIR(file_info.st_mode))
722 return false; 818 return false;
723 819
724 *normalized_path = real_path_result; 820 *normalized_path = real_path_result;
725 return true; 821 return true;
726 } 822 }
727 823
728 #if !defined(OS_MACOSX)
729 bool GetTempDir(FilePath* path) {
730 const char* tmp = getenv("TMPDIR");
731 if (tmp)
732 *path = FilePath(tmp);
733 else
734 #if defined(OS_ANDROID)
735 return PathService::Get(base::DIR_CACHE, path);
736 #else
737 *path = FilePath("/tmp");
738 #endif
739 return true;
740 }
741
742 #if !defined(OS_ANDROID)
743
744 #if defined(OS_LINUX)
745 // Determine if /dev/shm files can be mapped and then mprotect'd PROT_EXEC.
746 // This depends on the mount options used for /dev/shm, which vary among
747 // different Linux distributions and possibly local configuration. It also
748 // depends on details of kernel--ChromeOS uses the noexec option for /dev/shm
749 // but its kernel allows mprotect with PROT_EXEC anyway.
750
751 namespace {
752
753 bool DetermineDevShmExecutable() {
754 bool result = false;
755 FilePath path;
756 int fd = CreateAndOpenFdForTemporaryFile(FilePath("/dev/shm"), &path);
757 if (fd >= 0) {
758 ScopedFD shm_fd_closer(&fd);
759 DeleteFile(path, false);
760 long sysconf_result = sysconf(_SC_PAGESIZE);
761 CHECK_GE(sysconf_result, 0);
762 size_t pagesize = static_cast<size_t>(sysconf_result);
763 CHECK_GE(sizeof(pagesize), sizeof(sysconf_result));
764 void *mapping = mmap(NULL, pagesize, PROT_READ, MAP_SHARED, fd, 0);
765 if (mapping != MAP_FAILED) {
766 if (mprotect(mapping, pagesize, PROT_READ | PROT_EXEC) == 0)
767 result = true;
768 munmap(mapping, pagesize);
769 }
770 }
771 return result;
772 }
773
774 }; // namespace
775 #endif // defined(OS_LINUX)
776
777 bool GetShmemTempDir(FilePath* path, bool executable) {
778 #if defined(OS_LINUX)
779 bool use_dev_shm = true;
780 if (executable) {
781 static const bool s_dev_shm_executable = DetermineDevShmExecutable();
782 use_dev_shm = s_dev_shm_executable;
783 }
784 if (use_dev_shm) {
785 *path = FilePath("/dev/shm");
786 return true;
787 }
788 #endif
789 return GetTempDir(path);
790 }
791 #endif // !defined(OS_ANDROID)
792
793 FilePath GetHomeDir() {
794 #if defined(OS_CHROMEOS)
795 if (base::SysInfo::IsRunningOnChromeOS())
796 return FilePath("/home/chronos/user");
797 #endif
798
799 const char* home_dir = getenv("HOME");
800 if (home_dir && home_dir[0])
801 return FilePath(home_dir);
802
803 #if defined(OS_ANDROID)
804 DLOG(WARNING) << "OS_ANDROID: Home directory lookup not yet implemented.";
805 #elif defined(USE_GLIB) && !defined(OS_CHROMEOS)
806 // g_get_home_dir calls getpwent, which can fall through to LDAP calls.
807 base::ThreadRestrictions::AssertIOAllowed();
808
809 home_dir = g_get_home_dir();
810 if (home_dir && home_dir[0])
811 return FilePath(home_dir);
812 #endif
813
814 FilePath rv;
815 if (file_util::GetTempDir(&rv))
816 return rv;
817
818 // Last resort.
819 return FilePath("/tmp");
820 }
821 #endif // !defined(OS_MACOSX)
822
823 bool VerifyPathControlledByUser(const FilePath& base, 824 bool VerifyPathControlledByUser(const FilePath& base,
824 const FilePath& path, 825 const FilePath& path,
825 uid_t owner_uid, 826 uid_t owner_uid,
826 const std::set<gid_t>& group_gids) { 827 const std::set<gid_t>& group_gids) {
827 if (base != path && !base.IsParent(path)) { 828 if (base != path && !base.IsParent(path)) {
828 DLOG(ERROR) << "|base| must be a subdirectory of |path|. base = \"" 829 DLOG(ERROR) << "|base| must be a subdirectory of |path|. base = \""
829 << base.value() << "\", path = \"" << path.value() << "\""; 830 << base.value() << "\", path = \"" << path.value() << "\"";
830 return false; 831 return false;
831 } 832 }
832 833
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
970 result = false; 971 result = false;
971 if (HANDLE_EINTR(close(outfile)) < 0) 972 if (HANDLE_EINTR(close(outfile)) < 0)
972 result = false; 973 result = false;
973 974
974 return result; 975 return result;
975 } 976 }
976 #endif // !defined(OS_MACOSX) 977 #endif // !defined(OS_MACOSX)
977 978
978 } // namespace internal 979 } // namespace internal
979 } // namespace base 980 } // namespace base
OLDNEW
« no previous file with comments | « base/file_util_mac.mm ('k') | base/file_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698