15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <dirent.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libgen.h> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits.h> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h> 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h> 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h> 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/errno.h> 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/mman.h> 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/param.h> 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/stat.h> 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/time.h> 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h> 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <time.h> 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h> 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <AvailabilityMacros.h> 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/mac/foundation_util.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif !defined(OS_ANDROID) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <glib.h> 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fstream> 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/files/file_enumerator.h" 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/singleton.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h" 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h" 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 425e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h" 435e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h" 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/sys_string_conversions.h" 45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_restrictions.h" 47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/os_compat_android.h" 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_IOS) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <grp.h> 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/chromeos/chromeos_version.h" 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace base { 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_BSD) || defined(OS_MACOSX) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct stat stat_wrapper_t; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int CallStat(const char *path, stat_wrapper_t *sb) { 68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ThreadRestrictions::AssertIOAllowed(); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return stat(path, sb); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int CallLstat(const char *path, stat_wrapper_t *sb) { 72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ThreadRestrictions::AssertIOAllowed(); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return lstat(path, sb); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct stat64 stat_wrapper_t; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int CallStat(const char *path, stat_wrapper_t *sb) { 78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ThreadRestrictions::AssertIOAllowed(); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return stat64(path, sb); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int CallLstat(const char *path, stat_wrapper_t *sb) { 82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ThreadRestrictions::AssertIOAllowed(); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return lstat64(path, sb); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper for NormalizeFilePath(), defined below. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RealPath(const FilePath& path, FilePath* real_path) { 89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ThreadRestrictions::AssertIOAllowed(); // For realpath(). 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath::CharType buf[PATH_MAX]; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!realpath(path.value().c_str(), buf)) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *real_path = FilePath(buf); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper for VerifyPathControlledByUser. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VerifySpecificPathControlledByUser(const FilePath& path, 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uid_t owner_uid, 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::set<gid_t>& group_gids) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stat_wrapper_t stat_info; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CallLstat(path.value().c_str(), &stat_info) != 0) { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DPLOG(ERROR) << "Failed to get information on path " 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << path.value(); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (S_ISLNK(stat_info.st_mode)) { 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(ERROR) << "Path " << path.value() 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " is a symbolic link."; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stat_info.st_uid != owner_uid) { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(ERROR) << "Path " << path.value() 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " is owned by the wrong user."; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((stat_info.st_mode & S_IWGRP) && 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !ContainsKey(group_gids, stat_info.st_gid)) { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(ERROR) << "Path " << path.value() 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " is writable by an unprivileged group."; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stat_info.st_mode & S_IWOTH) { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(ERROR) << "Path " << path.value() 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " is writable by any user."; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstd::string TempFileName() { 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX) 139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return StringPrintf(".%s.XXXXXX", base::mac::BaseBundleID()); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(GOOGLE_CHROME_BUILD) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::string(".com.google.Chrome.XXXXXX"); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::string(".org.chromium.Chromium.XXXXXX"); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} // namespace 150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochFilePath MakeAbsoluteFilePath(const FilePath& input) { 152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ThreadRestrictions::AssertIOAllowed(); 153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch char full_path[PATH_MAX]; 154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (realpath(input.value().c_str(), full_path) == NULL) 155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return FilePath(); 156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return FilePath(full_path); 157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(erikkay): The Windows version of this accepts paths like "foo/bar/*" 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// which works both with and without the recursive flag. I'm not sure we need 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that functionality. If not, remove from file_util_win.cc, otherwise add it 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// here. 1637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool DeleteFile(const FilePath& path, bool recursive) { 164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ThreadRestrictions::AssertIOAllowed(); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* path_str = path.value().c_str(); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stat_wrapper_t file_info; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int test = CallLstat(path_str, &file_info); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (test != 0) { 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The Windows version defines this condition as success. 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ret = (errno == ENOENT || errno == ENOTDIR); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!S_ISDIR(file_info.st_mode)) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (unlink(path_str) == 0); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!recursive) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (rmdir(path_str) == 0); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = true; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::stack<std::string> directories; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) directories.push(path.value()); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FileEnumerator traversal(path, true, 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FileEnumerator::FILES | FileEnumerator::DIRECTORIES | 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FileEnumerator::SHOW_SYM_LINKS); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (FilePath current = traversal.Next(); success && !current.empty(); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current = traversal.Next()) { 186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (traversal.GetInfo().IsDirectory()) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) directories.push(current.value()); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = (unlink(current.value().c_str()) == 0); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (success && !directories.empty()) { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath dir = FilePath(directories.top()); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) directories.pop(); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = (rmdir(dir.value().c_str()) == 0); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return success; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool ReplaceFile(const FilePath& from_path, 201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const FilePath& to_path, 202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch PlatformFileError* error) { 203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ThreadRestrictions::AssertIOAllowed(); 204b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (rename(from_path.value().c_str(), to_path.value().c_str()) == 0) 205b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return true; 206b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (error) 207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *error = ErrnoToPlatformFileError(errno); 208b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return false; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CopyDirectory(const FilePath& from_path, 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FilePath& to_path, 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool recursive) { 2147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ThreadRestrictions::AssertIOAllowed(); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Some old callers of CopyDirectory want it to support wildcards. 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // After some discussion, we decided to fix those callers. 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Break loudly here if anyone tries to do this. 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(evanm): remove this once we're sure it's ok. 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(to_path.value().find('*') == std::string::npos); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(from_path.value().find('*') == std::string::npos); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char top_dir[PATH_MAX]; 2237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (strlcpy(top_dir, from_path.value().c_str(), 2247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch arraysize(top_dir)) >= arraysize(top_dir)) { 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This function does not properly handle destinations within the source 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath real_to_path = to_path; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (PathExists(real_to_path)) { 231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) real_to_path = MakeAbsoluteFilePath(real_to_path); 232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (real_to_path.empty()) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) real_to_path = MakeAbsoluteFilePath(real_to_path.DirName()); 236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (real_to_path.empty()) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FilePath real_from_path = MakeAbsoluteFilePath(from_path); 240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (real_from_path.empty()) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (real_to_path.value().size() >= real_from_path.value().size() && 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) real_to_path.value().compare(0, real_from_path.value().size(), 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) real_from_path.value()) == 0) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = true; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int traverse_type = FileEnumerator::FILES | FileEnumerator::SHOW_SYM_LINKS; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (recursive) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) traverse_type |= FileEnumerator::DIRECTORIES; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FileEnumerator traversal(from_path, recursive, traverse_type); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We have to mimic windows behavior here. |to_path| may not exist yet, 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // start the loop with |to_path|. 255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) struct stat from_stat; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath current = from_path; 257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (stat(from_path.value().c_str(), &from_stat) < 0) { 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(ERROR) << "CopyDirectory() couldn't stat source directory: " 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << from_path.value() << " errno = " << errno; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = false; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct stat to_path_stat; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath from_path_base = from_path; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (recursive && stat(to_path.value().c_str(), &to_path_stat) == 0 && 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) S_ISDIR(to_path_stat.st_mode)) { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the destination already exists and is a directory, then the 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // top level of source needs to be copied. 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) from_path_base = from_path.DirName(); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The Windows version of this function assumes that non-recursive calls 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will always have a directory for from_path. 273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(recursive || S_ISDIR(from_stat.st_mode)); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (success && !current.empty()) { 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // current is the source path, including from_path, so append 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the suffix after from_path to to_path to create the target_path. 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FilePath target_path(to_path); 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (from_path_base != current) { 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!from_path_base.AppendRelativePath(current, &target_path)) { 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) success = false; 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (S_ISDIR(from_stat.st_mode)) { 287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (mkdir(target_path.value().c_str(), from_stat.st_mode & 01777) != 0 && 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno != EEXIST) { 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(ERROR) << "CopyDirectory() couldn't create directory: " 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << target_path.value() << " errno = " << errno; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = false; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else if (S_ISREG(from_stat.st_mode)) { 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CopyFile(current, target_path)) { 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(ERROR) << "CopyDirectory() couldn't create file: " 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << target_path.value(); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = false; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(WARNING) << "CopyDirectory() skipping non-regular file: " 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << current.value(); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current = traversal.Next(); 305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!current.empty()) 306868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) from_stat = traversal.GetInfo().stat(); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return success; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PathExists(const FilePath& path) { 3137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ThreadRestrictions::AssertIOAllowed(); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return access(path.value().c_str(), F_OK) == 0; 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PathIsWritable(const FilePath& path) { 3187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ThreadRestrictions::AssertIOAllowed(); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return access(path.value().c_str(), W_OK) == 0; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryExists(const FilePath& path) { 3237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ThreadRestrictions::AssertIOAllowed(); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stat_wrapper_t file_info; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CallStat(path.value().c_str(), &file_info) == 0) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return S_ISDIR(file_info.st_mode); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} // namespace base 3317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 3327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// ----------------------------------------------------------------------------- 3337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 3347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochnamespace file_util { 3357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 3367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing base::stat_wrapper_t; 3377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing base::CallStat; 3387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing base::CallLstat; 3397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing base::DirectoryExists; 3407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing base::FileEnumerator; 3417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing base::FilePath; 3427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing base::MakeAbsoluteFilePath; 3437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing base::RealPath; 3447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing base::VerifySpecificPathControlledByUser; 3457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ReadFromFD(int fd, char* buffer, size_t bytes) { 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t total_read = 0; 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (total_read < bytes) { 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssize_t bytes_read = 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE_EINTR(read(fd, buffer + total_read, bytes - total_read)); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bytes_read <= 0) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_read += bytes_read; 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return total_read == bytes; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CreateSymbolicLink(const FilePath& target_path, 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FilePath& symlink_path) { 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!symlink_path.empty()); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!target_path.empty()); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ::symlink(target_path.value().c_str(), 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) symlink_path.value().c_str()) != -1; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ReadSymbolicLink(const FilePath& symlink_path, 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath* target_path) { 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!symlink_path.empty()); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(target_path); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buf[PATH_MAX]; 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssize_t count = ::readlink(symlink_path.value().c_str(), buf, arraysize(buf)); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (count <= 0) { 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target_path->clear(); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *target_path = FilePath(FilePath::StringType(buf, count)); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetPosixFilePermissions(const FilePath& path, int* mode) { 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(mode); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stat_wrapper_t file_info; 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Uses stat(), because on symbolic link, lstat() does not return valid 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // permission bits in st_mode 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CallStat(path.value().c_str(), &file_info) != 0) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *mode = file_info.st_mode & FILE_PERMISSION_MASK; 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SetPosixFilePermissions(const FilePath& path, 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int mode) { 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK((mode & ~FILE_PERMISSION_MASK) == 0); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Calls stat() so that we can preserve the higher bits like S_ISGID. 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stat_wrapper_t stat_buf; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CallStat(path.value().c_str(), &stat_buf) != 0) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clears the existing permission bits, and adds the new ones. 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mode_t updated_mode_bits = stat_buf.st_mode & ~FILE_PERMISSION_MASK; 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) updated_mode_bits |= mode & FILE_PERMISSION_MASK; 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HANDLE_EINTR(chmod(path.value().c_str(), updated_mode_bits)) != 0) 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates and opens a temporary file in |directory|, returning the 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// file descriptor. |path| is set to the temporary file path. 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function does NOT unlink() the file. 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CreateAndOpenFdForTemporaryFile(FilePath directory, FilePath* path) { 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); // For call to mkstemp(). 421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *path = directory.Append(base::TempFileName()); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& tmpdir_string = path->value(); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this should be OK since mkstemp just replaces characters in place 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* buffer = const_cast<char*>(tmpdir_string.c_str()); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HANDLE_EINTR(mkstemp(buffer)); 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CreateTemporaryFile(FilePath* path) { 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); // For call to close(). 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath directory; 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetTempDir(&directory)) 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd = CreateAndOpenFdForTemporaryFile(directory, path); 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fd < 0) 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ignore_result(HANDLE_EINTR(close(fd))); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FILE* CreateAndOpenTemporaryShmemFile(FilePath* path, bool executable) { 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath directory; 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetShmemTempDir(&directory, executable)) 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CreateAndOpenTemporaryFileInDir(directory, path); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FILE* CreateAndOpenTemporaryFileInDir(const FilePath& dir, FilePath* path) { 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd = CreateAndOpenFdForTemporaryFile(dir, path); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fd < 0) 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILE* file = fdopen(fd, "a+"); 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!file) 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ignore_result(HANDLE_EINTR(close(fd))); 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return file; 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CreateTemporaryFileInDir(const FilePath& dir, FilePath* temp_file) { 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); // For call to close(). 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd = CreateAndOpenFdForTemporaryFile(dir, temp_file); 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ((fd >= 0) && !HANDLE_EINTR(close(fd))); 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool CreateTemporaryDirInDirImpl(const FilePath& base_dir, 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FilePath::StringType& name_tmpl, 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath* new_dir) { 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); // For call to mkdtemp(). 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(name_tmpl.find("XXXXXX") != FilePath::StringType::npos) 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Directory name template must contain \"XXXXXX\"."; 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath sub_dir = base_dir.Append(name_tmpl); 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string sub_dir_string = sub_dir.value(); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this should be OK since mkdtemp just replaces characters in place 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* buffer = const_cast<char*>(sub_dir_string.c_str()); 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* dtemp = mkdtemp(buffer); 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dtemp) { 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DPLOG(ERROR) << "mkdtemp"; 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *new_dir = FilePath(dtemp); 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CreateTemporaryDirInDir(const FilePath& base_dir, 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FilePath::StringType& prefix, 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath* new_dir) { 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath::StringType mkdtemp_template = prefix; 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mkdtemp_template.append(FILE_PATH_LITERAL("XXXXXX")); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CreateTemporaryDirInDirImpl(base_dir, mkdtemp_template, new_dir); 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CreateNewTempDirectory(const FilePath::StringType& prefix, 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath* new_temp_path) { 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath tmpdir; 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetTempDir(&tmpdir)) 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return CreateTemporaryDirInDirImpl(tmpdir, base::TempFileName(), 502eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch new_temp_path); 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool CreateDirectoryAndGetError(const FilePath& full_path, 506868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::PlatformFileError* error) { 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); // For call to mkdir(). 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<FilePath> subpaths; 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Collect a list of all parent directories. 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath last_path = full_path; 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subpaths.push_back(full_path); 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (FilePath path = full_path.DirName(); 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path.value() != last_path.value(); path = path.DirName()) { 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subpaths.push_back(path); 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_path = path; 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Iterate through the parents and create the missing ones. 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<FilePath>::reverse_iterator i = subpaths.rbegin(); 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != subpaths.rend(); ++i) { 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (DirectoryExists(*i)) 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mkdir(i->value().c_str(), 0700) == 0) 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mkdir failed, but it might have failed with EEXIST, or some other error 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // due to the the directory appearing out of thin air. This can occur if 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // two processes are trying to create the same file system tree at the same 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // time. Check to see if it exists and make sure it is a directory. 530868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int saved_errno = errno; 531868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!DirectoryExists(*i)) { 532868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (error) 533868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *error = base::ErrnoToPlatformFileError(saved_errno); 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 535868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::FilePath MakeUniqueDirectory(const base::FilePath& path) { 541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const int kMaxAttempts = 20; 542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (int attempts = 0; attempts < kMaxAttempts; attempts++) { 543c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int uniquifier = 544c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GetUniquePathNumber(path, base::FilePath::StringType()); 545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (uniquifier < 0) 546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath test_path = (uniquifier == 0) ? path : 548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) path.InsertBeforeExtensionASCII( 549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::StringPrintf(" (%d)", uniquifier)); 550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (mkdir(test_path.value().c_str(), 0777) == 0) 551c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return test_path; 552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) else if (errno != EEXIST) 553c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return base::FilePath(); 556c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(rkc): Refactor GetFileInfo and FileEnumerator to handle symlinks 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// correctly. http://code.google.com/p/chromium-os/issues/detail?id=15948 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsLink(const FilePath& file_path) { 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stat_wrapper_t st; 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we can't lstat the file, it's safe to assume that the file won't at 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // least be a 'followable' link. 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CallLstat(file_path.value().c_str(), &st) != 0) 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (S_ISLNK(st.st_mode)) 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetFileInfo(const FilePath& file_path, base::PlatformFileInfo* results) { 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stat_wrapper_t file_info; 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CallStat(file_path.value().c_str(), &file_info) != 0) 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results->is_directory = S_ISDIR(file_info.st_mode); 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results->size = file_info.st_size; 579868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#if defined(OS_MACOSX) 580868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) results->last_modified = base::Time::FromTimeSpec(file_info.st_mtimespec); 581868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) results->last_accessed = base::Time::FromTimeSpec(file_info.st_atimespec); 582868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) results->creation_time = base::Time::FromTimeSpec(file_info.st_ctimespec); 583868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#elif defined(OS_ANDROID) 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results->last_modified = base::Time::FromTimeT(file_info.st_mtime); 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results->last_accessed = base::Time::FromTimeT(file_info.st_atime); 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results->creation_time = base::Time::FromTimeT(file_info.st_ctime); 587868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#else 588868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) results->last_modified = base::Time::FromTimeSpec(file_info.st_mtim); 589868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) results->last_accessed = base::Time::FromTimeSpec(file_info.st_atim); 590868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) results->creation_time = base::Time::FromTimeSpec(file_info.st_ctim); 591868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetInode(const FilePath& path, ino_t* inode) { 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); // For call to stat(). 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct stat buffer; 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = stat(path.value().c_str(), &buffer); 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result < 0) 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *inode = buffer.st_ino; 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FILE* OpenFile(const std::string& filename, const char* mode) { 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OpenFile(FilePath(filename), mode); 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FILE* OpenFile(const FilePath& filename, const char* mode) { 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILE* result = NULL; 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = fopen(filename.value().c_str(), mode); 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (!result && errno == EINTR); 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ReadFile(const FilePath& filename, char* data, int size) { 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd = HANDLE_EINTR(open(filename.value().c_str(), O_RDONLY)); 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fd < 0) 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssize_t bytes_read = HANDLE_EINTR(read(fd, data, size)); 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (int ret = HANDLE_EINTR(close(fd)) < 0) 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret; 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bytes_read; 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int WriteFile(const FilePath& filename, const char* data, int size) { 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd = HANDLE_EINTR(creat(filename.value().c_str(), 0666)); 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fd < 0) 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int bytes_written = WriteFileDescriptor(fd, data, size); 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (int ret = HANDLE_EINTR(close(fd)) < 0) 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret; 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bytes_written; 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int WriteFileDescriptor(const int fd, const char* data, int size) { 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Allow for partial writes. 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssize_t bytes_written_total = 0; 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ssize_t bytes_written_partial = 0; bytes_written_total < size; 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_written_total += bytes_written_partial) { 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_written_partial = 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE_EINTR(write(fd, data + bytes_written_total, 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size - bytes_written_total)); 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bytes_written_partial < 0) 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bytes_written_total; 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int AppendToFile(const FilePath& filename, const char* data, int size) { 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd = HANDLE_EINTR(open(filename.value().c_str(), O_WRONLY | O_APPEND)); 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fd < 0) 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int bytes_written = WriteFileDescriptor(fd, data, size); 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (int ret = HANDLE_EINTR(close(fd)) < 0) 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret; 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bytes_written; 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Gets the current working directory for the process. 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetCurrentDirectory(FilePath* dir) { 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // getcwd can return ENOENT, which implies it checks against the disk. 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char system_buffer[PATH_MAX] = ""; 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!getcwd(system_buffer, sizeof(system_buffer))) { 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *dir = FilePath(system_buffer); 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Sets the current working directory for the process. 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SetCurrentDirectory(const FilePath& path) { 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ret = chdir(path.value().c_str()); 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !ret; 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NormalizeFilePath(const FilePath& path, FilePath* normalized_path) { 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath real_path_result; 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!RealPath(path, &real_path_result)) 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // To be consistant with windows, fail if |real_path_result| is a 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // directory. 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stat_wrapper_t file_info; 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CallStat(real_path_result.value().c_str(), &file_info) != 0 || 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) S_ISDIR(file_info.st_mode)) 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *normalized_path = real_path_result; 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX) 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetTempDir(FilePath* path) { 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* tmp = getenv("TMPDIR"); 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tmp) 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *path = FilePath(tmp); 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PathService::Get(base::DIR_CACHE, path); 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *path = FilePath("/tmp"); 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_ANDROID) 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX) 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Determine if /dev/shm files can be mapped and then mprotect'd PROT_EXEC. 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This depends on the mount options used for /dev/shm, which vary among 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// different Linux distributions and possibly local configuration. It also 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// depends on details of kernel--ChromeOS uses the noexec option for /dev/shm 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// but its kernel allows mprotect with PROT_EXEC anyway. 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DetermineDevShmExecutable() { 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = false; 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath path; 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd = CreateAndOpenFdForTemporaryFile(FilePath("/dev/shm"), &path); 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fd >= 0) { 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedFD shm_fd_closer(&fd); 7387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DeleteFile(path, false); 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) long sysconf_result = sysconf(_SC_PAGESIZE); 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_GE(sysconf_result, 0); 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t pagesize = static_cast<size_t>(sysconf_result); 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_GE(sizeof(pagesize), sizeof(sysconf_result)); 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *mapping = mmap(NULL, pagesize, PROT_READ, MAP_SHARED, fd, 0); 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mapping != MAP_FAILED) { 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mprotect(mapping, pagesize, PROT_READ | PROT_EXEC) == 0) 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = true; 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) munmap(mapping, pagesize); 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; // namespace 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // defined(OS_LINUX) 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetShmemTempDir(FilePath* path, bool executable) { 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX) 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool use_dev_shm = true; 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (executable) { 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const bool s_dev_shm_executable = DetermineDevShmExecutable(); 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) use_dev_shm = s_dev_shm_executable; 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (use_dev_shm) { 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *path = FilePath("/dev/shm"); 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetTempDir(path); 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // !defined(OS_ANDROID) 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FilePath GetHomeDir() { 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS) 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::chromeos::IsRunningOnChromeOS()) 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FilePath("/home/chronos/user"); 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* home_dir = getenv("HOME"); 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (home_dir && home_dir[0]) 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FilePath(home_dir); 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(WARNING) << "OS_ANDROID: Home directory lookup not yet implemented."; 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // g_get_home_dir calls getpwent, which can fall through to LDAP calls. 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) home_dir = g_get_home_dir(); 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (home_dir && home_dir[0]) 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FilePath(home_dir); 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath rv; 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (file_util::GetTempDir(&rv)) 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Last resort. 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FilePath("/tmp"); 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // !defined(OS_MACOSX) 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VerifyPathControlledByUser(const FilePath& base, 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FilePath& path, 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uid_t owner_uid, 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::set<gid_t>& group_gids) { 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base != path && !base.IsParent(path)) { 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(ERROR) << "|base| must be a subdirectory of |path|. base = \"" 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << base.value() << "\", path = \"" << path.value() << "\""; 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<FilePath::StringType> base_components; 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<FilePath::StringType> path_components; 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base.GetComponents(&base_components); 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path.GetComponents(&path_components); 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<FilePath::StringType>::const_iterator ib, ip; 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ib = base_components.begin(), ip = path_components.begin(); 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ib != base_components.end(); ++ib, ++ip) { 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |base| must be a subpath of |path|, so all components should match. 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If these CHECKs fail, look at the test that base is a parent of 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // path at the top of this function. 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ip != path_components.end()); 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(*ip == *ib); 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath current_path = base; 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!VerifySpecificPathControlledByUser(current_path, owner_uid, group_gids)) 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (; ip != path_components.end(); ++ip) { 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_path = current_path.Append(*ip); 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!VerifySpecificPathControlledByUser( 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_path, owner_uid, group_gids)) 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX) && !defined(OS_IOS) 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VerifyPathControlledByAdmin(const FilePath& path) { 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const unsigned kRootUid = 0; 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FilePath kFileSystemRoot("/"); 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The name of the administrator group on mac os. 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* const kAdminGroupNames[] = { 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "admin", 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "wheel" 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reading the groups database may touch the file system. 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<gid_t> allowed_group_ids; 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0, ie = arraysize(kAdminGroupNames); i < ie; ++i) { 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct group *group_record = getgrnam(kAdminGroupNames[i]); 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!group_record) { 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DPLOG(ERROR) << "Could not get the group ID of group \"" 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << kAdminGroupNames[i] << "\"."; 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) allowed_group_ids.insert(group_record->gr_gid); 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return VerifyPathControlledByUser( 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kFileSystemRoot, path, kRootUid, allowed_group_ids); 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // defined(OS_MACOSX) && !defined(OS_IOS) 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int GetMaximumPathComponentLength(const FilePath& path) { 8732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 8742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return pathconf(path.value().c_str(), _PC_NAME_MAX); 8752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace file_util 8787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 8797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochnamespace base { 8807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochnamespace internal { 8817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 8827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool MoveUnsafe(const FilePath& from_path, const FilePath& to_path) { 8837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ThreadRestrictions::AssertIOAllowed(); 8847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Windows compatibility: if to_path exists, from_path and to_path 8857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // must be the same type, either both files, or both directories. 8867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch stat_wrapper_t to_file_info; 8877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (CallStat(to_path.value().c_str(), &to_file_info) == 0) { 8887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch stat_wrapper_t from_file_info; 8897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (CallStat(from_path.value().c_str(), &from_file_info) == 0) { 8907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (S_ISDIR(to_file_info.st_mode) != S_ISDIR(from_file_info.st_mode)) 8917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return false; 8927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } else { 8937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return false; 8947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 8957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 8967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 8977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (rename(from_path.value().c_str(), to_path.value().c_str()) == 0) 8987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return true; 8997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 9007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!CopyDirectory(from_path, to_path, true)) 9017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return false; 9027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 9037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DeleteFile(from_path, true); 9047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return true; 9057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 9067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 9077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#if !defined(OS_MACOSX) 9087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Mac has its own implementation, this is for all other Posix systems. 9097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool CopyFileUnsafe(const FilePath& from_path, const FilePath& to_path) { 9107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ThreadRestrictions::AssertIOAllowed(); 9117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch int infile = HANDLE_EINTR(open(from_path.value().c_str(), O_RDONLY)); 9127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (infile < 0) 9137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return false; 9147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 9157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch int outfile = HANDLE_EINTR(creat(to_path.value().c_str(), 0666)); 9167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (outfile < 0) { 9177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ignore_result(HANDLE_EINTR(close(infile))); 9187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return false; 9197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 9207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 9217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const size_t kBufferSize = 32768; 9227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::vector<char> buffer(kBufferSize); 9237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch bool result = true; 9247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 9257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch while (result) { 9267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ssize_t bytes_read = HANDLE_EINTR(read(infile, &buffer[0], buffer.size())); 9277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (bytes_read < 0) { 9287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch result = false; 9297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch break; 9307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 9317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (bytes_read == 0) 9327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch break; 9337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Allow for partial writes 9347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ssize_t bytes_written_per_read = 0; 9357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch do { 9367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ssize_t bytes_written_partial = HANDLE_EINTR(write( 9377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch outfile, 9387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch &buffer[bytes_written_per_read], 9397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch bytes_read - bytes_written_per_read)); 9407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (bytes_written_partial < 0) { 9417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch result = false; 9427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch break; 9437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 9447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch bytes_written_per_read += bytes_written_partial; 9457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } while (bytes_written_per_read < bytes_read); 9467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 9477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 9487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (HANDLE_EINTR(close(infile)) < 0) 9497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch result = false; 9507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (HANDLE_EINTR(close(outfile)) < 0) 9517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch result = false; 9527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 9537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return result; 9547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 9557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#endif // !defined(OS_MACOSX) 9567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 9577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} // namespace internal 9587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} // namespace base 959