@@ -790,16 +790,19 @@ void util_replaceAll(std::string &str, const std::string &from, const std::strin
790790}
791791
792792/* *
793- * Resolve prefix containing relative references (../ or ./)
793+ * Resolve path containing relative references (../ or ./)
794794 * to canonical path.
795- * @param prefix FujiNet path such as TNFS://myhost/path/to/here/
795+ * @param path FujiNet path such as TNFS://myhost/path/to/here/
796+ * or tnfs://myhost/some/filename.ext
796797 */
797- std::string util_get_canonical_path (std::string prefix )
798+ std::string util_get_canonical_path (std::string path )
798799{
800+ bool is_last_slash = (path.back () == ' /' ) ? true : false ;
801+
799802 std::size_t proto_host_len;
800803
801804 // stack to store the file's names.
802- std::stack<string> st;
805+ std::stack<std:: string> st;
803806
804807 // temporary string which stores the extracted
805808 // directory name or commands("." / "..")
@@ -811,35 +814,41 @@ std::string util_get_canonical_path(std::string prefix)
811814 std::string res;
812815
813816 // advance beyond protocol and hostname
814- proto_host_len = prefix .find (" ://" );
817+ proto_host_len = path .find (" ://" );
815818
816- if (proto_host_len > 0 )
819+ // If protocol delimiter "://" is found, skip over the protocol
820+ if (proto_host_len < std::string::npos)
817821 {
818- proto_host_len += 3 ;
819- proto_host_len = prefix.find (" /" , proto_host_len) + 1 ;
822+ proto_host_len += 3 ; // "://" is 3 chars
823+ proto_host_len = path.find (" /" , proto_host_len) + 1 ;
824+ res.append (path.substr (0 , proto_host_len));
825+ }
826+ else
827+ {
828+ proto_host_len = 0 ; // no protocol prefix and hostname
829+ // Preserve an absolute path if one is provided in the input
830+ if (!path.empty () && path[0 ] == ' /' )
831+ res = " /" ;
820832 }
821833
822- res.append (prefix.substr (0 , proto_host_len));
823-
824- int len_prefix = prefix.length ();
834+ int len_path = path.length ();
825835
826- // for (int i = proto_host_len-1; i < len_prefix; i++)
827- for (int i = proto_host_len; i < len_prefix; i++)
836+ for (int i = proto_host_len; i < len_path; i++)
828837 {
829838 // we will clear the temporary string
830839 // every time to accommodate new directory
831840 // name or command.
832841 dir.clear ();
833842
834843 // skip all the multiple '/' Eg. "/////""
835- while (prefix [i] == ' /' )
844+ while (path [i] == ' /' )
836845 i++;
837846
838847 // stores directory's name("a", "b" etc.)
839848 // or commands("."/"..") into dir
840- while (i < len_prefix && prefix [i] != ' /' )
849+ while (i < len_path && path [i] != ' /' )
841850 {
842- dir.push_back (prefix [i]);
851+ dir.push_back (path [i]);
843852 i++;
844853 }
845854
@@ -865,7 +874,7 @@ std::string util_get_canonical_path(std::string prefix)
865874
866875 // a temporary stack (st1) which will contain
867876 // the reverse of original stack(st).
868- std::stack<string> st1;
877+ std::stack<std:: string> st1;
869878 while (!st.empty ())
870879 {
871880 st1.push (st.top ());
@@ -888,7 +897,7 @@ std::string util_get_canonical_path(std::string prefix)
888897 }
889898
890899 // Append trailing slash if not already there
891- if ((res.length () > 0 ) && (res[res. length () - 1 ] != ' /' ))
900+ if ((res.length () > 0 ) && (res. back () != ' /' ) && is_last_slash )
892901 res.append (" /" );
893902
894903 return res;
@@ -1058,4 +1067,4 @@ char* util_strndup(const char* s, size_t n) {
10581067int get_value_or_default (const std::map<int , int >& map, int key, int default_value) {
10591068 auto it = map.find (key);
10601069 return it != map.end () ? it->second : default_value;
1061- }
1070+ }
0 commit comments