00001
00002
00003
00004
00005
00006
00007
00008 #include "fs.h"
00009 #include <fcntl.h>
00010 #include <string.h>
00011 #include <minix/com.h>
00012 #include <sys/stat.h>
00013 #include "buf.h"
00014 #include "file.h"
00015 #include "fproc.h"
00016 #include "inode.h"
00017 #include "param.h"
00018 #include "super.h"
00019
00020
00021 PRIVATE int allow_newroot= 1;
00022
00023 FORWARD _PROTOTYPE( dev_t name_to_dev, (char *path) );
00024
00025
00026
00027
00028 PUBLIC int do_mount()
00029 {
00030
00031
00032 register struct inode *rip, *root_ip;
00033 struct super_block *xp, *sp;
00034 dev_t dev;
00035 mode_t bits;
00036 int rdir, mdir;
00037 int i, r, found;
00038 struct fproc *tfp;
00039
00040
00041 if (!super_user) return(EPERM);
00042
00043
00044 if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
00045 if ( (dev = name_to_dev(user_path)) == NO_DEV) return(err_code);
00046
00047
00048 sp = NIL_SUPER;
00049 found = FALSE;
00050 for (xp = &super_block[0]; xp < &super_block[NR_SUPERS]; xp++) {
00051 if (xp->s_dev == dev)
00052 {
00053
00054 found = TRUE;
00055 sp= xp;
00056 break;
00057 }
00058 if (xp->s_dev == NO_DEV) sp = xp;
00059 }
00060 if (found)
00061 {
00062 printf(
00063 "do_mount: s_imount = 0x%x (%x, %d), s_isup = 0x%x (%x, %d), fp_rootdir = 0x%x\n",
00064 xp->s_imount, xp->s_imount->i_dev, xp->s_imount->i_num,
00065 xp->s_isup, xp->s_isup->i_dev, xp->s_isup->i_num,
00066 fproc[FS_PROC_NR].fp_rootdir);
00067
00068
00069
00070 if (xp->s_imount != xp->s_isup ||
00071 xp->s_isup == fproc[FS_PROC_NR].fp_rootdir)
00072 {
00073
00074
00075
00076
00077
00078
00079
00080 return(EBUSY);
00081 }
00082
00083 if (root_dev == xp->s_dev)
00084 {
00085 panic("fs", "inconsistency remounting old root",
00086 NO_NUM);
00087 }
00088
00089
00090 if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) {
00091 return(err_code);
00092 }
00093
00094 if ( (rip = eat_path(user_path)) == NIL_INODE) {
00095 return(err_code);
00096 }
00097
00098 r = OK;
00099
00100
00101 bits = rip->i_mode & I_TYPE;
00102 if (bits == I_BLOCK_SPECIAL || bits == I_CHAR_SPECIAL)
00103 r = ENOTDIR;
00104
00105
00106 root_ip= sp->s_isup;
00107
00108
00109 if (r == OK) {
00110 mdir = ((rip->i_mode & I_TYPE) == I_DIRECTORY);
00111
00112 rdir = ((root_ip->i_mode & I_TYPE) == I_DIRECTORY);
00113 if (!mdir && rdir) r = EISDIR;
00114 }
00115
00116
00117 if (r != OK) {
00118 put_inode(rip);
00119 return(r);
00120 }
00121
00122
00123 rip->i_mount = I_MOUNT;
00124
00125
00126 put_inode(sp->s_imount);
00127 sp->s_imount = rip;
00128 sp->s_rd_only = m_in.rd_only;
00129 allow_newroot= 0;
00130 return(OK);
00131 }
00132 if (sp == NIL_SUPER) return(ENFILE);
00133
00134
00135 if (dev_open(dev, who_e, m_in.rd_only ? R_BIT : (R_BIT|W_BIT)) != OK)
00136 return(EINVAL);
00137
00138
00139 (void) do_sync();
00140 invalidate(dev);
00141
00142
00143 sp->s_dev = dev;
00144 r = read_super(sp);
00145
00146
00147 if (r != OK) {
00148 dev_close(dev);
00149 sp->s_dev = NO_DEV;
00150 return(r);
00151 }
00152
00153
00154 if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) {
00155 dev_close(dev);
00156 sp->s_dev = NO_DEV;
00157 return(err_code);
00158 }
00159
00160 if (strcmp(user_path, "/") == 0 && allow_newroot)
00161 {
00162 printf("Replacing root\n");
00163
00164
00165 if ( (root_ip = get_inode(dev, ROOT_INODE)) == NIL_INODE) r = err_code;
00166 if (root_ip != NIL_INODE && root_ip->i_mode == 0) {
00167 r = EINVAL;
00168 }
00169
00170
00171
00172
00173 if (r != OK) {
00174 put_inode(root_ip);
00175 (void) do_sync();
00176 invalidate(dev);
00177 dev_close(dev);
00178 sp->s_dev = NO_DEV;
00179 return(r);
00180 }
00181
00182
00183 sp->s_imount = root_ip;
00184 dup_inode(root_ip);
00185 sp->s_isup = root_ip;
00186 sp->s_rd_only = m_in.rd_only;
00187 root_dev= dev;
00188
00189
00190 for (i= 0, tfp= fproc; i<NR_PROCS; i++, tfp++)
00191 {
00192 if (tfp->fp_pid == PID_FREE)
00193 continue;
00194 if (tfp->fp_rootdir == NULL)
00195 panic("fs", "do_mount: null rootdir", i);
00196 put_inode(tfp->fp_rootdir);
00197 dup_inode(root_ip);
00198 tfp->fp_rootdir= root_ip;
00199
00200 if (tfp->fp_workdir == NULL)
00201 panic("fs", "do_mount: null workdir", i);
00202 put_inode(tfp->fp_workdir);
00203 dup_inode(root_ip);
00204 tfp->fp_workdir= root_ip;
00205 }
00206
00207
00208 return(OK);
00209 }
00210
00211 if ( (rip = eat_path(user_path)) == NIL_INODE) {
00212 dev_close(dev);
00213 sp->s_dev = NO_DEV;
00214 return(err_code);
00215 }
00216
00217
00218 r = OK;
00219 if (rip->i_count > 1) r = EBUSY;
00220
00221
00222 bits = rip->i_mode & I_TYPE;
00223 if (bits == I_BLOCK_SPECIAL || bits == I_CHAR_SPECIAL) r = ENOTDIR;
00224
00225
00226 root_ip = NIL_INODE;
00227 if (r == OK) {
00228 if ( (root_ip = get_inode(dev, ROOT_INODE)) == NIL_INODE) r = err_code;
00229 }
00230 if (root_ip != NIL_INODE && root_ip->i_mode == 0) {
00231 r = EINVAL;
00232 }
00233
00234
00235 if (r == OK) {
00236 mdir = ((rip->i_mode & I_TYPE) == I_DIRECTORY);
00237 rdir = ((root_ip->i_mode & I_TYPE) == I_DIRECTORY);
00238 if (!mdir && rdir) r = EISDIR;
00239 }
00240
00241
00242 if (r != OK) {
00243 put_inode(rip);
00244 put_inode(root_ip);
00245 (void) do_sync();
00246 invalidate(dev);
00247 dev_close(dev);
00248 sp->s_dev = NO_DEV;
00249 return(r);
00250 }
00251
00252
00253 rip->i_mount = I_MOUNT;
00254 sp->s_imount = rip;
00255 sp->s_isup = root_ip;
00256 sp->s_rd_only = m_in.rd_only;
00257 allow_newroot= 0;
00258 return(OK);
00259 }
00260
00261
00262
00263
00264 PUBLIC int do_umount()
00265 {
00266
00267 dev_t dev;
00268
00269
00270 if (!super_user) return(EPERM);
00271
00272
00273 if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
00274 if ( (dev = name_to_dev(user_path)) == NO_DEV) return(err_code);
00275
00276 return(unmount(dev));
00277 }
00278
00279
00280
00281
00282 PUBLIC int unmount(dev)
00283 Dev_t dev;
00284 {
00285
00286 register struct inode *rip;
00287 struct super_block *sp, *sp1;
00288 int count;
00289
00290
00291
00292
00293 count = 0;
00294 for (rip = &inode[0]; rip< &inode[NR_INODES]; rip++)
00295 if (rip->i_count > 0 && rip->i_dev == dev) count += rip->i_count;
00296 if (count > 1) return(EBUSY);
00297
00298
00299 sp = NIL_SUPER;
00300 for (sp1 = &super_block[0]; sp1 < &super_block[NR_SUPERS]; sp1++) {
00301 if (sp1->s_dev == dev) {
00302 sp = sp1;
00303 break;
00304 }
00305 }
00306
00307
00308 (void) do_sync();
00309 invalidate(dev);
00310 if (sp == NIL_SUPER) {
00311 return(EINVAL);
00312 }
00313
00314
00315 dev_close(dev);
00316
00317
00318 sp->s_imount->i_mount = NO_MOUNT;
00319 put_inode(sp->s_imount);
00320 put_inode(sp->s_isup);
00321 sp->s_imount = NIL_INODE;
00322 sp->s_dev = NO_DEV;
00323 return(OK);
00324 }
00325
00326
00327
00328
00329 PRIVATE dev_t name_to_dev(path)
00330 char *path;
00331 {
00332
00333
00334
00335
00336 register struct inode *rip;
00337 register dev_t dev;
00338
00339
00340 if ( (rip = eat_path(path)) == NIL_INODE) return(NO_DEV);
00341
00342
00343 if ( (rip->i_mode & I_TYPE) != I_BLOCK_SPECIAL) {
00344 err_code = ENOTBLK;
00345 put_inode(rip);
00346 return(NO_DEV);
00347 }
00348
00349
00350 dev = (dev_t) rip->i_zone[0];
00351 put_inode(rip);
00352 return(dev);
00353 }