23 */
24
25 /*
26 * vnode ops for the /dev/vt directory
27 */
28
29 #include <sys/types.h>
30 #include <sys/param.h>
31 #include <sys/sysmacros.h>
32 #include <sys/sunndi.h>
33 #include <fs/fs_subr.h>
34 #include <sys/fs/dv_node.h>
35 #include <sys/fs/sdev_impl.h>
36 #include <sys/policy.h>
37 #include <sys/stat.h>
38 #include <sys/vfs_opreg.h>
39 #include <sys/tty.h>
40 #include <sys/vt_impl.h>
41 #include <sys/note.h>
42
43 /* warlock in this file only cares about variables shared by vt and devfs */
44 _NOTE(SCHEME_PROTECTS_DATA("Do not care", sdev_node vattr vnode))
45
46 #define DEVVT_UID_DEFAULT SDEV_UID_DEFAULT
47 #define DEVVT_GID_DEFAULT (0)
48 #define DEVVT_DEVMODE_DEFAULT (0600)
49 #define DEVVT_ACTIVE_NAME "active"
50 #define DEVVT_CONSUSER_NAME "console_user"
51
52 #define isdigit(ch) ((ch) >= '0' && (ch) <= '9')
53
54 /* attributes for VT nodes */
55 static vattr_t devvt_vattr = {
56 AT_TYPE|AT_MODE|AT_UID|AT_GID, /* va_mask */
57 VCHR, /* va_type */
58 S_IFCHR | DEVVT_DEVMODE_DEFAULT, /* va_mode */
59 DEVVT_UID_DEFAULT, /* va_uid */
60 DEVVT_GID_DEFAULT, /* va_gid */
61 0 /* 0 hereafter */
62 };
63
64 struct vnodeops *devvt_vnodeops;
65
180 }
181
182 /*ARGSUSED3*/
183 static int
184 devvt_lookup(struct vnode *dvp, char *nm, struct vnode **vpp,
185 struct pathname *pnp, int flags, struct vnode *rdir, struct cred *cred,
186 caller_context_t *ct, int *direntflags, pathname_t *realpnp)
187 {
188 struct sdev_node *sdvp = VTOSDEV(dvp);
189 struct sdev_node *dv;
190 struct vnode *rvp = NULL;
191 int type, error;
192
193 if ((strcmp(nm, DEVVT_ACTIVE_NAME) == 0) ||
194 (strcmp(nm, DEVVT_CONSUSER_NAME) == 0)) {
195 type = SDEV_VLINK;
196 } else {
197 type = SDEV_VATTR;
198 }
199
200 /* Give warlock a more clear call graph */
201 #ifndef __lock_lint
202 error = devname_lookup_func(sdvp, nm, vpp, cred,
203 devvt_create_rvp, type);
204 #else
205 devvt_create_rvp(0, 0, 0, 0, 0, 0);
206 #endif
207
208 if (error == 0) {
209 switch ((*vpp)->v_type) {
210 case VCHR:
211 dv = VTOSDEV(VTOS(*vpp)->s_realvp);
212 ASSERT(VOP_REALVP(SDEVTOV(dv), &rvp, NULL) == ENOSYS);
213 break;
214 case VDIR:
215 case VLNK:
216 dv = VTOSDEV(*vpp);
217 break;
218 default:
219 cmn_err(CE_PANIC, "devvt_lookup: Unsupported node "
220 "type: %p: %d", (void *)(*vpp), (*vpp)->v_type);
221 break;
222 }
223 ASSERT(SDEV_HELD(dv));
224 }
225
226 return (error);
345 break;
346 case SDEV_VTOR_STALE:
347 devvt_rebuild_stale_link(ddv, dv);
348 break;
349 }
350 }
351 }
352
353 static void
354 devvt_cleandir(struct vnode *dvp, struct cred *cred)
355 {
356 struct sdev_node *sdvp = VTOSDEV(dvp);
357 struct sdev_node *dv, *next = NULL;
358 int min, cnt;
359 char found = 0;
360
361 mutex_enter(&vc_lock);
362 cnt = VC_INSTANCES_COUNT;
363 mutex_exit(&vc_lock);
364
365 /* We have to fool warlock this way, otherwise it will complain */
366 #ifndef __lock_lint
367 if (rw_tryupgrade(&sdvp->sdev_contents) == NULL) {
368 rw_exit(&sdvp->sdev_contents);
369 rw_enter(&sdvp->sdev_contents, RW_WRITER);
370 }
371 #else
372 rw_enter(&sdvp->sdev_contents, RW_WRITER);
373 #endif
374
375 /* 1. prune invalid nodes and rebuild stale symlinks */
376 devvt_prunedir(sdvp);
377
378 /* 2. create missing nodes */
379 for (min = 0; min < cnt; min++) {
380 char nm[16];
381
382 if (vt_minor_valid(min) == B_FALSE)
383 continue;
384
385 (void) snprintf(nm, sizeof (nm), "%d", min);
386 found = 0;
387 for (dv = SDEV_FIRST_ENTRY(sdvp); dv; dv = next) {
388 next = SDEV_NEXT_ENTRY(sdvp, dv);
389
390 /* validate only ready nodes */
391 if (dv->sdev_state != SDEV_READY)
392 continue;
393 if (strcmp(nm, dv->sdev_name) == 0) {
404 found = 0;
405 for (dv = SDEV_FIRST_ENTRY(sdvp); dv; dv = next) {
406 next = SDEV_NEXT_ENTRY(sdvp, dv);
407
408 /* validate only ready nodes */
409 if (dv->sdev_state != SDEV_READY)
410 continue;
411 if ((strcmp(dv->sdev_name, DEVVT_ACTIVE_NAME) == NULL))
412 found |= 0x01;
413 if ((strcmp(dv->sdev_name, DEVVT_CONSUSER_NAME) == NULL))
414 found |= 0x02;
415
416 if ((found & 0x01) && (found & 0x02))
417 break;
418 }
419 if (!(found & 0x01))
420 devvt_create_snode(sdvp, DEVVT_ACTIVE_NAME, cred, SDEV_VLINK);
421 if (!(found & 0x02))
422 devvt_create_snode(sdvp, DEVVT_CONSUSER_NAME, cred, SDEV_VLINK);
423
424 #ifndef __lock_lint
425 rw_downgrade(&sdvp->sdev_contents);
426 #else
427 rw_exit(&sdvp->sdev_contents);
428 #endif
429 }
430
431 /*ARGSUSED4*/
432 static int
433 devvt_readdir(struct vnode *dvp, struct uio *uiop, struct cred *cred,
434 int *eofp, caller_context_t *ct, int flags)
435 {
436 if (uiop->uio_offset == 0) {
437 devvt_cleandir(dvp, cred);
438 }
439
440 return (devname_readdir_func(dvp, uiop, cred, eofp, 0));
441 }
442
443 /*
444 * We allow create to find existing nodes
445 * - if the node doesn't exist - EROFS
446 * - creating an existing dir read-only succeeds, otherwise EISDIR
447 * - exclusive creates fail - EEXIST
448 */
|
23 */
24
25 /*
26 * vnode ops for the /dev/vt directory
27 */
28
29 #include <sys/types.h>
30 #include <sys/param.h>
31 #include <sys/sysmacros.h>
32 #include <sys/sunndi.h>
33 #include <fs/fs_subr.h>
34 #include <sys/fs/dv_node.h>
35 #include <sys/fs/sdev_impl.h>
36 #include <sys/policy.h>
37 #include <sys/stat.h>
38 #include <sys/vfs_opreg.h>
39 #include <sys/tty.h>
40 #include <sys/vt_impl.h>
41 #include <sys/note.h>
42
43 #define DEVVT_UID_DEFAULT SDEV_UID_DEFAULT
44 #define DEVVT_GID_DEFAULT (0)
45 #define DEVVT_DEVMODE_DEFAULT (0600)
46 #define DEVVT_ACTIVE_NAME "active"
47 #define DEVVT_CONSUSER_NAME "console_user"
48
49 #define isdigit(ch) ((ch) >= '0' && (ch) <= '9')
50
51 /* attributes for VT nodes */
52 static vattr_t devvt_vattr = {
53 AT_TYPE|AT_MODE|AT_UID|AT_GID, /* va_mask */
54 VCHR, /* va_type */
55 S_IFCHR | DEVVT_DEVMODE_DEFAULT, /* va_mode */
56 DEVVT_UID_DEFAULT, /* va_uid */
57 DEVVT_GID_DEFAULT, /* va_gid */
58 0 /* 0 hereafter */
59 };
60
61 struct vnodeops *devvt_vnodeops;
62
177 }
178
179 /*ARGSUSED3*/
180 static int
181 devvt_lookup(struct vnode *dvp, char *nm, struct vnode **vpp,
182 struct pathname *pnp, int flags, struct vnode *rdir, struct cred *cred,
183 caller_context_t *ct, int *direntflags, pathname_t *realpnp)
184 {
185 struct sdev_node *sdvp = VTOSDEV(dvp);
186 struct sdev_node *dv;
187 struct vnode *rvp = NULL;
188 int type, error;
189
190 if ((strcmp(nm, DEVVT_ACTIVE_NAME) == 0) ||
191 (strcmp(nm, DEVVT_CONSUSER_NAME) == 0)) {
192 type = SDEV_VLINK;
193 } else {
194 type = SDEV_VATTR;
195 }
196
197 error = devname_lookup_func(sdvp, nm, vpp, cred,
198 devvt_create_rvp, type);
199
200 if (error == 0) {
201 switch ((*vpp)->v_type) {
202 case VCHR:
203 dv = VTOSDEV(VTOS(*vpp)->s_realvp);
204 ASSERT(VOP_REALVP(SDEVTOV(dv), &rvp, NULL) == ENOSYS);
205 break;
206 case VDIR:
207 case VLNK:
208 dv = VTOSDEV(*vpp);
209 break;
210 default:
211 cmn_err(CE_PANIC, "devvt_lookup: Unsupported node "
212 "type: %p: %d", (void *)(*vpp), (*vpp)->v_type);
213 break;
214 }
215 ASSERT(SDEV_HELD(dv));
216 }
217
218 return (error);
337 break;
338 case SDEV_VTOR_STALE:
339 devvt_rebuild_stale_link(ddv, dv);
340 break;
341 }
342 }
343 }
344
345 static void
346 devvt_cleandir(struct vnode *dvp, struct cred *cred)
347 {
348 struct sdev_node *sdvp = VTOSDEV(dvp);
349 struct sdev_node *dv, *next = NULL;
350 int min, cnt;
351 char found = 0;
352
353 mutex_enter(&vc_lock);
354 cnt = VC_INSTANCES_COUNT;
355 mutex_exit(&vc_lock);
356
357 if (rw_tryupgrade(&sdvp->sdev_contents) == NULL) {
358 rw_exit(&sdvp->sdev_contents);
359 rw_enter(&sdvp->sdev_contents, RW_WRITER);
360 }
361
362 /* 1. prune invalid nodes and rebuild stale symlinks */
363 devvt_prunedir(sdvp);
364
365 /* 2. create missing nodes */
366 for (min = 0; min < cnt; min++) {
367 char nm[16];
368
369 if (vt_minor_valid(min) == B_FALSE)
370 continue;
371
372 (void) snprintf(nm, sizeof (nm), "%d", min);
373 found = 0;
374 for (dv = SDEV_FIRST_ENTRY(sdvp); dv; dv = next) {
375 next = SDEV_NEXT_ENTRY(sdvp, dv);
376
377 /* validate only ready nodes */
378 if (dv->sdev_state != SDEV_READY)
379 continue;
380 if (strcmp(nm, dv->sdev_name) == 0) {
391 found = 0;
392 for (dv = SDEV_FIRST_ENTRY(sdvp); dv; dv = next) {
393 next = SDEV_NEXT_ENTRY(sdvp, dv);
394
395 /* validate only ready nodes */
396 if (dv->sdev_state != SDEV_READY)
397 continue;
398 if ((strcmp(dv->sdev_name, DEVVT_ACTIVE_NAME) == NULL))
399 found |= 0x01;
400 if ((strcmp(dv->sdev_name, DEVVT_CONSUSER_NAME) == NULL))
401 found |= 0x02;
402
403 if ((found & 0x01) && (found & 0x02))
404 break;
405 }
406 if (!(found & 0x01))
407 devvt_create_snode(sdvp, DEVVT_ACTIVE_NAME, cred, SDEV_VLINK);
408 if (!(found & 0x02))
409 devvt_create_snode(sdvp, DEVVT_CONSUSER_NAME, cred, SDEV_VLINK);
410
411 rw_downgrade(&sdvp->sdev_contents);
412 }
413
414 /*ARGSUSED4*/
415 static int
416 devvt_readdir(struct vnode *dvp, struct uio *uiop, struct cred *cred,
417 int *eofp, caller_context_t *ct, int flags)
418 {
419 if (uiop->uio_offset == 0) {
420 devvt_cleandir(dvp, cred);
421 }
422
423 return (devname_readdir_func(dvp, uiop, cred, eofp, 0));
424 }
425
426 /*
427 * We allow create to find existing nodes
428 * - if the node doesn't exist - EROFS
429 * - creating an existing dir read-only succeeds, otherwise EISDIR
430 * - exclusive creates fail - EEXIST
431 */
|