kernfs_vnops.c revision 1.19 1 1.1 cgd /*
2 1.17 cgd * Copyright (c) 1992 The Regents of the University of California
3 1.1 cgd * Copyright (c) 1990, 1992 Jan-Simon Pendry
4 1.1 cgd * All rights reserved.
5 1.1 cgd *
6 1.17 cgd * This code is derived from software donated to Berkeley by
7 1.1 cgd * Jan-Simon Pendry.
8 1.1 cgd *
9 1.2 cgd * Redistribution and use in source and binary forms, with or without
10 1.2 cgd * modification, are permitted provided that the following conditions
11 1.2 cgd * are met:
12 1.2 cgd * 1. Redistributions of source code must retain the above copyright
13 1.2 cgd * notice, this list of conditions and the following disclaimer.
14 1.2 cgd * 2. Redistributions in binary form must reproduce the above copyright
15 1.2 cgd * notice, this list of conditions and the following disclaimer in the
16 1.2 cgd * documentation and/or other materials provided with the distribution.
17 1.2 cgd * 3. All advertising materials mentioning features or use of this software
18 1.2 cgd * must display the following acknowledgement:
19 1.17 cgd * This product includes software developed by the University of
20 1.17 cgd * California, Berkeley and its contributors.
21 1.2 cgd * 4. Neither the name of the University nor the names of its contributors
22 1.2 cgd * may be used to endorse or promote products derived from this software
23 1.2 cgd * without specific prior written permission.
24 1.1 cgd *
25 1.2 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 1.2 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 1.2 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 1.2 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 1.2 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 1.2 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 1.2 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 1.2 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 1.2 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 1.2 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 1.2 cgd * SUCH DAMAGE.
36 1.1 cgd *
37 1.17 cgd * From:
38 1.17 cgd * Id: kernfs_vnops.c,v 4.1 1994/01/02 14:41:30 jsp Exp
39 1.17 cgd *
40 1.19 cgd * $Id: kernfs_vnops.c,v 1.19 1994/02/11 01:01:51 cgd Exp $
41 1.1 cgd */
42 1.1 cgd
43 1.1 cgd /*
44 1.1 cgd * Kernel parameter filesystem
45 1.1 cgd */
46 1.1 cgd
47 1.14 mycroft #include <sys/param.h>
48 1.14 mycroft #include <sys/systm.h>
49 1.14 mycroft #include <sys/kernel.h>
50 1.14 mycroft #include <sys/types.h>
51 1.14 mycroft #include <sys/time.h>
52 1.14 mycroft #include <sys/proc.h>
53 1.14 mycroft #include <sys/file.h>
54 1.14 mycroft #include <sys/vnode.h>
55 1.14 mycroft #include <sys/stat.h>
56 1.14 mycroft #include <sys/mount.h>
57 1.14 mycroft #include <sys/namei.h>
58 1.14 mycroft #include <sys/buf.h>
59 1.17 cgd #include <miscfs/kernfs/kernfs.h>
60 1.1 cgd
61 1.14 mycroft #include <ufs/dir.h> /* For readdir() XXX */
62 1.14 mycroft
63 1.17 cgd #define KSTRING 256 /* Largest I/O available via this filesystem */
64 1.17 cgd #define UIO_MX 32
65 1.1 cgd
66 1.17 cgd struct kern_target {
67 1.17 cgd char *kt_name;
68 1.17 cgd void *kt_data;
69 1.17 cgd #define KTT_NULL 1
70 1.17 cgd #define KTT_TIME 5
71 1.17 cgd #define KTT_INT 17
72 1.17 cgd #define KTT_STRING 31
73 1.17 cgd #define KTT_HOSTNAME 47
74 1.17 cgd #define KTT_AVENRUN 53
75 1.17 cgd int kt_tag;
76 1.17 cgd #define KTM_RO 0
77 1.17 cgd #define KTM_RO_MODE \
78 1.17 cgd ((VREAD) | (VREAD >> 3) | (VREAD >> 6))
79 1.17 cgd #define KTM_RW 43
80 1.17 cgd #define KTM_RW_MODE \
81 1.17 cgd ((VWRITE) | KTM_RO_MODE)
82 1.17 cgd #define KTM_DIR_MODE \
83 1.17 cgd ((VREAD|VEXEC) | ((VREAD|VEXEC) >> 3) | ((VREAD|VEXEC) >> 6))
84 1.17 cgd int kt_rw;
85 1.17 cgd enum vtype kt_vtype;
86 1.17 cgd } kern_targets[] = {
87 1.1 cgd /* NOTE: The name must be less than UIO_MX-16 chars in length */
88 1.17 cgd /* name data tag ro/rw */
89 1.17 cgd { ".", 0, KTT_NULL, KTM_RO, VDIR },
90 1.17 cgd { "copyright", copyright, KTT_STRING, KTM_RO, VREG },
91 1.17 cgd { "hostname", 0, KTT_HOSTNAME, KTM_RW, VREG },
92 1.17 cgd { "hz", &hz, KTT_INT, KTM_RO, VREG },
93 1.17 cgd { "loadavg", 0, KTT_AVENRUN, KTM_RO, VREG },
94 1.17 cgd { "physmem", &physmem, KTT_INT, KTM_RO, VREG },
95 1.17 cgd #if 0
96 1.17 cgd { "root", 0, KTT_NULL, KTM_RO, VDIR },
97 1.17 cgd #endif
98 1.17 cgd { "rootdev", 0, KTT_NULL, KTM_RO, VBLK },
99 1.17 cgd #ifdef notdef
100 1.17 cgd { "rrootdev", 0, KTT_NULL, KTM_RO, VCHR },
101 1.17 cgd #endif
102 1.17 cgd { "time", 0, KTT_TIME, KTM_RO, VREG },
103 1.17 cgd { "version", version, KTT_STRING, KTM_RO, VREG },
104 1.1 cgd };
105 1.1 cgd
106 1.17 cgd static int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
107 1.1 cgd
108 1.1 cgd static int
109 1.1 cgd kernfs_xread(kt, buf, len, lenp)
110 1.17 cgd struct kern_target *kt;
111 1.1 cgd char *buf;
112 1.1 cgd int len;
113 1.1 cgd int *lenp;
114 1.1 cgd {
115 1.1 cgd int xlen;
116 1.1 cgd
117 1.1 cgd switch (kt->kt_tag) {
118 1.1 cgd case KTT_TIME: {
119 1.1 cgd struct timeval tv;
120 1.1 cgd microtime(&tv);
121 1.1 cgd sprintf(buf, "%d %d\n", tv.tv_sec, tv.tv_usec);
122 1.1 cgd break;
123 1.1 cgd }
124 1.1 cgd
125 1.1 cgd case KTT_INT: {
126 1.1 cgd int *ip = kt->kt_data;
127 1.1 cgd sprintf(buf, "%d\n", *ip);
128 1.1 cgd break;
129 1.1 cgd }
130 1.1 cgd
131 1.1 cgd case KTT_STRING: {
132 1.1 cgd char *cp = kt->kt_data;
133 1.1 cgd int xlen = strlen(cp) + 1;
134 1.1 cgd
135 1.1 cgd if (xlen >= len)
136 1.1 cgd return (EINVAL);
137 1.1 cgd
138 1.1 cgd bcopy(cp, buf, xlen);
139 1.1 cgd break;
140 1.1 cgd }
141 1.1 cgd
142 1.1 cgd case KTT_HOSTNAME: {
143 1.1 cgd char *cp = hostname;
144 1.1 cgd int xlen = hostnamelen;
145 1.1 cgd
146 1.17 cgd if (xlen >= (len-2))
147 1.1 cgd return (EINVAL);
148 1.1 cgd
149 1.17 cgd bcopy(cp, buf, xlen);
150 1.6 cgd buf[xlen] = '\n';
151 1.6 cgd buf[xlen+1] = '\0';
152 1.1 cgd break;
153 1.1 cgd }
154 1.1 cgd
155 1.1 cgd case KTT_AVENRUN:
156 1.1 cgd sprintf(buf, "%d %d %d %d\n",
157 1.17 cgd averunnable.ldavg[0],
158 1.17 cgd averunnable.ldavg[1],
159 1.17 cgd averunnable.ldavg[2],
160 1.17 cgd averunnable.fscale);
161 1.1 cgd break;
162 1.1 cgd
163 1.1 cgd default:
164 1.1 cgd return (EINVAL);
165 1.1 cgd }
166 1.1 cgd
167 1.1 cgd *lenp = strlen(buf);
168 1.1 cgd return (0);
169 1.1 cgd }
170 1.1 cgd
171 1.1 cgd static int
172 1.1 cgd kernfs_xwrite(kt, buf, len)
173 1.17 cgd struct kern_target *kt;
174 1.1 cgd char *buf;
175 1.1 cgd int len;
176 1.1 cgd {
177 1.1 cgd switch (kt->kt_tag) {
178 1.1 cgd case KTT_HOSTNAME: {
179 1.1 cgd if (buf[len-1] == '\n')
180 1.1 cgd --len;
181 1.1 cgd bcopy(buf, hostname, len);
182 1.17 cgd hostname[len] = '\0';
183 1.6 cgd hostnamelen = len;
184 1.1 cgd return (0);
185 1.1 cgd }
186 1.1 cgd
187 1.1 cgd default:
188 1.1 cgd return (EIO);
189 1.1 cgd }
190 1.1 cgd }
191 1.1 cgd
192 1.1 cgd /*
193 1.17 cgd * implement access checking.
194 1.17 cgd *
195 1.17 cgd * something very similar to this code is duplicated
196 1.17 cgd * throughout the 4bsd kernel and should be moved
197 1.17 cgd * into kern/vfs_subr.c sometime.
198 1.17 cgd *
199 1.17 cgd * actually, the check for super-user is slightly
200 1.17 cgd * broken since it will allow read access to write-only
201 1.17 cgd * objects. this doesn't cause any particular trouble
202 1.17 cgd * but does mean that the i/o entry points need to check
203 1.17 cgd * that the operation really does make sense.
204 1.17 cgd */
205 1.17 cgd kernfs_access(vp, mode, cred, p)
206 1.17 cgd struct vnode *vp;
207 1.17 cgd int mode;
208 1.17 cgd struct ucred *cred;
209 1.17 cgd struct proc *p;
210 1.17 cgd {
211 1.17 cgd struct vattr *vap;
212 1.17 cgd struct vattr vattr;
213 1.17 cgd int error;
214 1.17 cgd
215 1.17 cgd /*
216 1.17 cgd * If you're the super-user,
217 1.17 cgd * you always get access.
218 1.17 cgd */
219 1.17 cgd if (cred->cr_uid == (uid_t) 0)
220 1.17 cgd return (0);
221 1.17 cgd vap = &vattr;
222 1.17 cgd if (error = VOP_GETATTR(vp, vap, cred, p))
223 1.17 cgd return (error);
224 1.17 cgd
225 1.17 cgd /*
226 1.17 cgd * Access check is based on only one of owner, group, public.
227 1.17 cgd * If not owner, then check group. If not a member of the
228 1.17 cgd * group, then check public access.
229 1.17 cgd */
230 1.17 cgd if (cred->cr_uid != vap->va_uid) {
231 1.17 cgd gid_t *gp;
232 1.17 cgd int i;
233 1.17 cgd
234 1.17 cgd mode >>= 3;
235 1.17 cgd gp = cred->cr_groups;
236 1.17 cgd for (i = 0; i < cred->cr_ngroups; i++, gp++)
237 1.17 cgd if (vap->va_gid == *gp)
238 1.17 cgd goto found;
239 1.17 cgd mode >>= 3;
240 1.17 cgd found:
241 1.17 cgd ;
242 1.17 cgd }
243 1.17 cgd
244 1.17 cgd if ((vap->va_mode & mode) == mode)
245 1.17 cgd return (0);
246 1.17 cgd
247 1.17 cgd return (EACCES);
248 1.17 cgd }
249 1.17 cgd
250 1.17 cgd /*
251 1.1 cgd * vp is the current namei directory
252 1.1 cgd * ndp is the name to locate in that directory...
253 1.1 cgd */
254 1.1 cgd kernfs_lookup(dvp, ndp, p)
255 1.1 cgd struct vnode *dvp;
256 1.1 cgd struct nameidata *ndp;
257 1.1 cgd struct proc *p;
258 1.1 cgd {
259 1.1 cgd char *pname = ndp->ni_ptr;
260 1.1 cgd int error = ENOENT;
261 1.1 cgd int i;
262 1.1 cgd struct vnode *fvp;
263 1.1 cgd
264 1.1 cgd #ifdef KERNFS_DIAGNOSTIC
265 1.1 cgd printf("kernfs_lookup(%s)\n", pname);
266 1.1 cgd #endif
267 1.1 cgd if (ndp->ni_namelen == 1 && *pname == '.') {
268 1.1 cgd ndp->ni_dvp = dvp;
269 1.1 cgd ndp->ni_vp = dvp;
270 1.1 cgd VREF(dvp);
271 1.1 cgd /*VOP_LOCK(dvp);*/
272 1.1 cgd return (0);
273 1.1 cgd }
274 1.13 cgd
275 1.17 cgd #if 0
276 1.1 cgd if (ndp->ni_namelen == 4 && bcmp(pname, "root", 4) == 0) {
277 1.17 cgd ndp->ni_dvp = rootdir;
278 1.1 cgd ndp->ni_vp = rootdir;
279 1.1 cgd VREF(rootdir);
280 1.17 cgd VREF(rootdir);
281 1.1 cgd VOP_LOCK(rootdir);
282 1.1 cgd return (0);
283 1.1 cgd }
284 1.13 cgd #endif
285 1.17 cgd
286 1.1 cgd /*
287 1.1 cgd * /kern/rootdev is the root device
288 1.1 cgd */
289 1.1 cgd if (ndp->ni_namelen == 7 && bcmp(pname, "rootdev", 7) == 0) {
290 1.17 cgd if (vfinddev(rootdev, VBLK, &fvp))
291 1.17 cgd return (ENXIO);
292 1.4 cgd ndp->ni_dvp = dvp;
293 1.17 cgd ndp->ni_vp = fvp;
294 1.17 cgd VREF(fvp);
295 1.17 cgd VOP_LOCK(fvp);
296 1.1 cgd return (0);
297 1.1 cgd }
298 1.1 cgd
299 1.17 cgd for (i = 0; i < nkern_targets; i++) {
300 1.17 cgd struct kern_target *kt = &kern_targets[i];
301 1.1 cgd if (ndp->ni_namelen == strlen(kt->kt_name) &&
302 1.1 cgd bcmp(kt->kt_name, pname, ndp->ni_namelen) == 0) {
303 1.1 cgd error = 0;
304 1.1 cgd break;
305 1.1 cgd }
306 1.1 cgd }
307 1.1 cgd
308 1.1 cgd #ifdef KERNFS_DIAGNOSTIC
309 1.1 cgd printf("kernfs_lookup: i = %d, error = %d\n", i, error);
310 1.1 cgd #endif
311 1.1 cgd
312 1.1 cgd if (error)
313 1.1 cgd goto bad;
314 1.1 cgd
315 1.1 cgd #ifdef KERNFS_DIAGNOSTIC
316 1.1 cgd printf("kernfs_lookup: allocate new vnode\n");
317 1.1 cgd #endif
318 1.10 cgd error = getnewvnode(VT_KERNFS, dvp->v_mount, &kernfs_vnodeops, &fvp);
319 1.1 cgd if (error)
320 1.1 cgd goto bad;
321 1.17 cgd VTOKERN(fvp)->kf_kt = &kern_targets[i];
322 1.1 cgd fvp->v_type = VTOKERN(fvp)->kf_kt->kt_vtype;
323 1.1 cgd ndp->ni_dvp = dvp;
324 1.1 cgd ndp->ni_vp = fvp;
325 1.1 cgd #ifdef KERNFS_DIAGNOSTIC
326 1.1 cgd printf("kernfs_lookup: newvp = %x\n", fvp);
327 1.1 cgd #endif
328 1.1 cgd return (0);
329 1.1 cgd
330 1.1 cgd bad:;
331 1.1 cgd ndp->ni_dvp = dvp;
332 1.1 cgd ndp->ni_vp = NULL;
333 1.1 cgd #ifdef KERNFS_DIAGNOSTIC
334 1.1 cgd printf("kernfs_lookup: error = %d\n", error);
335 1.1 cgd #endif
336 1.1 cgd return (error);
337 1.1 cgd }
338 1.1 cgd
339 1.1 cgd kernfs_open(vp, mode, cred, p)
340 1.1 cgd struct vnode *vp;
341 1.1 cgd int mode;
342 1.1 cgd struct ucred *cred;
343 1.1 cgd struct proc *p;
344 1.1 cgd {
345 1.17 cgd int error;
346 1.17 cgd struct filedesc *fdp;
347 1.17 cgd struct file *fp;
348 1.17 cgd int dfd;
349 1.17 cgd int fd;
350 1.1 cgd
351 1.17 cgd #ifdef KERNFS_DIAGNOSTIC
352 1.17 cgd printf("kernfs_open\n");
353 1.17 cgd #endif
354 1.1 cgd
355 1.9 cgd /*
356 1.17 cgd * Can always open the root (modulo perms)
357 1.9 cgd */
358 1.17 cgd if (vp->v_flag & VROOT)
359 1.9 cgd return (0);
360 1.17 cgd
361 1.17 cgd #ifdef KERNFS_DIAGNOSTIC
362 1.17 cgd printf("kernfs_open, mode = %x, file = %s\n",
363 1.17 cgd mode, VTOKERN(vp)->kf_kt->kt_name);
364 1.17 cgd #endif
365 1.17 cgd
366 1.17 cgd if ((mode & FWRITE) && VTOKERN(vp)->kf_kt->kt_rw != KTM_RW)
367 1.17 cgd return (EACCES);
368 1.17 cgd
369 1.17 cgd return (0);
370 1.8 cgd }
371 1.8 cgd
372 1.1 cgd kernfs_getattr(vp, vap, cred, p)
373 1.1 cgd struct vnode *vp;
374 1.1 cgd struct vattr *vap;
375 1.1 cgd struct ucred *cred;
376 1.1 cgd struct proc *p;
377 1.1 cgd {
378 1.1 cgd int error = 0;
379 1.1 cgd char strbuf[KSTRING];
380 1.17 cgd struct kern_target *kt = VTOKERN(vp)->kf_kt;
381 1.1 cgd
382 1.1 cgd bzero((caddr_t) vap, sizeof(*vap));
383 1.1 cgd vattr_null(vap);
384 1.17 cgd vap->va_uid = 0;
385 1.17 cgd vap->va_gid = 0;
386 1.1 cgd vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
387 1.1 cgd /* vap->va_qsize = 0; */
388 1.1 cgd vap->va_blocksize = DEV_BSIZE;
389 1.1 cgd microtime(&vap->va_atime);
390 1.1 cgd vap->va_mtime = vap->va_atime;
391 1.1 cgd vap->va_ctime = vap->va_ctime;
392 1.1 cgd vap->va_gen = 0;
393 1.1 cgd vap->va_flags = 0;
394 1.1 cgd vap->va_rdev = 0;
395 1.1 cgd /* vap->va_qbytes = 0; */
396 1.1 cgd vap->va_bytes = 0;
397 1.1 cgd
398 1.1 cgd if (vp->v_flag & VROOT) {
399 1.1 cgd #ifdef KERNFS_DIAGNOSTIC
400 1.1 cgd printf("kernfs_getattr: stat rootdir\n");
401 1.1 cgd #endif
402 1.17 cgd vap->va_type = VDIR;
403 1.17 cgd vap->va_mode = KTM_DIR_MODE;
404 1.1 cgd vap->va_nlink = 2;
405 1.1 cgd vap->va_fileid = 2;
406 1.1 cgd vap->va_size = DEV_BSIZE;
407 1.1 cgd } else {
408 1.1 cgd #ifdef KERNFS_DIAGNOSTIC
409 1.1 cgd printf("kernfs_getattr: stat target %s\n", kt->kt_name);
410 1.1 cgd #endif
411 1.17 cgd vap->va_type = kt->kt_vtype;
412 1.17 cgd vap->va_mode = (kt->kt_rw ? KTM_RW_MODE : KTM_RO_MODE);
413 1.1 cgd vap->va_nlink = 1;
414 1.17 cgd vap->va_fileid = 3 + (kt - kern_targets) / sizeof(*kt);
415 1.1 cgd error = kernfs_xread(kt, strbuf, sizeof(strbuf), &vap->va_size);
416 1.1 cgd }
417 1.1 cgd
418 1.1 cgd vp->v_type = vap->va_type;
419 1.1 cgd #ifdef KERNFS_DIAGNOSTIC
420 1.1 cgd printf("kernfs_getattr: return error %d\n", error);
421 1.1 cgd #endif
422 1.1 cgd return (error);
423 1.1 cgd }
424 1.1 cgd
425 1.1 cgd kernfs_setattr(vp, vap, cred, p)
426 1.1 cgd struct vnode *vp;
427 1.1 cgd struct vattr *vap;
428 1.1 cgd struct ucred *cred;
429 1.1 cgd struct proc *p;
430 1.1 cgd {
431 1.1 cgd
432 1.1 cgd /*
433 1.17 cgd * Silently ignore attribute changes.
434 1.17 cgd * This allows for open with truncate to have no
435 1.17 cgd * effect until some data is written. I want to
436 1.17 cgd * do it this way because all writes are atomic.
437 1.1 cgd */
438 1.17 cgd return (0);
439 1.1 cgd }
440 1.1 cgd
441 1.1 cgd static int
442 1.1 cgd kernfs_read(vp, uio, ioflag, cred)
443 1.1 cgd struct vnode *vp;
444 1.1 cgd struct uio *uio;
445 1.1 cgd int ioflag;
446 1.1 cgd struct ucred *cred;
447 1.1 cgd {
448 1.17 cgd struct kern_target *kt = VTOKERN(vp)->kf_kt;
449 1.1 cgd char strbuf[KSTRING];
450 1.1 cgd int off = uio->uio_offset;
451 1.1 cgd int len = 0;
452 1.1 cgd char *cp = strbuf;
453 1.1 cgd int error;
454 1.1 cgd #ifdef KERNFS_DIAGNOSTIC
455 1.1 cgd printf("kern_read %s\n", kt->kt_name);
456 1.1 cgd #endif
457 1.18 cgd
458 1.18 cgd if (vp->v_flag & VROOT)
459 1.19 cgd return (EOPNOTSUPP);
460 1.1 cgd
461 1.1 cgd error = kernfs_xread(kt, strbuf, sizeof(strbuf), &len);
462 1.1 cgd if (error)
463 1.1 cgd return (error);
464 1.1 cgd cp = strbuf + off;
465 1.1 cgd len -= off;
466 1.1 cgd return (uiomove(cp, len, uio));
467 1.1 cgd }
468 1.1 cgd
469 1.1 cgd static int
470 1.1 cgd kernfs_write(vp, uio, ioflag, cred)
471 1.1 cgd struct vnode *vp;
472 1.1 cgd struct uio *uio;
473 1.1 cgd int ioflag;
474 1.1 cgd struct ucred *cred;
475 1.1 cgd {
476 1.17 cgd struct kern_target *kt = VTOKERN(vp)->kf_kt;
477 1.1 cgd char strbuf[KSTRING];
478 1.1 cgd int len = uio->uio_resid;
479 1.1 cgd char *cp = strbuf;
480 1.1 cgd int xlen;
481 1.1 cgd int error;
482 1.1 cgd
483 1.1 cgd if (uio->uio_offset != 0)
484 1.1 cgd return (EINVAL);
485 1.1 cgd
486 1.1 cgd xlen = min(uio->uio_resid, KSTRING-1);
487 1.1 cgd error = uiomove(strbuf, xlen, uio);
488 1.1 cgd if (error)
489 1.1 cgd return (error);
490 1.1 cgd
491 1.1 cgd if (uio->uio_resid != 0)
492 1.1 cgd return (EIO);
493 1.1 cgd
494 1.1 cgd strbuf[xlen] = '\0';
495 1.17 cgd xlen = strlen(strbuf);
496 1.1 cgd return (kernfs_xwrite(kt, strbuf, xlen));
497 1.1 cgd }
498 1.1 cgd
499 1.17 cgd kernfs_readdir(vp, uio, cred, eofflagp)
500 1.1 cgd struct vnode *vp;
501 1.1 cgd struct uio *uio;
502 1.1 cgd struct ucred *cred;
503 1.1 cgd int *eofflagp;
504 1.1 cgd {
505 1.1 cgd struct filedesc *fdp;
506 1.1 cgd int i;
507 1.1 cgd int error;
508 1.1 cgd
509 1.1 cgd i = uio->uio_offset / UIO_MX;
510 1.1 cgd error = 0;
511 1.17 cgd while (uio->uio_resid > 0) {
512 1.1 cgd #ifdef KERNFS_DIAGNOSTIC
513 1.1 cgd printf("kernfs_readdir: i = %d\n", i);
514 1.1 cgd #endif
515 1.17 cgd if (i >= nkern_targets) {
516 1.1 cgd *eofflagp = 1;
517 1.1 cgd break;
518 1.1 cgd }
519 1.1 cgd {
520 1.1 cgd struct direct d;
521 1.1 cgd struct direct *dp = &d;
522 1.17 cgd struct kern_target *kt = &kern_targets[i];
523 1.1 cgd
524 1.1 cgd bzero((caddr_t) dp, UIO_MX);
525 1.1 cgd
526 1.1 cgd dp->d_namlen = strlen(kt->kt_name);
527 1.1 cgd bcopy(kt->kt_name, dp->d_name, dp->d_namlen+1);
528 1.1 cgd
529 1.1 cgd #ifdef KERNFS_DIAGNOSTIC
530 1.1 cgd printf("kernfs_readdir: name = %s, len = %d\n",
531 1.1 cgd dp->d_name, dp->d_namlen);
532 1.1 cgd #endif
533 1.1 cgd /*
534 1.1 cgd * Fill in the remaining fields
535 1.1 cgd */
536 1.1 cgd dp->d_reclen = UIO_MX;
537 1.1 cgd dp->d_ino = i + 3;
538 1.1 cgd /*
539 1.1 cgd * And ship to userland
540 1.1 cgd */
541 1.1 cgd error = uiomove((caddr_t) dp, UIO_MX, uio);
542 1.1 cgd if (error)
543 1.1 cgd break;
544 1.1 cgd }
545 1.1 cgd i++;
546 1.1 cgd }
547 1.1 cgd
548 1.1 cgd uio->uio_offset = i * UIO_MX;
549 1.1 cgd
550 1.1 cgd return (error);
551 1.1 cgd }
552 1.1 cgd
553 1.1 cgd kernfs_inactive(vp, p)
554 1.1 cgd struct vnode *vp;
555 1.1 cgd struct proc *p;
556 1.1 cgd {
557 1.1 cgd /*
558 1.1 cgd * Clear out the v_type field to avoid
559 1.1 cgd * nasty things happening in vgone().
560 1.1 cgd */
561 1.1 cgd vp->v_type = VNON;
562 1.1 cgd #ifdef KERNFS_DIAGNOSTIC
563 1.1 cgd printf("kernfs_inactive(%x)\n", vp);
564 1.1 cgd #endif
565 1.1 cgd return (0);
566 1.1 cgd }
567 1.1 cgd
568 1.1 cgd /*
569 1.1 cgd * Print out the contents of a kernfs vnode.
570 1.1 cgd */
571 1.1 cgd /* ARGSUSED */
572 1.1 cgd kernfs_print(vp)
573 1.1 cgd struct vnode *vp;
574 1.1 cgd {
575 1.17 cgd printf("tag VT_NON, kernfs vnode\n");
576 1.1 cgd }
577 1.1 cgd
578 1.1 cgd /*
579 1.1 cgd * kernfs vnode unsupported operation
580 1.1 cgd */
581 1.1 cgd kernfs_enotsupp()
582 1.1 cgd {
583 1.1 cgd return (EOPNOTSUPP);
584 1.1 cgd }
585 1.1 cgd
586 1.1 cgd /*
587 1.1 cgd * kernfs "should never get here" operation
588 1.1 cgd */
589 1.1 cgd kernfs_badop()
590 1.1 cgd {
591 1.1 cgd panic("kernfs: bad op");
592 1.1 cgd /* NOTREACHED */
593 1.1 cgd }
594 1.1 cgd
595 1.1 cgd /*
596 1.1 cgd * kernfs vnode null operation
597 1.1 cgd */
598 1.1 cgd kernfs_nullop()
599 1.1 cgd {
600 1.1 cgd return (0);
601 1.1 cgd }
602 1.1 cgd
603 1.1 cgd #define kernfs_create ((int (*) __P(( \
604 1.1 cgd struct nameidata *ndp, \
605 1.1 cgd struct vattr *vap, \
606 1.1 cgd struct proc *p))) kernfs_enotsupp)
607 1.1 cgd #define kernfs_mknod ((int (*) __P(( \
608 1.1 cgd struct nameidata *ndp, \
609 1.1 cgd struct vattr *vap, \
610 1.1 cgd struct ucred *cred, \
611 1.1 cgd struct proc *p))) kernfs_enotsupp)
612 1.1 cgd #define kernfs_close ((int (*) __P(( \
613 1.1 cgd struct vnode *vp, \
614 1.1 cgd int fflag, \
615 1.1 cgd struct ucred *cred, \
616 1.1 cgd struct proc *p))) nullop)
617 1.1 cgd #define kernfs_ioctl ((int (*) __P(( \
618 1.1 cgd struct vnode *vp, \
619 1.1 cgd int command, \
620 1.1 cgd caddr_t data, \
621 1.1 cgd int fflag, \
622 1.1 cgd struct ucred *cred, \
623 1.1 cgd struct proc *p))) kernfs_enotsupp)
624 1.1 cgd #define kernfs_select ((int (*) __P(( \
625 1.1 cgd struct vnode *vp, \
626 1.1 cgd int which, \
627 1.1 cgd int fflags, \
628 1.1 cgd struct ucred *cred, \
629 1.1 cgd struct proc *p))) kernfs_enotsupp)
630 1.1 cgd #define kernfs_mmap ((int (*) __P(( \
631 1.1 cgd struct vnode *vp, \
632 1.1 cgd int fflags, \
633 1.1 cgd struct ucred *cred, \
634 1.1 cgd struct proc *p))) kernfs_enotsupp)
635 1.1 cgd #define kernfs_fsync ((int (*) __P(( \
636 1.1 cgd struct vnode *vp, \
637 1.1 cgd int fflags, \
638 1.1 cgd struct ucred *cred, \
639 1.1 cgd int waitfor, \
640 1.1 cgd struct proc *p))) nullop)
641 1.1 cgd #define kernfs_seek ((int (*) __P(( \
642 1.1 cgd struct vnode *vp, \
643 1.1 cgd off_t oldoff, \
644 1.1 cgd off_t newoff, \
645 1.1 cgd struct ucred *cred))) nullop)
646 1.1 cgd #define kernfs_remove ((int (*) __P(( \
647 1.1 cgd struct nameidata *ndp, \
648 1.1 cgd struct proc *p))) kernfs_enotsupp)
649 1.1 cgd #define kernfs_link ((int (*) __P(( \
650 1.1 cgd struct vnode *vp, \
651 1.1 cgd struct nameidata *ndp, \
652 1.1 cgd struct proc *p))) kernfs_enotsupp)
653 1.1 cgd #define kernfs_rename ((int (*) __P(( \
654 1.1 cgd struct nameidata *fndp, \
655 1.1 cgd struct nameidata *tdnp, \
656 1.1 cgd struct proc *p))) kernfs_enotsupp)
657 1.1 cgd #define kernfs_mkdir ((int (*) __P(( \
658 1.1 cgd struct nameidata *ndp, \
659 1.1 cgd struct vattr *vap, \
660 1.1 cgd struct proc *p))) kernfs_enotsupp)
661 1.1 cgd #define kernfs_rmdir ((int (*) __P(( \
662 1.1 cgd struct nameidata *ndp, \
663 1.1 cgd struct proc *p))) kernfs_enotsupp)
664 1.1 cgd #define kernfs_symlink ((int (*) __P(( \
665 1.1 cgd struct nameidata *ndp, \
666 1.1 cgd struct vattr *vap, \
667 1.1 cgd char *target, \
668 1.1 cgd struct proc *p))) kernfs_enotsupp)
669 1.1 cgd #define kernfs_readlink ((int (*) __P(( \
670 1.1 cgd struct vnode *vp, \
671 1.1 cgd struct uio *uio, \
672 1.1 cgd struct ucred *cred))) kernfs_enotsupp)
673 1.1 cgd #define kernfs_abortop ((int (*) __P(( \
674 1.1 cgd struct nameidata *ndp))) nullop)
675 1.1 cgd #ifdef KERNFS_DIAGNOSTIC
676 1.1 cgd int kernfs_reclaim(vp)
677 1.1 cgd struct vnode *vp;
678 1.1 cgd {
679 1.1 cgd printf("kernfs_reclaim(%x)\n", vp);
680 1.1 cgd return (0);
681 1.1 cgd }
682 1.1 cgd #else
683 1.1 cgd #define kernfs_reclaim ((int (*) __P(( \
684 1.1 cgd struct vnode *vp))) nullop)
685 1.1 cgd #endif
686 1.1 cgd #define kernfs_lock ((int (*) __P(( \
687 1.1 cgd struct vnode *vp))) nullop)
688 1.1 cgd #define kernfs_unlock ((int (*) __P(( \
689 1.1 cgd struct vnode *vp))) nullop)
690 1.1 cgd #define kernfs_bmap ((int (*) __P(( \
691 1.1 cgd struct vnode *vp, \
692 1.1 cgd daddr_t bn, \
693 1.1 cgd struct vnode **vpp, \
694 1.1 cgd daddr_t *bnp))) kernfs_badop)
695 1.1 cgd #define kernfs_strategy ((int (*) __P(( \
696 1.1 cgd struct buf *bp))) kernfs_badop)
697 1.1 cgd #define kernfs_islocked ((int (*) __P(( \
698 1.1 cgd struct vnode *vp))) nullop)
699 1.1 cgd #define kernfs_advlock ((int (*) __P(( \
700 1.1 cgd struct vnode *vp, \
701 1.1 cgd caddr_t id, \
702 1.1 cgd int op, \
703 1.1 cgd struct flock *fl, \
704 1.1 cgd int flags))) kernfs_enotsupp)
705 1.1 cgd
706 1.1 cgd struct vnodeops kernfs_vnodeops = {
707 1.1 cgd kernfs_lookup, /* lookup */
708 1.1 cgd kernfs_create, /* create */
709 1.1 cgd kernfs_mknod, /* mknod */
710 1.1 cgd kernfs_open, /* open */
711 1.1 cgd kernfs_close, /* close */
712 1.1 cgd kernfs_access, /* access */
713 1.1 cgd kernfs_getattr, /* getattr */
714 1.1 cgd kernfs_setattr, /* setattr */
715 1.1 cgd kernfs_read, /* read */
716 1.1 cgd kernfs_write, /* write */
717 1.1 cgd kernfs_ioctl, /* ioctl */
718 1.1 cgd kernfs_select, /* select */
719 1.1 cgd kernfs_mmap, /* mmap */
720 1.1 cgd kernfs_fsync, /* fsync */
721 1.1 cgd kernfs_seek, /* seek */
722 1.1 cgd kernfs_remove, /* remove */
723 1.1 cgd kernfs_link, /* link */
724 1.1 cgd kernfs_rename, /* rename */
725 1.1 cgd kernfs_mkdir, /* mkdir */
726 1.1 cgd kernfs_rmdir, /* rmdir */
727 1.1 cgd kernfs_symlink, /* symlink */
728 1.1 cgd kernfs_readdir, /* readdir */
729 1.1 cgd kernfs_readlink, /* readlink */
730 1.1 cgd kernfs_abortop, /* abortop */
731 1.1 cgd kernfs_inactive, /* inactive */
732 1.1 cgd kernfs_reclaim, /* reclaim */
733 1.1 cgd kernfs_lock, /* lock */
734 1.1 cgd kernfs_unlock, /* unlock */
735 1.1 cgd kernfs_bmap, /* bmap */
736 1.1 cgd kernfs_strategy, /* strategy */
737 1.1 cgd kernfs_print, /* print */
738 1.1 cgd kernfs_islocked, /* islocked */
739 1.1 cgd kernfs_advlock, /* advlock */
740 1.1 cgd };
741