1a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov/* 2a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov * Copyright (C) 2015 The Android Open Source Project 3bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * All rights reserved. 4a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov * 5bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * Redistribution and use in source and binary forms, with or without 6bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * modification, are permitted provided that the following conditions 7bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * are met: 8bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * * Redistributions of source code must retain the above copyright 9bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * notice, this list of conditions and the following disclaimer. 10bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * * Redistributions in binary form must reproduce the above copyright 11bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * notice, this list of conditions and the following disclaimer in 12bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * the documentation and/or other materials provided with the 13bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * distribution. 14a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov * 15bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * SUCH DAMAGE. 27a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov */ 28a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov 29a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov#include "linker_utils.h" 3048ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov 31a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov#include "linker_debug.h" 3248ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov#include "linker_globals.h" 3348ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov 3448ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov#include "android-base/strings.h" 3548ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov 3648ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov#include <sys/stat.h> 3748ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov#include <unistd.h> 3848ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov 392a6d9b25437c42fd3e0284a6e7a607c842f59fe0Dimitry Ivanovvoid format_string(std::string* str, const std::vector<std::pair<std::string, std::string>>& params) { 402a6d9b25437c42fd3e0284a6e7a607c842f59fe0Dimitry Ivanov size_t pos = 0; 412a6d9b25437c42fd3e0284a6e7a607c842f59fe0Dimitry Ivanov while (pos < str->size()) { 422a6d9b25437c42fd3e0284a6e7a607c842f59fe0Dimitry Ivanov pos = str->find("$", pos); 432a6d9b25437c42fd3e0284a6e7a607c842f59fe0Dimitry Ivanov if (pos == std::string::npos) break; 442a6d9b25437c42fd3e0284a6e7a607c842f59fe0Dimitry Ivanov for (const auto& param : params) { 452a6d9b25437c42fd3e0284a6e7a607c842f59fe0Dimitry Ivanov const std::string& token = param.first; 462a6d9b25437c42fd3e0284a6e7a607c842f59fe0Dimitry Ivanov const std::string& replacement = param.second; 472a6d9b25437c42fd3e0284a6e7a607c842f59fe0Dimitry Ivanov if (str->substr(pos + 1, token.size()) == token) { 482a6d9b25437c42fd3e0284a6e7a607c842f59fe0Dimitry Ivanov str->replace(pos, token.size() + 1, replacement); 492a6d9b25437c42fd3e0284a6e7a607c842f59fe0Dimitry Ivanov // -1 to compensate for the ++pos below. 502a6d9b25437c42fd3e0284a6e7a607c842f59fe0Dimitry Ivanov pos += replacement.size() - 1; 512a6d9b25437c42fd3e0284a6e7a607c842f59fe0Dimitry Ivanov break; 522a6d9b25437c42fd3e0284a6e7a607c842f59fe0Dimitry Ivanov } else if (str->substr(pos + 1, token.size() + 2) == "{" + token + "}") { 532a6d9b25437c42fd3e0284a6e7a607c842f59fe0Dimitry Ivanov str->replace(pos, token.size() + 3, replacement); 542a6d9b25437c42fd3e0284a6e7a607c842f59fe0Dimitry Ivanov pos += replacement.size() - 1; 552a6d9b25437c42fd3e0284a6e7a607c842f59fe0Dimitry Ivanov break; 562a6d9b25437c42fd3e0284a6e7a607c842f59fe0Dimitry Ivanov } 572a6d9b25437c42fd3e0284a6e7a607c842f59fe0Dimitry Ivanov } 582a6d9b25437c42fd3e0284a6e7a607c842f59fe0Dimitry Ivanov // Skip $ in case it did not match any of the known substitutions. 592a6d9b25437c42fd3e0284a6e7a607c842f59fe0Dimitry Ivanov ++pos; 602a6d9b25437c42fd3e0284a6e7a607c842f59fe0Dimitry Ivanov } 612a6d9b25437c42fd3e0284a6e7a607c842f59fe0Dimitry Ivanov} 622a6d9b25437c42fd3e0284a6e7a607c842f59fe0Dimitry Ivanov 6348ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanovstd::string dirname(const char* path) { 6448ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov const char* last_slash = strrchr(path, '/'); 6548ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov 6648ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov if (last_slash == path) { 6748ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov return "/"; 6848ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov } else if (last_slash == nullptr) { 6948ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov return "."; 7048ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov } else { 7148ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov return std::string(path, last_slash - path); 7248ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov } 7348ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov} 74a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov 75a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanovbool normalize_path(const char* path, std::string* normalized_path) { 76a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov // Input should be an absolute path 77a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov if (path[0] != '/') { 78769b33fadf45a039741f932672ac2c4f901d7d4aDimitry Ivanov PRINT("normalize_path - invalid input: \"%s\", the input path should be absolute", path); 79a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov return false; 80a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov } 81a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov 82a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov const size_t len = strlen(path) + 1; 83a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov char buf[len]; 84a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov 85a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov const char* in_ptr = path; 86a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov char* out_ptr = buf; 87a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov 88a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov while (*in_ptr != 0) { 89a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov if (*in_ptr == '/') { 90a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov char c1 = in_ptr[1]; 91a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov if (c1 == '.') { 92a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov char c2 = in_ptr[2]; 93a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov if (c2 == '/') { 94a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov in_ptr += 2; 95a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov continue; 96a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov } else if (c2 == '.' && (in_ptr[3] == '/' || in_ptr[3] == 0)) { 97a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov in_ptr += 3; 98a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov while (out_ptr > buf && *--out_ptr != '/') { 99a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov } 100a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov if (in_ptr[0] == 0) { 101a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov // retain '/' 102a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov out_ptr++; 103a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov } 104a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov continue; 105a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov } 106a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov } else if (c1 == '/') { 107a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov ++in_ptr; 108a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov continue; 109a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov } 110a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov } 111a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov *out_ptr++ = *in_ptr++; 112a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov } 113a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov 114a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov *out_ptr = 0; 115a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov *normalized_path = buf; 116a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov return true; 117a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov} 118a1feb117e4d5614548574f28dede3443e073512bDmitriy Ivanov 11942d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanovbool file_is_in_dir(const std::string& file, const std::string& dir) { 12042d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov const char* needle = dir.c_str(); 12142d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov const char* haystack = file.c_str(); 12242d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov size_t needle_len = strlen(needle); 12342d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov 124284ae3559ed909613b189b98bdc3efab94373a30Dimitry Ivanov return strncmp(haystack, needle, needle_len) == 0 && 125284ae3559ed909613b189b98bdc3efab94373a30Dimitry Ivanov haystack[needle_len] == '/' && 126284ae3559ed909613b189b98bdc3efab94373a30Dimitry Ivanov strchr(haystack + needle_len + 1, '/') == nullptr; 127284ae3559ed909613b189b98bdc3efab94373a30Dimitry Ivanov} 128284ae3559ed909613b189b98bdc3efab94373a30Dimitry Ivanov 129284ae3559ed909613b189b98bdc3efab94373a30Dimitry Ivanovbool file_is_under_dir(const std::string& file, const std::string& dir) { 130284ae3559ed909613b189b98bdc3efab94373a30Dimitry Ivanov const char* needle = dir.c_str(); 131284ae3559ed909613b189b98bdc3efab94373a30Dimitry Ivanov const char* haystack = file.c_str(); 132284ae3559ed909613b189b98bdc3efab94373a30Dimitry Ivanov size_t needle_len = strlen(needle); 133284ae3559ed909613b189b98bdc3efab94373a30Dimitry Ivanov 134284ae3559ed909613b189b98bdc3efab94373a30Dimitry Ivanov return strncmp(haystack, needle, needle_len) == 0 && 135284ae3559ed909613b189b98bdc3efab94373a30Dimitry Ivanov haystack[needle_len] == '/'; 13642d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov} 13742d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov 13842d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanovconst char* const kZipFileSeparator = "!/"; 13942d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov 14042d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanovbool parse_zip_path(const char* input_path, std::string* zip_path, std::string* entry_path) { 14142d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov std::string normalized_path; 14242d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov if (!normalize_path(input_path, &normalized_path)) { 14342d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov return false; 14442d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov } 14542d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov 14642d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov const char* const path = normalized_path.c_str(); 147769b33fadf45a039741f932672ac2c4f901d7d4aDimitry Ivanov TRACE("Trying zip file open from path \"%s\" -> normalized \"%s\"", input_path, path); 14842d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov 14942d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov // Treat an '!/' separator inside a path as the separator between the name 15042d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov // of the zip file on disk and the subdirectory to search within it. 15142d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov // For example, if path is "foo.zip!/bar/bas/x.so", then we search for 15242d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov // "bar/bas/x.so" within "foo.zip". 15342d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov const char* const separator = strstr(path, kZipFileSeparator); 15442d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov if (separator == nullptr) { 15542d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov return false; 15642d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov } 15742d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov 15842d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov char buf[512]; 15942d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov if (strlcpy(buf, path, sizeof(buf)) >= sizeof(buf)) { 16042d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov PRINT("Warning: ignoring very long library path: %s", path); 16142d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov return false; 16242d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov } 16342d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov 16442d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov buf[separator - path] = '\0'; 16542d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov 16642d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov *zip_path = buf; 16742d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov *entry_path = &buf[separator - path + 2]; 16842d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov 16942d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov return true; 17042d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov} 17142d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov 17284bab5a9552cebf57795ade0e1abd5f7aee46479Dmitriy Ivanovconstexpr off64_t kPageMask = ~static_cast<off64_t>(PAGE_SIZE-1); 17384bab5a9552cebf57795ade0e1abd5f7aee46479Dmitriy Ivanov 17484bab5a9552cebf57795ade0e1abd5f7aee46479Dmitriy Ivanovoff64_t page_start(off64_t offset) { 17584bab5a9552cebf57795ade0e1abd5f7aee46479Dmitriy Ivanov return offset & kPageMask; 17684bab5a9552cebf57795ade0e1abd5f7aee46479Dmitriy Ivanov} 17784bab5a9552cebf57795ade0e1abd5f7aee46479Dmitriy Ivanov 17884bab5a9552cebf57795ade0e1abd5f7aee46479Dmitriy Ivanovbool safe_add(off64_t* out, off64_t a, size_t b) { 17984bab5a9552cebf57795ade0e1abd5f7aee46479Dmitriy Ivanov CHECK(a >= 0); 18084bab5a9552cebf57795ade0e1abd5f7aee46479Dmitriy Ivanov if (static_cast<uint64_t>(INT64_MAX - a) < b) { 18184bab5a9552cebf57795ade0e1abd5f7aee46479Dmitriy Ivanov return false; 18284bab5a9552cebf57795ade0e1abd5f7aee46479Dmitriy Ivanov } 18384bab5a9552cebf57795ade0e1abd5f7aee46479Dmitriy Ivanov 18484bab5a9552cebf57795ade0e1abd5f7aee46479Dmitriy Ivanov *out = a + b; 18584bab5a9552cebf57795ade0e1abd5f7aee46479Dmitriy Ivanov return true; 18684bab5a9552cebf57795ade0e1abd5f7aee46479Dmitriy Ivanov} 18784bab5a9552cebf57795ade0e1abd5f7aee46479Dmitriy Ivanov 18884bab5a9552cebf57795ade0e1abd5f7aee46479Dmitriy Ivanovsize_t page_offset(off64_t offset) { 18984bab5a9552cebf57795ade0e1abd5f7aee46479Dmitriy Ivanov return static_cast<size_t>(offset & (PAGE_SIZE-1)); 19084bab5a9552cebf57795ade0e1abd5f7aee46479Dmitriy Ivanov} 19184bab5a9552cebf57795ade0e1abd5f7aee46479Dmitriy Ivanov 19248ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanovvoid split_path(const char* path, const char* delimiters, 19348ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov std::vector<std::string>* paths) { 19448ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov if (path != nullptr && path[0] != 0) { 19548ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov *paths = android::base::Split(path, delimiters); 19648ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov } 19748ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov} 19848ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov 19948ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanovvoid resolve_paths(std::vector<std::string>& paths, 20048ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov std::vector<std::string>* resolved_paths) { 20148ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov resolved_paths->clear(); 20248ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov for (const auto& path : paths) { 20301fdb6ad571187498f47e570ba17441f560ba65cDimitry Ivanov // skip empty paths 20401fdb6ad571187498f47e570ba17441f560ba65cDimitry Ivanov if (path.empty()) { 20501fdb6ad571187498f47e570ba17441f560ba65cDimitry Ivanov continue; 20601fdb6ad571187498f47e570ba17441f560ba65cDimitry Ivanov } 20701fdb6ad571187498f47e570ba17441f560ba65cDimitry Ivanov 20848ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov char resolved_path[PATH_MAX]; 20948ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov const char* original_path = path.c_str(); 21048ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov if (realpath(original_path, resolved_path) != nullptr) { 21148ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov struct stat s; 21248ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov if (stat(resolved_path, &s) == 0) { 21348ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov if (S_ISDIR(s.st_mode)) { 21448ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov resolved_paths->push_back(resolved_path); 21548ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov } else { 21648ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov DL_WARN("Warning: \"%s\" is not a directory (excluding from path)", resolved_path); 21748ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov continue; 21848ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov } 21948ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov } else { 22048ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov DL_WARN("Warning: cannot stat file \"%s\": %s", resolved_path, strerror(errno)); 22148ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov continue; 22248ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov } 22348ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov } else { 22448ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov std::string zip_path; 22548ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov std::string entry_path; 22648ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov 22748ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov std::string normalized_path; 22848ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov 22948ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov if (!normalize_path(original_path, &normalized_path)) { 23048ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov DL_WARN("Warning: unable to normalize \"%s\"", original_path); 23148ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov continue; 23248ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov } 23348ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov 23448ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov if (parse_zip_path(normalized_path.c_str(), &zip_path, &entry_path)) { 23548ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov if (realpath(zip_path.c_str(), resolved_path) == nullptr) { 23648ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov DL_WARN("Warning: unable to resolve \"%s\": %s", zip_path.c_str(), strerror(errno)); 23748ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov continue; 23848ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov } 23948ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov 24048ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov resolved_paths->push_back(std::string(resolved_path) + kZipFileSeparator + entry_path); 24148ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov } 24248ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov } 24348ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov } 24448ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov} 24548ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov 246