| 224 | |
| 225 | |
| 226 | Try<VolumePath> parseVolumePath(const string& rootDir, const string& dir) |
| 227 | { |
| 228 | // TODO(chhsiao): Consider using `<regex>`, which requires GCC 4.9+. |
| 229 | |
| 230 | // Make sure there's a separator at the end of the `rootDir` so that |
| 231 | // we don't accidentally slice off part of a directory. |
| 232 | const string prefix = path::join(rootDir, ""); |
| 233 | |
| 234 | if (!strings::startsWith(dir, prefix)) { |
| 235 | return Error( |
| 236 | "Directory '" + dir + "' does not fall under the root directory '" + |
| 237 | rootDir + "'"); |
| 238 | } |
| 239 | |
| 240 | vector<string> tokens = strings::tokenize( |
| 241 | dir.substr(prefix.size()), |
| 242 | stringify(os::PATH_SEPARATOR)); |
| 243 | |
| 244 | // A complete volume path consists of 4 tokens: |
| 245 | // <type>/<name>/volumes/<volume_id> |
| 246 | if (tokens.size() != 4 || tokens[2] != VOLUMES_DIR) { |
| 247 | return Error( |
| 248 | "Path '" + path::join(tokens) + "' does not match the structure of a " |
| 249 | "volume path"); |
| 250 | } |
| 251 | |
| 252 | // Volume ID is percent-encoded to avoid invalid characters in the path. |
| 253 | Try<string> volumeId = http::decode(tokens[3]); |
| 254 | if (volumeId.isError()) { |
| 255 | return Error( |
| 256 | "Could not decode volume ID from string '" + tokens[3] + "': " + |
| 257 | volumeId.error()); |
| 258 | } |
| 259 | |
| 260 | return VolumePath{tokens[0], tokens[1], volumeId.get()}; |
| 261 | } |
| 262 | |
| 263 | |
| 264 | string getVolumeStatePath( |