getcwd.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. #include <errno.h>
  2. #include <sys/stat.h>
  3. #include <dirent.h>
  4. #include <string.h>
  5. /*
  6. * These functions find the absolute path to the current working directory.
  7. *
  8. * They don't use malloc or large amounts of stack space.
  9. */
  10. static char *recurser(); /* Routine to go up tree */
  11. static char *search_dir(); /* Routine to find the step back down */
  12. static char *path_buf;
  13. static int path_size;
  14. static dev_t root_dev;
  15. static ino_t root_ino;
  16. static struct stat st;
  17. char *getcwd(buf, size)
  18. char *buf;
  19. int size;
  20. {
  21. path_buf = buf;
  22. path_size = size;
  23. if (size < 3) {
  24. errno = ERANGE;
  25. return 0;
  26. }
  27. strcpy(path_buf, ".");
  28. if (stat("/", &st) < 0)
  29. return 0;
  30. root_dev = st.st_dev;
  31. root_ino = st.st_ino;
  32. return recurser();
  33. }
  34. static char *recurser()
  35. {
  36. dev_t this_dev;
  37. ino_t this_ino;
  38. if (stat(path_buf, &st) < 0)
  39. return 0;
  40. this_dev = st.st_dev;
  41. this_ino = st.st_ino;
  42. if (this_dev == root_dev && this_ino == root_ino) {
  43. strcpy(path_buf, "/");
  44. return path_buf;
  45. }
  46. if (strlen(path_buf) + 4 > path_size) {
  47. errno = ERANGE;
  48. return 0;
  49. }
  50. strcat(path_buf, "/..");
  51. if (recurser() == 0)
  52. return 0;
  53. return search_dir(this_dev, this_ino);
  54. }
  55. static char *search_dir(this_dev, this_ino)
  56. dev_t this_dev;
  57. ino_t this_ino;
  58. {
  59. DIR *dp;
  60. struct dirent *d;
  61. char *ptr;
  62. int slen;
  63. /* The test is for ELKS lib 0.0.9, this should be fixed in the real kernel */
  64. int slow_search = (sizeof(ino_t) != sizeof(d->d_ino));
  65. if (stat(path_buf, &st) < 0)
  66. return 0;
  67. if (this_dev != st.st_dev)
  68. slow_search = 1;
  69. slen = strlen(path_buf);
  70. ptr = path_buf + slen - 1;
  71. if (*ptr != '/') {
  72. if (slen + 2 > path_size) {
  73. errno = ERANGE;
  74. return 0;
  75. }
  76. strcpy(++ptr, "/");
  77. slen++;
  78. }
  79. slen++;
  80. dp = opendir(path_buf);
  81. if (dp == 0)
  82. return 0;
  83. while ((d = readdir(dp)) != 0) {
  84. if (slow_search || this_ino == d->d_ino) {
  85. if (slen + strlen(d->d_name) > path_size) {
  86. errno = ERANGE;
  87. return 0;
  88. }
  89. strcpy(ptr + 1, d->d_name);
  90. if (stat(path_buf, &st) < 0)
  91. continue;
  92. if (st.st_ino == this_ino && st.st_dev == this_dev) {
  93. closedir(dp);
  94. return path_buf;
  95. }
  96. }
  97. }
  98. closedir(dp);
  99. errno = ENOENT;
  100. return 0;
  101. }