LCOV - code coverage report
Current view: top level - ipc/chromium/src/base - file_util_posix.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 29 175 16.6 %
Date: 2017-07-14 16:53:18 Functions: 6 23 26.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
       4             : // Use of this source code is governed by a BSD-style license that can be
       5             : // found in the LICENSE file.
       6             : 
       7             : #include "base/file_util.h"
       8             : 
       9             : #include <dirent.h>
      10             : #include <errno.h>
      11             : #include <fcntl.h>
      12             : #include <fnmatch.h>
      13             : #include <libgen.h>
      14             : #include <stdio.h>
      15             : #include <string.h>
      16             : #include <errno.h>
      17             : #include <sys/mman.h>
      18             : #define _DARWIN_USE_64_BIT_INODE // Use 64-bit inode data structures
      19             : #include <sys/stat.h>
      20             : #include <sys/types.h>
      21             : #include <time.h>
      22             : #include <unistd.h>
      23             : 
      24             : #include <fstream>
      25             : #include <string>
      26             : #include <vector>
      27             : 
      28             : #include "base/basictypes.h"
      29             : #include "base/eintr_wrapper.h"
      30             : #include "base/file_path.h"
      31             : #include "base/logging.h"
      32             : #include "base/string_util.h"
      33             : #include "base/time.h"
      34             : 
      35             : namespace file_util {
      36             : 
      37             : #if defined(GOOGLE_CHROME_BUILD)
      38             : static const char* kTempFileName = "com.google.chrome.XXXXXX";
      39             : #else
      40             : static const char* kTempFileName = "org.chromium.XXXXXX";
      41             : #endif
      42             : 
      43           0 : bool AbsolutePath(FilePath* path) {
      44             :   char full_path[PATH_MAX];
      45           0 :   if (realpath(path->value().c_str(), full_path) == NULL)
      46           0 :     return false;
      47           0 :   *path = FilePath(full_path);
      48           0 :   return true;
      49             : }
      50             : 
      51             : // TODO(erikkay): The Windows version of this accepts paths like "foo/bar/*"
      52             : // which works both with and without the recursive flag.  I'm not sure we need
      53             : // that functionality. If not, remove from file_util_win.cc, otherwise add it
      54             : // here.
      55          13 : bool Delete(const FilePath& path) {
      56          13 :   const char* path_str = path.value().c_str();
      57             :   struct stat file_info;
      58          13 :   int test = stat(path_str, &file_info);
      59          13 :   if (test != 0) {
      60             :     // The Windows version defines this condition as success.
      61           0 :     bool ret = (errno == ENOENT || errno == ENOTDIR);
      62           0 :     return ret;
      63             :   }
      64          13 :   if (!S_ISDIR(file_info.st_mode))
      65          13 :     return (unlink(path_str) == 0);
      66             : 
      67           0 :   return (rmdir(path_str) == 0);
      68             : }
      69             : 
      70           0 : bool PathExists(const FilePath& path) {
      71             :   struct stat file_info;
      72           0 :   return (stat(path.value().c_str(), &file_info) == 0);
      73             : }
      74             : 
      75           0 : bool PathIsWritable(const FilePath& path) {
      76           0 :   FilePath test_path(path);
      77             :   struct stat file_info;
      78           0 :   if (stat(test_path.value().c_str(), &file_info) != 0) {
      79             :     // If the path doesn't exist, test the parent dir.
      80           0 :     test_path = test_path.DirName();
      81             :     // If the parent dir doesn't exist, then return false (the path is not
      82             :     // directly writable).
      83           0 :     if (stat(test_path.value().c_str(), &file_info) != 0)
      84           0 :       return false;
      85             :   }
      86           0 :   if (S_IWOTH & file_info.st_mode)
      87           0 :     return true;
      88           0 :   if (getegid() == file_info.st_gid && (S_IWGRP & file_info.st_mode))
      89           0 :     return true;
      90           0 :   if (geteuid() == file_info.st_uid && (S_IWUSR & file_info.st_mode))
      91           0 :     return true;
      92           0 :   return false;
      93             : }
      94             : 
      95           0 : bool DirectoryExists(const FilePath& path) {
      96             :   struct stat file_info;
      97           0 :   if (stat(path.value().c_str(), &file_info) == 0)
      98           0 :     return S_ISDIR(file_info.st_mode);
      99           0 :   return false;
     100             : }
     101             : 
     102          15 : bool ReadFromFD(int fd, char* buffer, size_t bytes) {
     103          15 :   size_t total_read = 0;
     104          45 :   while (total_read < bytes) {
     105             :     ssize_t bytes_read =
     106          15 :         HANDLE_EINTR(read(fd, buffer + total_read, bytes - total_read));
     107          15 :     if (bytes_read <= 0)
     108           0 :       break;
     109          15 :     total_read += bytes_read;
     110             :   }
     111          15 :   return total_read == bytes;
     112             : }
     113             : 
     114             : // Creates and opens a temporary file in |directory|, returning the
     115             : // file descriptor.  |path| is set to the temporary file path.
     116             : // Note TODO(erikkay) comment in header for BlahFileName() calls; the
     117             : // intent is to rename these files BlahFile() (since they create
     118             : // files, not filenames).  This function does NOT unlink() the file.
     119          13 : int CreateAndOpenFdForTemporaryFile(FilePath directory, FilePath* path) {
     120          13 :   *path = directory.Append(kTempFileName);
     121          13 :   const std::string& tmpdir_string = path->value();
     122             :   // this should be OK since mkstemp just replaces characters in place
     123          13 :   char* buffer = const_cast<char*>(tmpdir_string.c_str());
     124             : 
     125          13 :   return mkstemp(buffer);
     126             : }
     127             : 
     128           0 : bool CreateTemporaryFileName(FilePath* path) {
     129           0 :   FilePath directory;
     130           0 :   if (!GetTempDir(&directory))
     131           0 :     return false;
     132           0 :   int fd = CreateAndOpenFdForTemporaryFile(directory, path);
     133           0 :   if (fd < 0)
     134           0 :     return false;
     135           0 :   close(fd);
     136           0 :   return true;
     137             : }
     138             : 
     139          13 : FILE* CreateAndOpenTemporaryShmemFile(FilePath* path) {
     140          26 :   FilePath directory;
     141          13 :   if (!GetShmemTempDir(&directory))
     142           0 :     return NULL;
     143             : 
     144          13 :   return CreateAndOpenTemporaryFileInDir(directory, path);
     145             : }
     146             : 
     147          13 : FILE* CreateAndOpenTemporaryFileInDir(const FilePath& dir, FilePath* path) {
     148          13 :   int fd = CreateAndOpenFdForTemporaryFile(dir, path);
     149          13 :   if (fd < 0)
     150           0 :     return NULL;
     151             : 
     152          13 :   return fdopen(fd, "a+");
     153             : }
     154             : 
     155           0 : bool CreateTemporaryFileNameInDir(const std::wstring& dir,
     156             :                                   std::wstring* temp_file) {
     157             :   // Not implemented yet.
     158           0 :   NOTREACHED();
     159           0 :   return false;
     160             : }
     161             : 
     162           0 : bool CreateNewTempDirectory(const FilePath::StringType& prefix,
     163             :                             FilePath* new_temp_path) {
     164           0 :   FilePath tmpdir;
     165           0 :   if (!GetTempDir(&tmpdir))
     166           0 :     return false;
     167           0 :   tmpdir = tmpdir.Append(kTempFileName);
     168           0 :   std::string tmpdir_string = tmpdir.value();
     169             : #ifdef ANDROID
     170             :   char* dtemp = NULL;
     171             : #else
     172             :   // this should be OK since mkdtemp just replaces characters in place
     173           0 :   char* buffer = const_cast<char*>(tmpdir_string.c_str());
     174           0 :   char* dtemp = mkdtemp(buffer);
     175             : #endif
     176           0 :   if (!dtemp)
     177           0 :     return false;
     178           0 :   *new_temp_path = FilePath(dtemp);
     179           0 :   return true;
     180             : }
     181             : 
     182           0 : bool CreateDirectory(const FilePath& full_path) {
     183           0 :   std::vector<FilePath> subpaths;
     184             : 
     185             :   // Collect a list of all parent directories.
     186           0 :   FilePath last_path = full_path;
     187           0 :   subpaths.push_back(full_path);
     188           0 :   for (FilePath path = full_path.DirName();
     189           0 :        path.value() != last_path.value(); path = path.DirName()) {
     190           0 :     subpaths.push_back(path);
     191           0 :     last_path = path;
     192             :   }
     193             : 
     194             :   // Iterate through the parents and create the missing ones.
     195           0 :   for (std::vector<FilePath>::reverse_iterator i = subpaths.rbegin();
     196           0 :        i != subpaths.rend(); ++i) {
     197           0 :     if (!DirectoryExists(*i)) {
     198           0 :       if (mkdir(i->value().c_str(), 0777) != 0)
     199           0 :         return false;
     200             :     }
     201             :   }
     202           0 :   return true;
     203             : }
     204             : 
     205           0 : bool GetFileInfo(const FilePath& file_path, FileInfo* results) {
     206             :   struct stat file_info;
     207           0 :   if (stat(file_path.value().c_str(), &file_info) != 0)
     208           0 :     return false;
     209           0 :   results->is_directory = S_ISDIR(file_info.st_mode);
     210           0 :   results->size = file_info.st_size;
     211           0 :   return true;
     212             : }
     213             : 
     214           0 : FILE* OpenFile(const std::string& filename, const char* mode) {
     215           0 :   return OpenFile(FilePath(filename), mode);
     216             : }
     217             : 
     218           0 : FILE* OpenFile(const FilePath& filename, const char* mode) {
     219           0 :   return fopen(filename.value().c_str(), mode);
     220             : }
     221             : 
     222           0 : int ReadFile(const FilePath& filename, char* data, int size) {
     223           0 :   int fd = open(filename.value().c_str(), O_RDONLY);
     224           0 :   if (fd < 0)
     225           0 :     return -1;
     226             : 
     227           0 :   int ret_value = HANDLE_EINTR(read(fd, data, size));
     228           0 :   HANDLE_EINTR(close(fd));
     229           0 :   return ret_value;
     230             : }
     231             : 
     232           0 : int WriteFile(const FilePath& filename, const char* data, int size) {
     233           0 :   int fd = creat(filename.value().c_str(), 0666);
     234           0 :   if (fd < 0)
     235           0 :     return -1;
     236             : 
     237             :   // Allow for partial writes
     238           0 :   ssize_t bytes_written_total = 0;
     239           0 :   do {
     240             :     ssize_t bytes_written_partial =
     241           0 :       HANDLE_EINTR(write(fd, data + bytes_written_total,
     242             :                          size - bytes_written_total));
     243           0 :     if (bytes_written_partial < 0) {
     244           0 :       HANDLE_EINTR(close(fd));
     245           0 :       return -1;
     246             :     }
     247           0 :     bytes_written_total += bytes_written_partial;
     248           0 :   } while (bytes_written_total < size);
     249             : 
     250           0 :   HANDLE_EINTR(close(fd));
     251           0 :   return bytes_written_total;
     252             : }
     253             : 
     254             : // Gets the current working directory for the process.
     255           0 : bool GetCurrentDirectory(FilePath* dir) {
     256           0 :   char system_buffer[PATH_MAX] = "";
     257           0 :   if (!getcwd(system_buffer, sizeof(system_buffer))) {
     258           0 :     NOTREACHED();
     259           0 :     return false;
     260             :   }
     261           0 :   *dir = FilePath(system_buffer);
     262           0 :   return true;
     263             : }
     264             : 
     265             : // Sets the current working directory for the process.
     266           0 : bool SetCurrentDirectory(const FilePath& path) {
     267           0 :   int ret = chdir(path.value().c_str());
     268           0 :   return !ret;
     269             : }
     270             : 
     271             : #if !defined(OS_MACOSX)
     272           0 : bool GetTempDir(FilePath* path) {
     273           0 :   const char* tmp = getenv("TMPDIR");
     274           0 :   if (tmp)
     275           0 :     *path = FilePath(tmp);
     276             :   else
     277           0 :     *path = FilePath("/tmp");
     278           0 :   return true;
     279             : }
     280             : 
     281          13 : bool GetShmemTempDir(FilePath* path) {
     282             : #if defined(OS_LINUX) && !defined(ANDROID)
     283          13 :   *path = FilePath("/dev/shm");
     284          13 :   return true;
     285             : #else
     286             :   return GetTempDir(path);
     287             : #endif
     288             : }
     289             : 
     290           0 : bool CopyFile(const FilePath& from_path, const FilePath& to_path) {
     291           0 :   int infile = open(from_path.value().c_str(), O_RDONLY);
     292           0 :   if (infile < 0)
     293           0 :     return false;
     294             : 
     295           0 :   int outfile = creat(to_path.value().c_str(), 0666);
     296           0 :   if (outfile < 0) {
     297           0 :     close(infile);
     298           0 :     return false;
     299             :   }
     300             : 
     301           0 :   const size_t kBufferSize = 32768;
     302           0 :   std::vector<char> buffer(kBufferSize);
     303           0 :   bool result = true;
     304             : 
     305           0 :   while (result) {
     306           0 :     ssize_t bytes_read = HANDLE_EINTR(read(infile, &buffer[0], buffer.size()));
     307           0 :     if (bytes_read < 0) {
     308           0 :       result = false;
     309           0 :       break;
     310             :     }
     311           0 :     if (bytes_read == 0)
     312           0 :       break;
     313             :     // Allow for partial writes
     314           0 :     ssize_t bytes_written_per_read = 0;
     315           0 :     do {
     316           0 :       ssize_t bytes_written_partial = HANDLE_EINTR(write(
     317             :           outfile,
     318             :           &buffer[bytes_written_per_read],
     319             :           bytes_read - bytes_written_per_read));
     320           0 :       if (bytes_written_partial < 0) {
     321           0 :         result = false;
     322           0 :         break;
     323             :       }
     324           0 :       bytes_written_per_read += bytes_written_partial;
     325           0 :     } while (bytes_written_per_read < bytes_read);
     326             :   }
     327             : 
     328           0 :   if (HANDLE_EINTR(close(infile)) < 0)
     329           0 :     result = false;
     330           0 :   if (HANDLE_EINTR(close(outfile)) < 0)
     331           0 :     result = false;
     332             : 
     333           0 :   return result;
     334             : }
     335             : #endif // !defined(OS_MACOSX)
     336             : 
     337             : } // namespace file_util

Generated by: LCOV version 1.13