|
|
@@ -2975,81 +2975,144 @@ kwsys_stl::string SystemTools::GetActualCaseForPath(const char* p)
|
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
-void SystemTools::SplitPath(const char* p,
|
|
|
- kwsys_stl::vector<kwsys_stl::string>& components)
|
|
|
+const char* SystemTools::SplitPathRootComponent(const char* p,
|
|
|
+ kwsys_stl::string* root)
|
|
|
{
|
|
|
- components.clear();
|
|
|
// Identify the root component.
|
|
|
const char* c = p;
|
|
|
if((c[0] == '/' && c[1] == '/') || (c[0] == '\\' && c[1] == '\\'))
|
|
|
{
|
|
|
// Network path.
|
|
|
- components.push_back("//");
|
|
|
+ if(root)
|
|
|
+ {
|
|
|
+ *root = "//";
|
|
|
+ }
|
|
|
c += 2;
|
|
|
}
|
|
|
else if(c[0] == '/')
|
|
|
{
|
|
|
// Unix path.
|
|
|
- components.push_back("/");
|
|
|
+ if(root)
|
|
|
+ {
|
|
|
+ *root = "/";
|
|
|
+ }
|
|
|
c += 1;
|
|
|
}
|
|
|
else if(c[0] && c[1] == ':' && (c[2] == '/' || c[2] == '\\'))
|
|
|
{
|
|
|
// Windows path.
|
|
|
- kwsys_stl::string root = "_:/";
|
|
|
- root[0] = c[0];
|
|
|
- components.push_back(root);
|
|
|
+ if(root)
|
|
|
+ {
|
|
|
+ (*root) = "_:/";
|
|
|
+ (*root)[0] = c[0];
|
|
|
+ }
|
|
|
c += 3;
|
|
|
}
|
|
|
else if(c[0] && c[1] == ':')
|
|
|
{
|
|
|
// Path relative to a windows drive working directory.
|
|
|
- kwsys_stl::string root = "_:";
|
|
|
- root[0] = c[0];
|
|
|
- components.push_back(root);
|
|
|
+ if(root)
|
|
|
+ {
|
|
|
+ (*root) = "_:";
|
|
|
+ (*root)[0] = c[0];
|
|
|
+ }
|
|
|
c += 2;
|
|
|
}
|
|
|
-#ifdef HAVE_GETPWNAM
|
|
|
else if(c[0] == '~')
|
|
|
{
|
|
|
- int numChars = 1;
|
|
|
- while(c[numChars] && c[numChars] != '/')
|
|
|
+ // Home directory. The returned root should always have a
|
|
|
+ // trailing slash so that appending components as
|
|
|
+ // c[0]c[1]/c[2]/... works. The remaining path returned should
|
|
|
+ // skip the first slash if it exists:
|
|
|
+ //
|
|
|
+ // "~" : root = "~/" , return ""
|
|
|
+ // "~/ : root = "~/" , return ""
|
|
|
+ // "~/x : root = "~/" , return "x"
|
|
|
+ // "~u" : root = "~u/", return ""
|
|
|
+ // "~u/" : root = "~u/", return ""
|
|
|
+ // "~u/x" : root = "~u/", return "x"
|
|
|
+ int n = 1;
|
|
|
+ while(c[n] && c[n] != '/')
|
|
|
{
|
|
|
- numChars++;
|
|
|
+ ++n;
|
|
|
}
|
|
|
- const char* homedir;
|
|
|
- if(numChars == 1)
|
|
|
+ if(root)
|
|
|
{
|
|
|
- homedir = getenv("HOME");
|
|
|
+ root->assign(c, n);
|
|
|
+ *root += '/';
|
|
|
}
|
|
|
- else
|
|
|
+ if(c[n] == '/')
|
|
|
+ {
|
|
|
+ ++n;
|
|
|
+ }
|
|
|
+ c += n;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // Relative path.
|
|
|
+ if(root)
|
|
|
{
|
|
|
- char user[PATH_MAX];
|
|
|
- strncpy(user, c+1, numChars-1);
|
|
|
- user[numChars] = '\0';
|
|
|
- passwd* pw = getpwnam(user);
|
|
|
- if(p)
|
|
|
+ *root = "";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Return the remaining path.
|
|
|
+ return c;
|
|
|
+}
|
|
|
+
|
|
|
+//----------------------------------------------------------------------------
|
|
|
+void SystemTools::SplitPath(const char* p,
|
|
|
+ kwsys_stl::vector<kwsys_stl::string>& components,
|
|
|
+ bool expand_home_dir)
|
|
|
+{
|
|
|
+ const char* c = p;
|
|
|
+ components.clear();
|
|
|
+
|
|
|
+ // Identify the root component.
|
|
|
+ {
|
|
|
+ kwsys_stl::string root;
|
|
|
+ c = SystemTools::SplitPathRootComponent(c, &root);
|
|
|
+
|
|
|
+ // Expand home directory references if requested.
|
|
|
+ if(expand_home_dir && !root.empty() && root[0] == '~')
|
|
|
+ {
|
|
|
+ kwsys_stl::string homedir;
|
|
|
+ root = root.substr(0, root.size()-1);
|
|
|
+ if(root.size() == 1)
|
|
|
+ {
|
|
|
+#if defined(_WIN32) && !defined(__CYGWIN__)
|
|
|
+ if(const char* h = getenv("USERPROFILE"))
|
|
|
{
|
|
|
- homedir = pw->pw_dir;
|
|
|
+ homedir = h;
|
|
|
}
|
|
|
else
|
|
|
+#endif
|
|
|
+ if(const char* h = getenv("HOME"))
|
|
|
{
|
|
|
- homedir = "";
|
|
|
+ homedir = h;
|
|
|
+ }
|
|
|
+ }
|
|
|
+#ifdef HAVE_GETPWNAM
|
|
|
+ else if(passwd* pw = getpwnam(root.c_str()+1))
|
|
|
+ {
|
|
|
+ if(pw->pw_dir)
|
|
|
+ {
|
|
|
+ homedir = pw->pw_dir;
|
|
|
}
|
|
|
}
|
|
|
- kwsys_stl::vector<kwsys_stl::string> home_components;
|
|
|
- SystemTools::SplitPath(homedir, home_components);
|
|
|
- components.insert(components.end(),
|
|
|
- home_components.begin(),
|
|
|
- home_components.end());
|
|
|
- c += numChars;
|
|
|
- }
|
|
|
#endif
|
|
|
+ if(!homedir.empty() && (homedir[homedir.size()-1] == '/' ||
|
|
|
+ homedir[homedir.size()-1] == '\\'))
|
|
|
+ {
|
|
|
+ homedir = homedir.substr(0, homedir.size()-1);
|
|
|
+ }
|
|
|
+ SystemTools::SplitPath(homedir.c_str(), components);
|
|
|
+ }
|
|
|
else
|
|
|
{
|
|
|
- // Relative path.
|
|
|
- components.push_back("");
|
|
|
+ components.push_back(root);
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
// Parse the remaining components.
|
|
|
const char* first = c;
|