• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
PathProviderPosix(int key,FilePath * result)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