1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/base_paths.h" 6 7 #include <ostream> 8 #include <string> 9 10 #include "build/build_config.h" 11 #include "base/environment.h" 12 #include "base/file_path.h" 13 #include "base/file_util.h" 14 #include "base/logging.h" 15 #include "base/memory/scoped_ptr.h" 16 #include "base/path_service.h" 17 #include "base/nix/xdg_util.h" 18 19 #if defined(OS_FREEBSD) 20 #include <sys/param.h> 21 #include <sys/sysctl.h> 22 #endif 23 24 namespace base { 25 26 #if defined(OS_LINUX) 27 const char kSelfExe[] = "/proc/self/exe"; 28 #elif defined(OS_SOLARIS) 29 const char kSelfExe[] = getexecname(); 30 #endif 31 32 // The name of this file relative to the source root. This is used for checking 33 // that the source checkout is in the correct place. 34 static const char kThisSourceFile[] = "base/base_paths_linux.cc"; 35 36 bool PathProviderPosix(int key, FilePath* result) { 37 FilePath path; 38 switch (key) { 39 case base::FILE_EXE: 40 case base::FILE_MODULE: { // TODO(evanm): is this correct? 41 #if defined(OS_LINUX) 42 FilePath bin_dir; 43 if (!file_util::ReadSymbolicLink(FilePath(kSelfExe), &bin_dir)) { 44 NOTREACHED() << "Unable to resolve " << kSelfExe << "."; 45 return false; 46 } 47 *result = bin_dir; 48 return true; 49 #elif defined(OS_FREEBSD) 50 int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; 51 char bin_dir[PATH_MAX + 1]; 52 size_t length = sizeof(bin_dir); 53 int error = sysctl(name, 4, bin_dir, &length, NULL, 0); 54 if (error < 0 || length == 0 || strlen(bin_dir) == 0) { 55 NOTREACHED() << "Unable to resolve path."; 56 return false; 57 } 58 bin_dir[strlen(bin_dir)] = 0; 59 *result = FilePath(bin_dir); 60 return true; 61 #endif 62 } 63 case base::DIR_SOURCE_ROOT: { 64 // Allow passing this in the environment, for more flexibility in build 65 // tree configurations (sub-project builds, gyp --output_dir, etc.) 66 scoped_ptr<base::Environment> env(base::Environment::Create()); 67 std::string cr_source_root; 68 if (env->GetVar("CR_SOURCE_ROOT", &cr_source_root)) { 69 path = FilePath(cr_source_root); 70 if (file_util::PathExists(path.Append(kThisSourceFile))) { 71 *result = path; 72 return true; 73 } else { 74 LOG(WARNING) << "CR_SOURCE_ROOT is set, but it appears to not " 75 << "point to the correct source root directory."; 76 } 77 } 78 // On POSIX, unit tests execute two levels deep from the source root. 79 // For example: out/{Debug|Release}/net_unittest 80 if (PathService::Get(base::DIR_EXE, &path)) { 81 path = path.DirName().DirName(); 82 if (file_util::PathExists(path.Append(kThisSourceFile))) { 83 *result = path; 84 return true; 85 } 86 } 87 // In a case of WebKit-only checkout, executable files are put into 88 // <root of checkout>/out/{Debug|Release}, and we should return 89 // <root of checkout>/Source/WebKit/chromium for DIR_SOURCE_ROOT. 90 if (PathService::Get(base::DIR_EXE, &path)) { 91 path = path.DirName().DirName().Append("Source/WebKit/chromium"); 92 if (file_util::PathExists(path.Append(kThisSourceFile))) { 93 *result = path; 94 return true; 95 } 96 } 97 // If that failed (maybe the build output is symlinked to a different 98 // drive) try assuming the current directory is the source root. 99 if (file_util::GetCurrentDirectory(&path) && 100 file_util::PathExists(path.Append(kThisSourceFile))) { 101 *result = path; 102 return true; 103 } 104 LOG(ERROR) << "Couldn't find your source root. " 105 << "Try running from your chromium/src directory."; 106 return false; 107 } 108 case base::DIR_CACHE: 109 #ifdef ANDROID 110 NOTREACHED(); 111 return false; 112 #else 113 scoped_ptr<base::Environment> env(base::Environment::Create()); 114 FilePath cache_dir(base::nix::GetXDGDirectory(env.get(), "XDG_CACHE_HOME", 115 ".cache")); 116 *result = cache_dir; 117 return true; 118 #endif 119 } 120 return false; 121 } 122 123 } // namespace base 124