summaryrefslogtreecommitdiff
path: root/zen/file_access.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'zen/file_access.cpp')
-rwxr-xr-xzen/file_access.cpp69
1 files changed, 48 insertions, 21 deletions
diff --git a/zen/file_access.cpp b/zen/file_access.cpp
index 1711e934..18c0ed26 100755
--- a/zen/file_access.cpp
+++ b/zen/file_access.cpp
@@ -32,13 +32,45 @@ using namespace zen;
Opt<PathComponents> zen::parsePathComponents(const Zstring& itemPath)
{
+ auto doParse = [&](int sepCountVolumeRoot, bool rootWithSep) -> Opt<PathComponents>
+ {
+ const Zstring itemPathFmt = appendSeparator(itemPath); //simplify analysis of root without seperator, e.g. \\server-name\share
+ int sepCount = 0;
+ for (auto it = itemPathFmt.begin(); it != itemPathFmt.end(); ++it)
+ if (*it == FILE_NAME_SEPARATOR)
+ if (++sepCount == sepCountVolumeRoot)
+ {
+ Zstring rootPath(itemPathFmt.begin(), rootWithSep ? it + 1 : it);
+
+ Zstring relPath(it + 1, itemPathFmt.end());
+ trim(relPath, true, true, [](Zchar c) { return c == FILE_NAME_SEPARATOR; });
+
+ return PathComponents({ rootPath, relPath });
+ }
+ return NoValue();
+ };
+
if (startsWith(itemPath, "/"))
{
- Zstring relPath(itemPath.c_str() + 1);
- if (endsWith(relPath, FILE_NAME_SEPARATOR))
- relPath.pop_back();
- return PathComponents({ "/", relPath });
+ if (startsWith(itemPath, "/media/"))
+ {
+ //Ubuntu: e.g. /media/zenju/DEVICE_NAME
+ if (const char* username = ::getenv("USER"))
+ if (startsWith(itemPath, std::string("/media/") + username + "/"))
+ return doParse(4 /*sepCountVolumeRoot*/, false /*rootWithSep*/);
+
+ //Ubuntu: e.g. /media/cdrom0
+ return doParse(3 /*sepCountVolumeRoot*/, false /*rootWithSep*/);
+ }
+
+ if (startsWith(itemPath, "/run/media/")) //Suse: e.g. /run/media/zenju/DEVICE_NAME
+ if (const char* username = ::getenv("USER"))
+ if (startsWith(itemPath, std::string("/run/media/") + username + "/"))
+ return doParse(5 /*sepCountVolumeRoot*/, false /*rootWithSep*/);
+
+ return doParse(1 /*sepCountVolumeRoot*/, true /*rootWithSep*/);
}
+
//we do NOT support relative paths!
return NoValue();
}
@@ -115,9 +147,9 @@ PathStatus zen::getPathStatus(const Zstring& itemPath) //throw FileError
Opt<ItemType> zen::getItemTypeIfExists(const Zstring& itemPath) //throw FileError
{
- const PathStatus pd = getPathStatus(itemPath); //throw FileError
- if (pd.relPath.empty())
- return pd.existingType;
+ const PathStatus ps = getPathStatus(itemPath); //throw FileError
+ if (ps.relPath.empty())
+ return ps.existingType;
return NoValue();
}
@@ -541,23 +573,18 @@ void zen::createDirectoryIfMissingRecursion(const Zstring& dirPath) //throw File
}
catch (FileError&)
{
- Opt<PathStatus> pd;
- try { pd = getPathStatus(dirPath); /*throw FileError*/ }
- catch (FileError&) {} //previous exception is more relevant
+ const PathStatus ps = getPathStatus(dirPath); //throw FileError
+ if (ps.existingType == ItemType::FILE)
+ throw;
- if (pd &&
- pd->existingType != ItemType::FILE &&
- pd->relPath.size() != 1) //don't repeat the very same createDirectory() call from above!
- {
- Zstring intermediatePath = pd->existingPath;
- for (const Zstring& itemName : pd->relPath)
+ //ps.relPath.size() == 1 => same createDirectory() call from above? Maybe parent folder was created by parallel thread shortly after failure!
+ Zstring intermediatePath = ps.existingPath;
+ for (const Zstring& itemName : ps.relPath)
+ try
{
- intermediatePath = appendSeparator(intermediatePath) + itemName;
- createDirectory(intermediatePath); //throw FileError, (ErrorTargetExisting)
+ createDirectory(intermediatePath = appendSeparator(intermediatePath) + itemName); //throw FileError, ErrorTargetExisting
}
- return;
- }
- throw;
+ catch (ErrorTargetExisting&) {} //possible, if createDirectoryIfMissingRecursion() is run in parallel
}
}
bgstack15