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

317 lines
6.6 KiB

10 years ago
  1. #include <defs.h>
  2. #include <string.h>
  3. #include <vmm.h>
  4. #include <proc.h>
  5. #include <kmalloc.h>
  6. #include <vfs.h>
  7. #include <file.h>
  8. #include <iobuf.h>
  9. #include <sysfile.h>
  10. #include <stat.h>
  11. #include <dirent.h>
  12. #include <unistd.h>
  13. #include <error.h>
  14. #include <assert.h>
  15. #define IOBUF_SIZE 4096
  16. /* copy_path - copy path name */
  17. static int
  18. copy_path(char **to, const char *from) {
  19. struct mm_struct *mm = current->mm;
  20. char *buffer;
  21. if ((buffer = kmalloc(FS_MAX_FPATH_LEN + 1)) == NULL) {
  22. return -E_NO_MEM;
  23. }
  24. lock_mm(mm);
  25. if (!copy_string(mm, buffer, from, FS_MAX_FPATH_LEN + 1)) {
  26. unlock_mm(mm);
  27. goto failed_cleanup;
  28. }
  29. unlock_mm(mm);
  30. *to = buffer;
  31. return 0;
  32. failed_cleanup:
  33. kfree(buffer);
  34. return -E_INVAL;
  35. }
  36. /* sysfile_open - open file */
  37. int
  38. sysfile_open(const char *__path, uint32_t open_flags) {
  39. int ret;
  40. char *path;
  41. if ((ret = copy_path(&path, __path)) != 0) {
  42. return ret;
  43. }
  44. ret = file_open(path, open_flags);
  45. kfree(path);
  46. return ret;
  47. }
  48. /* sysfile_close - close file */
  49. int
  50. sysfile_close(int fd) {
  51. return file_close(fd);
  52. }
  53. /* sysfile_read - read file */
  54. int
  55. sysfile_read(int fd, void *base, size_t len) {
  56. struct mm_struct *mm = current->mm;
  57. if (len == 0) {
  58. return 0;
  59. }
  60. if (!file_testfd(fd, 1, 0)) {
  61. return -E_INVAL;
  62. }
  63. void *buffer;
  64. if ((buffer = kmalloc(IOBUF_SIZE)) == NULL) {
  65. return -E_NO_MEM;
  66. }
  67. int ret = 0;
  68. size_t copied = 0, alen;
  69. while (len != 0) {
  70. if ((alen = IOBUF_SIZE) > len) {
  71. alen = len;
  72. }
  73. ret = file_read(fd, buffer, alen, &alen);
  74. if (alen != 0) {
  75. lock_mm(mm);
  76. {
  77. if (copy_to_user(mm, base, buffer, alen)) {
  78. assert(len >= alen);
  79. base += alen, len -= alen, copied += alen;
  80. }
  81. else if (ret == 0) {
  82. ret = -E_INVAL;
  83. }
  84. }
  85. unlock_mm(mm);
  86. }
  87. if (ret != 0 || alen == 0) {
  88. goto out;
  89. }
  90. }
  91. out:
  92. kfree(buffer);
  93. if (copied != 0) {
  94. return copied;
  95. }
  96. return ret;
  97. }
  98. /* sysfile_write - write file */
  99. int
  100. sysfile_write(int fd, void *base, size_t len) {
  101. struct mm_struct *mm = current->mm;
  102. if (len == 0) {
  103. return 0;
  104. }
  105. if (!file_testfd(fd, 0, 1)) {
  106. return -E_INVAL;
  107. }
  108. void *buffer;
  109. if ((buffer = kmalloc(IOBUF_SIZE)) == NULL) {
  110. return -E_NO_MEM;
  111. }
  112. int ret = 0;
  113. size_t copied = 0, alen;
  114. while (len != 0) {
  115. if ((alen = IOBUF_SIZE) > len) {
  116. alen = len;
  117. }
  118. lock_mm(mm);
  119. {
  120. if (!copy_from_user(mm, buffer, base, alen, 0)) {
  121. ret = -E_INVAL;
  122. }
  123. }
  124. unlock_mm(mm);
  125. if (ret == 0) {
  126. ret = file_write(fd, buffer, alen, &alen);
  127. if (alen != 0) {
  128. assert(len >= alen);
  129. base += alen, len -= alen, copied += alen;
  130. }
  131. }
  132. if (ret != 0 || alen == 0) {
  133. goto out;
  134. }
  135. }
  136. out:
  137. kfree(buffer);
  138. if (copied != 0) {
  139. return copied;
  140. }
  141. return ret;
  142. }
  143. /* sysfile_seek - seek file */
  144. int
  145. sysfile_seek(int fd, off_t pos, int whence) {
  146. return file_seek(fd, pos, whence);
  147. }
  148. /* sysfile_fstat - stat file */
  149. int
  150. sysfile_fstat(int fd, struct stat *__stat) {
  151. struct mm_struct *mm = current->mm;
  152. int ret;
  153. struct stat __local_stat, *stat = &__local_stat;
  154. if ((ret = file_fstat(fd, stat)) != 0) {
  155. return ret;
  156. }
  157. lock_mm(mm);
  158. {
  159. if (!copy_to_user(mm, __stat, stat, sizeof(struct stat))) {
  160. ret = -E_INVAL;
  161. }
  162. }
  163. unlock_mm(mm);
  164. return ret;
  165. }
  166. /* sysfile_fsync - sync file */
  167. int
  168. sysfile_fsync(int fd) {
  169. return file_fsync(fd);
  170. }
  171. /* sysfile_chdir - change dir */
  172. int
  173. sysfile_chdir(const char *__path) {
  174. int ret;
  175. char *path;
  176. if ((ret = copy_path(&path, __path)) != 0) {
  177. return ret;
  178. }
  179. ret = vfs_chdir(path);
  180. kfree(path);
  181. return ret;
  182. }
  183. /* sysfile_link - link file */
  184. int
  185. sysfile_link(const char *__path1, const char *__path2) {
  186. int ret;
  187. char *old_path, *new_path;
  188. if ((ret = copy_path(&old_path, __path1)) != 0) {
  189. return ret;
  190. }
  191. if ((ret = copy_path(&new_path, __path2)) != 0) {
  192. kfree(old_path);
  193. return ret;
  194. }
  195. ret = vfs_link(old_path, new_path);
  196. kfree(old_path), kfree(new_path);
  197. return ret;
  198. }
  199. /* sysfile_rename - rename file */
  200. int
  201. sysfile_rename(const char *__path1, const char *__path2) {
  202. int ret;
  203. char *old_path, *new_path;
  204. if ((ret = copy_path(&old_path, __path1)) != 0) {
  205. return ret;
  206. }
  207. if ((ret = copy_path(&new_path, __path2)) != 0) {
  208. kfree(old_path);
  209. return ret;
  210. }
  211. ret = vfs_rename(old_path, new_path);
  212. kfree(old_path), kfree(new_path);
  213. return ret;
  214. }
  215. /* sysfile_unlink - unlink file */
  216. int
  217. sysfile_unlink(const char *__path) {
  218. int ret;
  219. char *path;
  220. if ((ret = copy_path(&path, __path)) != 0) {
  221. return ret;
  222. }
  223. ret = vfs_unlink(path);
  224. kfree(path);
  225. return ret;
  226. }
  227. /* sysfile_get cwd - get current working directory */
  228. int
  229. sysfile_getcwd(char *buf, size_t len) {
  230. struct mm_struct *mm = current->mm;
  231. if (len == 0) {
  232. return -E_INVAL;
  233. }
  234. int ret = -E_INVAL;
  235. lock_mm(mm);
  236. {
  237. if (user_mem_check(mm, (uintptr_t)buf, len, 1)) {
  238. struct iobuf __iob, *iob = iobuf_init(&__iob, buf, len, 0);
  239. ret = vfs_getcwd(iob);
  240. }
  241. }
  242. unlock_mm(mm);
  243. return ret;
  244. }
  245. /* sysfile_getdirentry - get the file entry in DIR */
  246. int
  247. sysfile_getdirentry(int fd, struct dirent *__direntp) {
  248. struct mm_struct *mm = current->mm;
  249. struct dirent *direntp;
  250. if ((direntp = kmalloc(sizeof(struct dirent))) == NULL) {
  251. return -E_NO_MEM;
  252. }
  253. int ret = 0;
  254. lock_mm(mm);
  255. {
  256. if (!copy_from_user(mm, &(direntp->offset), &(__direntp->offset), sizeof(direntp->offset), 1)) {
  257. ret = -E_INVAL;
  258. }
  259. }
  260. unlock_mm(mm);
  261. if (ret != 0 || (ret = file_getdirentry(fd, direntp)) != 0) {
  262. goto out;
  263. }
  264. lock_mm(mm);
  265. {
  266. if (!copy_to_user(mm, __direntp, direntp, sizeof(struct dirent))) {
  267. ret = -E_INVAL;
  268. }
  269. }
  270. unlock_mm(mm);
  271. out:
  272. kfree(direntp);
  273. return ret;
  274. }
  275. /* sysfile_dup - duplicate fd1 to fd2 */
  276. int
  277. sysfile_dup(int fd1, int fd2) {
  278. return file_dup(fd1, fd2);
  279. }
  280. int
  281. sysfile_pipe(int *fd_store) {
  282. return -E_UNIMP;
  283. }
  284. int
  285. sysfile_mkfifo(const char *__name, uint32_t open_flags) {
  286. return -E_UNIMP;
  287. }