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