1 /* vfs_syscalls.c 4.20 82/03/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. This version does not follow links. 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, 0); 54 if (ip == NULL) 55 return; 56 stat1(ip, uap->sb); 57 iput(ip); 58 } 59 60 /* 61 * Lstat system call. This version does follow links. 62 */ 63 lstat() 64 { 65 register struct inode *ip; 66 register struct a { 67 char *fname; 68 struct stat *sb; 69 } *uap; 70 71 uap = (struct a *)u.u_ap; 72 ip = namei(uchar, 0, 1); 73 if (ip == NULL) 74 return; 75 stat1(ip, uap->sb); 76 iput(ip); 77 } 78 79 /* 80 * The basic routine for fstat and stat: 81 * get the inode and pass appropriate parts back. 82 */ 83 stat1(ip, ub) 84 register struct inode *ip; 85 struct stat *ub; 86 { 87 register struct dinode *dp; 88 register struct buf *bp; 89 struct stat ds; 90 91 IUPDAT(ip, &time, &time, 0); 92 /* 93 * First copy from inode table 94 */ 95 ds.st_dev = ip->i_dev; 96 ds.st_ino = ip->i_number; 97 ds.st_mode = ip->i_mode; 98 ds.st_nlink = ip->i_nlink; 99 ds.st_uid = ip->i_uid; 100 ds.st_gid = ip->i_gid; 101 ds.st_rdev = (dev_t)ip->i_un.i_rdev; 102 ds.st_size = ip->i_size; 103 /* 104 * next the dates in the disk 105 */ 106 bp = bread(ip->i_dev, itod(ip->i_number)); 107 dp = bp->b_un.b_dino; 108 dp += itoo(ip->i_number); 109 ds.st_atime = dp->di_atime; 110 ds.st_mtime = dp->di_mtime; 111 ds.st_ctime = dp->di_ctime; 112 brelse(bp); 113 if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) 114 u.u_error = EFAULT; 115 } 116 117 /* 118 * Return target name of a symbolic link 119 */ 120 readlink() 121 { 122 register struct inode *ip; 123 register struct a { 124 char *name; 125 char *buf; 126 int count; 127 } *uap; 128 129 ip = namei(uchar, 0, 0); 130 if (ip == NULL) 131 return; 132 if ((ip->i_mode&IFMT) != IFLNK) { 133 u.u_error = ENXIO; 134 goto out; 135 } 136 uap = (struct a *)u.u_ap; 137 u.u_offset = 0; 138 u.u_base = uap->buf; 139 u.u_count = uap->count; 140 u.u_segflg = 0; 141 readi(ip); 142 out: 143 iput(ip); 144 u.u_r.r_val1 = uap->count - u.u_count; 145 } 146 147 /* 148 * symlink -- make a symbolic link 149 */ 150 symlink() 151 { 152 register struct a { 153 char *target; 154 char *linkname; 155 } *uap; 156 register struct inode *ip; 157 register char *tp; 158 register c, nc; 159 160 uap = (struct a *)u.u_ap; 161 tp = uap->target; 162 nc = 0; 163 while (c = fubyte(tp)) { 164 if (c < 0) { 165 u.u_error = EFAULT; 166 return; 167 } 168 tp++; 169 nc++; 170 } 171 u.u_dirp = uap->linkname; 172 ip = namei(uchar, 1, 0); 173 if (ip) { 174 iput(ip); 175 u.u_error = EEXIST; 176 return; 177 } 178 if (u.u_error) 179 return; 180 ip = maknode(IFLNK | 0777); 181 if (ip == NULL) 182 return; 183 u.u_base = uap->target; 184 u.u_count = nc; 185 u.u_offset = 0; 186 u.u_segflg = 0; 187 writei(ip); 188 iput(ip); 189 } 190 191 /* 192 * the dup system call. 193 */ 194 dup() 195 { 196 register struct file *fp; 197 register struct a { 198 int fdes; 199 int fdes2; 200 } *uap; 201 register i, m; 202 203 uap = (struct a *)u.u_ap; 204 m = uap->fdes & ~077; 205 uap->fdes &= 077; 206 fp = getf(uap->fdes); 207 if (fp == NULL) 208 return; 209 if ((m&0100) == 0) { 210 if ((i = ufalloc()) < 0) 211 return; 212 } else { 213 i = uap->fdes2; 214 if (i<0 || i>=NOFILE) { 215 u.u_error = EBADF; 216 return; 217 } 218 u.u_r.r_val1 = i; 219 } 220 if (i != uap->fdes) { 221 if (u.u_ofile[i]!=NULL) 222 closef(u.u_ofile[i], 0); 223 if (u.u_error) 224 return; 225 u.u_ofile[i] = fp; 226 fp->f_count++; 227 } 228 } 229 230 /* 231 * Mount system call. 232 */ 233 smount() 234 { 235 dev_t dev; 236 register struct inode *ip; 237 register struct mount *mp; 238 struct mount *smp; 239 register struct filsys *fp; 240 struct buf *bp; 241 register struct a { 242 char *fspec; 243 char *freg; 244 int ronly; 245 } *uap; 246 register char *cp; 247 248 uap = (struct a *)u.u_ap; 249 dev = getmdev(); 250 if (u.u_error) 251 return; 252 u.u_dirp = (caddr_t)uap->freg; 253 ip = namei(uchar, 0, 1); 254 if (ip == NULL) 255 return; 256 if (ip->i_count!=1 || (ip->i_mode&IFMT) != IFDIR) 257 goto out; 258 smp = NULL; 259 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { 260 if (mp->m_bufp != NULL) { 261 if (dev == mp->m_dev) 262 goto out; 263 } else 264 if (smp == NULL) 265 smp = mp; 266 } 267 mp = smp; 268 if (mp == NULL) 269 goto out; 270 (*bdevsw[major(dev)].d_open)(dev, !uap->ronly); 271 if (u.u_error) 272 goto out; 273 bp = bread(dev, SUPERB); 274 if (u.u_error) { 275 brelse(bp); 276 goto out1; 277 } 278 mp->m_inodp = ip; 279 mp->m_dev = dev; 280 bp->b_flags |= B_LOCKED; 281 mp->m_bufp = bp; 282 fp = bp->b_un.b_filsys; 283 fp->s_ilock = 0; 284 fp->s_flock = 0; 285 fp->s_ronly = uap->ronly & 1; 286 fp->s_nbehind = 0; 287 fp->s_lasti = 1; 288 u.u_dirp = uap->freg; 289 for (cp = fp->s_fsmnt; cp < &fp->s_fsmnt[sizeof (fp->s_fsmnt) - 1]; ) 290 if ((*cp++ = uchar()) == 0) 291 u.u_dirp--; /* get 0 again */ 292 *cp = 0; 293 brelse(bp); 294 ip->i_flag |= IMOUNT; 295 irele(ip); 296 return; 297 298 out: 299 u.u_error = EBUSY; 300 out1: 301 iput(ip); 302 } 303 304 /* 305 * the umount system call. 306 */ 307 sumount() 308 { 309 dev_t dev; 310 register struct inode *ip; 311 register struct mount *mp; 312 struct buf *bp; 313 int stillopen, flag; 314 register struct a { 315 char *fspec; 316 }; 317 318 dev = getmdev(); 319 if (u.u_error) 320 return; 321 xumount(dev); /* remove unused sticky files from text table */ 322 update(0); 323 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 324 if (mp->m_bufp != NULL && dev == mp->m_dev) 325 goto found; 326 u.u_error = EINVAL; 327 return; 328 329 found: 330 stillopen = 0; 331 for (ip = inode; ip < inodeNINODE; ip++) 332 if (ip->i_number != 0 && dev == ip->i_dev) { 333 u.u_error = EBUSY; 334 return; 335 } else if (ip->i_number != 0 && (ip->i_mode&IFMT) == IFBLK && 336 ip->i_un.i_rdev == dev) 337 stillopen++; 338 ip = mp->m_inodp; 339 ip->i_flag &= ~IMOUNT; 340 ilock(ip); 341 iput(ip); 342 if ((bp = getblk(dev, SUPERB)) != mp->m_bufp) 343 panic("umount"); 344 bp->b_flags &= ~B_LOCKED; 345 flag = !bp->b_un.b_filsys->s_ronly; 346 mp->m_bufp = NULL; 347 brelse(bp); 348 mpurge(mp - &mount[0]); 349 if (!stillopen) { 350 (*bdevsw[major(dev)].d_close)(dev, flag); 351 binval(dev); 352 } 353 } 354 355 /* 356 * Common code for mount and umount. 357 * Check that the user's argument is a reasonable 358 * thing on which to mount, and return the device number if so. 359 */ 360 dev_t 361 getmdev() 362 { 363 dev_t dev; 364 register struct inode *ip; 365 366 if (!suser()) 367 return(NODEV); 368 ip = namei(uchar, 0, 1); 369 if (ip == NULL) 370 return(NODEV); 371 if ((ip->i_mode&IFMT) != IFBLK) 372 u.u_error = ENOTBLK; 373 dev = (dev_t)ip->i_un.i_rdev; 374 if (major(dev) >= nblkdev) 375 u.u_error = ENXIO; 376 iput(ip); 377 return(dev); 378 } 379