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