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