#include "base/basictypes.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
+#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
namespace {
-#if defined(OS_BSD) || defined(OS_MACOSX)
-typedef struct stat stat_wrapper_t;
+#if defined(OS_BSD) || defined(OS_MACOSX) || defined(OS_NACL)
static int CallStat(const char *path, stat_wrapper_t *sb) {
ThreadRestrictions::AssertIOAllowed();
return stat(path, sb);
ThreadRestrictions::AssertIOAllowed();
return lstat(path, sb);
}
-#else
-typedef struct stat64 stat_wrapper_t;
+#else // defined(OS_BSD) || defined(OS_MACOSX) || defined(OS_NACL)
static int CallStat(const char *path, stat_wrapper_t *sb) {
ThreadRestrictions::AssertIOAllowed();
return stat64(path, sb);
ThreadRestrictions::AssertIOAllowed();
return lstat64(path, sb);
}
-#if defined(OS_ANDROID)
-static int CallFstat(int fd, stat_wrapper_t *sb) {
- ThreadRestrictions::AssertIOAllowed();
- return fstat64(fd, sb);
-}
-#endif
-#endif
+#endif // !(defined(OS_BSD) || defined(OS_MACOSX) || defined(OS_NACL))
// Helper for NormalizeFilePath(), defined below.
bool RealPath(const FilePath& path, FilePath* real_path) {
bool DetermineDevShmExecutable() {
bool result = false;
FilePath path;
- int fd = CreateAndOpenFdForTemporaryFile(FilePath("/dev/shm"), &path);
- if (fd >= 0) {
- file_util::ScopedFD shm_fd_closer(&fd);
+
+ ScopedFD fd(CreateAndOpenFdForTemporaryFile(FilePath("/dev/shm"), &path));
+ if (fd.is_valid()) {
DeleteFile(path, false);
long sysconf_result = sysconf(_SC_PAGESIZE);
CHECK_GE(sysconf_result, 0);
size_t pagesize = static_cast<size_t>(sysconf_result);
CHECK_GE(sizeof(pagesize), sizeof(sysconf_result));
- void *mapping = mmap(NULL, pagesize, PROT_READ, MAP_SHARED, fd, 0);
+ void* mapping = mmap(NULL, pagesize, PROT_READ, MAP_SHARED, fd.get(), 0);
if (mapping != MAP_FAILED) {
if (mprotect(mapping, pagesize, PROT_READ | PROT_EXEC) == 0)
result = true;
}
#endif // !defined(OS_MACOSX)
-#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
-// This is implemented in file_util_mac.mm and file_util_android.cc for those
-// platforms.
-bool GetShmemTempDir(bool executable, FilePath* path) {
-#if defined(OS_LINUX)
- bool use_dev_shm = true;
- if (executable) {
- static const bool s_dev_shm_executable = DetermineDevShmExecutable();
- use_dev_shm = s_dev_shm_executable;
- }
- if (use_dev_shm) {
- *path = FilePath("/dev/shm");
- return true;
- }
-#endif
- return GetTempDir(path);
-}
-#endif // !defined(OS_MACOSX) && !defined(OS_ANDROID)
-
-#if !defined(OS_MACOSX)
+#if !defined(OS_MACOSX) // Mac implementation is in file_util_mac.mm.
FilePath GetHomeDir() {
#if defined(OS_CHROMEOS)
- if (SysInfo::IsRunningOnChromeOS())
- return FilePath("/home/chronos/user");
+ if (SysInfo::IsRunningOnChromeOS()) {
+ // On Chrome OS chrome::DIR_USER_DATA is overridden with a primary user
+ // homedir once it becomes available. Return / as the safe option.
+ return FilePath("/");
+ }
#endif
const char* home_dir = getenv("HOME");
#if defined(OS_ANDROID)
DLOG(WARNING) << "OS_ANDROID: Home directory lookup not yet implemented.";
#elif defined(USE_GLIB) && !defined(OS_CHROMEOS)
- // g_get_home_dir calls getpwent, which can fall through to LDAP calls.
- ThreadRestrictions::AssertIOAllowed();
-
+ // g_get_home_dir calls getpwent, which can fall through to LDAP calls so
+ // this may do I/O. However, it should be rare that $HOME is not defined and
+ // this is typically called from the path service which has no threading
+ // restrictions. The path service will cache the result which limits the
+ // badness of blocking on I/O. As a result, we don't have a thread
+ // restriction here.
home_dir = g_get_home_dir();
if (home_dir && home_dir[0])
return FilePath(home_dir);
return true;
}
-FILE* CreateAndOpenTemporaryShmemFile(FilePath* path, bool executable) {
- FilePath directory;
- if (!GetShmemTempDir(executable, &directory))
- return NULL;
-
- return CreateAndOpenTemporaryFileInDir(directory, path);
-}
-
FILE* CreateAndOpenTemporaryFileInDir(const FilePath& dir, FilePath* path) {
int fd = CreateAndOpenFdForTemporaryFile(dir, path);
if (fd < 0)
stat_wrapper_t file_info;
#if defined(OS_ANDROID)
if (file_path.IsContentUri()) {
- int fd = OpenContentUriForRead(file_path);
- if (fd < 0)
- return false;
- file_util::ScopedFD scoped_fd(&fd);
- if (CallFstat(fd, &file_info) != 0)
+ File file = OpenContentUriForRead(file_path);
+ if (!file.IsValid())
return false;
+ return file.GetInfo(results);
} else {
#endif // defined(OS_ANDROID)
if (CallStat(file_path.value().c_str(), &file_info) != 0)
#if defined(OS_ANDROID)
}
#endif // defined(OS_ANDROID)
- results->is_directory = S_ISDIR(file_info.st_mode);
- results->size = file_info.st_size;
-#if defined(OS_MACOSX)
- results->last_modified = Time::FromTimeSpec(file_info.st_mtimespec);
- results->last_accessed = Time::FromTimeSpec(file_info.st_atimespec);
- results->creation_time = Time::FromTimeSpec(file_info.st_ctimespec);
-#elif defined(OS_ANDROID)
- results->last_modified = Time::FromTimeT(file_info.st_mtime);
- results->last_accessed = Time::FromTimeT(file_info.st_atime);
- results->creation_time = Time::FromTimeT(file_info.st_ctime);
-#else
- results->last_modified = Time::FromTimeSpec(file_info.st_mtim);
- results->last_accessed = Time::FromTimeSpec(file_info.st_atim);
- results->creation_time = Time::FromTimeSpec(file_info.st_ctim);
-#endif
+
+ results->FromStat(file_info);
return true;
}
return result;
}
-int ReadFile(const FilePath& filename, char* data, int size) {
+// NaCl doesn't implement system calls to open files directly.
+#if !defined(OS_NACL)
+FILE* FileToFILE(File file, const char* mode) {
+ FILE* stream = fdopen(file.GetPlatformFile(), mode);
+ if (stream)
+ file.TakePlatformFile();
+ return stream;
+}
+#endif // !defined(OS_NACL)
+
+int ReadFile(const FilePath& filename, char* data, int max_size) {
ThreadRestrictions::AssertIOAllowed();
int fd = HANDLE_EINTR(open(filename.value().c_str(), O_RDONLY));
if (fd < 0)
return -1;
- ssize_t bytes_read = HANDLE_EINTR(read(fd, data, size));
- if (int ret = IGNORE_EINTR(close(fd)) < 0)
- return ret;
+ ssize_t bytes_read = HANDLE_EINTR(read(fd, data, max_size));
+ if (IGNORE_EINTR(close(fd)) < 0)
+ return -1;
return bytes_read;
}
-} // namespace base
-
-// -----------------------------------------------------------------------------
-
-namespace file_util {
-
-using base::stat_wrapper_t;
-using base::CallStat;
-using base::CallLstat;
-using base::CreateAndOpenFdForTemporaryFile;
-using base::DirectoryExists;
-using base::FileEnumerator;
-using base::FilePath;
-using base::MakeAbsoluteFilePath;
-using base::VerifySpecificPathControlledByUser;
-
-base::FilePath MakeUniqueDirectory(const base::FilePath& path) {
- const int kMaxAttempts = 20;
- for (int attempts = 0; attempts < kMaxAttempts; attempts++) {
- int uniquifier =
- GetUniquePathNumber(path, base::FilePath::StringType());
- if (uniquifier < 0)
- break;
- base::FilePath test_path = (uniquifier == 0) ? path :
- path.InsertBeforeExtensionASCII(
- base::StringPrintf(" (%d)", uniquifier));
- if (mkdir(test_path.value().c_str(), 0777) == 0)
- return test_path;
- else if (errno != EEXIST)
- break;
- }
- return base::FilePath();
-}
-
-FILE* OpenFile(const std::string& filename, const char* mode) {
- return OpenFile(FilePath(filename), mode);
-}
-
int WriteFile(const FilePath& filename, const char* data, int size) {
- base::ThreadRestrictions::AssertIOAllowed();
- int fd = HANDLE_EINTR(creat(filename.value().c_str(), 0666));
+ ThreadRestrictions::AssertIOAllowed();
+ int fd = HANDLE_EINTR(creat(filename.value().c_str(), 0640));
if (fd < 0)
return -1;
int bytes_written = WriteFileDescriptor(fd, data, size);
- if (int ret = IGNORE_EINTR(close(fd)) < 0)
- return ret;
+ if (IGNORE_EINTR(close(fd)) < 0)
+ return -1;
return bytes_written;
}
}
int AppendToFile(const FilePath& filename, const char* data, int size) {
- base::ThreadRestrictions::AssertIOAllowed();
+ ThreadRestrictions::AssertIOAllowed();
int fd = HANDLE_EINTR(open(filename.value().c_str(), O_WRONLY | O_APPEND));
if (fd < 0)
return -1;
int bytes_written = WriteFileDescriptor(fd, data, size);
- if (int ret = IGNORE_EINTR(close(fd)) < 0)
- return ret;
+ if (IGNORE_EINTR(close(fd)) < 0)
+ return -1;
return bytes_written;
}
// Gets the current working directory for the process.
bool GetCurrentDirectory(FilePath* dir) {
// getcwd can return ENOENT, which implies it checks against the disk.
- base::ThreadRestrictions::AssertIOAllowed();
+ ThreadRestrictions::AssertIOAllowed();
char system_buffer[PATH_MAX] = "";
if (!getcwd(system_buffer, sizeof(system_buffer))) {
// Sets the current working directory for the process.
bool SetCurrentDirectory(const FilePath& path) {
- base::ThreadRestrictions::AssertIOAllowed();
+ ThreadRestrictions::AssertIOAllowed();
int ret = chdir(path.value().c_str());
return !ret;
}
};
// Reading the groups database may touch the file system.
- base::ThreadRestrictions::AssertIOAllowed();
+ ThreadRestrictions::AssertIOAllowed();
std::set<gid_t> allowed_group_ids;
for (int i = 0, ie = arraysize(kAdminGroupNames); i < ie; ++i) {
#endif // defined(OS_MACOSX) && !defined(OS_IOS)
int GetMaximumPathComponentLength(const FilePath& path) {
- base::ThreadRestrictions::AssertIOAllowed();
+ ThreadRestrictions::AssertIOAllowed();
return pathconf(path.value().c_str(), _PC_NAME_MAX);
}
-} // namespace file_util
+#if !defined(OS_ANDROID)
+// This is implemented in file_util_android.cc for that platform.
+bool GetShmemTempDir(bool executable, FilePath* path) {
+#if defined(OS_LINUX)
+ bool use_dev_shm = true;
+ if (executable) {
+ static const bool s_dev_shm_executable = DetermineDevShmExecutable();
+ use_dev_shm = s_dev_shm_executable;
+ }
+ if (use_dev_shm) {
+ *path = FilePath("/dev/shm");
+ return true;
+ }
+#endif
+ return GetTempDir(path);
+}
+#endif // !defined(OS_ANDROID)
+
+// -----------------------------------------------------------------------------
-namespace base {
namespace internal {
bool MoveUnsafe(const FilePath& from_path, const FilePath& to_path) {