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