1
0

realpath.c 839 B

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. #include <stdlib.h>
  2. #include <limits.h>
  3. #include <sys/stat.h>
  4. #include <fcntl.h>
  5. #include <errno.h>
  6. #include <unistd.h>
  7. #include <string.h>
  8. #include "syscall.h"
  9. char *realpath(const char *restrict filename, char *restrict resolved)
  10. {
  11. int fd;
  12. ssize_t r;
  13. struct stat st1, st2;
  14. char buf[15+3*sizeof(int)];
  15. char tmp[PATH_MAX];
  16. if (!filename) {
  17. errno = EINVAL;
  18. return 0;
  19. }
  20. fd = sys_open(filename, O_PATH|O_NONBLOCK|O_CLOEXEC);
  21. if (fd < 0) return 0;
  22. __procfdname(buf, fd);
  23. r = readlink(buf, tmp, sizeof tmp - 1);
  24. if (r < 0) goto err;
  25. tmp[r] = 0;
  26. fstat(fd, &st1);
  27. r = stat(tmp, &st2);
  28. if (r<0 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) {
  29. if (!r) errno = ELOOP;
  30. goto err;
  31. }
  32. __syscall(SYS_close, fd);
  33. return resolved ? strcpy(resolved, tmp) : strdup(tmp);
  34. err:
  35. __syscall(SYS_close, fd);
  36. return 0;
  37. }