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)// Defines base::PathProviderPosix, default path provider on POSIX OSes that
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// don't have their own base_paths_OS.cc implementation (i.e. all but Mac and
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Android).
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ostream>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_paths.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/environment.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/files/file_util.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/nix/xdg_util.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
2058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "base/process/process_metrics.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_FREEBSD)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/param.h>
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/sysctl.h>
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_SOLARIS)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h>
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PathProviderPosix(int key, FilePath* result) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FilePath path;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (key) {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case base::FILE_EXE:
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case base::FILE_MODULE: {  // TODO(evanm): is this correct?
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FilePath bin_dir;
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (!ReadSymbolicLink(FilePath(kProcSelfExe), &bin_dir)) {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTREACHED() << "Unable to resolve " << kProcSelfExe << ".";
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = bin_dir;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_FREEBSD)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      char bin_dir[PATH_MAX + 1];
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      size_t length = sizeof(bin_dir);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Upon return, |length| is the number of bytes written to |bin_dir|
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // including the string terminator.
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int error = sysctl(name, 4, bin_dir, &length, NULL, 0);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (error < 0 || length <= 1) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTREACHED() << "Unable to resolve path.";
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = FilePath(FilePath::StringType(bin_dir, length - 1));
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_SOLARIS)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      char bin_dir[PATH_MAX + 1];
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (realpath(getexecname(), bin_dir) == NULL) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTREACHED() << "Unable to resolve " << getexecname() << ".";
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = FilePath(bin_dir);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_OPENBSD)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // There is currently no way to get the executable path on OpenBSD
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      char* cpath;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((cpath = getenv("CHROME_EXE_PATH")) != NULL)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result = FilePath(cpath);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result = FilePath("/usr/local/chrome/chrome");
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case base::DIR_SOURCE_ROOT: {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Allow passing this in the environment, for more flexibility in build
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // tree configurations (sub-project builds, gyp --output_dir, etc.)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_ptr<base::Environment> env(base::Environment::Create());
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string cr_source_root;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (env->GetVar("CR_SOURCE_ROOT", &cr_source_root)) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        path = FilePath(cr_source_root);
837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        if (base::PathExists(path)) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          *result = path;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DLOG(WARNING) << "CR_SOURCE_ROOT is set, but it appears to not "
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        << "point to a directory.";
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // On POSIX, unit tests execute two levels deep from the source root.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // For example:  out/{Debug|Release}/net_unittest
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (PathService::Get(base::DIR_EXE, &path)) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result = path.DirName().DirName();
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DLOG(ERROR) << "Couldn't find your source root.  "
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  << "Try running from your chromium/src directory.";
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case base::DIR_USER_DESKTOP:
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = base::nix::GetXDGUserDirectory("DESKTOP", "Desktop");
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case base::DIR_CACHE: {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_ptr<base::Environment> env(base::Environment::Create());
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FilePath cache_dir(base::nix::GetXDGDirectory(env.get(), "XDG_CACHE_HOME",
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    ".cache"));
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = cache_dir;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
117