root/kern/vfs/vfspath.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vfs_open
  2. vfs_close
  3. vfs_remove
  4. vfs_rename
  5. vfs_link
  6. vfs_symlink
  7. vfs_readlink
  8. vfs_mkdir
  9. 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 

/* [<][>][^][v][top][bottom][index][help] */