char *GetParentDirectoryCopy(const char *path) /** * WARNING: Remember to free return value. **/ { assert(path); assert(strlen(path) > 0); char *path_copy = xstrdup(path); if(strcmp(path_copy, "/") == 0) { return path_copy; } char *sp = (char *)LastFileSeparator(path_copy); if(!sp) { Log(LOG_LEVEL_ERR, "Path %s does not contain file separators (GetParentDirectory())", path_copy); free(path_copy); return NULL; } if(sp == FirstFileSeparator(path_copy)) // don't chop off first path separator { *(sp + 1) = '\0'; } else { *sp = '\0'; } return path_copy; }
static void test_first_file_separator(void **state) { const char *out; char *in1 = "/tmp/myfile"; out = FirstFileSeparator(in1); assert_true(out == in1); char *in2 = "/tmp/myfile"; out = FirstFileSeparator(in2); assert_true(out == in2); char *in3 = "c:\\tmp\\myfile"; out = FirstFileSeparator(in3); assert_true(out == in3 + 2); char *in4 = "\\\\my\\windows\\share"; out = FirstFileSeparator(in4); assert_true(out == in4 + 1); }
bool ChopLastNode(char *str) /* Chop off trailing node name (possible blank) starting from last character and removing up to the first / encountered e.g. /a/b/c -> /a/b /a/b/ -> /a/b Will also collapse redundant/repeating path separators. */ { char *sp; int ret; DeleteRedundantSlashes(str); /* Here cast is necessary and harmless, str is modifiable */ if ((sp = (char *) LastFileSeparator(str)) == NULL) { int pos = RootDirLength(str); if (str[pos] == '\0') { ret = false; } else { str[pos] = '.'; str[pos + 1] = '\0'; ret = true; } } else { // Don't chop the root slash in an absolute path. if (IsAbsoluteFileName(str) && FirstFileSeparator(str) == sp) { *(++sp) = '\0'; } else { *sp = '\0'; } ret = true; } return ret; }