00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include <types.h>
00035 #include <kern/errno.h>
00036 #include <kern/fcntl.h>
00037 #include <limits.h>
00038 #include <lib.h>
00039 #include <vfs.h>
00040 #include <vnode.h>
00041
00042
00043
00044 int
00045 vfs_open(char *path, int openflags, mode_t mode, struct vnode **ret)
00046 {
00047 int how;
00048 int result;
00049 int canwrite;
00050 struct vnode *vn = NULL;
00051
00052 how = openflags & O_ACCMODE;
00053
00054 switch (how) {
00055 case O_RDONLY:
00056 canwrite=0;
00057 break;
00058 case O_WRONLY:
00059 case O_RDWR:
00060 canwrite=1;
00061 break;
00062 default:
00063 return EINVAL;
00064 }
00065
00066 if (openflags & O_CREAT) {
00067 char name[NAME_MAX+1];
00068 struct vnode *dir;
00069 int excl = (openflags & O_EXCL)!=0;
00070
00071 result = vfs_lookparent(path, &dir, name, sizeof(name));
00072 if (result) {
00073 return result;
00074 }
00075
00076 result = VOP_CREAT(dir, name, excl, mode, &vn);
00077
00078 VOP_DECREF(dir);
00079 }
00080 else {
00081 result = vfs_lookup(path, &vn);
00082 }
00083
00084 if (result) {
00085 return result;
00086 }
00087
00088 KASSERT(vn != NULL);
00089
00090 result = VOP_OPEN(vn, openflags);
00091 if (result) {
00092 VOP_DECREF(vn);
00093 return result;
00094 }
00095
00096 VOP_INCOPEN(vn);
00097
00098 if (openflags & O_TRUNC) {
00099 if (canwrite==0) {
00100 result = EINVAL;
00101 }
00102 else {
00103 result = VOP_TRUNCATE(vn, 0);
00104 }
00105 if (result) {
00106 VOP_DECOPEN(vn);
00107 VOP_DECREF(vn);
00108 return result;
00109 }
00110 }
00111
00112 *ret = vn;
00113
00114 return 0;
00115 }
00116
00117
00118 void
00119 vfs_close(struct vnode *vn)
00120 {
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135 VOP_DECOPEN(vn);
00136 VOP_DECREF(vn);
00137 }
00138
00139
00140 int
00141 vfs_remove(char *path)
00142 {
00143 struct vnode *dir;
00144 char name[NAME_MAX+1];
00145 int result;
00146
00147 result = vfs_lookparent(path, &dir, name, sizeof(name));
00148 if (result) {
00149 return result;
00150 }
00151
00152 result = VOP_REMOVE(dir, name);
00153 VOP_DECREF(dir);
00154
00155 return result;
00156 }
00157
00158
00159 int
00160 vfs_rename(char *oldpath, char *newpath)
00161 {
00162 struct vnode *olddir;
00163 char oldname[NAME_MAX+1];
00164 struct vnode *newdir;
00165 char newname[NAME_MAX+1];
00166 int result;
00167
00168 result = vfs_lookparent(oldpath, &olddir, oldname, sizeof(oldname));
00169 if (result) {
00170 return result;
00171 }
00172 result = vfs_lookparent(newpath, &newdir, newname, sizeof(newname));
00173 if (result) {
00174 VOP_DECREF(olddir);
00175 return result;
00176 }
00177
00178 if (olddir->vn_fs==NULL || newdir->vn_fs==NULL ||
00179 olddir->vn_fs != newdir->vn_fs) {
00180 VOP_DECREF(newdir);
00181 VOP_DECREF(olddir);
00182 return EXDEV;
00183 }
00184
00185 result = VOP_RENAME(olddir, oldname, newdir, newname);
00186
00187 VOP_DECREF(newdir);
00188 VOP_DECREF(olddir);
00189
00190 return result;
00191 }
00192
00193
00194 int
00195 vfs_link(char *oldpath, char *newpath)
00196 {
00197 struct vnode *oldfile;
00198 struct vnode *newdir;
00199 char newname[NAME_MAX+1];
00200 int result;
00201
00202 result = vfs_lookup(oldpath, &oldfile);
00203 if (result) {
00204 return result;
00205 }
00206 result = vfs_lookparent(newpath, &newdir, newname, sizeof(newname));
00207 if (result) {
00208 VOP_DECREF(oldfile);
00209 return result;
00210 }
00211
00212 if (oldfile->vn_fs==NULL || newdir->vn_fs==NULL ||
00213 oldfile->vn_fs != newdir->vn_fs) {
00214 VOP_DECREF(newdir);
00215 VOP_DECREF(oldfile);
00216 return EXDEV;
00217 }
00218
00219 result = VOP_LINK(newdir, newname, oldfile);
00220
00221 VOP_DECREF(newdir);
00222 VOP_DECREF(oldfile);
00223
00224 return result;
00225 }
00226
00227
00228
00229
00230
00231
00232
00233
00234 int
00235 vfs_symlink(const char *contents, char *path)
00236 {
00237 struct vnode *newdir;
00238 char newname[NAME_MAX+1];
00239 int result;
00240
00241 result = vfs_lookparent(path, &newdir, newname, sizeof(newname));
00242 if (result) {
00243 return result;
00244 }
00245
00246 result = VOP_SYMLINK(newdir, newname, contents);
00247 VOP_DECREF(newdir);
00248
00249 return result;
00250 }
00251
00252
00253
00254
00255
00256
00257
00258
00259 int
00260 vfs_readlink(char *path, struct uio *uio)
00261 {
00262 struct vnode *vn;
00263 int result;
00264
00265 result = vfs_lookup(path, &vn);
00266 if (result) {
00267 return result;
00268 }
00269
00270 result = VOP_READLINK(vn, uio);
00271
00272 VOP_DECREF(vn);
00273
00274 return result;
00275 }
00276
00277
00278
00279
00280 int
00281 vfs_mkdir(char *path, mode_t mode)
00282 {
00283 struct vnode *parent;
00284 char name[NAME_MAX+1];
00285 int result;
00286
00287 result = vfs_lookparent(path, &parent, name, sizeof(name));
00288 if (result) {
00289 return result;
00290 }
00291
00292 result = VOP_MKDIR(parent, name, mode);
00293
00294 VOP_DECREF(parent);
00295
00296 return result;
00297 }
00298
00299
00300
00301
00302 int
00303 vfs_rmdir(char *path)
00304 {
00305 struct vnode *parent;
00306 char name[NAME_MAX+1];
00307 int result;
00308
00309 result = vfs_lookparent(path, &parent, name, sizeof(name));
00310 if (result) {
00311 return result;
00312 }
00313
00314 result = VOP_RMDIR(parent, name);
00315
00316 VOP_DECREF(parent);
00317
00318 return result;
00319 }
00320