| 834 | |
| 835 | |
| 836 | Result<string> FilesProcess::resolve(const string& path) |
| 837 | { |
| 838 | // Suppose we have: /1/2/hello_world.txt |
| 839 | // And we attach: /1/2 as /sandbox |
| 840 | // Then this function would resolve the following virtual path |
| 841 | // into the actual path: |
| 842 | // input: /sandbox/hello_world.txt |
| 843 | // output: /1/2/hello_world.txt |
| 844 | // |
| 845 | // Try and see if this path has been attached. We check for the |
| 846 | // longest possible prefix match and if found append any suffix to |
| 847 | // the attached path (provided the path is to a directory). |
| 848 | vector<string> tokens = strings::split( |
| 849 | strings::remove(path, stringify(os::PATH_SEPARATOR), strings::SUFFIX), |
| 850 | stringify(os::PATH_SEPARATOR)); |
| 851 | |
| 852 | string suffix; |
| 853 | while (!tokens.empty()) { |
| 854 | string prefix = path::join(tokens); |
| 855 | |
| 856 | if (!paths.contains(prefix)) { |
| 857 | if (suffix.empty()) { |
| 858 | suffix = tokens.back(); |
| 859 | } else { |
| 860 | suffix = path::join(tokens.back(), suffix); |
| 861 | } |
| 862 | |
| 863 | tokens.pop_back(); |
| 864 | continue; |
| 865 | } |
| 866 | |
| 867 | // Determine the final path: if it's a directory, append the |
| 868 | // suffix, if it's not a directory and there is a suffix, return |
| 869 | // 'Not Found'. |
| 870 | string path = paths[prefix]; |
| 871 | if (os::stat::isdir(path)) { |
| 872 | path = path::join(path, suffix, os::PATH_SEPARATOR); |
| 873 | |
| 874 | // Canonicalize the absolute path. |
| 875 | Result<string> realpath = os::realpath(path); |
| 876 | if (realpath.isError()) { |
| 877 | return Error( |
| 878 | "Failed to determine canonical path of '" + path + |
| 879 | "': " + realpath.error()); |
| 880 | } else if (realpath.isNone()) { |
| 881 | return None(); |
| 882 | } |
| 883 | |
| 884 | // Make sure the canonicalized absolute path is accessible |
| 885 | // (i.e., not outside the "chroot"). |
| 886 | if (!strings::startsWith(realpath.get(), paths[prefix])) { |
| 887 | return Error("'" + path + "' is inaccessible"); |
| 888 | } |
| 889 | |
| 890 | path = realpath.get(); |
| 891 | } else if (suffix != "") { |
| 892 | // Request is assuming attached path is a directory, but it is |
| 893 | // not! Rather than 'Bad Request', treat this as 'Not Found'. |
no test coverage detected