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 <limits.h>
00037 #include <lib.h>
00038 #include <synch.h>
00039 #include <vfs.h>
00040 #include <fs.h>
00041 #include <vnode.h>
00042
00043 static struct vnode *bootfs_vnode = NULL;
00044
00045
00046
00047
00048 static
00049 void
00050 change_bootfs(struct vnode *newvn)
00051 {
00052 struct vnode *oldvn;
00053
00054 oldvn = bootfs_vnode;
00055 bootfs_vnode = newvn;
00056
00057 if (oldvn != NULL) {
00058 VOP_DECREF(oldvn);
00059 }
00060 }
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 int
00071 vfs_setbootfs(const char *fsname)
00072 {
00073 char tmp[NAME_MAX+1];
00074 char *s;
00075 int result;
00076 struct vnode *newguy;
00077
00078 vfs_biglock_acquire();
00079
00080 snprintf(tmp, sizeof(tmp)-1, "%s", fsname);
00081 s = strchr(tmp, ':');
00082 if (s) {
00083
00084 if (strlen(s)>0) {
00085 vfs_biglock_release();
00086 return EINVAL;
00087 }
00088 }
00089 else {
00090 strcat(tmp, ":");
00091 }
00092
00093 result = vfs_chdir(tmp);
00094 if (result) {
00095 vfs_biglock_release();
00096 return result;
00097 }
00098
00099 result = vfs_getcurdir(&newguy);
00100 if (result) {
00101 vfs_biglock_release();
00102 return result;
00103 }
00104
00105 change_bootfs(newguy);
00106
00107 vfs_biglock_release();
00108 return 0;
00109 }
00110
00111
00112
00113
00114 void
00115 vfs_clearbootfs(void)
00116 {
00117 vfs_biglock_acquire();
00118 change_bootfs(NULL);
00119 vfs_biglock_release();
00120 }
00121
00122
00123
00124
00125
00126
00127
00128 static
00129 int
00130 getdevice(char *path, char **subpath, struct vnode **startvn)
00131 {
00132 int slash=-1, colon=-1, i;
00133 struct vnode *vn;
00134 int result;
00135
00136 KASSERT(vfs_biglock_do_i_hold());
00137
00138
00139
00140
00141
00142 for (i=0; path[i]; i++) {
00143 if (path[i]==':') {
00144 colon = i;
00145 break;
00146 }
00147 if (path[i]=='/') {
00148 slash = i;
00149 break;
00150 }
00151 }
00152
00153 if (colon < 0 && slash != 0) {
00154
00155
00156
00157
00158
00159
00160
00161 *subpath = path;
00162 return vfs_getcurdir(startvn);
00163 }
00164
00165 if (colon>0) {
00166
00167 path[colon]=0;
00168 while (path[colon+1]=='/') {
00169
00170 colon++;
00171 }
00172 *subpath = &path[colon+1];
00173
00174 result = vfs_getroot(path, startvn);
00175 if (result) {
00176 return result;
00177 }
00178
00179 return 0;
00180 }
00181
00182
00183
00184
00185
00186
00187
00188 KASSERT(colon==0 || slash==0);
00189
00190 if (path[0]=='/') {
00191 if (bootfs_vnode==NULL) {
00192 return ENOENT;
00193 }
00194 VOP_INCREF(bootfs_vnode);
00195 *startvn = bootfs_vnode;
00196 }
00197 else {
00198 KASSERT(path[0]==':');
00199
00200 result = vfs_getcurdir(&vn);
00201 if (result) {
00202 return result;
00203 }
00204
00205
00206
00207
00208
00209 KASSERT(vn->vn_fs!=NULL);
00210
00211 *startvn = FSOP_GETROOT(vn->vn_fs);
00212
00213 VOP_DECREF(vn);
00214 }
00215
00216 while (path[1]=='/') {
00217
00218 path++;
00219 }
00220
00221 *subpath = path+1;
00222
00223 return 0;
00224 }
00225
00226
00227
00228
00229
00230
00231 int
00232 vfs_lookparent(char *path, struct vnode **retval,
00233 char *buf, size_t buflen)
00234 {
00235 struct vnode *startvn;
00236 int result;
00237
00238 vfs_biglock_acquire();
00239
00240 result = getdevice(path, &path, &startvn);
00241 if (result) {
00242 vfs_biglock_release();
00243 return result;
00244 }
00245
00246 if (strlen(path)==0) {
00247
00248
00249
00250
00251
00252 result = EINVAL;
00253 }
00254 else {
00255 result = VOP_LOOKPARENT(startvn, path, retval, buf, buflen);
00256 }
00257
00258 VOP_DECREF(startvn);
00259
00260 vfs_biglock_release();
00261 return result;
00262 }
00263
00264 int
00265 vfs_lookup(char *path, struct vnode **retval)
00266 {
00267 struct vnode *startvn;
00268 int result;
00269
00270 vfs_biglock_acquire();
00271
00272 result = getdevice(path, &path, &startvn);
00273 if (result) {
00274 vfs_biglock_release();
00275 return result;
00276 }
00277
00278 if (strlen(path)==0) {
00279 *retval = startvn;
00280 vfs_biglock_release();
00281 return 0;
00282 }
00283
00284 result = VOP_LOOKUP(startvn, path, retval);
00285
00286 VOP_DECREF(startvn);
00287 vfs_biglock_release();
00288 return result;
00289 }