// Regex pattern to detect if path is relative by // matching for valid '.' or '..' path components static const regex_t dot_regex; static const char *dot_pattern = "(^\\.{1,2}/|/\\.{1,2}/|/\\.{1,2}$)"; // Initializer function automatically invoked when shared library is loaded __attribute__((constructor)) static void library_initialize(void) { int err; if ((err = regcomp((regex_t *)&dot_regex, dot_pattern, REG_EXTENDED | REG_NOSUB))) { fprintf(stderr, "error err=%d compiling regex=%s\n", err, dot_pattern); abort(); } } static int make_abspath(const char *src, char *buff, size_t size) { // Check if we even have relative path to resolve by // looking for '.' before the last directory component const char *rpos = strrchr(src, '/'); if (!rpos || rpos == src || regexec(&dot_regex, src, 0, NULL, 0)) { GITCEPTOR_TRACE("not a relative path=%s\n", src); strncpy(buff, src, size); return 0; } char *last = NULL; char path[PATH_MAX]; buff[0] = '\0'; strncpy(path, src, sizeof(path)); for (char *word = strtok_r(path, "/", &last); word; word = strtok_r(NULL, "/", &last)) { // Skip referring to current directory or repeat slash if (!*word || !strcmp(word, ".")) { continue; } // Traverse up to parent directory by popping the current leaf if (!strcmp(word, "..")) { char *right_slash = strrchr(buff, '/'); if (right_slash) { right_slash[0] = '\0'; } continue; } // Append valid directory component to absolute path strncat(buff, "/", size); strncat(buff, word, size); } return '\0' == *buff ? -1 : 0; }