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