dirent.c 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. #include <fcntl.h>
  2. #include <dirent.h>
  3. #include <string.h>
  4. #include <syscall.h>
  5. DIR* opendir(const char* name)
  6. {
  7. // TODO: set flags
  8. int fd = open(name, O_DIRECTORY);
  9. if (fd < 0)
  10. return NULL;
  11. return fdopendir(fd);
  12. }
  13. DIR* fdopendir(int fd)
  14. {
  15. static DIR dirs[64];
  16. static int next = 0;
  17. dirs[next].fd = fd;
  18. dirs[next].bpos = 0;
  19. return dirs + next++;
  20. }
  21. struct kernel_dirent {
  22. ino_t d_ino; // inode number
  23. uint32_t d_off; // ignored
  24. uint16_t d_reclen; // length of this struct user_dirent
  25. char d_name[1]; // file name with a padding zero
  26. // uint8_t d_type; // file type, with offset of (d_reclen - 1)
  27. };
  28. size_t fill_dirent(struct dirent* dent, char* buffer, size_t bpos)
  29. {
  30. struct kernel_dirent* dp = (struct kernel_dirent*)(buffer + bpos);
  31. dent->d_ino = dp->d_ino;
  32. dent->d_off = dp->d_off;
  33. dent->d_reclen = dp->d_reclen;
  34. dent->d_type = buffer[bpos + dp->d_reclen - 1];
  35. strncpy(dent->d_name, dp->d_name, sizeof(dent->d_name));
  36. dent->d_name[sizeof(dent->d_name) - 1] = 0;
  37. return bpos + dp->d_reclen;
  38. }
  39. struct dirent* readdir(DIR* dirp)
  40. {
  41. if (dirp->bpos) {
  42. if (dirp->bpos >= dirp->blen) {
  43. dirp->bpos = 0;
  44. } else {
  45. goto fill;
  46. }
  47. }
  48. dirp->blen = syscall3(SYS_getdents,
  49. dirp->fd,
  50. (uint32_t)dirp->buffer,
  51. sizeof(dirp->buffer)
  52. );
  53. if (dirp->blen <= 0)
  54. return NULL;
  55. fill:
  56. dirp->bpos = fill_dirent(&dirp->dent, dirp->buffer, dirp->bpos);
  57. return &dirp->dent;
  58. }