Advertisement
mechanicker

abspath implementation without filesystem calls

Jan 15th, 2023
1,036
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 1.60 KB | Source Code | 0 0
  1. // Regex pattern to detect if path is relative by
  2. // matching for valid '.' or '..' path components
  3. static const regex_t dot_regex;
  4. static const char *dot_pattern = "(^\\.{1,2}/|/\\.{1,2}/|/\\.{1,2}$)";
  5.  
  6. // Initializer function automatically invoked when shared library is loaded
  7. __attribute__((constructor)) static void library_initialize(void)
  8. {
  9.     int err;
  10.     if ((err = regcomp((regex_t *)&dot_regex, dot_pattern,
  11.                REG_EXTENDED | REG_NOSUB))) {
  12.         fprintf(stderr, "error err=%d compiling regex=%s\n", err,
  13.             dot_pattern);
  14.         abort();
  15.     }
  16. }
  17.  
  18. static int make_abspath(const char *src, char *buff, size_t size)
  19. {
  20.     // Check if we even have relative path to resolve by
  21.     // looking for '.' before the last directory component
  22.     const char *rpos = strrchr(src, '/');
  23.     if (!rpos || rpos == src || regexec(&dot_regex, src, 0, NULL, 0)) {
  24.         GITCEPTOR_TRACE("not a relative path=%s\n", src);
  25.         strncpy(buff, src, size);
  26.         return 0;
  27.     }
  28.  
  29.     char *last = NULL;
  30.     char path[PATH_MAX];
  31.     buff[0] = '\0';
  32.     strncpy(path, src, sizeof(path));
  33.  
  34.     for (char *word = strtok_r(path, "/", &last); word;
  35.          word = strtok_r(NULL, "/", &last)) {
  36.         // Skip referring to current directory or repeat slash
  37.         if (!*word || !strcmp(word, ".")) {
  38.             continue;
  39.         }
  40.  
  41.         // Traverse up to parent directory by popping the current leaf
  42.         if (!strcmp(word, "..")) {
  43.             char *right_slash = strrchr(buff, '/');
  44.             if (right_slash) {
  45.                 right_slash[0] = '\0';
  46.             }
  47.             continue;
  48.         }
  49.  
  50.         // Append valid directory component to absolute path
  51.         strncat(buff, "/", size);
  52.         strncat(buff, word, size);
  53.     }
  54.  
  55.     return '\0' == *buff ? -1 : 0;
  56. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement