《操作系统》的实验代码。
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.

126 lines
2.6 KiB

12 years ago
  1. #include <defs.h>
  2. #include <string.h>
  3. #include <vfs.h>
  4. #include <inode.h>
  5. #include <iobuf.h>
  6. #include <stat.h>
  7. #include <proc.h>
  8. #include <error.h>
  9. #include <assert.h>
  10. /*
  11. * get_cwd_nolock - retrieve current process's working directory. without lock protect
  12. */
  13. static struct inode *
  14. get_cwd_nolock(void) {
  15. return current->filesp->pwd;
  16. }
  17. /*
  18. * set_cwd_nolock - set current working directory.
  19. */
  20. static void
  21. set_cwd_nolock(struct inode *pwd) {
  22. current->filesp->pwd = pwd;
  23. }
  24. /*
  25. * lock_cfs - lock the fs related process on current process
  26. */
  27. static void
  28. lock_cfs(void) {
  29. lock_files(current->filesp);
  30. }
  31. /*
  32. * unlock_cfs - unlock the fs related process on current process
  33. */
  34. static void
  35. unlock_cfs(void) {
  36. unlock_files(current->filesp);
  37. }
  38. /*
  39. * vfs_get_curdir - Get current directory as a inode.
  40. */
  41. int
  42. vfs_get_curdir(struct inode **dir_store) {
  43. struct inode *node;
  44. if ((node = get_cwd_nolock()) != NULL) {
  45. vop_ref_inc(node);
  46. *dir_store = node;
  47. return 0;
  48. }
  49. return -E_NOENT;
  50. }
  51. /*
  52. * vfs_set_curdir - Set current directory as a inode.
  53. * The passed inode must in fact be a directory.
  54. */
  55. int
  56. vfs_set_curdir(struct inode *dir) {
  57. int ret = 0;
  58. lock_cfs();
  59. struct inode *old_dir;
  60. if ((old_dir = get_cwd_nolock()) != dir) {
  61. if (dir != NULL) {
  62. uint32_t type;
  63. if ((ret = vop_gettype(dir, &type)) != 0) {
  64. goto out;
  65. }
  66. if (!S_ISDIR(type)) {
  67. ret = -E_NOTDIR;
  68. goto out;
  69. }
  70. vop_ref_inc(dir);
  71. }
  72. set_cwd_nolock(dir);
  73. if (old_dir != NULL) {
  74. vop_ref_dec(old_dir);
  75. }
  76. }
  77. out:
  78. unlock_cfs();
  79. return ret;
  80. }
  81. /*
  82. * vfs_chdir - Set current directory, as a pathname. Use vfs_lookup to translate
  83. * it to a inode.
  84. */
  85. int
  86. vfs_chdir(char *path) {
  87. int ret;
  88. struct inode *node;
  89. if ((ret = vfs_lookup(path, &node)) == 0) {
  90. ret = vfs_set_curdir(node);
  91. vop_ref_dec(node);
  92. }
  93. return ret;
  94. }
  95. /*
  96. * vfs_getcwd - retrieve current working directory(cwd).
  97. */
  98. int
  99. vfs_getcwd(struct iobuf *iob) {
  100. int ret;
  101. struct inode *node;
  102. if ((ret = vfs_get_curdir(&node)) != 0) {
  103. return ret;
  104. }
  105. assert(node->in_fs != NULL);
  106. const char *devname = vfs_get_devname(node->in_fs);
  107. if ((ret = iobuf_move(iob, (char *)devname, strlen(devname), 1, NULL)) != 0) {
  108. goto out;
  109. }
  110. char colon = ':';
  111. if ((ret = iobuf_move(iob, &colon, sizeof(colon), 1, NULL)) != 0) {
  112. goto out;
  113. }
  114. ret = vop_namefile(node, iob);
  115. out:
  116. vop_ref_dec(node);
  117. return ret;
  118. }