os161-1.99
 All Data Structures
vfspath.c
00001 /*
00002  * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
00003  *      The President and Fellows of Harvard College.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the University nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  */
00029 
00030 /*
00031  * High-level VFS operations on pathnames.
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 /* Does most of the work for open(). */
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 /* Does most of the work for close(). */
00118 void
00119 vfs_close(struct vnode *vn)
00120 {
00121         /*
00122          * VOP_DECOPEN and VOP_DECREF don't return errors.
00123          *
00124          * We assume that the file system makes every reasonable
00125          * effort to not fail. If it does fail - such as on a hard I/O
00126          * error or something - vnode.c prints a warning. The reason
00127          * we don't report errors up to or above this level is that
00128          *    (1) most application software does not check for close
00129          *        failing, and more importantly
00130          *    (2) we're often called from places like process exit
00131          *        where reporting the error is impossible and
00132          *        meaningful recovery is entirely impractical.
00133          */
00134 
00135         VOP_DECOPEN(vn);
00136         VOP_DECREF(vn);
00137 }
00138 
00139 /* Does most of the work for remove(). */
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 /* Does most of the work for rename(). */
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 /* Does most of the work for link(). */
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  * Does most of the work for symlink().
00229  *
00230  * Note, however, if you're implementing symlinks, that various
00231  * other parts of the VFS layer are missing crucial elements of
00232  * support for symlinks.
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  * Does most of the work for readlink().
00254  *
00255  * Note, however, if you're implementing symlinks, that various
00256  * other parts of the VFS layer are missing crucial elements of
00257  * support for symlinks.
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  * Does most of the work for mkdir.
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  * Does most of the work for rmdir.
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 
 All Data Structures