1 #define DEBUG 1 2 /* 3 * Copyright (c) 2000 4 * Poul-Henning Kamp. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Neither the name of the University nor the names of its contributors 12 * may be used to endorse or promote products derived from this software 13 * without specific prior written permission. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * From: FreeBSD: src/sys/miscfs/kernfs/kernfs_vfsops.c 1.36 28 * 29 * $FreeBSD$ 30 */ 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/kernel.h> 35 #include <sys/dirent.h> 36 #include <sys/conf.h> 37 #include <sys/proc.h> 38 #include <sys/vnode.h> 39 #include <sys/mount.h> 40 #include <sys/malloc.h> 41 #include <sys/eventhandler.h> 42 #include <sys/ctype.h> 43 44 #define DEVFS_INTERN 45 #include <fs/devfs/devfs.h> 46 47 struct devfs_dirent * 48 devfs_newdirent(char *name, int namelen) 49 { 50 int i; 51 struct devfs_dirent *de; 52 struct dirent d; 53 54 d.d_namlen = namelen; 55 i = sizeof (*de) + GENERIC_DIRSIZ(&d); 56 MALLOC(de, struct devfs_dirent *, i, M_DEVFS, M_WAITOK); 57 bzero(de, i); 58 de->de_dirent = (struct dirent *)(de + 1); 59 de->de_dirent->d_namlen = namelen; 60 de->de_dirent->d_reclen = GENERIC_DIRSIZ(&d); 61 bcopy(name, de->de_dirent->d_name, namelen + 1); 62 nanotime(&de->de_ctime); 63 return (de); 64 } 65 66 struct devfs_dir * 67 devfs_vmkdir(void) 68 { 69 struct devfs_dir *dd; 70 struct devfs_dirent *de; 71 72 MALLOC(dd, struct devfs_dir *, sizeof(*dd), M_DEVFS, M_WAITOK); 73 bzero(dd, sizeof(*dd)); 74 TAILQ_INIT(&dd->dd_list); 75 76 de = devfs_newdirent(".", 1); 77 de->de_dirent->d_type = DT_DIR; 78 TAILQ_INSERT_TAIL(&dd->dd_list, de, de_list); 79 de = TAILQ_FIRST(&dd->dd_list); 80 de->de_mode = 0755; 81 return (dd); 82 } 83 84 void 85 devfs_delete(struct devfs_dir *dd, struct devfs_dirent *de) 86 { 87 88 if (de->de_symlink) { 89 FREE(de->de_symlink, M_DEVFS); 90 de->de_symlink = NULL; 91 } 92 if (de->de_vnode) { 93 de->de_vnode->v_data = NULL; 94 vdrop(de->de_vnode); 95 } 96 TAILQ_REMOVE(&dd->dd_list, de, de_list); 97 FREE(de, M_DEVFS); 98 } 99 100 void 101 devfs_purge(struct devfs_dir *dd) 102 { 103 struct devfs_dirent *de; 104 105 for (;;) { 106 de = TAILQ_FIRST(&dd->dd_list); 107 if (de == NULL) 108 break; 109 devfs_delete(dd, de); 110 } 111 FREE(dd, M_DEVFS); 112 } 113 114 115 int 116 devfs_populate(struct devfs_mount *dm) 117 { 118 int i, j; 119 dev_t dev, pdev; 120 struct devfs_dir *dd; 121 struct devfs_dirent *de; 122 char *q, *s; 123 124 while (dm->dm_generation != devfs_generation) { 125 dm->dm_generation = devfs_generation; 126 for (i = 0; i < NDEVINO; i++) { 127 dev = devfs_inot[i]; 128 de = dm->dm_dirent[i]; 129 if (dev == NULL && de != NULL) { 130 #if 0 131 printf("Del ino%d %s\n", i, de->de_dirent->d_name); 132 #endif 133 dd = de->de_dir; 134 dm->dm_dirent[i] = NULL; 135 TAILQ_REMOVE(&dd->dd_list, de, de_list); 136 if (de->de_vnode) { 137 de->de_vnode->v_data = NULL; 138 vdrop(de->de_vnode); 139 } 140 FREE(de, M_DEVFS); 141 continue; 142 } 143 if (dev == NULL) 144 continue; 145 if (de != NULL) 146 continue; 147 dd = dm->dm_basedir; 148 s = dev->si_name; 149 for (q = s; *q != '/' && *q != '\0'; q++) 150 continue; 151 if (*q == '/') { 152 continue; 153 } 154 de = devfs_newdirent(s, q - s); 155 if (dev->si_flags & SI_ALIAS) { 156 de->de_inode = dm->dm_inode++; 157 de->de_uid = 0; 158 de->de_gid = 0; 159 de->de_mode = 0642; 160 de->de_dirent->d_type = DT_LNK; 161 pdev = dev->si_drv1; 162 j = strlen(pdev->si_name) + 1; 163 MALLOC(de->de_symlink, char *, j, M_DEVFS, M_WAITOK); 164 bcopy(pdev->si_name, de->de_symlink, j); 165 } else { 166 de->de_inode = i; 167 de->de_uid = dev->si_uid; 168 de->de_gid = dev->si_gid; 169 de->de_mode = dev->si_mode; 170 de->de_dirent->d_type = DT_CHR; 171 dm->dm_dirent[i] = de; 172 } 173 TAILQ_INSERT_TAIL(&dd->dd_list, de, de_list); 174 #if 0 175 printf("Add ino%d %s\n", i, dev->si_name); 176 #endif 177 } 178 } 179 return (0); 180 } 181 182 dev_t devfs_inot[NDEVINO]; 183 int devfs_nino = 3; 184 unsigned devfs_generation; 185 186 static void 187 devfs_create(dev_t dev) 188 { 189 if (dev->si_inode == 0 && devfs_nino < NDEVINO) 190 dev->si_inode = devfs_nino++; 191 if (dev->si_inode == 0) { 192 printf("NDEVINO too small\n"); 193 return; 194 } 195 devfs_inot[dev->si_inode] = dev; 196 devfs_generation++; 197 } 198 199 static void 200 devfs_remove(dev_t dev) 201 { 202 devfs_inot[dev->si_inode] = NULL; 203 devfs_generation++; 204 } 205 206 devfs_create_t *devfs_create_hook = devfs_create; 207 devfs_remove_t *devfs_remove_hook = devfs_remove; 208 209 int 210 devfs_stdclone(char *name, char **namep, char *stem, int *unit) 211 { 212 int u, i; 213 214 if (bcmp(stem, name, strlen(stem)) != 0) 215 return (0); 216 i = strlen(stem); 217 if (!isdigit(name[i])) 218 return (0); 219 u = 0; 220 while (isdigit(name[i])) { 221 u *= 10; 222 u += name[i++] - '0'; 223 } 224 *unit = u; 225 if (namep) 226 *namep = &name[i]; 227 if (name[i]) 228 return (2); 229 return (1); 230 } 231