OSDN Git Service

Trim root path from output
authorJooyung Han <jooyung@google.com>
Thu, 20 Feb 2020 09:21:03 +0000 (18:21 +0900)
committerJooyung Han <jooyung@google.com>
Fri, 21 Feb 2020 05:57:45 +0000 (14:57 +0900)
When linkerconfig runs on host with --root argument, it prints root as
well like following:

$ linkerconfig --vndk R --root /tmp/test_root
...
namespace.foo.search_paths = /tmp/test_root/product/${LIB}
..

This change trims root from path variables and apex paths so the output
look more like real output.

Bug: n/a
Test: build/boot
      run linkerconfig on host and compare outputs

Change-Id: Icc91f297047f059684a42d825048e50e26873520

17 files changed:
contents/configuration/baseconfig.cc
contents/configuration/legacy.cc
contents/namespace/postinstall.cc
contents/namespace/productdefault.cc
contents/namespace/system.cc
contents/namespace/systemdefault.cc
contents/namespace/vendordefault.cc
contents/namespace/vndkinsystem.cc
contents/tests/backward_compatibility/testbase.h
generator/variableloader.cc
main.cc
modules/apex.cc
modules/include/linkerconfig/apex.h
modules/include/linkerconfig/stringutil.h [new file with mode: 0644]
modules/stringutil.cc [new file with mode: 0644]
modules/tests/apex_test.cc
modules/tests/apex_testbase.h

index 41b2731..d9aa86d 100644 (file)
@@ -58,12 +58,12 @@ android::linkerconfig::modules::Configuration CreateBaseConfiguration(
   std::vector<DirToSection> dirToSection = {
       {"/system/bin/", "system"},
       {"/system/xbin/", "system"},
-      {"/" + Var("SYSTEM_EXT", "system_ext") + "/bin/", "system"},
+      {Var("SYSTEM_EXT") + "/bin/", "system"},
 
       // Processes from the product partition will have a separate section if
       // PRODUCT_PRODUCT_VNDK_VERSION is defined. Otherwise, they are run from
       // the "system" section.
-      {"/" + Var("PRODUCT", "product") + "/bin/", "product"},
+      {Var("PRODUCT") + "/bin/", "product"},
 
       {"/odm/bin/", "vendor"},
       {"/vendor/bin/", "vendor"},
index 52e0186..b857a3d 100644 (file)
@@ -35,8 +35,8 @@ android::linkerconfig::modules::Configuration CreateLegacyConfiguration(
   const std::vector<DirToSection> kDirToSection = {
       // All binaries gets the same configuration 'legacy'
       {"/system", "legacy"},
-      {"/" + Var("SYSTEM_EXT", "system_ext"), "legacy"},
-      {"/" + Var("PRODUCT", "product"), "legacy"},
+      {Var("SYSTEM_EXT"), "legacy"},
+      {Var("PRODUCT"), "legacy"},
       {"/vendor", "legacy"},
       {"/odm", "legacy"},
       {"/sbin", "legacy"},
index 89e75e4..4eed9ea 100644 (file)
@@ -26,9 +26,8 @@ Namespace BuildPostInstallNamespace([[maybe_unused]] const Context& ctx) {
   Namespace ns("default", /*is_isolated=*/false,
                /*is_visible=*/false);
   ns.AddSearchPath("/system/${LIB}", AsanPath::NONE);
-  ns.AddSearchPath("/" + Var("SYSTEM_EXT", "system_ext") + "/${LIB}",
-                   AsanPath::NONE);
-  ns.AddSearchPath("/" + Var("PRODUCT", "product") + "/${LIB}", AsanPath::NONE);
+  ns.AddSearchPath(Var("SYSTEM_EXT") + "/${LIB}", AsanPath::NONE);
+  ns.AddSearchPath(Var("PRODUCT") + "/${LIB}", AsanPath::NONE);
 
   return ns;
 }
index 98eca47..23fe083 100644 (file)
@@ -29,9 +29,9 @@ namespace contents {
 Namespace BuildProductDefaultNamespace([[maybe_unused]] const Context& ctx) {
   Namespace ns("default", /*is_isolated=*/true, /*is_visible=*/true);
 
-  ns.AddSearchPath("/" + Var("PRODUCT", "product") + "/${LIB}",
+  ns.AddSearchPath(Var("PRODUCT", "product") + "/${LIB}",
                    AsanPath::WITH_DATA_ASAN);
-  ns.AddPermittedPath("/" + Var("PRODUCT", "product"), AsanPath::WITH_DATA_ASAN);
+  ns.AddPermittedPath(Var("PRODUCT", "product"), AsanPath::WITH_DATA_ASAN);
 
   ns.GetLink(ctx.GetSystemNamespaceName())
       .AddSharedLib(Var("LLNDK_LIBRARIES_PRODUCT"));
index 1c8c1a1..97de965 100644 (file)
@@ -31,11 +31,9 @@ namespace contents {
 Namespace BuildSystemNamespace([[maybe_unused]] const Context& ctx) {
   Namespace ns("system", /*is_isolated=*/false, /*is_visible=*/false);
   ns.AddSearchPath("/system/${LIB}", AsanPath::WITH_DATA_ASAN);
-  ns.AddSearchPath("/" + Var("SYSTEM_EXT", "system_ext") + "/${LIB}",
-                   AsanPath::WITH_DATA_ASAN);
+  ns.AddSearchPath(Var("SYSTEM_EXT") + "/${LIB}", AsanPath::WITH_DATA_ASAN);
   if (!IsProductVndkVersionDefined()) {
-    ns.AddSearchPath("/" + Var("PRODUCT", "product") + "/${LIB}",
-                     AsanPath::WITH_DATA_ASAN);
+    ns.AddSearchPath(Var("PRODUCT") + "/${LIB}", AsanPath::WITH_DATA_ASAN);
   }
 
   ns.AddRequires(std::vector{"libdexfile_external.so",
index 98296ab..37a5ea3 100644 (file)
@@ -31,8 +31,8 @@ namespace linkerconfig {
 namespace contents {
 Namespace BuildSystemDefaultNamespace([[maybe_unused]] const Context& ctx) {
   bool is_fully_treblelized = ctx.IsDefaultConfig();
-  std::string product = Var("PRODUCT", "product");
-  std::string system_ext = Var("SYSTEM_EXT", "system_ext");
+  std::string product = Var("PRODUCT");
+  std::string system_ext = Var("SYSTEM_EXT");
 
   // Visible to allow links to be created at runtime, e.g. through
   // android_link_namespaces in libnativeloader.
@@ -41,11 +41,11 @@ Namespace BuildSystemDefaultNamespace([[maybe_unused]] const Context& ctx) {
                /*is_visible=*/true);
 
   ns.AddSearchPath("/system/${LIB}", AsanPath::WITH_DATA_ASAN);
-  ns.AddSearchPath("/" + system_ext + "/${LIB}", AsanPath::WITH_DATA_ASAN);
+  ns.AddSearchPath(system_ext + "/${LIB}", AsanPath::WITH_DATA_ASAN);
   if (!IsProductVndkVersionDefined() || !is_fully_treblelized) {
     // System processes can search product libs only if product VNDK is not
     // enforced.
-    ns.AddSearchPath("/" + product + "/${LIB}", AsanPath::WITH_DATA_ASAN);
+    ns.AddSearchPath(product + "/${LIB}", AsanPath::WITH_DATA_ASAN);
   }
   if (!is_fully_treblelized) {
     ns.AddSearchPath("/vendor/${LIB}", AsanPath::WITH_DATA_ASAN);
@@ -64,7 +64,7 @@ Namespace BuildSystemDefaultNamespace([[maybe_unused]] const Context& ctx) {
         "/system/${LIB}/drm",
         "/system/${LIB}/extractors",
         "/system/${LIB}/hw",
-        "/" + system_ext + "/${LIB}",
+        system_ext + "/${LIB}",
 
         // These are where odex files are located. libart has to be able to
         // dlopen the files
@@ -72,9 +72,9 @@ Namespace BuildSystemDefaultNamespace([[maybe_unused]] const Context& ctx) {
 
         "/system/app",
         "/system/priv-app",
-        "/" + system_ext + "/framework",
-        "/" + system_ext + "/app",
-        "/" + system_ext + "/priv-app",
+        system_ext + "/framework",
+        system_ext + "/app",
+        system_ext + "/priv-app",
         "/vendor/framework",
         "/vendor/app",
         "/vendor/priv-app",
@@ -85,9 +85,9 @@ Namespace BuildSystemDefaultNamespace([[maybe_unused]] const Context& ctx) {
         "/odm/app",
         "/odm/priv-app",
         "/oem/app",
-        "/" + product + "/framework",
-        "/" + product + "/app",
-        "/" + product + "/priv-app",
+        product + "/framework",
+        product + "/app",
+        product + "/priv-app",
         "/data",
         "/mnt/expand",
         "/apex/com.android.runtime/${LIB}/bionic",
@@ -98,7 +98,7 @@ Namespace BuildSystemDefaultNamespace([[maybe_unused]] const Context& ctx) {
     }
     if (!IsProductVndkVersionDefined()) {
       // System processes can use product libs only if product VNDK is not enforced.
-      ns.AddPermittedPath("/" + product + "/${LIB}", AsanPath::SAME_PATH);
+      ns.AddPermittedPath(product + "/${LIB}", AsanPath::SAME_PATH);
     }
   }
 
index 3539ab4..51e7160 100644 (file)
@@ -67,10 +67,8 @@ Namespace BuildVendorDefaultNamespace([[maybe_unused]] const Context& ctx) {
   // VNDK-Lite devices require broader access from vendor to system/product partition
   if (is_vndklite) {
     ns.AddSearchPath("/system/${LIB}", AsanPath::WITH_DATA_ASAN);
-    ns.AddSearchPath("/" + Var("SYSTEM_EXT", "system_ext") + "/${LIB}",
-                     AsanPath::WITH_DATA_ASAN);
-    ns.AddSearchPath("/" + Var("PRODUCT", "product") + "/${LIB}",
-                     AsanPath::WITH_DATA_ASAN);
+    ns.AddSearchPath(Var("SYSTEM_EXT") + "/${LIB}", AsanPath::WITH_DATA_ASAN);
+    ns.AddSearchPath(Var("PRODUCT") + "/${LIB}", AsanPath::WITH_DATA_ASAN);
     // Put system vndk at the last search order in vndk_lite for GSI
     ns.AddSearchPath(
         "/apex/com.android.vndk.v" + Var("VENDOR_VNDK_VERSION") + "/${LIB}",
index 071e08c..77d243a 100644 (file)
@@ -42,11 +42,9 @@ Namespace BuildVndkInSystemNamespace([[maybe_unused]] const Context& ctx) {
 
   // The search paths here should be kept the same as that of the 'system' namespace.
   ns.AddSearchPath("/system/${LIB}", AsanPath::WITH_DATA_ASAN);
-  ns.AddSearchPath("/" + Var("SYSTEM_EXT", "system_ext") + "/${LIB}",
-                   AsanPath::WITH_DATA_ASAN);
+  ns.AddSearchPath(Var("SYSTEM_EXT") + "/${LIB}", AsanPath::WITH_DATA_ASAN);
   if (!IsProductVndkVersionDefined()) {
-    ns.AddSearchPath("/" + Var("PRODUCT", "product") + "/${LIB}",
-                     AsanPath::WITH_DATA_ASAN);
+    ns.AddSearchPath(Var("PRODUCT") + "/${LIB}", AsanPath::WITH_DATA_ASAN);
   }
 
   if (android::linkerconfig::modules::IsVndkInSystemNamespace()) {
index 83d9aa2..193b85e 100644 (file)
@@ -38,6 +38,9 @@ inline void MockVariables(std::string vndk_ver = "Q") {
   MockVndkVariables("PRODUCT", vndk_ver);
   Variables::AddValue("ro.product.vndk.version", vndk_ver);
 
+  Variables::AddValue("SYSTEM_EXT", "/system_ext");
+  Variables::AddValue("PRODUCT", "/procut");
+
   Variables::AddValue("VNDK_USING_CORE_VARIANT_LIBRARIES",
                       "vndk_using_core_variant_libraries");
   Variables::AddValue("STUB_LIBRARIES", "stub_libraries");
index 8a60de0..4cd0e83 100644 (file)
 #include "linkerconfig/environment.h"
 #include "linkerconfig/librarylistloader.h"
 #include "linkerconfig/log.h"
+#include "linkerconfig/stringutil.h"
 #include "linkerconfig/variables.h"
 
 using android::base::Result;
 using android::linkerconfig::modules::GetProductVndkVersion;
 using android::linkerconfig::modules::GetVendorVndkVersion;
+using android::linkerconfig::modules::TrimPrefix;
 using android::linkerconfig::modules::Variables;
 
 namespace {
@@ -78,30 +80,29 @@ void LoadVndkVersionVariable() {
 Result<std::string> GetRealPath(std::string target_path) {
   char resolved_path[PATH_MAX];
   if (realpath(target_path.c_str(), resolved_path) != nullptr) {
-    int start_index = 0;
-    if (resolved_path[0] == '/') {
-      start_index = 1;
-    }
-    return &resolved_path[start_index];
+    return resolved_path;
   }
 
   return ErrnoErrorf("Failed to get realpath from {}", target_path);
 }
 
-void LoadVariableFromPartitionPath(std::string variable_name, std::string path) {
-  auto real_path = GetRealPath(path);
+void LoadVariableFromPartitionPath(const std::string& root,
+                                   std::string variable_name,
+                                   std::string partition) {
+  auto real_path = GetRealPath(root + partition);
 
   if (real_path.ok()) {
-    Variables::AddValue(variable_name, *real_path);
+    Variables::AddValue(variable_name, TrimPrefix(*real_path, root));
   } else {
     LOG(WARNING) << real_path.error();
+    Variables::AddValue(variable_name, partition);
   }
 }
 
 void LoadPartitionPathVariables(const std::string& root) {
   // TODO(b/141714913): generalize path handling
-  LoadVariableFromPartitionPath("PRODUCT", root + "/product");
-  LoadVariableFromPartitionPath("SYSTEM_EXT", root + "/system_ext");
+  LoadVariableFromPartitionPath(root, "PRODUCT", "/product");
+  LoadVariableFromPartitionPath(root, "SYSTEM_EXT", "/system_ext");
 }
 
 void LoadVndkLibraryListVariables(const std::string& root,
diff --git a/main.cc b/main.cc
index d82ebf6..de7ba23 100644 (file)
--- a/main.cc
+++ b/main.cc
@@ -13,9 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include <android-base/result.h>
-#include <getopt.h>
 
+#include <climits>
+#include <cstdlib>
 #include <cstring>
 #include <fstream>
 #include <iostream>
 
 #include <errno.h>
 #include <fcntl.h>
+#include <getopt.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 
+#include <android-base/result.h>
+
 #include "linkerconfig/apex.h"
 #include "linkerconfig/apexconfig.h"
 #include "linkerconfig/baseconfig.h"
@@ -81,6 +84,14 @@ struct ProgramArgs {
   exit(status);
 }
 
+std::string RealPath(std::string_view path) {
+  char resolved_path[PATH_MAX];
+  if (realpath(path.data(), resolved_path) != nullptr) {
+    return resolved_path;
+  }
+  PrintUsage(-1);
+}
+
 bool ParseArgs(int argc, char* argv[], ProgramArgs* args) {
   int parse_result;
   while ((parse_result = getopt_long(
@@ -93,7 +104,7 @@ bool ParseArgs(int argc, char* argv[], ProgramArgs* args) {
         args->strict = true;
         break;
       case 'r':
-        args->root = optarg;
+        args->root = RealPath(optarg);
         break;
       case 'v':
         args->vndk_version = optarg;
@@ -170,8 +181,7 @@ Result<void> UpdatePermission([[maybe_unused]] const std::string& file_path) {
 }
 
 Context GetContext(ProgramArgs args) {
-  const std::string apex_root = args.root + "/apex";
-  auto apex_list = android::linkerconfig::modules::ScanActiveApexes(apex_root);
+  auto apex_list = android::linkerconfig::modules::ScanActiveApexes(args.root);
   Context ctx;
   for (auto const& apex_item : apex_list) {
     auto apex_info = apex_item.second;
index 6c71073..9c31979 100644 (file)
 
 #include <apexutil.h>
 
+#include "linkerconfig/stringutil.h"
+
 namespace {
+
 bool DirExists(const std::string& path) {
   return access(path.c_str(), F_OK) == 0;
 }
+
 }  // namespace
 
 namespace android {
 namespace linkerconfig {
 namespace modules {
-std::map<std::string, ApexInfo> ScanActiveApexes(const std::string& apex_root) {
+
+std::map<std::string, ApexInfo> ScanActiveApexes(const std::string& root) {
   std::map<std::string, ApexInfo> apexes;
+  const auto apex_root = root + apex::kApexRoot;
   for (const auto& [path, manifest] : apex::GetActivePackages(apex_root)) {
     bool has_bin = DirExists(path + "/bin");
     bool has_lib = DirExists(path + "/lib") || DirExists(path + "/lib64");
     ApexInfo info(manifest.name(),
-                  path,
+                  TrimPrefix(path, root),
                   {manifest.providenativelibs().begin(),
                    manifest.providenativelibs().end()},
                   {manifest.requirenativelibs().begin(),
@@ -45,6 +51,7 @@ std::map<std::string, ApexInfo> ScanActiveApexes(const std::string& apex_root) {
   }
   return apexes;
 }
+
 }  // namespace modules
 }  // namespace linkerconfig
 }  // namespace android
\ No newline at end of file
index 4e0a6dc..8fb7d32 100644 (file)
@@ -48,7 +48,7 @@ struct ApexInfo {
   }
 };
 
-std::map<std::string, ApexInfo> ScanActiveApexes(const std::string& apex_root);
+std::map<std::string, ApexInfo> ScanActiveApexes(const std::string& root);
 }  // namespace modules
 }  // namespace linkerconfig
 }  // namespace android
\ No newline at end of file
diff --git a/modules/include/linkerconfig/stringutil.h b/modules/include/linkerconfig/stringutil.h
new file mode 100644 (file)
index 0000000..f5896f5
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <string>
+
+namespace android {
+namespace linkerconfig {
+namespace modules {
+std::string TrimPrefix(const std::string& s, const std::string& prefix);
+}
+}  // namespace linkerconfig
+}  // namespace android
\ No newline at end of file
diff --git a/modules/stringutil.cc b/modules/stringutil.cc
new file mode 100644 (file)
index 0000000..e695e3b
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "linkerconfig/stringutil.h"
+
+#include <android-base/strings.h>
+
+namespace android {
+namespace linkerconfig {
+namespace modules {
+std::string TrimPrefix(const std::string& s, const std::string& prefix) {
+  if (android::base::StartsWith(s, prefix)) {
+    return s.substr(prefix.size());
+  }
+  return s;
+}
+}  // namespace modules
+}  // namespace linkerconfig
+}  // namespace android
\ No newline at end of file
index b3b2053..2385d0f 100644 (file)
@@ -96,11 +96,11 @@ TEST(apex_namespace, resolve_between_apex_namespaces) {
 
 TEST_F(ApexTest, scan_apex_dir) {
   PrepareApex("foo", {}, {"bar.so"});
-  WriteFile("foo/bin/foo", "");
+  WriteFile("/apex/foo/bin/foo", "");
   PrepareApex("bar", {"bar.so"}, {});
-  WriteFile("bar/lib64/bar.so", "");
+  WriteFile("/apex/bar/lib64/bar.so", "");
 
-  auto apexes = ScanActiveApexes(apex_root);
+  auto apexes = ScanActiveApexes(root);
   ASSERT_EQ(2U, apexes.size());
 
   ASSERT_THAT(apexes["foo"].require_libs, Contains("bar.so"));
index a7f5e87..d32086e 100644 (file)
 
 #include "linkerconfig/apex.h"
 
+#include <iostream>
+
 struct ApexTest : ::testing::Test {
   TemporaryDir tmp_dir;
-  std::string apex_root;
+  std::string root;
 
   void SetUp() override {
-    apex_root = tmp_dir.path + std::string("/");
+    root = tmp_dir.path;
   }
 
   android::linkerconfig::modules::ApexInfo PrepareApex(
@@ -40,10 +42,11 @@ struct ApexTest : ::testing::Test {
     for (auto lib : required_libs) {
       manifest.add_requirenativelibs(lib);
     }
-    WriteFile(apex_name + "/apex_manifest.pb", manifest.SerializeAsString());
+    const auto apex_path = "/apex/" + apex_name;
+    WriteFile(apex_path + "/apex_manifest.pb", manifest.SerializeAsString());
     return android::linkerconfig::modules::ApexInfo(
         manifest.name(),
-        tmp_dir.path,
+        apex_path,
         {manifest.providenativelibs().begin(),
          manifest.providenativelibs().end()},
         {manifest.requirenativelibs().begin(),
@@ -55,13 +58,15 @@ struct ApexTest : ::testing::Test {
   void Mkdir(std::string dir_path) {
     if (access(dir_path.c_str(), F_OK) == 0) return;
     Mkdir(android::base::Dirname(dir_path));
+    std::cout << "mkdir(" + dir_path + ")\n";
     ASSERT_NE(-1, mkdir(dir_path.c_str(), 0755) == -1)
         << "Failed to create a directory: " << dir_path;
   }
 
   void WriteFile(std::string file, std::string content) {
-    std::string file_path = apex_root + file;
+    std::string file_path = root + file;
     Mkdir(::android::base::Dirname(file_path));
+    std::cout << "writeFile(" + file_path + ")\n";
     ASSERT_TRUE(::android::base::WriteStringToFile(content, file_path))
         << "Failed to write a file: " << file_path;
   }