Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
script3r
GitHub Repository: script3r/os161
Path: blob/master/kern/vfs/vfspath.c
2096 views
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
321
322