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/dirent.h> 35 #include <sys/conf.h> 36 #include <sys/vnode.h> 37 #include <sys/malloc.h> 38 #include <sys/eventhandler.h> 39 #include <sys/ctype.h> 40 41 #define DEVFS_INTERN 42 #include <fs/devfs/devfs.h> 43 44 struct devfs_dirent * 45 devfs_newdirent(char *name, int namelen) 46 { 47 int i; 48 struct devfs_dirent *de; 49 struct dirent d; 50 51 d.d_namlen = namelen; 52 i = sizeof (*de) + GENERIC_DIRSIZ(&d); 53 MALLOC(de, struct devfs_dirent *, i, M_DEVFS, M_WAITOK); 54 bzero(de, i); 55 de->de_dirent = (struct dirent *)(de + 1); 56 de->de_dirent->d_namlen = namelen; 57 de->de_dirent->d_reclen = GENERIC_DIRSIZ(&d); 58 bcopy(name, de->de_dirent->d_name, namelen + 1); 59 nanotime(&de->de_ctime); 60 return (de); 61 } 62 63 struct devfs_dir * 64 devfs_vmkdir(void) 65 { 66 struct devfs_dir *dd; 67 struct devfs_dirent *de; 68 69 MALLOC(dd, struct devfs_dir *, sizeof(*dd), M_DEVFS, M_WAITOK); 70 bzero(dd, sizeof(*dd)); 71 TAILQ_INIT(&dd->dd_list); 72 73 de = devfs_newdirent(".", 1); 74 de->de_dirent->d_type = DT_DIR; 75 TAILQ_INSERT_TAIL(&dd->dd_list, de, de_list); 76 de = TAILQ_FIRST(&dd->dd_list); 77 de->de_mode = 0755; 78 return (dd); 79 } 80 81 void 82 devfs_delete(struct devfs_dir *dd, struct devfs_dirent *de) 83 { 84 85 if (de->de_symlink) { 86 FREE(de->de_symlink, M_DEVFS); 87 de->de_symlink = NULL; 88 } 89 if (de->de_vnode) { 90 de->de_vnode->v_data = NULL; 91 vdrop(de->de_vnode); 92 } 93 TAILQ_REMOVE(&dd->dd_list, de, de_list); 94 FREE(de, M_DEVFS); 95 } 96 97 void 98 devfs_purge(struct devfs_dir *dd) 99 { 100 struct devfs_dirent *de; 101 102 for (;;) { 103 de = TAILQ_FIRST(&dd->dd_list); 104 if (de == NULL) 105 break; 106 devfs_delete(dd, de); 107 } 108 FREE(dd, M_DEVFS); 109 } 110 111 112 int 113 devfs_populate(struct devfs_mount *dm) 114 { 115 int i, j; 116 dev_t dev, pdev; 117 struct devfs_dir *dd; 118 struct devfs_dirent *de; 119 char *q, *s; 120 121 while (dm->dm_generation != devfs_generation) { 122 dm->dm_generation = devfs_generation; 123 for (i = 0; i < NDEVINO; i++) { 124 dev = devfs_inot[i]; 125 de = dm->dm_dirent[i]; 126 if (dev == NULL && de != NULL) { 127 #if 0 128 printf("Del ino%d %s\n", i, de->de_dirent->d_name); 129 #endif 130 dd = de->de_dir; 131 dm->dm_dirent[i] = NULL; 132 TAILQ_REMOVE(&dd->dd_list, de, de_list); 133 if (de->de_vnode) { 134 de->de_vnode->v_data = NULL; 135 vdrop(de->de_vnode); 136 } 137 FREE(de, M_DEVFS); 138 continue; 139 } 140 if (dev == NULL) 141 continue; 142 if (de != NULL) 143 continue; 144 dd = dm->dm_basedir; 145 s = dev->si_name; 146 for (q = s; *q != '/' && *q != '\0'; q++) 147 continue; 148 if (*q == '/') { 149 continue; 150 } 151 de = devfs_newdirent(s, q - s); 152 if (dev->si_flags & SI_ALIAS) { 153 de->de_inode = dm->dm_inode++; 154 de->de_uid = 0; 155 de->de_gid = 0; 156 de->de_mode = 0642; 157 de->de_dirent->d_type = DT_LNK; 158 pdev = dev->si_drv1; 159 j = strlen(pdev->si_name) + 1; 160 MALLOC(de->de_symlink, char *, j, M_DEVFS, M_WAITOK); 161 bcopy(pdev->si_name, de->de_symlink, j); 162 } else { 163 de->de_inode = i; 164 de->de_uid = dev->si_uid; 165 de->de_gid = dev->si_gid; 166 de->de_mode = dev->si_mode; 167 de->de_dirent->d_type = DT_CHR; 168 dm->dm_dirent[i] = de; 169 } 170 TAILQ_INSERT_TAIL(&dd->dd_list, de, de_list); 171 #if 0 172 printf("Add ino%d %s\n", i, dev->si_name); 173 #endif 174 } 175 } 176 return (0); 177 } 178 179 dev_t devfs_inot[NDEVINO]; 180 int devfs_nino = 3; 181 unsigned devfs_generation; 182 183 static void 184 devfs_create(dev_t dev) 185 { 186 if (dev->si_inode == 0 && devfs_nino < NDEVINO) 187 dev->si_inode = devfs_nino++; 188 if (dev->si_inode == 0) { 189 printf("NDEVINO too small\n"); 190 return; 191 } 192 devfs_inot[dev->si_inode] = dev; 193 devfs_generation++; 194 } 195 196 static void 197 devfs_remove(dev_t dev) 198 { 199 devfs_inot[dev->si_inode] = NULL; 200 devfs_generation++; 201 } 202 203 devfs_create_t *devfs_create_hook = devfs_create; 204 devfs_remove_t *devfs_remove_hook = devfs_remove; 205 206 int 207 devfs_stdclone(char *name, char **namep, char *stem, int *unit) 208 { 209 int u, i; 210 211 if (bcmp(stem, name, strlen(stem)) != 0) 212 return (0); 213 i = strlen(stem); 214 if (!isdigit(name[i])) 215 return (0); 216 u = 0; 217 while (isdigit(name[i])) { 218 u *= 10; 219 u += name[i++] - '0'; 220 } 221 *unit = u; 222 if (namep) 223 *namep = &name[i]; 224 if (name[i]) 225 return (2); 226 return (1); 227 } 228