blob: 26dd77c47965e830c40e67a2553bc6c942397a89 [file] [log] [blame]
/* Copyright (C) 2007-2009 The Android Open Source Project
**
** This software is licensed under the terms of the GNU General Public
** License version 2, as published by the Free Software Foundation, and
** may be copied, distributed, and modified under those terms.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
*/
#include "android/utils/path.h"
#include "android/base/files/PathUtils.h"
#include "android/base/memory/ScopedPtr.h"
#include "android/base/misc/StringUtils.h"
#include "android/base/system/System.h"
#include "android/base/system/Win32UnicodeString.h"
#include <string>
#include <vector>
using android::base::PathUtils;
using android::base::ScopedCPtr;
using android::base::strDup;
using android::base::System;
ABool path_exists(const char* path) {
return System::get()->pathExists(path);
}
ABool path_is_regular(const char* path) {
return System::get()->pathIsFile(path);
}
ABool path_is_dir(const char* path) {
return System::get()->pathIsDir(path);
}
ABool path_can_read(const char* path) {
return System::get()->pathCanRead(path);
}
ABool path_can_write(const char* path) {
return System::get()->pathCanWrite(path);
}
ABool path_can_exec(const char* path) {
return System::get()->pathCanExec(path);
}
ABool path_is_absolute(const char* path) {
return PathUtils::isAbsolute(path);
}
char* path_get_absolute(const char* path) {
if (path_is_absolute(path)) {
return ASTRDUP(path);
}
std::string currentDir = System::get()->getCurrentDirectory();
std::vector<std::string> currentItems =
PathUtils::decompose(currentDir.c_str());
std::vector<std::string> pathItems = PathUtils::decompose(path);
for (const auto& item : pathItems) {
currentItems.push_back(item);
}
return strDup(PathUtils::recompose(currentItems));
}
int path_split(const char* path, char** dirname, char** basename) {
std::string dir, file;
if (!PathUtils::split(path, &dir, &file)) {
return -1;
}
if (dirname) {
*dirname = strDup(dir);
}
if (basename) {
*basename = strDup(file);
}
return 0;
}
char* path_dirname(const char* path) {
std::string dir;
if (!PathUtils::split(path, &dir, nullptr)) {
return nullptr;
}
return strDup(dir);
}
char* path_basename(const char* path) {
std::string file;
if (!PathUtils::split(path, nullptr, &file)) {
return nullptr;
}
return strDup(file);
}
#ifdef _WIN32
using android::base::Win32UnicodeString;
extern "C"
char* realpath_with_length(const char* path,
char* resolved_path,
size_t max_length) {
Win32UnicodeString widePath(path);
// Let the call allocate memory for us, then we can check against max_length
ScopedCPtr<wchar_t> result(_wfullpath(nullptr, widePath.c_str(), 0));
if (result.get() == nullptr) {
return nullptr;
}
auto utf8Path = Win32UnicodeString::convertToUtf8(result.get());
if (resolved_path == nullptr) {
// Passing in a null pointer is valid and should lead to allocation
// without checking the length argument
return strDup(utf8Path);
}
if (utf8Path.size() + 1 >= max_length) {
// This mimics the behavior of _wfullpath where if the buffer is not
// sufficiently large to hold the string plus a null terminator the call
// will fail and return nullptr
return nullptr;
}
strcpy(resolved_path, utf8Path.c_str());
return resolved_path;
}
#endif // _WIN32