addition for netldis
[unix-history] / usr / src / sys / kern / vfs_vnops.c
CommitLineData
fc96c615
BJ
1/* vfs_vnops.c 3.1 %H% */
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)();
54 struct chan *cp;
55
56 if(fp == NULL)
57 return;
58 if (fp->f_count > 1) {
59 fp->f_count--;
60 return;
61 }
62 ip = fp->f_inode;
63 flag = fp->f_flag;
64 cp = fp->f_un.f_chan;
65 dev = (dev_t)ip->i_un.i_rdev;
66 mode = ip->i_mode;
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
77 switch(mode&IFMT) {
78
79 case IFCHR:
80 case IFMPC:
81 cfunc = cdevsw[major(dev)].d_close;
82 break;
83
84 case IFBLK:
85 case IFMPB:
86 cfunc = bdevsw[major(dev)].d_close;
87 break;
88 default:
89 return;
90 }
91
92 if (flag & FMP)
93 goto call;
94
95 for(fp=file; fp < &file[NFILE]; fp++)
96 if (fp->f_count && fp->f_inode==ip)
97 return;
98
99call:
100 (*cfunc)(dev, flag, cp);
101}
102
103/*
104 * openi called to allow handler
105 * of special files to initialize and
106 * validate before actual IO.
107 */
108openi(ip, rw)
109register struct inode *ip;
110{
111 dev_t dev;
112 register unsigned int maj;
113
114 dev = (dev_t)ip->i_un.i_rdev;
115 maj = major(dev);
116 switch(ip->i_mode&IFMT) {
117
118 case IFCHR:
119 case IFMPC:
120 if(maj >= nchrdev)
121 goto bad;
122 (*cdevsw[maj].d_open)(dev, rw);
123 break;
124
125 case IFBLK:
126 case IFMPB:
127 if(maj >= nblkdev)
128 goto bad;
129 (*bdevsw[maj].d_open)(dev, rw);
130 }
131 return;
132
133bad:
134 u.u_error = ENXIO;
135}
136
137/*
138 * Check mode permission on inode pointer.
139 * Mode is READ, WRITE or EXEC.
140 * In the case of WRITE, the
141 * read-only status of the file
142 * system is checked.
143 * Also in WRITE, prototype text
144 * segments cannot be written.
145 * The mode is shifted to select
146 * the owner/group/other fields.
147 * The super user is granted all
148 * permissions.
149 */
150access(ip, mode)
151register struct inode *ip;
152{
153 register m;
154
155 m = mode;
156 if(m == IWRITE) {
157 if(getfs(ip->i_dev)->s_ronly != 0) {
158 u.u_error = EROFS;
159 return(1);
160 }
161 if (ip->i_flag&ITEXT) /* try to free text */
162 xrele(ip);
163 if(ip->i_flag & ITEXT) {
164 u.u_error = ETXTBSY;
165 return(1);
166 }
167 }
168 if(u.u_uid == 0)
169 return(0);
170 if(u.u_uid != ip->i_uid) {
171 m >>= 3;
172 if(u.u_gid != ip->i_gid)
173 m >>= 3;
174 }
175 if((ip->i_mode&m) != 0)
176 return(0);
177
178 u.u_error = EACCES;
179 return(1);
180}
181
182/*
183 * Look up a pathname and test if
184 * the resultant inode is owned by the
185 * current user.
186 * If not, try for super-user.
187 * If permission is granted,
188 * return inode pointer.
189 */
190struct inode *
191owner()
192{
193 register struct inode *ip;
194
195 ip = namei(uchar, 0);
196 if(ip == NULL)
197 return(NULL);
198 if(u.u_uid == ip->i_uid)
199 return(ip);
200 if(suser())
201 return(ip);
202 iput(ip);
203 return(NULL);
204}
205
206/*
207 * Test if the current user is the
208 * super user.
209 */
210suser()
211{
212
213 if(u.u_uid == 0) {
214 u.u_acflag |= ASU;
215 return(1);
216 }
217 u.u_error = EPERM;
218 return(0);
219}
220
221/*
222 * Allocate a user file descriptor.
223 */
224ufalloc()
225{
226 register i;
227
228 for(i=0; i<NOFILE; i++)
229 if(u.u_ofile[i] == NULL) {
230 u.u_r.r_val1 = i;
231 u.u_pofile[i] = 0;
232 return(i);
233 }
234 u.u_error = EMFILE;
235 return(-1);
236}
237
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);
256 for(fp = &file[0]; fp < &file[NFILE]; fp++)
257 if(fp->f_count == 0) {
258 u.u_ofile[i] = fp;
259 fp->f_count++;
260 fp->f_un.f_offset = 0;
261 return(fp);
262 }
263 printf("no file\n");
264 u.u_error = ENFILE;
265 return(NULL);
266}