vfspath.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. /*
  2. * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
  3. * The President and Fellows of Harvard College.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the University nor the names of its contributors
  14. * may be used to endorse or promote products derived from this software
  15. * without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
  21. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. */
  29. /*
  30. * High-level VFS operations on pathnames.
  31. */
  32. #include <types.h>
  33. #include <kern/errno.h>
  34. #include <kern/fcntl.h>
  35. #include <limits.h>
  36. #include <lib.h>
  37. #include <vfs.h>
  38. #include <vnode.h>
  39. /* Does most of the work for open(). */
  40. int
  41. vfs_open(char *path, int openflags, mode_t mode, struct vnode **ret)
  42. {
  43. int how;
  44. int result;
  45. int canwrite;
  46. struct vnode *vn = NULL;
  47. how = openflags & O_ACCMODE;
  48. switch (how) {
  49. case O_RDONLY:
  50. canwrite=0;
  51. break;
  52. case O_WRONLY:
  53. case O_RDWR:
  54. canwrite=1;
  55. break;
  56. default:
  57. return EINVAL;
  58. }
  59. if (openflags & O_CREAT) {
  60. char name[NAME_MAX+1];
  61. struct vnode *dir;
  62. int excl = (openflags & O_EXCL)!=0;
  63. result = vfs_lookparent(path, &dir, name, sizeof(name));
  64. if (result) {
  65. return result;
  66. }
  67. result = VOP_CREAT(dir, name, excl, mode, &vn);
  68. VOP_DECREF(dir);
  69. }
  70. else {
  71. result = vfs_lookup(path, &vn);
  72. }
  73. if (result) {
  74. return result;
  75. }
  76. KASSERT(vn != NULL);
  77. result = VOP_OPEN(vn, openflags);
  78. if (result) {
  79. VOP_DECREF(vn);
  80. return result;
  81. }
  82. VOP_INCOPEN(vn);
  83. if (openflags & O_TRUNC) {
  84. if (canwrite==0) {
  85. result = EINVAL;
  86. }
  87. else {
  88. result = VOP_TRUNCATE(vn, 0);
  89. }
  90. if (result) {
  91. VOP_DECOPEN(vn);
  92. VOP_DECREF(vn);
  93. return result;
  94. }
  95. }
  96. *ret = vn;
  97. return 0;
  98. }
  99. /* Does most of the work for close(). */
  100. void
  101. vfs_close(struct vnode *vn)
  102. {
  103. /*
  104. * VOP_DECOPEN and VOP_DECREF don't return errors.
  105. *
  106. * We assume that the file system makes every reasonable
  107. * effort to not fail. If it does fail - such as on a hard I/O
  108. * error or something - vnode.c prints a warning. The reason
  109. * we don't report errors up to or above this level is that
  110. * (1) most application software does not check for close
  111. * failing, and more importantly
  112. * (2) we're often called from places like process exit
  113. * where reporting the error is impossible and
  114. * meaningful recovery is entirely impractical.
  115. */
  116. VOP_DECOPEN(vn);
  117. VOP_DECREF(vn);
  118. }
  119. /* Does most of the work for remove(). */
  120. int
  121. vfs_remove(char *path)
  122. {
  123. struct vnode *dir;
  124. char name[NAME_MAX+1];
  125. int result;
  126. result = vfs_lookparent(path, &dir, name, sizeof(name));
  127. if (result) {
  128. return result;
  129. }
  130. result = VOP_REMOVE(dir, name);
  131. VOP_DECREF(dir);
  132. return result;
  133. }
  134. /* Does most of the work for rename(). */
  135. int
  136. vfs_rename(char *oldpath, char *newpath)
  137. {
  138. struct vnode *olddir;
  139. char oldname[NAME_MAX+1];
  140. struct vnode *newdir;
  141. char newname[NAME_MAX+1];
  142. int result;
  143. result = vfs_lookparent(oldpath, &olddir, oldname, sizeof(oldname));
  144. if (result) {
  145. return result;
  146. }
  147. result = vfs_lookparent(newpath, &newdir, newname, sizeof(newname));
  148. if (result) {
  149. VOP_DECREF(olddir);
  150. return result;
  151. }
  152. if (olddir->vn_fs==NULL || newdir->vn_fs==NULL ||
  153. olddir->vn_fs != newdir->vn_fs) {
  154. VOP_DECREF(newdir);
  155. VOP_DECREF(olddir);
  156. return EXDEV;
  157. }
  158. result = VOP_RENAME(olddir, oldname, newdir, newname);
  159. VOP_DECREF(newdir);
  160. VOP_DECREF(olddir);
  161. return result;
  162. }
  163. /* Does most of the work for link(). */
  164. int
  165. vfs_link(char *oldpath, char *newpath)
  166. {
  167. struct vnode *oldfile;
  168. struct vnode *newdir;
  169. char newname[NAME_MAX+1];
  170. int result;
  171. result = vfs_lookup(oldpath, &oldfile);
  172. if (result) {
  173. return result;
  174. }
  175. result = vfs_lookparent(newpath, &newdir, newname, sizeof(newname));
  176. if (result) {
  177. VOP_DECREF(oldfile);
  178. return result;
  179. }
  180. if (oldfile->vn_fs==NULL || newdir->vn_fs==NULL ||
  181. oldfile->vn_fs != newdir->vn_fs) {
  182. VOP_DECREF(newdir);
  183. VOP_DECREF(oldfile);
  184. return EXDEV;
  185. }
  186. result = VOP_LINK(newdir, newname, oldfile);
  187. VOP_DECREF(newdir);
  188. VOP_DECREF(oldfile);
  189. return result;
  190. }
  191. /*
  192. * Does most of the work for symlink().
  193. *
  194. * Note, however, if you're implementing symlinks, that various
  195. * other parts of the VFS layer are missing crucial elements of
  196. * support for symlinks.
  197. */
  198. int
  199. vfs_symlink(const char *contents, char *path)
  200. {
  201. struct vnode *newdir;
  202. char newname[NAME_MAX+1];
  203. int result;
  204. result = vfs_lookparent(path, &newdir, newname, sizeof(newname));
  205. if (result) {
  206. return result;
  207. }
  208. result = VOP_SYMLINK(newdir, newname, contents);
  209. VOP_DECREF(newdir);
  210. return result;
  211. }
  212. /*
  213. * Does most of the work for readlink().
  214. *
  215. * Note, however, if you're implementing symlinks, that various
  216. * other parts of the VFS layer are missing crucial elements of
  217. * support for symlinks.
  218. */
  219. int
  220. vfs_readlink(char *path, struct uio *uio)
  221. {
  222. struct vnode *vn;
  223. int result;
  224. result = vfs_lookup(path, &vn);
  225. if (result) {
  226. return result;
  227. }
  228. result = VOP_READLINK(vn, uio);
  229. VOP_DECREF(vn);
  230. return result;
  231. }
  232. /*
  233. * Does most of the work for mkdir.
  234. */
  235. int
  236. vfs_mkdir(char *path, mode_t mode)
  237. {
  238. struct vnode *parent;
  239. char name[NAME_MAX+1];
  240. int result;
  241. result = vfs_lookparent(path, &parent, name, sizeof(name));
  242. if (result) {
  243. return result;
  244. }
  245. result = VOP_MKDIR(parent, name, mode);
  246. VOP_DECREF(parent);
  247. return result;
  248. }
  249. /*
  250. * Does most of the work for rmdir.
  251. */
  252. int
  253. vfs_rmdir(char *path)
  254. {
  255. struct vnode *parent;
  256. char name[NAME_MAX+1];
  257. int result;
  258. result = vfs_lookparent(path, &parent, name, sizeof(name));
  259. if (result) {
  260. return result;
  261. }
  262. result = VOP_RMDIR(parent, name);
  263. VOP_DECREF(parent);
  264. return result;
  265. }