1 /* vfs_syscalls.c 4.7 02/26/81 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/mount.h" 6 #include "../h/ino.h" 7 #include "../h/reg.h" 8 #include "../h/buf.h" 9 #include "../h/filsys.h" 10 #include "../h/dir.h" 11 #include "../h/user.h" 12 #include "../h/inode.h" 13 #include "../h/file.h" 14 #include "../h/conf.h" 15 #include "../h/stat.h" 16 #include "../h/inline.h" 17 18 /* 19 * the fstat system call. 20 */ 21 fstat() 22 { 23 register struct file *fp; 24 register struct a { 25 int fdes; 26 struct stat *sb; 27 } *uap; 28 29 uap = (struct a *)u.u_ap; 30 fp = getf(uap->fdes); 31 if(fp == NULL) 32 return; 33 stat1(fp->f_inode, uap->sb, fp->f_flag&FPIPE? fp->f_un.f_offset: 0); 34 } 35 36 /* 37 * the stat system call. 38 */ 39 stat() 40 { 41 register struct inode *ip; 42 register struct a { 43 char *fname; 44 struct stat *sb; 45 } *uap; 46 47 uap = (struct a *)u.u_ap; 48 ip = namei(uchar, 0); 49 if(ip == NULL) 50 return; 51 stat1(ip, uap->sb, (off_t)0); 52 iput(ip); 53 } 54 55 /* 56 * The basic routine for fstat and stat: 57 * get the inode and pass appropriate parts back. 58 */ 59 stat1(ip, ub, pipeadj) 60 register struct inode *ip; 61 struct stat *ub; 62 off_t pipeadj; 63 { 64 register struct dinode *dp; 65 register struct buf *bp; 66 struct stat ds; 67 68 IUPDAT(ip, &time, &time, 0); 69 /* 70 * first copy from inode table 71 */ 72 ds.st_dev = ip->i_dev; 73 ds.st_ino = ip->i_number; 74 ds.st_mode = ip->i_mode; 75 ds.st_nlink = ip->i_nlink; 76 ds.st_uid = ip->i_uid; 77 ds.st_gid = ip->i_gid; 78 ds.st_rdev = (dev_t)ip->i_un.i_rdev; 79 ds.st_size = ip->i_size - pipeadj; 80 /* 81 * next the dates in the disk 82 */ 83 bp = bread(ip->i_dev, itod(ip->i_number)); 84 dp = bp->b_un.b_dino; 85 dp += itoo(ip->i_number); 86 ds.st_atime = dp->di_atime; 87 ds.st_mtime = dp->di_mtime; 88 ds.st_ctime = dp->di_ctime; 89 brelse(bp); 90 if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) 91 u.u_error = EFAULT; 92 } 93 94 /* 95 * the dup system call. 96 */ 97 dup() 98 { 99 register struct file *fp; 100 register struct a { 101 int fdes; 102 int fdes2; 103 } *uap; 104 register i, m; 105 106 uap = (struct a *)u.u_ap; 107 m = uap->fdes & ~077; 108 uap->fdes &= 077; 109 fp = getf(uap->fdes); 110 if(fp == NULL) 111 return; 112 if ((m&0100) == 0) { 113 if ((i = ufalloc()) < 0) 114 return; 115 } else { 116 i = uap->fdes2; 117 if (i<0 || i>=NOFILE) { 118 u.u_error = EBADF; 119 return; 120 } 121 if (u.u_vrpages[i]) { 122 u.u_error = ETXTBSY; 123 return; 124 } 125 u.u_r.r_val1 = i; 126 } 127 if (i!=uap->fdes) { 128 if (u.u_ofile[i]!=NULL) 129 closef(u.u_ofile[i]); 130 u.u_ofile[i] = fp; 131 fp->f_count++; 132 } 133 } 134 135 /* 136 * the mount system call. 137 */ 138 smount() 139 { 140 dev_t dev; 141 register struct inode *ip; 142 register struct mount *mp; 143 struct mount *smp; 144 register struct filsys *fp; 145 struct buf *bp; 146 register struct a { 147 char *fspec; 148 char *freg; 149 int ronly; 150 } *uap; 151 152 uap = (struct a *)u.u_ap; 153 dev = getmdev(); 154 if(u.u_error) 155 return; 156 u.u_dirp = (caddr_t)uap->freg; 157 ip = namei(uchar, 0); 158 if(ip == NULL) 159 return; 160 if(ip->i_count!=1 || (ip->i_mode&(IFBLK&IFCHR))!=0) 161 goto out; 162 smp = NULL; 163 for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { 164 if(mp->m_bufp != NULL) { 165 if(dev == mp->m_dev) 166 goto out; 167 } else 168 if(smp == NULL) 169 smp = mp; 170 } 171 mp = smp; 172 if(mp == NULL) 173 goto out; 174 (*bdevsw[major(dev)].d_open)(dev, !uap->ronly); 175 if(u.u_error) 176 goto out; 177 bp = bread(dev, SUPERB); 178 if(u.u_error) { 179 brelse(bp); 180 goto out1; 181 } 182 mp->m_inodp = ip; 183 mp->m_dev = dev; 184 bp->b_flags |= B_LOCKED; 185 mp->m_bufp = bp; 186 fp = bp->b_un.b_filsys; 187 fp->s_ilock = 0; 188 fp->s_flock = 0; 189 fp->s_ronly = uap->ronly & 1; 190 fp->s_nbehind = 0; 191 fp->s_lasti = 1; 192 brelse(bp); 193 ip->i_flag |= IMOUNT; 194 prele(ip); 195 return; 196 197 out: 198 u.u_error = EBUSY; 199 out1: 200 iput(ip); 201 } 202 203 /* 204 * the umount system call. 205 */ 206 sumount() 207 { 208 dev_t dev; 209 register struct inode *ip; 210 register struct mount *mp; 211 struct buf *bp; 212 int stillopen, flag; 213 register struct a { 214 char *fspec; 215 }; 216 217 dev = getmdev(); 218 if(u.u_error) 219 return; 220 xumount(dev); /* remove unused sticky files from text table */ 221 update(); 222 for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 223 if(mp->m_bufp != NULL && dev == mp->m_dev) 224 goto found; 225 u.u_error = EINVAL; 226 return; 227 228 found: 229 stillopen = 0; 230 for(ip = inode; ip < inodeNINODE; ip++) 231 if (ip->i_number != 0 && dev == ip->i_dev) { 232 u.u_error = EBUSY; 233 return; 234 } else if (ip->i_number != 0 && (ip->i_mode&IFMT) == IFBLK && 235 ip->i_un.i_rdev == dev) 236 stillopen++; 237 ip = mp->m_inodp; 238 ip->i_flag &= ~IMOUNT; 239 plock(ip); 240 iput(ip); 241 if ((bp = getblk(dev, SUPERB)) != mp->m_bufp) 242 panic("umount"); 243 bp->b_flags &= ~B_LOCKED; 244 flag = !bp->b_un.b_filsys->s_ronly; 245 mp->m_bufp = NULL; 246 brelse(bp); 247 mpurge(mp - &mount[0]); 248 if (!stillopen) { 249 (*bdevsw[major(dev)].d_close)(dev, flag); 250 binval(dev); 251 } 252 } 253 254 /* 255 * Common code for mount and umount. 256 * Check that the user's argument is a reasonable 257 * thing on which to mount, and return the device number if so. 258 */ 259 dev_t 260 getmdev() 261 { 262 dev_t dev; 263 register struct inode *ip; 264 265 if (!suser()) 266 return(NODEV); 267 ip = namei(uchar, 0); 268 if(ip == NULL) 269 return(NODEV); 270 if((ip->i_mode&IFMT) != IFBLK) 271 u.u_error = ENOTBLK; 272 dev = (dev_t)ip->i_un.i_rdev; 273 if(major(dev) >= nblkdev) 274 u.u_error = ENXIO; 275 iput(ip); 276 return(dev); 277 } 278