Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 804e819c authored by Tomasz Wasilczyk's avatar Tomasz Wasilczyk
Browse files

Move String8 path functions to androidfw and aapt

Test: m checkbuild
Bug: 295394788
Change-Id: I9488bc5632cbd47c83f6b5f2df4c87eb324a1e8e
parent cc7212dd
Loading
Loading
Loading
Loading
+26 −1
Original line number Diff line number Diff line
@@ -80,7 +80,10 @@ cc_library {
    export_include_dirs: ["include"],
    export_shared_lib_headers: ["libz"],
    static_libs: ["libincfs-utils"],
    whole_static_libs: ["libincfs-utils"],
    whole_static_libs: [
        "libandroidfw_pathutils",
        "libincfs-utils",
    ],
    export_static_lib_headers: ["libincfs-utils"],
    target: {
        android: {
@@ -132,6 +135,28 @@ cc_library {
    },
}

cc_library_static {
    name: "libandroidfw_pathutils",
    defaults: ["libandroidfw_defaults"],
    host_supported: true,
    export_include_dirs: ["include_pathutils"],
    srcs: [
        "PathUtils.cpp",
    ],
    shared_libs: [
        "libutils",
    ],
    target: {
        windows: {
            enabled: true,
        },
    },
    visibility: [
        ":__subpackages__",
        "//frameworks/base/tools/aapt",
    ],
}

common_test_libs = [
    "libandroidfw",
    "libbase",
+20 −20
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include <androidfw/AssetDir.h>
#include <androidfw/AssetManager.h>
#include <androidfw/misc.h>
#include <androidfw/PathUtils.h>
#include <androidfw/ResourceTypes.h>
#include <androidfw/ZipFileRO.h>
#include <cutils/atomic.h>
@@ -88,7 +89,7 @@ String8 idmapPathForPackagePath(const String8& pkgPath) {
    const char* root = getenv("ANDROID_DATA");
    LOG_ALWAYS_FATAL_IF(root == NULL, "ANDROID_DATA not set");
    String8 path(root);
    path.appendPath(kResourceCache);
    appendPath(path, kResourceCache);

    char buf[256]; // 256 chars should be enough for anyone...
    strncpy(buf, pkgPath.c_str(), 255);
@@ -104,7 +105,7 @@ String8 idmapPathForPackagePath(const String8& pkgPath) {
        }
        ++p;
    }
    path.appendPath(filename);
    appendPath(path, filename);
    path.append("@idmap");

    return path;
@@ -181,7 +182,7 @@ bool AssetManager::addAssetPath(

    String8 realPath(path);
    if (kAppZipName) {
        realPath.appendPath(kAppZipName);
        appendPath(realPath, kAppZipName);
    }
    ap.type = ::getFileType(realPath.c_str());
    if (ap.type == kFileTypeRegular) {
@@ -367,7 +368,7 @@ bool AssetManager::addDefaultAssets()
    LOG_ALWAYS_FATAL_IF(root == NULL, "ANDROID_ROOT not set");

    String8 path(root);
    path.appendPath(kSystemAssets);
    appendPath(path, kSystemAssets);

    return addAssetPath(path, NULL, false /* appAsLib */, true /* isSystemAsset */);
}
@@ -439,7 +440,7 @@ Asset* AssetManager::open(const char* fileName, AccessMode mode)
    LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager");

    String8 assetName(kAssetsRoot);
    assetName.appendPath(fileName);
    appendPath(assetName, fileName);

    /*
     * For each top-level asset path, search for the asset.
@@ -587,8 +588,8 @@ bool AssetManager::appendPathToResTable(asset_path& ap, bool appAsLib) const {
                const char* data = getenv("ANDROID_DATA");
                LOG_ALWAYS_FATAL_IF(data == NULL, "ANDROID_DATA not set");
                String8 overlaysListPath(data);
                overlaysListPath.appendPath(kResourceCache);
                overlaysListPath.appendPath("overlays.list");
                appendPath(overlaysListPath, kResourceCache);
                appendPath(overlaysListPath, "overlays.list");
                addSystemOverlays(overlaysListPath.c_str(), ap.path, sharedRes, nextEntryIdx);
#endif
                sharedRes = const_cast<AssetManager*>(this)->
@@ -789,7 +790,7 @@ Asset* AssetManager::openNonAssetInPathLocked(const char* fileName, AccessMode m
    /* look at the filesystem on disk */
    if (ap.type == kFileTypeDirectory) {
        String8 path(ap.path);
        path.appendPath(fileName);
        appendPath(path, fileName);

        pAsset = openAssetFromFileLocked(path, mode);

@@ -841,9 +842,9 @@ String8 AssetManager::createZipSourceNameLocked(const String8& zipFileName,
    sourceName.append(zipFileName);
    sourceName.append(":");
    if (dirName.length() > 0) {
        sourceName.appendPath(dirName);
        appendPath(sourceName, dirName);
    }
    sourceName.appendPath(fileName);
    appendPath(sourceName, fileName);
    return sourceName;
}

@@ -853,7 +854,7 @@ String8 AssetManager::createZipSourceNameLocked(const String8& zipFileName,
String8 AssetManager::createPathNameLocked(const asset_path& ap, const char* rootDir)
{
    String8 path(ap.path);
    if (rootDir != NULL) path.appendPath(rootDir);
    if (rootDir != NULL) appendPath(path, rootDir);
    return path;
}

@@ -897,7 +898,7 @@ Asset* AssetManager::openAssetFromFileLocked(const String8& pathName,
{
    Asset* pAsset = NULL;

    if (strcasecmp(pathName.getPathExtension().c_str(), ".gz") == 0) {
    if (strcasecmp(getPathExtension(pathName).c_str(), ".gz") == 0) {
        //printf("TRYING '%s'\n", (const char*) pathName);
        pAsset = Asset::createFromCompressedFile(pathName.c_str(), mode);
    } else {
@@ -1078,8 +1079,7 @@ bool AssetManager::scanAndMergeDirLocked(SortedVector<AssetDir::FileInfo>* pMerg
    //printf("scanAndMergeDir: %s %s %s\n", ap.path.c_str(), rootDir, dirName);

    String8 path = createPathNameLocked(ap, rootDir);
    if (dirName[0] != '\0')
        path.appendPath(dirName);
    if (dirName[0] != '\0') appendPath(path, dirName);

    SortedVector<AssetDir::FileInfo>* pContents = scanDirLocked(path);
    if (pContents == NULL)
@@ -1176,7 +1176,7 @@ SortedVector<AssetDir::FileInfo>* AssetManager::scanDirLocked(const String8& pat
            fileType = kFileTypeUnknown;
#else
        // stat the file
        fileType = ::getFileType(path.appendPathCopy(entry->d_name).c_str());
        fileType = ::getFileType(appendPathCopy(path, entry->d_name).c_str());
#endif

        if (fileType != kFileTypeRegular && fileType != kFileTypeDirectory)
@@ -1184,9 +1184,9 @@ SortedVector<AssetDir::FileInfo>* AssetManager::scanDirLocked(const String8& pat

        AssetDir::FileInfo info;
        info.set(String8(entry->d_name), fileType);
        if (strcasecmp(info.getFileName().getPathExtension().c_str(), ".gz") == 0)
            info.setFileName(info.getFileName().getBasePath());
        info.setSourceName(path.appendPathCopy(info.getFileName()));
        if (strcasecmp(getPathExtension(info.getFileName()).c_str(), ".gz") == 0)
            info.setFileName(getBasePath(info.getFileName()));
        info.setSourceName(appendPathCopy(path, info.getFileName()));
        pContents->add(info);
    }

@@ -1220,7 +1220,7 @@ bool AssetManager::scanAndMergeZipLocked(SortedVector<AssetDir::FileInfo>* pMerg

    /* convert "sounds" to "rootDir/sounds" */
    if (rootDir != NULL) dirName = rootDir;
    dirName.appendPath(baseDirName);
    appendPath(dirName, baseDirName);

    /*
     * Scan through the list of files, looking for a match.  The files in
@@ -1269,7 +1269,7 @@ bool AssetManager::scanAndMergeZipLocked(SortedVector<AssetDir::FileInfo>* pMerg
            if (nextSlash == NULL) {
                /* this is a file in the requested directory */

                info.set(String8(nameBuf).getPathLeaf(), kFileTypeRegular);
                info.set(getPathLeaf(String8(nameBuf)), kFileTypeRegular);

                info.setSourceName(
                    createZipSourceNameLocked(zipName, dirName, info.getFileName()));
+4 −3
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#include <utime.h>
#include <zlib.h>

#include <androidfw/PathUtils.h>
#include <log/log.h>
#include <utils/ByteOrder.h>
#include <utils/KeyedVector.h>
@@ -606,14 +607,14 @@ int write_tarfile(const String8& packageName, const String8& domain,
            prefix += packageName;
        }
        if (domain.length() > 0) {
            prefix.appendPath(domain);
            appendPath(prefix, domain);
        }

        // pax extended means we don't put in a prefix field, and put a different
        // string in the basic name field.  We can also construct the full path name
        // out of the substrings we've now built.
        fullname = prefix;
        fullname.appendPath(relpath);
        appendPath(fullname, relpath);

        // ustar:
        //    [   0 : 100 ]; file name/path
@@ -654,7 +655,7 @@ int write_tarfile(const String8& packageName, const String8& domain,
        // Now build the pax *header* templated on the ustar header
        memcpy(paxHeader, buf, 512);

        String8 leaf = fullname.getPathLeaf();
        String8 leaf = getPathLeaf(fullname);
        memset(paxHeader, 0, 100);                  // rewrite the name area
        snprintf(paxHeader, 100, "PaxHeader/%s", leaf.c_str());
        memset(paxHeader + 345, 0, 155);            // rewrite the prefix area
+135 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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 <androidfw/PathUtils.h>

#include <utils/Compat.h>

namespace android {

String8 getPathLeaf(const String8& str) {
    const char* cp;
    const char*const buf = str.c_str();

    cp = strrchr(buf, OS_PATH_SEPARATOR);
    if (cp == nullptr)
        return str;
    else
        return String8(cp+1);
}

String8 getPathDir(const String8& str8) {
    const char* cp;
    const char*const str = str8.c_str();

    cp = strrchr(str, OS_PATH_SEPARATOR);
    if (cp == nullptr)
        return String8();
    else
        return String8(str, cp - str);
}

static char* findExtension(const String8& str8) {
    const char* lastSlash;
    const char* lastDot;
    const char* const str = str8.c_str();

    // only look at the filename
    lastSlash = strrchr(str, OS_PATH_SEPARATOR);
    if (lastSlash == nullptr)
        lastSlash = str;
    else
        lastSlash++;

    // find the last dot
    lastDot = strrchr(lastSlash, '.');
    if (lastDot == nullptr)
        return nullptr;

    // looks good, ship it
    return const_cast<char*>(lastDot);
}

String8 getPathExtension(const String8& str) {
    char* ext;

    ext = findExtension(str);
    if (ext != nullptr)
        return String8(ext);
    else
        return String8();
}

String8 getBasePath(const String8& str8) {
    char* ext;
    const char* const str = str8.c_str();

    ext = findExtension(str8);
    if (ext == nullptr)
        return str8;
    else
        return String8(str, ext - str);
}

static void setPathName(String8& s, const char* name) {
    size_t len = strlen(name);
    char* buf = s.lockBuffer(len);

    memcpy(buf, name, len);

    // remove trailing path separator, if present
    if (len > 0 && buf[len - 1] == OS_PATH_SEPARATOR) len--;
    buf[len] = '\0';

    s.unlockBuffer(len);
}

String8& appendPath(String8& str, const char* name) {
    // TODO: The test below will fail for Win32 paths. Fix later or ignore.
    if (name[0] != OS_PATH_SEPARATOR) {
        if (*name == '\0') {
            // nothing to do
            return str;
        }

        size_t len = str.length();
        if (len == 0) {
            // no existing filename, just use the new one
            setPathName(str, name);
            return str;
        }

        // make room for oldPath + '/' + newPath
        int newlen = strlen(name);

        char* buf = str.lockBuffer(len+1+newlen);

        // insert a '/' if needed
        if (buf[len-1] != OS_PATH_SEPARATOR)
            buf[len++] = OS_PATH_SEPARATOR;

        memcpy(buf+len, name, newlen+1);
        len += newlen;

        str.unlockBuffer(len);
        return str;
    } else {
        setPathName(str, name);
        return str;
    }
}

} // namespace android
+98 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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 <utils/String8.h>

/* This library contains path manipulation functions that are used only by androidfw and aapt.
 * When it's possible, migrate all uses to std::filesystem::path.
 */

namespace android {

/**
 * Get just the filename component.
 *
 * DEPRECATED: use std::filesystem::path::filename
 *
 * "/tmp/foo/bar.c" --> "bar.c"
 */
String8 getPathLeaf(const String8& str);

/**
 * Remove the last (file name) component, leaving just the directory
 * name.
 *
 * DEPRECATED: use std::filesystem::path::parent_path
 *
 * "/tmp/foo/bar.c" --> "/tmp/foo"
 * "/tmp" --> "" // ????? shouldn't this be "/" ???? XXX
 * "bar.c" --> ""
 */
String8 getPathDir(const String8& str);

/**
 * Return the filename extension.  This is the last '.' and any number
 * of characters that follow it.  The '.' is included in case we
 * decide to expand our definition of what constitutes an extension.
 *
 * DEPRECATED: use std::filesystem::path::extension
 *
 * "/tmp/foo/bar.c" --> ".c"
 * "/tmp" --> ""
 * "/tmp/foo.bar/baz" --> ""
 * "foo.jpeg" --> ".jpeg"
 * "foo." --> ""
 */
String8 getPathExtension(const String8& str);

/**
 * Return the path without the extension.  Rules for what constitutes
 * an extension are described in the comment for getPathExtension().
 *
 * DEPRECATED: use std::filesystem::path::stem and std::filesystem::path::parent_path
 *
 * "/tmp/foo/bar.c" --> "/tmp/foo/bar"
 */
String8 getBasePath(const String8& str);

/**
 * Add a component to the pathname.  We guarantee that there is
 * exactly one path separator between the old path and the new.
 * If there is no existing name, we just copy the new name in.
 *
 * DEPRECATED: use std::filesystem::path::operator/=
 *
 * If leaf is a fully qualified path (i.e. starts with '/', it
 * replaces whatever was there before.
 */
String8& appendPath(String8& str, const char* leaf);
inline String8& appendPath(String8& str, const String8& leaf) {
    return appendPath(str, leaf.c_str());
}

/**
 * Like appendPath(), but does not affect this string.  Returns a new one instead.
 *
 * DEPRECATED: use std::filesystem::operator/
 */
inline String8 appendPathCopy(String8 str, const char* leaf) { return appendPath(str, leaf); }
inline String8 appendPathCopy(String8 str, const String8& leaf) {
    return appendPath(str, leaf.c_str());
}

} // namespace android
Loading