abspath.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. #include "cache.h"
  2. /*
  3. * Do not use this for inspecting *tracked* content. When path is a
  4. * symlink to a directory, we do not want to say it is a directory when
  5. * dealing with tracked content in the working tree.
  6. */
  7. static int is_directory(const char *path)
  8. {
  9. struct stat st;
  10. return (!stat(path, &st) && S_ISDIR(st.st_mode));
  11. }
  12. /* We allow "recursive" symbolic links. Only within reason, though. */
  13. #define MAXDEPTH 5
  14. const char *make_absolute_path(const char *path)
  15. {
  16. static char bufs[2][PATH_MAX + 1], *buf = bufs[0], *next_buf = bufs[1];
  17. char cwd[1024] = "";
  18. int buf_index = 1, len;
  19. int depth = MAXDEPTH;
  20. char *last_elem = NULL;
  21. struct stat st;
  22. if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
  23. die ("Too long path: %.*s", 60, path);
  24. while (depth--) {
  25. if (!is_directory(buf)) {
  26. char *last_slash = strrchr(buf, '/');
  27. if (last_slash) {
  28. *last_slash = '\0';
  29. last_elem = xstrdup(last_slash + 1);
  30. } else {
  31. last_elem = xstrdup(buf);
  32. *buf = '\0';
  33. }
  34. }
  35. if (*buf) {
  36. if (!*cwd && !getcwd(cwd, sizeof(cwd)))
  37. die ("Could not get current working directory");
  38. if (chdir(buf))
  39. die ("Could not switch to '%s'", buf);
  40. }
  41. if (!getcwd(buf, PATH_MAX))
  42. die ("Could not get current working directory");
  43. if (last_elem) {
  44. int len = strlen(buf);
  45. if (len + strlen(last_elem) + 2 > PATH_MAX)
  46. die ("Too long path name: '%s/%s'",
  47. buf, last_elem);
  48. buf[len] = '/';
  49. strcpy(buf + len + 1, last_elem);
  50. free(last_elem);
  51. last_elem = NULL;
  52. }
  53. if (!lstat(buf, &st) && S_ISLNK(st.st_mode)) {
  54. len = readlink(buf, next_buf, PATH_MAX);
  55. if (len < 0)
  56. die ("Invalid symlink: %s", buf);
  57. if (PATH_MAX <= len)
  58. die("symbolic link too long: %s", buf);
  59. next_buf[len] = '\0';
  60. buf = next_buf;
  61. buf_index = 1 - buf_index;
  62. next_buf = bufs[buf_index];
  63. } else
  64. break;
  65. }
  66. if (*cwd && chdir(cwd))
  67. die ("Could not change back to '%s'", cwd);
  68. return buf;
  69. }
  70. static const char *get_pwd_cwd(void)
  71. {
  72. static char cwd[PATH_MAX + 1];
  73. char *pwd;
  74. struct stat cwd_stat, pwd_stat;
  75. if (getcwd(cwd, PATH_MAX) == NULL)
  76. return NULL;
  77. pwd = getenv("PWD");
  78. if (pwd && strcmp(pwd, cwd)) {
  79. stat(cwd, &cwd_stat);
  80. if (!stat(pwd, &pwd_stat) &&
  81. pwd_stat.st_dev == cwd_stat.st_dev &&
  82. pwd_stat.st_ino == cwd_stat.st_ino) {
  83. strlcpy(cwd, pwd, PATH_MAX);
  84. }
  85. }
  86. return cwd;
  87. }
  88. const char *make_nonrelative_path(const char *path)
  89. {
  90. static char buf[PATH_MAX + 1];
  91. if (is_absolute_path(path)) {
  92. if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
  93. die("Too long path: %.*s", 60, path);
  94. } else {
  95. const char *cwd = get_pwd_cwd();
  96. if (!cwd)
  97. die("Cannot determine the current working directory");
  98. if (snprintf(buf, PATH_MAX, "%s/%s", cwd, path) >= PATH_MAX)
  99. die("Too long path: %.*s", 60, path);
  100. }
  101. return buf;
  102. }