int git_path_root(const char *path) { int offset = 0; /* Does the root of the path look like a windows drive ? */ if (LOOKS_LIKE_DRIVE_PREFIX(path)) offset += 2; #ifdef GIT_WIN32 /* Are we dealing with a windows network path? */ else if ((path[0] == '/' && path[1] == '/' && path[2] != '/') || (path[0] == '\\' && path[1] == '\\' && path[2] != '\\')) { offset += 2; /* Skip the computer name segment */ while (path[offset] && path[offset] != '/' && path[offset] != '\\') offset++; } #endif if (path[offset] == '/' || path[offset] == '\\') return offset; return -1; /* Not a real error - signals that path is not rooted */ }
/* * Determine if the path is a Windows prefix and, if so, returns * its actual lentgh. If it is not a prefix, returns -1. */ static int win32_prefix_length(const char *path, int len) { #ifndef GIT_WIN32 GIT_UNUSED(path); GIT_UNUSED(len); #else /* * Mimic unix behavior where '/.git' returns '/': 'C:/.git' will return * 'C:/' here */ if (len == 2 && LOOKS_LIKE_DRIVE_PREFIX(path)) return 2; /* * Similarly checks if we're dealing with a network computer name * '//computername/.git' will return '//computername/' */ if (looks_like_network_computer_name(path, len)) return len; #endif return -1; }
/* * Based on the Android implementation, BSD licensed. * Check http://android.git.kernel.org/ */ int git_path_dirname_r(git_buf *buffer, const char *path) { const char *endp; int result, len; /* Empty or NULL string gets treated as "." */ if (path == NULL || *path == '\0') { path = "."; len = 1; goto Exit; } /* Strip trailing slashes */ endp = path + strlen(path) - 1; while (endp > path && *endp == '/') endp--; /* Find the start of the dir */ while (endp > path && *endp != '/') endp--; /* Either the dir is "/" or there are no slashes */ if (endp == path) { path = (*endp == '/') ? "/" : "."; len = 1; goto Exit; } do { endp--; } while (endp > path && *endp == '/'); /* Cast is safe because max path < max int */ len = (int)(endp - path + 1); #ifdef GIT_WIN32 /* Mimic unix behavior where '/.git' returns '/': 'C:/.git' will return 'C:/' here */ if (len == 2 && LOOKS_LIKE_DRIVE_PREFIX(path)) { len = 3; goto Exit; } /* Similarly checks if we're dealing with a network computer name '//computername/.git' will return '//computername/' */ if (looks_like_network_computer_name(path, len)) { len++; goto Exit; } #endif Exit: result = len; if (buffer != NULL && git_buf_set(buffer, path, len) < 0) return -1; return result; }