Skip to content

Commit

Permalink
Support Windows Long Paths (#104)
Browse files Browse the repository at this point in the history
* Support Windows Long Paths
  • Loading branch information
fpetrini15 authored Nov 7, 2024
1 parent ac03a5d commit 343e7e4
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 5 deletions.
15 changes: 15 additions & 0 deletions include/triton/backend/backend_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -688,4 +688,19 @@ TRITONSERVER_Error* ValidateStringBuffer(
const size_t expected_element_cnt, const char* input_name,
std::vector<std::pair<const char*, const uint32_t>>* str_list);

/// Converts incoming utf-8 path to an OS valid path
///
/// On Linux there is not much to do.
/// On Windows we need to take care of the long paths and handle them correctly
/// to avoid legacy issues with MAX_PATH
///
/// More details:
/// https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=registry
///
/// \param path The path to validate
/// \param ret_path The updated valid path as per the OS requirements
/// \return a TRITONSERVER_Error indicating success or failure.
TRITONSERVER_Error* GetOSValidPath(
const std::string& path, std::string& ret_path);

}} // namespace triton::backend
38 changes: 33 additions & 5 deletions src/backend_common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -784,18 +784,22 @@ GetDirectoryContents(const std::string& path, std::set<std::string>* contents)
TRITONSERVER_Error*
FileExists(const std::string& path, bool* exists)
{
*exists = (access(path.c_str(), F_OK) == 0);
std::string valid_path;
GetOSValidPath(path, valid_path);
*exists = (access(valid_path.c_str(), F_OK) == 0);
return nullptr; // success
}

TRITONSERVER_Error*
ReadTextFile(const std::string& path, std::string* contents)
{
std::ifstream in(path, std::ios::in | std::ios::binary);
std::string valid_path;
GetOSValidPath(path, valid_path);
std::ifstream in(valid_path, std::ios::in | std::ios::binary);
if (!in) {
return TRITONSERVER_ErrorNew(
TRITONSERVER_ERROR_INTERNAL,
("failed to open/read file '" + path + "': " + strerror(errno))
("failed to open/read file '" + valid_path + "': " + strerror(errno))
.c_str());
}

Expand All @@ -813,11 +817,14 @@ IsDirectory(const std::string& path, bool* is_dir)
{
*is_dir = false;

std::string valid_path;
GetOSValidPath(path, valid_path);

struct stat st;
if (stat(path.c_str(), &st) != 0) {
if (stat(valid_path.c_str(), &st) != 0) {
return TRITONSERVER_ErrorNew(
TRITONSERVER_ERROR_INTERNAL,
(std::string("failed to stat file ") + path).c_str());
(std::string("failed to stat file ") + valid_path).c_str());
}

*is_dir = S_ISDIR(st.st_mode);
Expand Down Expand Up @@ -1432,4 +1439,25 @@ ValidateStringBuffer(
return nullptr;
}

TRITONSERVER_Error*
GetOSValidPath(const std::string& path, std::string& ret_path)
{
std::string l_path(path);
#ifdef _WIN32
constexpr const const char* kWindowsLongPathPrefix = "\\\\?\\";
// On Windows long paths must be marked correctly otherwise, due to backwards
// compatibility, all paths are limited to MAX_PATH length
if (l_path.size() >= MAX_PATH) {
// Must be prefixed with "\\?\" to be considered long path
if (l_path.substr(0, 4) != (kWindowsLongPathPrefix)) {
// Long path but not "tagged" correctly
l_path = (kWindowsLongPathPrefix) + l_path;
}
}
std::replace(l_path.begin(), l_path.end(), '/', '\\');
#endif
ret_path = l_path;
return nullptr;
}

}} // namespace triton::backend

0 comments on commit 343e7e4

Please sign in to comment.