/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- vfs_open
- vfs_close
- vfs_remove
- vfs_rename
- vfs_link
- vfs_symlink
- vfs_readlink
- vfs_mkdir
- vfs_rmdir
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 /*
31 * High-level VFS operations on pathnames.
32 */
33
34 #include <types.h>
35 #include <kern/errno.h>
36 #include <kern/fcntl.h>
37 #include <limits.h>
38 #include <lib.h>
39 #include <vfs.h>
40 #include <vnode.h>
41
42
43 /* Does most of the work for open(). */
44 int
45 vfs_open(char *path, int openflags, mode_t mode, struct vnode **ret)
46 {
47 int how;
48 int result;
49 int canwrite;
50 struct vnode *vn = NULL;
51
52 how = openflags & O_ACCMODE;
53
54 switch (how) {
55 case O_RDONLY:
56 canwrite=0;
57 break;
58 case O_WRONLY:
59 case O_RDWR:
60 canwrite=1;
61 break;
62 default:
63 return EINVAL;
64 }
65
66 if (openflags & O_CREAT) {
67 char name[NAME_MAX+1];
68 struct vnode *dir;
69 int excl = (openflags & O_EXCL)!=0;
70
71 result = vfs_lookparent(path, &dir, name, sizeof(name));
72 if (result) {
73 return result;
74 }
75
76 result = VOP_CREAT(dir, name, excl, mode, &vn);
77
78 VOP_DECREF(dir);
79 }
80 else {
81 result = vfs_lookup(path, &vn);
82 }
83
84 if (result) {
85 return result;
86 }
87
88 KASSERT(vn != NULL);
89
90 result = VOP_OPEN(vn, openflags);
91 if (result) {
92 VOP_DECREF(vn);
93 return result;
94 }
95
96 VOP_INCOPEN(vn);
97
98 if (openflags & O_TRUNC) {
99 if (canwrite==0) {
100 result = EINVAL;
101 }
102 else {
103 result = VOP_TRUNCATE(vn, 0);
104 }
105 if (result) {
106 VOP_DECOPEN(vn);
107 VOP_DECREF(vn);
108 return result;
109 }
110 }
111
112 *ret = vn;
113
114 return 0;
115 }
116
117 /* Does most of the work for close(). */
118 void
119 vfs_close(struct vnode *vn)
120 {
121 /*
122 * VOP_DECOPEN and VOP_DECREF don't return errors.
123 *
124 * We assume that the file system makes every reasonable
125 * effort to not fail. If it does fail - such as on a hard I/O
126 * error or something - vnode.c prints a warning. The reason
127 * we don't report errors up to or above this level is that
128 * (1) most application software does not check for close
129 * failing, and more importantly
130 * (2) we're often called from places like process exit
131 * where reporting the error is impossible and
132 * meaningful recovery is entirely impractical.
133 */
134
135 VOP_DECOPEN(vn);
136 VOP_DECREF(vn);
137 }
138
139 /* Does most of the work for remove(). */
140 int
141 vfs_remove(char *path)
142 {
143 struct vnode *dir;
144 char name[NAME_MAX+1];
145 int result;
146
147 result = vfs_lookparent(path, &dir, name, sizeof(name));
148 if (result) {
149 return result;
150 }
151
152 result = VOP_REMOVE(dir, name);
153 VOP_DECREF(dir);
154
155 return result;
156 }
157
158 /* Does most of the work for rename(). */
159 int
160 vfs_rename(char *oldpath, char *newpath)
161 {
162 struct vnode *olddir;
163 char oldname[NAME_MAX+1];
164 struct vnode *newdir;
165 char newname[NAME_MAX+1];
166 int result;
167
168 result = vfs_lookparent(oldpath, &olddir, oldname, sizeof(oldname));
169 if (result) {
170 return result;
171 }
172 result = vfs_lookparent(newpath, &newdir, newname, sizeof(newname));
173 if (result) {
174 VOP_DECREF(olddir);
175 return result;
176 }
177
178 if (olddir->vn_fs==NULL || newdir->vn_fs==NULL ||
179 olddir->vn_fs != newdir->vn_fs) {
180 VOP_DECREF(newdir);
181 VOP_DECREF(olddir);
182 return EXDEV;
183 }
184
185 result = VOP_RENAME(olddir, oldname, newdir, newname);
186
187 VOP_DECREF(newdir);
188 VOP_DECREF(olddir);
189
190 return result;
191 }
192
193 /* Does most of the work for link(). */
194 int
195 vfs_link(char *oldpath, char *newpath)
196 {
197 struct vnode *oldfile;
198 struct vnode *newdir;
199 char newname[NAME_MAX+1];
200 int result;
201
202 result = vfs_lookup(oldpath, &oldfile);
203 if (result) {
204 return result;
205 }
206 result = vfs_lookparent(newpath, &newdir, newname, sizeof(newname));
207 if (result) {
208 VOP_DECREF(oldfile);
209 return result;
210 }
211
212 if (oldfile->vn_fs==NULL || newdir->vn_fs==NULL ||
213 oldfile->vn_fs != newdir->vn_fs) {
214 VOP_DECREF(newdir);
215 VOP_DECREF(oldfile);
216 return EXDEV;
217 }
218
219 result = VOP_LINK(newdir, newname, oldfile);
220
221 VOP_DECREF(newdir);
222 VOP_DECREF(oldfile);
223
224 return result;
225 }
226
227 /*
228 * Does most of the work for symlink().
229 *
230 * Note, however, if you're implementing symlinks, that various
231 * other parts of the VFS layer are missing crucial elements of
232 * support for symlinks.
233 */
234 int
235 vfs_symlink(const char *contents, char *path)
236 {
237 struct vnode *newdir;
238 char newname[NAME_MAX+1];
239 int result;
240
241 result = vfs_lookparent(path, &newdir, newname, sizeof(newname));
242 if (result) {
243 return result;
244 }
245
246 result = VOP_SYMLINK(newdir, newname, contents);
247 VOP_DECREF(newdir);
248
249 return result;
250 }
251
252 /*
253 * Does most of the work for readlink().
254 *
255 * Note, however, if you're implementing symlinks, that various
256 * other parts of the VFS layer are missing crucial elements of
257 * support for symlinks.
258 */
259 int
260 vfs_readlink(char *path, struct uio *uio)
261 {
262 struct vnode *vn;
263 int result;
264
265 result = vfs_lookup(path, &vn);
266 if (result) {
267 return result;
268 }
269
270 result = VOP_READLINK(vn, uio);
271
272 VOP_DECREF(vn);
273
274 return result;
275 }
276
277 /*
278 * Does most of the work for mkdir.
279 */
280 int
281 vfs_mkdir(char *path, mode_t mode)
282 {
283 struct vnode *parent;
284 char name[NAME_MAX+1];
285 int result;
286
287 result = vfs_lookparent(path, &parent, name, sizeof(name));
288 if (result) {
289 return result;
290 }
291
292 result = VOP_MKDIR(parent, name, mode);
293
294 VOP_DECREF(parent);
295
296 return result;
297 }
298
299 /*
300 * Does most of the work for rmdir.
301 */
302 int
303 vfs_rmdir(char *path)
304 {
305 struct vnode *parent;
306 char name[NAME_MAX+1];
307 int result;
308
309 result = vfs_lookparent(path, &parent, name, sizeof(name));
310 if (result) {
311 return result;
312 }
313
314 result = VOP_RMDIR(parent, name);
315
316 VOP_DECREF(parent);
317
318 return result;
319 }
320