mirror of the now-defunct rocklinux.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

129 lines
3.4 KiB

  1. --- ./libshell/realpath.c 27 Jan 2004 21:50:42 -0000 1.9
  2. +++ ./libshell/realpath.c 10 May 2004 16:44:14 -0000 1.10
  3. @@ -1,14 +1,3 @@
  4. -/* realpath - determine the absolute pathname of a file
  5. -
  6. - Copyright (C) 2003 Thomas M. Ogrisegg <tom-dietlibc@fnord.at>
  7. -
  8. - This realpath has still space for improvements:
  9. - e.g., if the initial path does not start with '/' it should
  10. - be checked whether the first path component(s) is/are symlinks.
  11. - This would save lots of filesystem lookups, but also greatly
  12. - increases complexity.
  13. -*/
  14. -
  15. #include <sys/types.h>
  16. #include <sys/stat.h>
  17. #include <stdlib.h>
  18. @@ -16,75 +5,44 @@
  19. #include <errno.h>
  20. #include <unistd.h>
  21. #include <string.h>
  22. +#include <fcntl.h>
  23. -#define CD(x) (x=='/'||!x)
  24. -
  25. -char *
  26. -realpath (const char *file, char *dst)
  27. -{
  28. - unsigned char buffer[PATH_MAX];
  29. - size_t i, off;
  30. -
  31. - if (!file || !dst) { errno = EINVAL; return (NULL); }
  32. - if (!*file) { errno = ENOENT; return (NULL); }
  33. -
  34. - if (*file != '/') {
  35. - if (!getcwd (buffer, sizeof (buffer))) return (NULL);
  36. - off = strlen (buffer);
  37. - while (file[0] == '.' && file[1] == '.' && file[2] == '/') {
  38. - if (off) off--;
  39. - while (off && buffer[off] != '/') off--;
  40. - file += 3;
  41. - }
  42. - buffer[off++] = '/';
  43. - i = strlen (file);
  44. - if (i+off >= PATH_MAX) return (NULL);
  45. - memcpy (buffer+off, file, i+1);
  46. - file = buffer;
  47. +static char* myrealpath(const char* file, char* dest, int count) {
  48. +/* assume dest has PATH_MAX space */
  49. + char buf[PATH_MAX+1];
  50. + char* c;
  51. + int i;
  52. +
  53. + if (count<0) { errno=EMLINK; return 0; }
  54. + if (chdir(file)==0)
  55. + /* hurray! The easy case: it's a directory! */
  56. + return getcwd(dest,PATH_MAX);
  57. +
  58. + c=strrchr(file,'/');
  59. + if (c) {
  60. + if (c-file>PATH_MAX) return 0;
  61. + memcpy(buf,file,c-file);
  62. + buf[c-file]=0;
  63. + if (chdir(buf)==-1) return 0;
  64. + file=c+1;
  65. }
  66. -
  67. - off = i = 0;
  68. -
  69. - while (file[i]) {
  70. - if (file[i] == '.' && file[i-1] == '/' &&
  71. - ((file[i+1] == '.'&&CD(file[i+2])) || CD(file[i+1]))) {
  72. - if (file[i+1] == '/') { i+=2; continue; }
  73. - if (file[i+1] == '.') {
  74. - if (off > 2) off -= 2;
  75. - while (off && dst[off] != '/') off--;
  76. - i++;
  77. - }
  78. - i++;
  79. - continue;
  80. - }
  81. -
  82. - if (file[i] == '/' && off < PATH_MAX) {
  83. - unsigned char buf[PATH_MAX];
  84. - int ret;
  85. -
  86. - if (file[i+1] == '/') { i+=2; continue; }
  87. -
  88. - if (off) {
  89. - if (dst[off-1] == '/') { i++; continue; }
  90. -
  91. -last_test:
  92. - dst[off] = 0;
  93. - if (-1 != (ret = readlink (dst, buf, sizeof (buf)))) {
  94. - struct stat st;
  95. - buf[ret] = 0;
  96. - if (-1 == stat (buf, &st)) return (NULL);
  97. - if (ret+(PATH_MAX-i) > PATH_MAX) return (NULL);
  98. - strcpy (buf+ret, file+i);
  99. - return (realpath (buf, dst));
  100. - } else
  101. - if (errno == EACCES || errno == ENOENT) return (NULL);
  102. -
  103. - if (!file[i]) return (dst);
  104. - }
  105. - }
  106. - dst[off++] = file[i++];
  107. + if (readlink(file,buf,PATH_MAX)==0)
  108. + return myrealpath(buf,dest,count-1);
  109. + if (getcwd(dest,PATH_MAX)==0) return 0;
  110. + i=strlen(dest); dest[i]='/'; ++i;
  111. + for (; i<PATH_MAX-1; ++i) {
  112. + if (!(dest[i]=*file)) break;
  113. + ++file;
  114. }
  115. + dest[i]=0;
  116. + return dest;
  117. +}
  118. - if (off > 2 && dst[off-1] == '/') off--;
  119. - goto last_test;
  120. +char* realpath(const char* file, char* dest) {
  121. + int fd=open(".",O_RDONLY); /* save directory */
  122. + char* res=myrealpath(file,dest,31);
  123. + fchdir(fd);
  124. + close(fd);
  125. + return res;
  126. }
  127. +