xref: /freebsd/sys/fs/devfs/devfs_devs.c (revision 3f54a085a603b050163611ce23972ee8de7636f1)
13f54a085SPoul-Henning Kamp #define DEBUG 1
23f54a085SPoul-Henning Kamp /*
33f54a085SPoul-Henning Kamp  * Copyright (c) 2000
43f54a085SPoul-Henning Kamp  *	Poul-Henning Kamp.  All rights reserved.
53f54a085SPoul-Henning Kamp  *
63f54a085SPoul-Henning Kamp  * Redistribution and use in source and binary forms, with or without
73f54a085SPoul-Henning Kamp  * modification, are permitted provided that the following conditions
83f54a085SPoul-Henning Kamp  * are met:
93f54a085SPoul-Henning Kamp  * 1. Redistributions of source code must retain the above copyright
103f54a085SPoul-Henning Kamp  *    notice, this list of conditions and the following disclaimer.
113f54a085SPoul-Henning Kamp  * 2. Neither the name of the University nor the names of its contributors
123f54a085SPoul-Henning Kamp  *    may be used to endorse or promote products derived from this software
133f54a085SPoul-Henning Kamp  *    without specific prior written permission.
143f54a085SPoul-Henning Kamp  *
153f54a085SPoul-Henning Kamp  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
163f54a085SPoul-Henning Kamp  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
173f54a085SPoul-Henning Kamp  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
183f54a085SPoul-Henning Kamp  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
193f54a085SPoul-Henning Kamp  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
203f54a085SPoul-Henning Kamp  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
213f54a085SPoul-Henning Kamp  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
223f54a085SPoul-Henning Kamp  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
233f54a085SPoul-Henning Kamp  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
243f54a085SPoul-Henning Kamp  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
253f54a085SPoul-Henning Kamp  * SUCH DAMAGE.
263f54a085SPoul-Henning Kamp  *
273f54a085SPoul-Henning Kamp  * From: FreeBSD: src/sys/miscfs/kernfs/kernfs_vfsops.c 1.36
283f54a085SPoul-Henning Kamp  *
293f54a085SPoul-Henning Kamp  * $FreeBSD$
303f54a085SPoul-Henning Kamp  */
313f54a085SPoul-Henning Kamp 
323f54a085SPoul-Henning Kamp #include <sys/param.h>
333f54a085SPoul-Henning Kamp #include <sys/systm.h>
343f54a085SPoul-Henning Kamp #include <sys/kernel.h>
353f54a085SPoul-Henning Kamp #include <sys/dirent.h>
363f54a085SPoul-Henning Kamp #include <sys/conf.h>
373f54a085SPoul-Henning Kamp #include <sys/proc.h>
383f54a085SPoul-Henning Kamp #include <sys/vnode.h>
393f54a085SPoul-Henning Kamp #include <sys/mount.h>
403f54a085SPoul-Henning Kamp #include <sys/malloc.h>
413f54a085SPoul-Henning Kamp #include <sys/eventhandler.h>
423f54a085SPoul-Henning Kamp #include <sys/ctype.h>
433f54a085SPoul-Henning Kamp 
443f54a085SPoul-Henning Kamp #define DEVFS_INTERN
453f54a085SPoul-Henning Kamp #include <fs/devfs/devfs.h>
463f54a085SPoul-Henning Kamp 
473f54a085SPoul-Henning Kamp struct devfs_dirent *
483f54a085SPoul-Henning Kamp devfs_newdirent(char *name, int namelen)
493f54a085SPoul-Henning Kamp {
503f54a085SPoul-Henning Kamp 	int i;
513f54a085SPoul-Henning Kamp 	struct devfs_dirent *de;
523f54a085SPoul-Henning Kamp 	struct dirent d;
533f54a085SPoul-Henning Kamp 
543f54a085SPoul-Henning Kamp 	d.d_namlen = namelen;
553f54a085SPoul-Henning Kamp 	i = sizeof (*de) + GENERIC_DIRSIZ(&d);
563f54a085SPoul-Henning Kamp 	MALLOC(de, struct devfs_dirent *, i, M_DEVFS, M_WAITOK);
573f54a085SPoul-Henning Kamp 	bzero(de, i);
583f54a085SPoul-Henning Kamp 	de->de_dirent = (struct dirent *)(de + 1);
593f54a085SPoul-Henning Kamp 	de->de_dirent->d_namlen = namelen;
603f54a085SPoul-Henning Kamp 	de->de_dirent->d_reclen = GENERIC_DIRSIZ(&d);
613f54a085SPoul-Henning Kamp 	bcopy(name, de->de_dirent->d_name, namelen + 1);
623f54a085SPoul-Henning Kamp 	nanotime(&de->de_ctime);
633f54a085SPoul-Henning Kamp 	return (de);
643f54a085SPoul-Henning Kamp }
653f54a085SPoul-Henning Kamp 
663f54a085SPoul-Henning Kamp struct devfs_dir *
673f54a085SPoul-Henning Kamp devfs_vmkdir(void)
683f54a085SPoul-Henning Kamp {
693f54a085SPoul-Henning Kamp 	struct devfs_dir *dd;
703f54a085SPoul-Henning Kamp 	struct devfs_dirent *de;
713f54a085SPoul-Henning Kamp 
723f54a085SPoul-Henning Kamp 	MALLOC(dd, struct devfs_dir *, sizeof(*dd), M_DEVFS, M_WAITOK);
733f54a085SPoul-Henning Kamp 	bzero(dd, sizeof(*dd));
743f54a085SPoul-Henning Kamp 	TAILQ_INIT(&dd->dd_list);
753f54a085SPoul-Henning Kamp 
763f54a085SPoul-Henning Kamp 	de = devfs_newdirent(".", 1);
773f54a085SPoul-Henning Kamp 	de->de_dirent->d_type = DT_DIR;
783f54a085SPoul-Henning Kamp 	TAILQ_INSERT_TAIL(&dd->dd_list, de, de_list);
793f54a085SPoul-Henning Kamp 	de = TAILQ_FIRST(&dd->dd_list);
803f54a085SPoul-Henning Kamp 	de->de_mode = 0755;
813f54a085SPoul-Henning Kamp 	return (dd);
823f54a085SPoul-Henning Kamp }
833f54a085SPoul-Henning Kamp 
843f54a085SPoul-Henning Kamp void
853f54a085SPoul-Henning Kamp devfs_delete(struct devfs_dir *dd, struct devfs_dirent *de)
863f54a085SPoul-Henning Kamp {
873f54a085SPoul-Henning Kamp 
883f54a085SPoul-Henning Kamp 	if (de->de_symlink) {
893f54a085SPoul-Henning Kamp 		FREE(de->de_symlink, M_DEVFS);
903f54a085SPoul-Henning Kamp 		de->de_symlink = NULL;
913f54a085SPoul-Henning Kamp 	}
923f54a085SPoul-Henning Kamp 	if (de->de_vnode) {
933f54a085SPoul-Henning Kamp 		de->de_vnode->v_data = NULL;
943f54a085SPoul-Henning Kamp 		vdrop(de->de_vnode);
953f54a085SPoul-Henning Kamp 	}
963f54a085SPoul-Henning Kamp 	TAILQ_REMOVE(&dd->dd_list, de, de_list);
973f54a085SPoul-Henning Kamp 	FREE(de, M_DEVFS);
983f54a085SPoul-Henning Kamp }
993f54a085SPoul-Henning Kamp 
1003f54a085SPoul-Henning Kamp void
1013f54a085SPoul-Henning Kamp devfs_purge(struct devfs_dir *dd)
1023f54a085SPoul-Henning Kamp {
1033f54a085SPoul-Henning Kamp 	struct devfs_dirent *de;
1043f54a085SPoul-Henning Kamp 
1053f54a085SPoul-Henning Kamp 	for (;;) {
1063f54a085SPoul-Henning Kamp 		de = TAILQ_FIRST(&dd->dd_list);
1073f54a085SPoul-Henning Kamp 		if (de == NULL)
1083f54a085SPoul-Henning Kamp 			break;
1093f54a085SPoul-Henning Kamp 		devfs_delete(dd, de);
1103f54a085SPoul-Henning Kamp 	}
1113f54a085SPoul-Henning Kamp 	FREE(dd, M_DEVFS);
1123f54a085SPoul-Henning Kamp }
1133f54a085SPoul-Henning Kamp 
1143f54a085SPoul-Henning Kamp 
1153f54a085SPoul-Henning Kamp int
1163f54a085SPoul-Henning Kamp devfs_populate(struct devfs_mount *dm)
1173f54a085SPoul-Henning Kamp {
1183f54a085SPoul-Henning Kamp 	int i, j;
1193f54a085SPoul-Henning Kamp 	dev_t dev, pdev;
1203f54a085SPoul-Henning Kamp 	struct devfs_dir *dd;
1213f54a085SPoul-Henning Kamp 	struct devfs_dirent *de;
1223f54a085SPoul-Henning Kamp 	char *q, *s;
1233f54a085SPoul-Henning Kamp 
1243f54a085SPoul-Henning Kamp 	while (dm->dm_generation != devfs_generation) {
1253f54a085SPoul-Henning Kamp 		dm->dm_generation = devfs_generation;
1263f54a085SPoul-Henning Kamp 		for (i = 0; i < NDEVINO; i++) {
1273f54a085SPoul-Henning Kamp 			dev = devfs_inot[i];
1283f54a085SPoul-Henning Kamp 			de = dm->dm_dirent[i];
1293f54a085SPoul-Henning Kamp 			if (dev == NULL && de != NULL) {
1303f54a085SPoul-Henning Kamp #if 0
1313f54a085SPoul-Henning Kamp 				printf("Del ino%d %s\n", i, de->de_dirent->d_name);
1323f54a085SPoul-Henning Kamp #endif
1333f54a085SPoul-Henning Kamp 				dd = de->de_dir;
1343f54a085SPoul-Henning Kamp 				dm->dm_dirent[i] = NULL;
1353f54a085SPoul-Henning Kamp 				TAILQ_REMOVE(&dd->dd_list, de, de_list);
1363f54a085SPoul-Henning Kamp 				if (de->de_vnode) {
1373f54a085SPoul-Henning Kamp 					de->de_vnode->v_data = NULL;
1383f54a085SPoul-Henning Kamp 					vdrop(de->de_vnode);
1393f54a085SPoul-Henning Kamp 				}
1403f54a085SPoul-Henning Kamp 				FREE(de, M_DEVFS);
1413f54a085SPoul-Henning Kamp 				continue;
1423f54a085SPoul-Henning Kamp 			}
1433f54a085SPoul-Henning Kamp 			if (dev == NULL)
1443f54a085SPoul-Henning Kamp 				continue;
1453f54a085SPoul-Henning Kamp 			if (de != NULL)
1463f54a085SPoul-Henning Kamp 				continue;
1473f54a085SPoul-Henning Kamp 			dd = dm->dm_basedir;
1483f54a085SPoul-Henning Kamp 			s = dev->si_name;
1493f54a085SPoul-Henning Kamp 			for (q = s; *q != '/' && *q != '\0'; q++)
1503f54a085SPoul-Henning Kamp 				continue;
1513f54a085SPoul-Henning Kamp 			if (*q == '/') {
1523f54a085SPoul-Henning Kamp 				continue;
1533f54a085SPoul-Henning Kamp 			}
1543f54a085SPoul-Henning Kamp 			de = devfs_newdirent(s, q - s);
1553f54a085SPoul-Henning Kamp 			if (dev->si_flags & SI_ALIAS) {
1563f54a085SPoul-Henning Kamp 				de->de_inode = dm->dm_inode++;
1573f54a085SPoul-Henning Kamp 				de->de_uid = 0;
1583f54a085SPoul-Henning Kamp 				de->de_gid = 0;
1593f54a085SPoul-Henning Kamp 				de->de_mode = 0642;
1603f54a085SPoul-Henning Kamp 				de->de_dirent->d_type = DT_LNK;
1613f54a085SPoul-Henning Kamp 				pdev = dev->si_drv1;
1623f54a085SPoul-Henning Kamp 				j = strlen(pdev->si_name) + 1;
1633f54a085SPoul-Henning Kamp 				MALLOC(de->de_symlink, char *, j, M_DEVFS, M_WAITOK);
1643f54a085SPoul-Henning Kamp 				bcopy(pdev->si_name, de->de_symlink, j);
1653f54a085SPoul-Henning Kamp 			} else {
1663f54a085SPoul-Henning Kamp 				de->de_inode = i;
1673f54a085SPoul-Henning Kamp 				de->de_uid = dev->si_uid;
1683f54a085SPoul-Henning Kamp 				de->de_gid = dev->si_gid;
1693f54a085SPoul-Henning Kamp 				de->de_mode = dev->si_mode;
1703f54a085SPoul-Henning Kamp 				de->de_dirent->d_type = DT_CHR;
1713f54a085SPoul-Henning Kamp 				dm->dm_dirent[i] = de;
1723f54a085SPoul-Henning Kamp 			}
1733f54a085SPoul-Henning Kamp 			TAILQ_INSERT_TAIL(&dd->dd_list, de, de_list);
1743f54a085SPoul-Henning Kamp #if 0
1753f54a085SPoul-Henning Kamp 			printf("Add ino%d %s\n", i, dev->si_name);
1763f54a085SPoul-Henning Kamp #endif
1773f54a085SPoul-Henning Kamp 		}
1783f54a085SPoul-Henning Kamp 	}
1793f54a085SPoul-Henning Kamp 	return (0);
1803f54a085SPoul-Henning Kamp }
1813f54a085SPoul-Henning Kamp 
1823f54a085SPoul-Henning Kamp dev_t devfs_inot[NDEVINO];
1833f54a085SPoul-Henning Kamp int devfs_nino = 3;
1843f54a085SPoul-Henning Kamp unsigned devfs_generation;
1853f54a085SPoul-Henning Kamp 
1863f54a085SPoul-Henning Kamp static void
1873f54a085SPoul-Henning Kamp devfs_create(dev_t dev)
1883f54a085SPoul-Henning Kamp {
1893f54a085SPoul-Henning Kamp 	if (dev->si_inode == 0 && devfs_nino < NDEVINO)
1903f54a085SPoul-Henning Kamp 		dev->si_inode = devfs_nino++;
1913f54a085SPoul-Henning Kamp 	if (dev->si_inode == 0) {
1923f54a085SPoul-Henning Kamp 		printf("NDEVINO too small\n");
1933f54a085SPoul-Henning Kamp 		return;
1943f54a085SPoul-Henning Kamp 	}
1953f54a085SPoul-Henning Kamp 	devfs_inot[dev->si_inode] = dev;
1963f54a085SPoul-Henning Kamp 	devfs_generation++;
1973f54a085SPoul-Henning Kamp }
1983f54a085SPoul-Henning Kamp 
1993f54a085SPoul-Henning Kamp static void
2003f54a085SPoul-Henning Kamp devfs_remove(dev_t dev)
2013f54a085SPoul-Henning Kamp {
2023f54a085SPoul-Henning Kamp 	devfs_inot[dev->si_inode] = NULL;
2033f54a085SPoul-Henning Kamp 	devfs_generation++;
2043f54a085SPoul-Henning Kamp }
2053f54a085SPoul-Henning Kamp 
2063f54a085SPoul-Henning Kamp devfs_create_t *devfs_create_hook = devfs_create;
2073f54a085SPoul-Henning Kamp devfs_remove_t *devfs_remove_hook = devfs_remove;
2083f54a085SPoul-Henning Kamp 
2093f54a085SPoul-Henning Kamp int
2103f54a085SPoul-Henning Kamp devfs_stdclone(char *name, char **namep, char *stem, int *unit)
2113f54a085SPoul-Henning Kamp {
2123f54a085SPoul-Henning Kamp 	int u, i;
2133f54a085SPoul-Henning Kamp 
2143f54a085SPoul-Henning Kamp 	if (bcmp(stem, name, strlen(stem)) != 0)
2153f54a085SPoul-Henning Kamp 		return (0);
2163f54a085SPoul-Henning Kamp 	i = strlen(stem);
2173f54a085SPoul-Henning Kamp 	if (!isdigit(name[i]))
2183f54a085SPoul-Henning Kamp 		return (0);
2193f54a085SPoul-Henning Kamp 	u = 0;
2203f54a085SPoul-Henning Kamp 	while (isdigit(name[i])) {
2213f54a085SPoul-Henning Kamp 		u *= 10;
2223f54a085SPoul-Henning Kamp 		u += name[i++] - '0';
2233f54a085SPoul-Henning Kamp 	}
2243f54a085SPoul-Henning Kamp 	*unit = u;
2253f54a085SPoul-Henning Kamp 	if (namep)
2263f54a085SPoul-Henning Kamp 		*namep = &name[i];
2273f54a085SPoul-Henning Kamp 	if (name[i])
2283f54a085SPoul-Henning Kamp 		return (2);
2293f54a085SPoul-Henning Kamp 	return (1);
2303f54a085SPoul-Henning Kamp }
231