kernfs_vnops.c revision 1.22 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.22 mycroft * $Id: kernfs_vnops.c,v 1.22 1994/05/17 06:59:17 mycroft 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.20 ws { "..", 0, KTT_NULL, KTM_RO, VDIR },
91 1.17 cgd { "copyright", copyright, KTT_STRING, KTM_RO, VREG },
92 1.17 cgd { "hostname", 0, KTT_HOSTNAME, KTM_RW, VREG },
93 1.17 cgd { "hz", &hz, KTT_INT, KTM_RO, VREG },
94 1.17 cgd { "loadavg", 0, KTT_AVENRUN, KTM_RO, VREG },
95 1.17 cgd { "physmem", &physmem, KTT_INT, KTM_RO, VREG },
96 1.17 cgd #if 0
97 1.17 cgd { "root", 0, KTT_NULL, KTM_RO, VDIR },
98 1.17 cgd #endif
99 1.17 cgd { "rootdev", 0, KTT_NULL, KTM_RO, VBLK },
100 1.17 cgd #ifdef notdef
101 1.17 cgd { "rrootdev", 0, KTT_NULL, KTM_RO, VCHR },
102 1.17 cgd #endif
103 1.17 cgd { "time", 0, KTT_TIME, KTM_RO, VREG },
104 1.17 cgd { "version", version, KTT_STRING, KTM_RO, VREG },
105 1.1 cgd };
106 1.1 cgd
107 1.17 cgd static int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
108 1.1 cgd
109 1.1 cgd static int
110 1.1 cgd kernfs_xread(kt, buf, len, lenp)
111 1.17 cgd struct kern_target *kt;
112 1.1 cgd char *buf;
113 1.1 cgd int len;
114 1.1 cgd int *lenp;
115 1.1 cgd {
116 1.1 cgd int xlen;
117 1.1 cgd
118 1.1 cgd switch (kt->kt_tag) {
119 1.1 cgd case KTT_TIME: {
120 1.1 cgd struct timeval tv;
121 1.1 cgd microtime(&tv);
122 1.1 cgd sprintf(buf, "%d %d\n", tv.tv_sec, tv.tv_usec);
123 1.1 cgd break;
124 1.1 cgd }
125 1.1 cgd
126 1.1 cgd case KTT_INT: {
127 1.1 cgd int *ip = kt->kt_data;
128 1.1 cgd sprintf(buf, "%d\n", *ip);
129 1.1 cgd break;
130 1.1 cgd }
131 1.1 cgd
132 1.1 cgd case KTT_STRING: {
133 1.1 cgd char *cp = kt->kt_data;
134 1.1 cgd int xlen = strlen(cp) + 1;
135 1.1 cgd
136 1.1 cgd if (xlen >= len)
137 1.1 cgd return (EINVAL);
138 1.1 cgd
139 1.1 cgd bcopy(cp, buf, xlen);
140 1.1 cgd break;
141 1.1 cgd }
142 1.1 cgd
143 1.1 cgd case KTT_HOSTNAME: {
144 1.1 cgd char *cp = hostname;
145 1.1 cgd int xlen = hostnamelen;
146 1.1 cgd
147 1.17 cgd if (xlen >= (len-2))
148 1.1 cgd return (EINVAL);
149 1.1 cgd
150 1.17 cgd bcopy(cp, buf, xlen);
151 1.6 cgd buf[xlen] = '\n';
152 1.6 cgd buf[xlen+1] = '\0';
153 1.1 cgd break;
154 1.1 cgd }
155 1.1 cgd
156 1.1 cgd case KTT_AVENRUN:
157 1.1 cgd sprintf(buf, "%d %d %d %d\n",
158 1.17 cgd averunnable.ldavg[0],
159 1.17 cgd averunnable.ldavg[1],
160 1.17 cgd averunnable.ldavg[2],
161 1.17 cgd averunnable.fscale);
162 1.1 cgd break;
163 1.1 cgd
164 1.1 cgd default:
165 1.1 cgd return (EINVAL);
166 1.1 cgd }
167 1.1 cgd
168 1.1 cgd *lenp = strlen(buf);
169 1.1 cgd return (0);
170 1.1 cgd }
171 1.1 cgd
172 1.1 cgd static int
173 1.1 cgd kernfs_xwrite(kt, buf, len)
174 1.17 cgd struct kern_target *kt;
175 1.1 cgd char *buf;
176 1.1 cgd int len;
177 1.1 cgd {
178 1.1 cgd switch (kt->kt_tag) {
179 1.1 cgd case KTT_HOSTNAME: {
180 1.1 cgd if (buf[len-1] == '\n')
181 1.1 cgd --len;
182 1.1 cgd bcopy(buf, hostname, len);
183 1.17 cgd hostname[len] = '\0';
184 1.6 cgd hostnamelen = len;
185 1.1 cgd return (0);
186 1.1 cgd }
187 1.1 cgd
188 1.1 cgd default:
189 1.1 cgd return (EIO);
190 1.1 cgd }
191 1.1 cgd }
192 1.1 cgd
193 1.1 cgd /*
194 1.17 cgd * implement access checking.
195 1.17 cgd *
196 1.17 cgd * something very similar to this code is duplicated
197 1.17 cgd * throughout the 4bsd kernel and should be moved
198 1.17 cgd * into kern/vfs_subr.c sometime.
199 1.17 cgd *
200 1.17 cgd * actually, the check for super-user is slightly
201 1.17 cgd * broken since it will allow read access to write-only
202 1.17 cgd * objects. this doesn't cause any particular trouble
203 1.17 cgd * but does mean that the i/o entry points need to check
204 1.17 cgd * that the operation really does make sense.
205 1.17 cgd */
206 1.17 cgd kernfs_access(vp, mode, cred, p)
207 1.17 cgd struct vnode *vp;
208 1.17 cgd int mode;
209 1.17 cgd struct ucred *cred;
210 1.17 cgd struct proc *p;
211 1.17 cgd {
212 1.17 cgd struct vattr *vap;
213 1.17 cgd struct vattr vattr;
214 1.17 cgd int error;
215 1.17 cgd
216 1.17 cgd /*
217 1.17 cgd * If you're the super-user,
218 1.17 cgd * you always get access.
219 1.17 cgd */
220 1.17 cgd if (cred->cr_uid == (uid_t) 0)
221 1.17 cgd return (0);
222 1.17 cgd vap = &vattr;
223 1.17 cgd if (error = VOP_GETATTR(vp, vap, cred, p))
224 1.17 cgd return (error);
225 1.17 cgd
226 1.17 cgd /*
227 1.17 cgd * Access check is based on only one of owner, group, public.
228 1.17 cgd * If not owner, then check group. If not a member of the
229 1.17 cgd * group, then check public access.
230 1.17 cgd */
231 1.17 cgd if (cred->cr_uid != vap->va_uid) {
232 1.17 cgd gid_t *gp;
233 1.17 cgd int i;
234 1.17 cgd
235 1.17 cgd mode >>= 3;
236 1.17 cgd gp = cred->cr_groups;
237 1.17 cgd for (i = 0; i < cred->cr_ngroups; i++, gp++)
238 1.17 cgd if (vap->va_gid == *gp)
239 1.17 cgd goto found;
240 1.17 cgd mode >>= 3;
241 1.17 cgd found:
242 1.17 cgd ;
243 1.17 cgd }
244 1.17 cgd
245 1.17 cgd if ((vap->va_mode & mode) == mode)
246 1.17 cgd return (0);
247 1.17 cgd
248 1.17 cgd return (EACCES);
249 1.17 cgd }
250 1.17 cgd
251 1.17 cgd /*
252 1.1 cgd * vp is the current namei directory
253 1.1 cgd * ndp is the name to locate in that directory...
254 1.1 cgd */
255 1.1 cgd kernfs_lookup(dvp, ndp, p)
256 1.1 cgd struct vnode *dvp;
257 1.1 cgd struct nameidata *ndp;
258 1.1 cgd struct proc *p;
259 1.1 cgd {
260 1.1 cgd char *pname = ndp->ni_ptr;
261 1.1 cgd int error = ENOENT;
262 1.1 cgd int i;
263 1.1 cgd struct vnode *fvp;
264 1.1 cgd
265 1.1 cgd #ifdef KERNFS_DIAGNOSTIC
266 1.1 cgd printf("kernfs_lookup(%s)\n", pname);
267 1.1 cgd #endif
268 1.1 cgd if (ndp->ni_namelen == 1 && *pname == '.') {
269 1.1 cgd ndp->ni_dvp = dvp;
270 1.1 cgd ndp->ni_vp = dvp;
271 1.1 cgd VREF(dvp);
272 1.1 cgd /*VOP_LOCK(dvp);*/
273 1.1 cgd return (0);
274 1.1 cgd }
275 1.13 cgd
276 1.17 cgd #if 0
277 1.1 cgd if (ndp->ni_namelen == 4 && bcmp(pname, "root", 4) == 0) {
278 1.17 cgd ndp->ni_dvp = rootdir;
279 1.1 cgd ndp->ni_vp = rootdir;
280 1.1 cgd VREF(rootdir);
281 1.17 cgd VREF(rootdir);
282 1.1 cgd VOP_LOCK(rootdir);
283 1.1 cgd return (0);
284 1.1 cgd }
285 1.13 cgd #endif
286 1.17 cgd
287 1.1 cgd /*
288 1.1 cgd * /kern/rootdev is the root device
289 1.1 cgd */
290 1.1 cgd if (ndp->ni_namelen == 7 && bcmp(pname, "rootdev", 7) == 0) {
291 1.17 cgd if (vfinddev(rootdev, VBLK, &fvp))
292 1.17 cgd return (ENXIO);
293 1.4 cgd ndp->ni_dvp = dvp;
294 1.17 cgd ndp->ni_vp = fvp;
295 1.17 cgd VREF(fvp);
296 1.17 cgd VOP_LOCK(fvp);
297 1.1 cgd return (0);
298 1.1 cgd }
299 1.1 cgd
300 1.17 cgd for (i = 0; i < nkern_targets; i++) {
301 1.17 cgd struct kern_target *kt = &kern_targets[i];
302 1.1 cgd if (ndp->ni_namelen == strlen(kt->kt_name) &&
303 1.1 cgd bcmp(kt->kt_name, pname, ndp->ni_namelen) == 0) {
304 1.1 cgd error = 0;
305 1.1 cgd break;
306 1.1 cgd }
307 1.1 cgd }
308 1.1 cgd
309 1.1 cgd #ifdef KERNFS_DIAGNOSTIC
310 1.1 cgd printf("kernfs_lookup: i = %d, error = %d\n", i, error);
311 1.1 cgd #endif
312 1.1 cgd
313 1.1 cgd if (error)
314 1.1 cgd goto bad;
315 1.1 cgd
316 1.1 cgd #ifdef KERNFS_DIAGNOSTIC
317 1.1 cgd printf("kernfs_lookup: allocate new vnode\n");
318 1.1 cgd #endif
319 1.10 cgd error = getnewvnode(VT_KERNFS, dvp->v_mount, &kernfs_vnodeops, &fvp);
320 1.1 cgd if (error)
321 1.1 cgd goto bad;
322 1.17 cgd VTOKERN(fvp)->kf_kt = &kern_targets[i];
323 1.1 cgd fvp->v_type = VTOKERN(fvp)->kf_kt->kt_vtype;
324 1.1 cgd ndp->ni_dvp = dvp;
325 1.1 cgd ndp->ni_vp = fvp;
326 1.1 cgd #ifdef KERNFS_DIAGNOSTIC
327 1.1 cgd printf("kernfs_lookup: newvp = %x\n", fvp);
328 1.1 cgd #endif
329 1.1 cgd return (0);
330 1.1 cgd
331 1.1 cgd bad:;
332 1.1 cgd ndp->ni_dvp = dvp;
333 1.1 cgd ndp->ni_vp = NULL;
334 1.1 cgd #ifdef KERNFS_DIAGNOSTIC
335 1.1 cgd printf("kernfs_lookup: error = %d\n", error);
336 1.1 cgd #endif
337 1.1 cgd return (error);
338 1.1 cgd }
339 1.1 cgd
340 1.1 cgd kernfs_open(vp, mode, cred, p)
341 1.1 cgd struct vnode *vp;
342 1.1 cgd int mode;
343 1.1 cgd struct ucred *cred;
344 1.1 cgd struct proc *p;
345 1.1 cgd {
346 1.17 cgd int error;
347 1.17 cgd struct filedesc *fdp;
348 1.17 cgd struct file *fp;
349 1.17 cgd int dfd;
350 1.17 cgd int fd;
351 1.1 cgd
352 1.17 cgd #ifdef KERNFS_DIAGNOSTIC
353 1.17 cgd printf("kernfs_open\n");
354 1.17 cgd #endif
355 1.1 cgd
356 1.9 cgd /*
357 1.17 cgd * Can always open the root (modulo perms)
358 1.9 cgd */
359 1.17 cgd if (vp->v_flag & VROOT)
360 1.9 cgd return (0);
361 1.17 cgd
362 1.17 cgd #ifdef KERNFS_DIAGNOSTIC
363 1.17 cgd printf("kernfs_open, mode = %x, file = %s\n",
364 1.17 cgd mode, VTOKERN(vp)->kf_kt->kt_name);
365 1.17 cgd #endif
366 1.17 cgd
367 1.17 cgd if ((mode & FWRITE) && VTOKERN(vp)->kf_kt->kt_rw != KTM_RW)
368 1.17 cgd return (EACCES);
369 1.17 cgd
370 1.17 cgd return (0);
371 1.8 cgd }
372 1.8 cgd
373 1.1 cgd kernfs_getattr(vp, vap, cred, p)
374 1.1 cgd struct vnode *vp;
375 1.1 cgd struct vattr *vap;
376 1.1 cgd struct ucred *cred;
377 1.1 cgd struct proc *p;
378 1.1 cgd {
379 1.1 cgd int error = 0;
380 1.1 cgd char strbuf[KSTRING];
381 1.17 cgd struct kern_target *kt = VTOKERN(vp)->kf_kt;
382 1.1 cgd
383 1.1 cgd bzero((caddr_t) vap, sizeof(*vap));
384 1.1 cgd vattr_null(vap);
385 1.17 cgd vap->va_uid = 0;
386 1.17 cgd vap->va_gid = 0;
387 1.1 cgd vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[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_bytes = 0;
396 1.1 cgd
397 1.1 cgd if (vp->v_flag & VROOT) {
398 1.1 cgd #ifdef KERNFS_DIAGNOSTIC
399 1.1 cgd printf("kernfs_getattr: stat rootdir\n");
400 1.1 cgd #endif
401 1.17 cgd vap->va_type = VDIR;
402 1.17 cgd vap->va_mode = KTM_DIR_MODE;
403 1.1 cgd vap->va_nlink = 2;
404 1.1 cgd vap->va_fileid = 2;
405 1.1 cgd vap->va_size = DEV_BSIZE;
406 1.1 cgd } else {
407 1.22 mycroft int nbytes;
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.22 mycroft error = kernfs_xread(kt, strbuf, sizeof(strbuf), &nbytes);
416 1.22 mycroft vap->va_size = nbytes;
417 1.1 cgd }
418 1.1 cgd
419 1.1 cgd vp->v_type = vap->va_type;
420 1.1 cgd #ifdef KERNFS_DIAGNOSTIC
421 1.1 cgd printf("kernfs_getattr: return error %d\n", error);
422 1.1 cgd #endif
423 1.1 cgd return (error);
424 1.1 cgd }
425 1.1 cgd
426 1.1 cgd kernfs_setattr(vp, vap, cred, p)
427 1.1 cgd struct vnode *vp;
428 1.1 cgd struct vattr *vap;
429 1.1 cgd struct ucred *cred;
430 1.1 cgd struct proc *p;
431 1.1 cgd {
432 1.1 cgd
433 1.1 cgd /*
434 1.17 cgd * Silently ignore attribute changes.
435 1.17 cgd * This allows for open with truncate to have no
436 1.17 cgd * effect until some data is written. I want to
437 1.17 cgd * do it this way because all writes are atomic.
438 1.1 cgd */
439 1.17 cgd return (0);
440 1.1 cgd }
441 1.1 cgd
442 1.1 cgd static int
443 1.1 cgd kernfs_read(vp, uio, ioflag, cred)
444 1.1 cgd struct vnode *vp;
445 1.1 cgd struct uio *uio;
446 1.1 cgd int ioflag;
447 1.1 cgd struct ucred *cred;
448 1.1 cgd {
449 1.17 cgd struct kern_target *kt = VTOKERN(vp)->kf_kt;
450 1.1 cgd char strbuf[KSTRING];
451 1.1 cgd int off = uio->uio_offset;
452 1.1 cgd int len = 0;
453 1.1 cgd char *cp = strbuf;
454 1.1 cgd int error;
455 1.1 cgd #ifdef KERNFS_DIAGNOSTIC
456 1.1 cgd printf("kern_read %s\n", kt->kt_name);
457 1.1 cgd #endif
458 1.18 cgd
459 1.18 cgd if (vp->v_flag & VROOT)
460 1.19 cgd return (EOPNOTSUPP);
461 1.1 cgd
462 1.1 cgd error = kernfs_xread(kt, strbuf, sizeof(strbuf), &len);
463 1.1 cgd if (error)
464 1.1 cgd return (error);
465 1.1 cgd cp = strbuf + off;
466 1.1 cgd len -= off;
467 1.1 cgd return (uiomove(cp, len, uio));
468 1.1 cgd }
469 1.1 cgd
470 1.1 cgd static int
471 1.1 cgd kernfs_write(vp, uio, ioflag, cred)
472 1.1 cgd struct vnode *vp;
473 1.1 cgd struct uio *uio;
474 1.1 cgd int ioflag;
475 1.1 cgd struct ucred *cred;
476 1.1 cgd {
477 1.17 cgd struct kern_target *kt = VTOKERN(vp)->kf_kt;
478 1.1 cgd char strbuf[KSTRING];
479 1.1 cgd int len = uio->uio_resid;
480 1.1 cgd char *cp = strbuf;
481 1.1 cgd int xlen;
482 1.1 cgd int error;
483 1.1 cgd
484 1.1 cgd if (uio->uio_offset != 0)
485 1.1 cgd return (EINVAL);
486 1.1 cgd
487 1.1 cgd xlen = min(uio->uio_resid, KSTRING-1);
488 1.1 cgd error = uiomove(strbuf, xlen, uio);
489 1.1 cgd if (error)
490 1.1 cgd return (error);
491 1.1 cgd
492 1.1 cgd if (uio->uio_resid != 0)
493 1.1 cgd return (EIO);
494 1.1 cgd
495 1.1 cgd strbuf[xlen] = '\0';
496 1.17 cgd xlen = strlen(strbuf);
497 1.1 cgd return (kernfs_xwrite(kt, strbuf, xlen));
498 1.1 cgd }
499 1.1 cgd
500 1.17 cgd kernfs_readdir(vp, uio, cred, eofflagp)
501 1.1 cgd struct vnode *vp;
502 1.1 cgd struct uio *uio;
503 1.1 cgd struct ucred *cred;
504 1.1 cgd int *eofflagp;
505 1.1 cgd {
506 1.1 cgd struct filedesc *fdp;
507 1.1 cgd int i;
508 1.1 cgd int error;
509 1.1 cgd
510 1.1 cgd i = uio->uio_offset / UIO_MX;
511 1.1 cgd error = 0;
512 1.17 cgd while (uio->uio_resid > 0) {
513 1.1 cgd #ifdef KERNFS_DIAGNOSTIC
514 1.1 cgd printf("kernfs_readdir: i = %d\n", i);
515 1.1 cgd #endif
516 1.17 cgd if (i >= nkern_targets) {
517 1.1 cgd *eofflagp = 1;
518 1.1 cgd break;
519 1.1 cgd }
520 1.1 cgd {
521 1.1 cgd struct direct d;
522 1.1 cgd struct direct *dp = &d;
523 1.17 cgd struct kern_target *kt = &kern_targets[i];
524 1.1 cgd
525 1.1 cgd bzero((caddr_t) dp, UIO_MX);
526 1.1 cgd
527 1.1 cgd dp->d_namlen = strlen(kt->kt_name);
528 1.1 cgd bcopy(kt->kt_name, dp->d_name, dp->d_namlen+1);
529 1.1 cgd
530 1.1 cgd #ifdef KERNFS_DIAGNOSTIC
531 1.1 cgd printf("kernfs_readdir: name = %s, len = %d\n",
532 1.1 cgd dp->d_name, dp->d_namlen);
533 1.1 cgd #endif
534 1.1 cgd /*
535 1.1 cgd * Fill in the remaining fields
536 1.1 cgd */
537 1.1 cgd dp->d_reclen = UIO_MX;
538 1.1 cgd dp->d_ino = i + 3;
539 1.1 cgd /*
540 1.1 cgd * And ship to userland
541 1.1 cgd */
542 1.1 cgd error = uiomove((caddr_t) dp, UIO_MX, uio);
543 1.1 cgd if (error)
544 1.1 cgd break;
545 1.1 cgd }
546 1.1 cgd i++;
547 1.1 cgd }
548 1.1 cgd
549 1.1 cgd uio->uio_offset = i * UIO_MX;
550 1.1 cgd
551 1.1 cgd return (error);
552 1.1 cgd }
553 1.1 cgd
554 1.1 cgd kernfs_inactive(vp, p)
555 1.1 cgd struct vnode *vp;
556 1.1 cgd struct proc *p;
557 1.1 cgd {
558 1.1 cgd /*
559 1.1 cgd * Clear out the v_type field to avoid
560 1.1 cgd * nasty things happening in vgone().
561 1.1 cgd */
562 1.1 cgd vp->v_type = VNON;
563 1.1 cgd #ifdef KERNFS_DIAGNOSTIC
564 1.1 cgd printf("kernfs_inactive(%x)\n", vp);
565 1.1 cgd #endif
566 1.1 cgd return (0);
567 1.1 cgd }
568 1.1 cgd
569 1.1 cgd /*
570 1.1 cgd * Print out the contents of a kernfs vnode.
571 1.1 cgd */
572 1.1 cgd /* ARGSUSED */
573 1.1 cgd kernfs_print(vp)
574 1.1 cgd struct vnode *vp;
575 1.1 cgd {
576 1.17 cgd printf("tag VT_NON, kernfs vnode\n");
577 1.1 cgd }
578 1.1 cgd
579 1.1 cgd /*
580 1.1 cgd * kernfs vnode unsupported operation
581 1.1 cgd */
582 1.1 cgd kernfs_enotsupp()
583 1.1 cgd {
584 1.1 cgd return (EOPNOTSUPP);
585 1.1 cgd }
586 1.1 cgd
587 1.1 cgd /*
588 1.1 cgd * kernfs "should never get here" operation
589 1.1 cgd */
590 1.1 cgd kernfs_badop()
591 1.1 cgd {
592 1.1 cgd panic("kernfs: bad op");
593 1.1 cgd /* NOTREACHED */
594 1.1 cgd }
595 1.1 cgd
596 1.1 cgd /*
597 1.1 cgd * kernfs vnode null operation
598 1.1 cgd */
599 1.1 cgd kernfs_nullop()
600 1.1 cgd {
601 1.1 cgd return (0);
602 1.1 cgd }
603 1.1 cgd
604 1.1 cgd #define kernfs_create ((int (*) __P(( \
605 1.1 cgd struct nameidata *ndp, \
606 1.1 cgd struct vattr *vap, \
607 1.1 cgd struct proc *p))) kernfs_enotsupp)
608 1.1 cgd #define kernfs_mknod ((int (*) __P(( \
609 1.1 cgd struct nameidata *ndp, \
610 1.1 cgd struct vattr *vap, \
611 1.1 cgd struct ucred *cred, \
612 1.1 cgd struct proc *p))) kernfs_enotsupp)
613 1.1 cgd #define kernfs_close ((int (*) __P(( \
614 1.1 cgd struct vnode *vp, \
615 1.1 cgd int fflag, \
616 1.1 cgd struct ucred *cred, \
617 1.1 cgd struct proc *p))) nullop)
618 1.1 cgd #define kernfs_ioctl ((int (*) __P(( \
619 1.1 cgd struct vnode *vp, \
620 1.1 cgd int command, \
621 1.1 cgd caddr_t data, \
622 1.1 cgd int fflag, \
623 1.1 cgd struct ucred *cred, \
624 1.1 cgd struct proc *p))) kernfs_enotsupp)
625 1.1 cgd #define kernfs_select ((int (*) __P(( \
626 1.1 cgd struct vnode *vp, \
627 1.1 cgd int which, \
628 1.1 cgd int fflags, \
629 1.1 cgd struct ucred *cred, \
630 1.1 cgd struct proc *p))) kernfs_enotsupp)
631 1.1 cgd #define kernfs_mmap ((int (*) __P(( \
632 1.1 cgd struct vnode *vp, \
633 1.1 cgd int fflags, \
634 1.1 cgd struct ucred *cred, \
635 1.1 cgd struct proc *p))) kernfs_enotsupp)
636 1.1 cgd #define kernfs_fsync ((int (*) __P(( \
637 1.1 cgd struct vnode *vp, \
638 1.1 cgd int fflags, \
639 1.1 cgd struct ucred *cred, \
640 1.1 cgd int waitfor, \
641 1.1 cgd struct proc *p))) nullop)
642 1.1 cgd #define kernfs_seek ((int (*) __P(( \
643 1.1 cgd struct vnode *vp, \
644 1.1 cgd off_t oldoff, \
645 1.1 cgd off_t newoff, \
646 1.1 cgd struct ucred *cred))) nullop)
647 1.1 cgd #define kernfs_remove ((int (*) __P(( \
648 1.1 cgd struct nameidata *ndp, \
649 1.1 cgd struct proc *p))) kernfs_enotsupp)
650 1.1 cgd #define kernfs_link ((int (*) __P(( \
651 1.1 cgd struct vnode *vp, \
652 1.1 cgd struct nameidata *ndp, \
653 1.1 cgd struct proc *p))) kernfs_enotsupp)
654 1.1 cgd #define kernfs_rename ((int (*) __P(( \
655 1.1 cgd struct nameidata *fndp, \
656 1.1 cgd struct nameidata *tdnp, \
657 1.1 cgd struct proc *p))) kernfs_enotsupp)
658 1.1 cgd #define kernfs_mkdir ((int (*) __P(( \
659 1.1 cgd struct nameidata *ndp, \
660 1.1 cgd struct vattr *vap, \
661 1.1 cgd struct proc *p))) kernfs_enotsupp)
662 1.1 cgd #define kernfs_rmdir ((int (*) __P(( \
663 1.1 cgd struct nameidata *ndp, \
664 1.1 cgd struct proc *p))) kernfs_enotsupp)
665 1.1 cgd #define kernfs_symlink ((int (*) __P(( \
666 1.1 cgd struct nameidata *ndp, \
667 1.1 cgd struct vattr *vap, \
668 1.1 cgd char *target, \
669 1.1 cgd struct proc *p))) kernfs_enotsupp)
670 1.1 cgd #define kernfs_readlink ((int (*) __P(( \
671 1.1 cgd struct vnode *vp, \
672 1.1 cgd struct uio *uio, \
673 1.1 cgd struct ucred *cred))) kernfs_enotsupp)
674 1.1 cgd #define kernfs_abortop ((int (*) __P(( \
675 1.1 cgd struct nameidata *ndp))) nullop)
676 1.1 cgd #ifdef KERNFS_DIAGNOSTIC
677 1.1 cgd int kernfs_reclaim(vp)
678 1.1 cgd struct vnode *vp;
679 1.1 cgd {
680 1.1 cgd printf("kernfs_reclaim(%x)\n", vp);
681 1.1 cgd return (0);
682 1.1 cgd }
683 1.1 cgd #else
684 1.1 cgd #define kernfs_reclaim ((int (*) __P(( \
685 1.1 cgd struct vnode *vp))) nullop)
686 1.1 cgd #endif
687 1.1 cgd #define kernfs_lock ((int (*) __P(( \
688 1.1 cgd struct vnode *vp))) nullop)
689 1.1 cgd #define kernfs_unlock ((int (*) __P(( \
690 1.1 cgd struct vnode *vp))) nullop)
691 1.1 cgd #define kernfs_bmap ((int (*) __P(( \
692 1.1 cgd struct vnode *vp, \
693 1.1 cgd daddr_t bn, \
694 1.1 cgd struct vnode **vpp, \
695 1.1 cgd daddr_t *bnp))) kernfs_badop)
696 1.1 cgd #define kernfs_strategy ((int (*) __P(( \
697 1.1 cgd struct buf *bp))) kernfs_badop)
698 1.1 cgd #define kernfs_islocked ((int (*) __P(( \
699 1.1 cgd struct vnode *vp))) nullop)
700 1.1 cgd #define kernfs_advlock ((int (*) __P(( \
701 1.1 cgd struct vnode *vp, \
702 1.1 cgd caddr_t id, \
703 1.1 cgd int op, \
704 1.1 cgd struct flock *fl, \
705 1.1 cgd int flags))) kernfs_enotsupp)
706 1.1 cgd
707 1.1 cgd struct vnodeops kernfs_vnodeops = {
708 1.1 cgd kernfs_lookup, /* lookup */
709 1.1 cgd kernfs_create, /* create */
710 1.1 cgd kernfs_mknod, /* mknod */
711 1.1 cgd kernfs_open, /* open */
712 1.1 cgd kernfs_close, /* close */
713 1.1 cgd kernfs_access, /* access */
714 1.1 cgd kernfs_getattr, /* getattr */
715 1.1 cgd kernfs_setattr, /* setattr */
716 1.1 cgd kernfs_read, /* read */
717 1.1 cgd kernfs_write, /* write */
718 1.1 cgd kernfs_ioctl, /* ioctl */
719 1.1 cgd kernfs_select, /* select */
720 1.1 cgd kernfs_mmap, /* mmap */
721 1.1 cgd kernfs_fsync, /* fsync */
722 1.1 cgd kernfs_seek, /* seek */
723 1.1 cgd kernfs_remove, /* remove */
724 1.1 cgd kernfs_link, /* link */
725 1.1 cgd kernfs_rename, /* rename */
726 1.1 cgd kernfs_mkdir, /* mkdir */
727 1.1 cgd kernfs_rmdir, /* rmdir */
728 1.1 cgd kernfs_symlink, /* symlink */
729 1.1 cgd kernfs_readdir, /* readdir */
730 1.1 cgd kernfs_readlink, /* readlink */
731 1.1 cgd kernfs_abortop, /* abortop */
732 1.1 cgd kernfs_inactive, /* inactive */
733 1.1 cgd kernfs_reclaim, /* reclaim */
734 1.1 cgd kernfs_lock, /* lock */
735 1.1 cgd kernfs_unlock, /* unlock */
736 1.1 cgd kernfs_bmap, /* bmap */
737 1.1 cgd kernfs_strategy, /* strategy */
738 1.1 cgd kernfs_print, /* print */
739 1.1 cgd kernfs_islocked, /* islocked */
740 1.1 cgd kernfs_advlock, /* advlock */
741 1.1 cgd };
742