fixed bug in 2.6 caused by bizarre semantics of .am directive
[unix-history] / usr / src / sys / kern / vfs_vnops.c
CommitLineData
36a4b8e3 1/* vfs_vnops.c 3.4 %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)();
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++)
36a4b8e3
BJ
96 if (fp->f_count && (ip=fp->f_inode)->i_un.i_rdev==dev &&
97 (ip->i_mode&IFMT) == (mode&IFMT))
fc96c615
BJ
98 return;
99
100call:
101 (*cfunc)(dev, flag, cp);
102}
103
104/*
105 * openi called to allow handler
106 * of special files to initialize and
107 * validate before actual IO.
108 */
109openi(ip, rw)
110register struct inode *ip;
111{
112 dev_t dev;
113 register unsigned int maj;
114
115 dev = (dev_t)ip->i_un.i_rdev;
116 maj = major(dev);
117 switch(ip->i_mode&IFMT) {
118
119 case IFCHR:
120 case IFMPC:
121 if(maj >= nchrdev)
122 goto bad;
123 (*cdevsw[maj].d_open)(dev, rw);
124 break;
125
126 case IFBLK:
127 case IFMPB:
128 if(maj >= nblkdev)
129 goto bad;
130 (*bdevsw[maj].d_open)(dev, rw);
131 }
132 return;
133
134bad:
135 u.u_error = ENXIO;
136}
137
138/*
139 * Check mode permission on inode pointer.
140 * Mode is READ, WRITE or EXEC.
141 * In the case of WRITE, the
142 * read-only status of the file
143 * system is checked.
144 * Also in WRITE, prototype text
145 * segments cannot be written.
146 * The mode is shifted to select
147 * the owner/group/other fields.
148 * The super user is granted all
149 * permissions.
150 */
151access(ip, mode)
152register struct inode *ip;
153{
154 register m;
155
156 m = mode;
157 if(m == IWRITE) {
158 if(getfs(ip->i_dev)->s_ronly != 0) {
159 u.u_error = EROFS;
160 return(1);
161 }
162 if (ip->i_flag&ITEXT) /* try to free text */
163 xrele(ip);
164 if(ip->i_flag & ITEXT) {
165 u.u_error = ETXTBSY;
166 return(1);
167 }
168 }
169 if(u.u_uid == 0)
170 return(0);
171 if(u.u_uid != ip->i_uid) {
172 m >>= 3;
173 if(u.u_gid != ip->i_gid)
174 m >>= 3;
175 }
176 if((ip->i_mode&m) != 0)
177 return(0);
178
179 u.u_error = EACCES;
180 return(1);
181}
182
183/*
184 * Look up a pathname and test if
185 * the resultant inode is owned by the
186 * current user.
187 * If not, try for super-user.
188 * If permission is granted,
189 * return inode pointer.
190 */
191struct inode *
192owner()
193{
194 register struct inode *ip;
195
196 ip = namei(uchar, 0);
197 if(ip == NULL)
198 return(NULL);
199 if(u.u_uid == ip->i_uid)
200 return(ip);
201 if(suser())
202 return(ip);
203 iput(ip);
204 return(NULL);
205}
206
207/*
208 * Test if the current user is the
209 * super user.
210 */
211suser()
212{
213
214 if(u.u_uid == 0) {
215 u.u_acflag |= ASU;
216 return(1);
217 }
218 u.u_error = EPERM;
219 return(0);
220}
221
222/*
223 * Allocate a user file descriptor.
224 */
225ufalloc()
226{
227 register i;
228
229 for(i=0; i<NOFILE; i++)
230 if(u.u_ofile[i] == NULL) {
231 u.u_r.r_val1 = i;
232 u.u_pofile[i] = 0;
233 return(i);
234 }
235 u.u_error = EMFILE;
236 return(-1);
237}
238
9c98386a 239struct file *lastf = &file[0];
fc96c615
BJ
240/*
241 * Allocate a user file descriptor
242 * and a file structure.
243 * Initialize the descriptor
244 * to point at the file structure.
245 *
246 * no file -- if there are no available
247 * file structures.
248 */
249struct file *
250falloc()
251{
252 register struct file *fp;
253 register i;
254
255 i = ufalloc();
256 if(i < 0)
257 return(NULL);
9c98386a
BJ
258 for(fp = lastf; fp < &file[NFILE]; fp++)
259 if(fp->f_count == 0)
260 goto slot;
261 for(fp = &file[0]; fp < lastf; fp++)
262 if(fp->f_count == 0)
263 goto slot;
fc96c615
BJ
264 printf("no file\n");
265 u.u_error = ENFILE;
266 return(NULL);
9c98386a
BJ
267slot:
268 u.u_ofile[i] = fp;
269 fp->f_count++;
270 fp->f_un.f_offset = 0;
271 lastf = fp + 1;
272 return(fp);
fc96c615 273}