1 /* vfs_vnops.c 4.13 81/10/11 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/dir.h" 6 #include "../h/user.h" 7 #include "../h/filsys.h" 8 #include "../h/file.h" 9 #include "../h/conf.h" 10 #include "../h/inode.h" 11 #include "../h/reg.h" 12 #include "../h/acct.h" 13 #include "../h/mount.h" 14 15 /* 16 * Convert a user supplied 17 * file descriptor into a pointer 18 * to a file structure. 19 * Only task is to check range 20 * of the descriptor. 21 */ 22 struct file * 23 getf(f) 24 register int f; 25 { 26 register struct file *fp; 27 28 if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 29 u.u_error = EBADF; 30 return (NULL); 31 } 32 return (fp); 33 } 34 35 /* 36 * Internal form of close. 37 * Decrement reference count on 38 * file structure. 39 * Also make sure the pipe protocol 40 * does not constipate. 41 * 42 * Decrement reference count on the inode following 43 * removal to the referencing file structure. 44 * Call device handler on last close. 45 */ 46 closef(fp) 47 register struct file *fp; 48 { 49 register struct inode *ip; 50 register struct mount *mp; 51 int flag, mode; 52 dev_t dev; 53 register int (*cfunc)(); 54 55 if(fp == NULL) 56 return; 57 if (fp->f_count > 1) { 58 fp->f_count--; 59 return; 60 } 61 flag = fp->f_flag; 62 #ifdef BBNNET 63 if (flag&FNET) { 64 netclose(fp); 65 return; 66 } 67 #endif 68 if (flag & FPORT) { 69 ptclose(fp); 70 fp->f_count = 0; 71 return; 72 } 73 ip = fp->f_inode; 74 dev = (dev_t)ip->i_un.i_rdev; 75 mode = ip->i_mode & IFMT; 76 plock(ip); 77 iput(ip); 78 fp->f_count = 0; 79 80 switch (mode) { 81 82 case IFCHR: 83 cfunc = cdevsw[major(dev)].d_close; 84 break; 85 86 case IFBLK: 87 /* 88 * We don't want to really close the device if it is mounted 89 */ 90 for (mp = mount; mp < &mount[NMOUNT]; mp++) 91 if (mp->m_bufp != NULL && mp->m_dev == dev) 92 return; 93 cfunc = bdevsw[major(dev)].d_close; 94 break; 95 default: 96 return; 97 } 98 99 for(fp=file; fp < fileNFILE; fp++) { 100 #ifdef BBNNET 101 if (fp->f_flag & FNET) 102 continue; 103 #endif 104 if (fp->f_count && (ip = fp->f_inode) && 105 ip->i_un.i_rdev == dev && 106 (ip->i_mode&IFMT) == mode) 107 return; 108 } 109 if (mode == IFBLK) { 110 /* 111 * on last close of a block device (that isn't mounted) 112 * we must invalidate any in core blocks 113 */ 114 bflush(dev); 115 binval(dev); 116 } 117 (*cfunc)(dev, flag, fp); 118 } 119 120 /* 121 * openi called to allow handler 122 * of special files to initialize and 123 * validate before actual IO. 124 */ 125 openi(ip, rw) 126 register struct inode *ip; 127 { 128 dev_t dev; 129 register unsigned int maj; 130 131 dev = (dev_t)ip->i_un.i_rdev; 132 maj = major(dev); 133 switch(ip->i_mode&IFMT) { 134 135 case IFCHR: 136 if(maj >= nchrdev) 137 goto bad; 138 (*cdevsw[maj].d_open)(dev, rw); 139 break; 140 141 case IFBLK: 142 if(maj >= nblkdev) 143 goto bad; 144 (*bdevsw[maj].d_open)(dev, rw); 145 } 146 return; 147 148 bad: 149 u.u_error = ENXIO; 150 } 151 152 /* 153 * Check mode permission on inode pointer. 154 * Mode is READ, WRITE or EXEC. 155 * In the case of WRITE, the 156 * read-only status of the file 157 * system is checked. 158 * Also in WRITE, prototype text 159 * segments cannot be written. 160 * The mode is shifted to select 161 * the owner/group/other fields. 162 * The super user is granted all 163 * permissions. 164 */ 165 access(ip, mode) 166 register struct inode *ip; 167 { 168 register m; 169 170 m = mode; 171 if(m == IWRITE) { 172 if(getfs(ip->i_dev)->s_ronly != 0) { 173 u.u_error = EROFS; 174 return(1); 175 } 176 if (ip->i_flag&ITEXT) /* try to free text */ 177 xrele(ip); 178 if(ip->i_flag & ITEXT) { 179 u.u_error = ETXTBSY; 180 return(1); 181 } 182 } 183 if(u.u_uid == 0) 184 return(0); 185 if(u.u_uid != ip->i_uid) { 186 m >>= 3; 187 if(u.u_gid != ip->i_gid) 188 m >>= 3; 189 } 190 if((ip->i_mode&m) != 0) 191 return(0); 192 193 u.u_error = EACCES; 194 return(1); 195 } 196 197 /* 198 * Look up a pathname and test if 199 * the resultant inode is owned by the 200 * current user. 201 * If not, try for super-user. 202 * If permission is granted, 203 * return inode pointer. 204 */ 205 struct inode * 206 owner() 207 { 208 register struct inode *ip; 209 210 ip = namei(uchar, 0); 211 if(ip == NULL) 212 return(NULL); 213 if(u.u_uid == ip->i_uid) 214 return(ip); 215 if(suser()) 216 return(ip); 217 iput(ip); 218 return(NULL); 219 } 220 221 /* 222 * Test if the current user is the 223 * super user. 224 */ 225 suser() 226 { 227 228 if(u.u_uid == 0) { 229 u.u_acflag |= ASU; 230 return(1); 231 } 232 u.u_error = EPERM; 233 return(0); 234 } 235 236 /* 237 * Allocate a user file descriptor. 238 */ 239 ufalloc() 240 { 241 register i; 242 243 for(i=0; i<NOFILE; i++) 244 if(u.u_ofile[i] == NULL) { 245 u.u_r.r_val1 = i; 246 u.u_pofile[i] = 0; 247 return(i); 248 } 249 u.u_error = EMFILE; 250 return(-1); 251 } 252 253 struct file *lastf; 254 /* 255 * Allocate a user file descriptor 256 * and a file structure. 257 * Initialize the descriptor 258 * to point at the file structure. 259 */ 260 struct file * 261 falloc() 262 { 263 register struct file *fp; 264 register i; 265 266 i = ufalloc(); 267 if (i < 0) 268 return(NULL); 269 if (lastf == 0) 270 lastf = file; 271 for (fp = lastf; fp < fileNFILE; fp++) 272 if (fp->f_count == 0) 273 goto slot; 274 for (fp = file; fp < lastf; fp++) 275 if (fp->f_count == 0) 276 goto slot; 277 tablefull("file"); 278 u.u_error = ENFILE; 279 return (NULL); 280 slot: 281 u.u_ofile[i] = fp; 282 fp->f_count++; 283 fp->f_un.f_offset = 0; 284 fp->f_inode = 0; 285 lastf = fp + 1; 286 return (fp); 287 } 288