summaryrefslogtreecommitdiffstats
path: root/ipc/chromium/src/base/file_util_posix.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/chromium/src/base/file_util_posix.cc')
-rw-r--r--ipc/chromium/src/base/file_util_posix.cc337
1 files changed, 337 insertions, 0 deletions
diff --git a/ipc/chromium/src/base/file_util_posix.cc b/ipc/chromium/src/base/file_util_posix.cc
new file mode 100644
index 000000000..d64897404
--- /dev/null
+++ b/ipc/chromium/src/base/file_util_posix.cc
@@ -0,0 +1,337 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/file_util.h"
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fnmatch.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/mman.h>
+#define _DARWIN_USE_64_BIT_INODE // Use 64-bit inode data structures
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <fstream>
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/eintr_wrapper.h"
+#include "base/file_path.h"
+#include "base/logging.h"
+#include "base/string_util.h"
+#include "base/time.h"
+
+namespace file_util {
+
+#if defined(GOOGLE_CHROME_BUILD)
+static const char* kTempFileName = "com.google.chrome.XXXXXX";
+#else
+static const char* kTempFileName = "org.chromium.XXXXXX";
+#endif
+
+bool AbsolutePath(FilePath* path) {
+ char full_path[PATH_MAX];
+ if (realpath(path->value().c_str(), full_path) == NULL)
+ return false;
+ *path = FilePath(full_path);
+ return true;
+}
+
+// TODO(erikkay): The Windows version of this accepts paths like "foo/bar/*"
+// which works both with and without the recursive flag. I'm not sure we need
+// that functionality. If not, remove from file_util_win.cc, otherwise add it
+// here.
+bool Delete(const FilePath& path) {
+ const char* path_str = path.value().c_str();
+ struct stat file_info;
+ int test = stat(path_str, &file_info);
+ if (test != 0) {
+ // The Windows version defines this condition as success.
+ bool ret = (errno == ENOENT || errno == ENOTDIR);
+ return ret;
+ }
+ if (!S_ISDIR(file_info.st_mode))
+ return (unlink(path_str) == 0);
+
+ return (rmdir(path_str) == 0);
+}
+
+bool PathExists(const FilePath& path) {
+ struct stat file_info;
+ return (stat(path.value().c_str(), &file_info) == 0);
+}
+
+bool PathIsWritable(const FilePath& path) {
+ FilePath test_path(path);
+ struct stat file_info;
+ if (stat(test_path.value().c_str(), &file_info) != 0) {
+ // If the path doesn't exist, test the parent dir.
+ test_path = test_path.DirName();
+ // If the parent dir doesn't exist, then return false (the path is not
+ // directly writable).
+ if (stat(test_path.value().c_str(), &file_info) != 0)
+ return false;
+ }
+ if (S_IWOTH & file_info.st_mode)
+ return true;
+ if (getegid() == file_info.st_gid && (S_IWGRP & file_info.st_mode))
+ return true;
+ if (geteuid() == file_info.st_uid && (S_IWUSR & file_info.st_mode))
+ return true;
+ return false;
+}
+
+bool DirectoryExists(const FilePath& path) {
+ struct stat file_info;
+ if (stat(path.value().c_str(), &file_info) == 0)
+ return S_ISDIR(file_info.st_mode);
+ return false;
+}
+
+bool ReadFromFD(int fd, char* buffer, size_t bytes) {
+ size_t total_read = 0;
+ while (total_read < bytes) {
+ ssize_t bytes_read =
+ HANDLE_EINTR(read(fd, buffer + total_read, bytes - total_read));
+ if (bytes_read <= 0)
+ break;
+ total_read += bytes_read;
+ }
+ return total_read == bytes;
+}
+
+// Creates and opens a temporary file in |directory|, returning the
+// file descriptor. |path| is set to the temporary file path.
+// Note TODO(erikkay) comment in header for BlahFileName() calls; the
+// intent is to rename these files BlahFile() (since they create
+// files, not filenames). This function does NOT unlink() the file.
+int CreateAndOpenFdForTemporaryFile(FilePath directory, FilePath* path) {
+ *path = directory.Append(kTempFileName);
+ const std::string& tmpdir_string = path->value();
+ // this should be OK since mkstemp just replaces characters in place
+ char* buffer = const_cast<char*>(tmpdir_string.c_str());
+
+ return mkstemp(buffer);
+}
+
+bool CreateTemporaryFileName(FilePath* path) {
+ FilePath directory;
+ if (!GetTempDir(&directory))
+ return false;
+ int fd = CreateAndOpenFdForTemporaryFile(directory, path);
+ if (fd < 0)
+ return false;
+ close(fd);
+ return true;
+}
+
+FILE* CreateAndOpenTemporaryShmemFile(FilePath* path) {
+ FilePath directory;
+ if (!GetShmemTempDir(&directory))
+ return NULL;
+
+ return CreateAndOpenTemporaryFileInDir(directory, path);
+}
+
+FILE* CreateAndOpenTemporaryFileInDir(const FilePath& dir, FilePath* path) {
+ int fd = CreateAndOpenFdForTemporaryFile(dir, path);
+ if (fd < 0)
+ return NULL;
+
+ return fdopen(fd, "a+");
+}
+
+bool CreateTemporaryFileNameInDir(const std::wstring& dir,
+ std::wstring* temp_file) {
+ // Not implemented yet.
+ NOTREACHED();
+ return false;
+}
+
+bool CreateNewTempDirectory(const FilePath::StringType& prefix,
+ FilePath* new_temp_path) {
+ FilePath tmpdir;
+ if (!GetTempDir(&tmpdir))
+ return false;
+ tmpdir = tmpdir.Append(kTempFileName);
+ std::string tmpdir_string = tmpdir.value();
+#ifdef ANDROID
+ char* dtemp = NULL;
+#else
+ // this should be OK since mkdtemp just replaces characters in place
+ char* buffer = const_cast<char*>(tmpdir_string.c_str());
+ char* dtemp = mkdtemp(buffer);
+#endif
+ if (!dtemp)
+ return false;
+ *new_temp_path = FilePath(dtemp);
+ return true;
+}
+
+bool CreateDirectory(const FilePath& full_path) {
+ std::vector<FilePath> subpaths;
+
+ // Collect a list of all parent directories.
+ FilePath last_path = full_path;
+ subpaths.push_back(full_path);
+ for (FilePath path = full_path.DirName();
+ path.value() != last_path.value(); path = path.DirName()) {
+ subpaths.push_back(path);
+ last_path = path;
+ }
+
+ // Iterate through the parents and create the missing ones.
+ for (std::vector<FilePath>::reverse_iterator i = subpaths.rbegin();
+ i != subpaths.rend(); ++i) {
+ if (!DirectoryExists(*i)) {
+ if (mkdir(i->value().c_str(), 0777) != 0)
+ return false;
+ }
+ }
+ return true;
+}
+
+bool GetFileInfo(const FilePath& file_path, FileInfo* results) {
+ struct stat file_info;
+ if (stat(file_path.value().c_str(), &file_info) != 0)
+ return false;
+ results->is_directory = S_ISDIR(file_info.st_mode);
+ results->size = file_info.st_size;
+ return true;
+}
+
+FILE* OpenFile(const std::string& filename, const char* mode) {
+ return OpenFile(FilePath(filename), mode);
+}
+
+FILE* OpenFile(const FilePath& filename, const char* mode) {
+ return fopen(filename.value().c_str(), mode);
+}
+
+int ReadFile(const FilePath& filename, char* data, int size) {
+ int fd = open(filename.value().c_str(), O_RDONLY);
+ if (fd < 0)
+ return -1;
+
+ int ret_value = HANDLE_EINTR(read(fd, data, size));
+ HANDLE_EINTR(close(fd));
+ return ret_value;
+}
+
+int WriteFile(const FilePath& filename, const char* data, int size) {
+ int fd = creat(filename.value().c_str(), 0666);
+ if (fd < 0)
+ return -1;
+
+ // Allow for partial writes
+ ssize_t bytes_written_total = 0;
+ do {
+ ssize_t bytes_written_partial =
+ HANDLE_EINTR(write(fd, data + bytes_written_total,
+ size - bytes_written_total));
+ if (bytes_written_partial < 0) {
+ HANDLE_EINTR(close(fd));
+ return -1;
+ }
+ bytes_written_total += bytes_written_partial;
+ } while (bytes_written_total < size);
+
+ HANDLE_EINTR(close(fd));
+ return bytes_written_total;
+}
+
+// Gets the current working directory for the process.
+bool GetCurrentDirectory(FilePath* dir) {
+ char system_buffer[PATH_MAX] = "";
+ if (!getcwd(system_buffer, sizeof(system_buffer))) {
+ NOTREACHED();
+ return false;
+ }
+ *dir = FilePath(system_buffer);
+ return true;
+}
+
+// Sets the current working directory for the process.
+bool SetCurrentDirectory(const FilePath& path) {
+ int ret = chdir(path.value().c_str());
+ return !ret;
+}
+
+#if !defined(OS_MACOSX)
+bool GetTempDir(FilePath* path) {
+ const char* tmp = getenv("TMPDIR");
+ if (tmp)
+ *path = FilePath(tmp);
+ else
+ *path = FilePath("/tmp");
+ return true;
+}
+
+bool GetShmemTempDir(FilePath* path) {
+#if defined(OS_LINUX) && !defined(ANDROID)
+ *path = FilePath("/dev/shm");
+ return true;
+#else
+ return GetTempDir(path);
+#endif
+}
+
+bool CopyFile(const FilePath& from_path, const FilePath& to_path) {
+ int infile = open(from_path.value().c_str(), O_RDONLY);
+ if (infile < 0)
+ return false;
+
+ int outfile = creat(to_path.value().c_str(), 0666);
+ if (outfile < 0) {
+ close(infile);
+ return false;
+ }
+
+ const size_t kBufferSize = 32768;
+ std::vector<char> buffer(kBufferSize);
+ bool result = true;
+
+ while (result) {
+ ssize_t bytes_read = HANDLE_EINTR(read(infile, &buffer[0], buffer.size()));
+ if (bytes_read < 0) {
+ result = false;
+ break;
+ }
+ if (bytes_read == 0)
+ break;
+ // Allow for partial writes
+ ssize_t bytes_written_per_read = 0;
+ do {
+ ssize_t bytes_written_partial = HANDLE_EINTR(write(
+ outfile,
+ &buffer[bytes_written_per_read],
+ bytes_read - bytes_written_per_read));
+ if (bytes_written_partial < 0) {
+ result = false;
+ break;
+ }
+ bytes_written_per_read += bytes_written_partial;
+ } while (bytes_written_per_read < bytes_read);
+ }
+
+ if (HANDLE_EINTR(close(infile)) < 0)
+ result = false;
+ if (HANDLE_EINTR(close(outfile)) < 0)
+ result = false;
+
+ return result;
+}
+#endif // !defined(OS_MACOSX)
+
+} // namespace file_util