/* Create single-use devices for /dev/apm and /dev/apmctl. */ static void apm_clone(void *arg, struct ucred *cred, char *name, int namelen, struct cdev **dev) { int ctl_dev, unit; if (*dev != NULL) return; if (strcmp(name, "apmctl") == 0) ctl_dev = TRUE; else if (strcmp(name, "apm") == 0) ctl_dev = FALSE; else return; /* Always create a new device and unit number. */ unit = -1; if (clone_create(&apm_clones, &apm_cdevsw, &unit, dev, 0)) { if (ctl_dev) { *dev = make_dev(&apm_cdevsw, unit, UID_ROOT, GID_OPERATOR, 0660, "apmctl%d", unit); } else { *dev = make_dev(&apm_cdevsw, unit, UID_ROOT, GID_OPERATOR, 0664, "apm%d", unit); } if (*dev != NULL) { dev_ref(*dev); (*dev)->si_flags |= SI_CHEAPCLONE; } } }
static void tunclone(void *arg, char *name, int namelen, struct cdev **dev) { int u, i; if (*dev != NULL) return; if (strcmp(name, TUNNAME) == 0) { u = -1; } else if (dev_stdclone(name, NULL, TUNNAME, &u) != 1) return; /* Don't recognise the name */ if (u != -1 && u > IF_MAXUNIT) return; /* Unit number too high */ /* find any existing device, or allocate new unit number */ i = clone_create(&tunclones, &tun_cdevsw, &u, dev, 0); if (i) { /* No preexisting struct cdev *, create one */ *dev = make_dev(&tun_cdevsw, unit2minor(u), UID_UUCP, GID_DIALER, 0600, "tun%d", u); if (*dev != NULL) (*dev)->si_flags |= SI_CHEAPCLONE; } }
static void dtrace_clone(void *arg, struct ucred *cred, char *name, int namelen, struct cdev **dev) { int u = -1; size_t len; if (*dev != NULL) return; len = strlen(name); if (len != 6 && len != 13) return; if (bcmp(name,"dtrace",6) != 0) return; if (len == 13 && bcmp(name,"dtrace/dtrace",13) != 0) return; /* Clone the device to the new minor number. */ if (clone_create(&dtrace_clones, &dtrace_cdevsw, &u, dev, 0) != 0) /* Create the /dev/dtrace/dtraceNN entry. */ *dev = make_dev_cred(&dtrace_cdevsw, u, cred, UID_ROOT, GID_WHEEL, 0600, "dtrace/dtrace%d", u); if (*dev != NULL) { dev_ref(*dev); (*dev)->si_flags |= SI_CHEAPCLONE; } }
static void sms1xxx_demux_clone(void *arg, struct ucred *cred, char *name, int namelen, struct cdev **dev) { char buf[40]; int filtnr = 0; int unit; struct sms1xxx_softc *sc = arg; TRACE(TRACE_OPEN,"name=%s\n",name); if (*dev != NULL || sc == NULL) return; snprintf(buf,39,"dvb/adapter%d/demux0",device_get_unit(sc->sc_dev)); if(strcmp(name,buf) != 0) return; for(filtnr = 0; filtnr < MAX_FILTERS; ++filtnr) { if(sc->filter[filtnr].pid == PIDFREE) break; } if(filtnr >= MAX_FILTERS) { ERR("no more filter free\n"); return; } if(sc->filter[filtnr].dev != NULL) { ERR("filter %d not free\n", filtnr); return; } /* Clones are shared among devices, so handle unit numbers manually by reserving a range of MAX_FILTERS units per-device (clone_create will fail setting unit number automatically : unit number assignment is done by crawling sc's (only) clones and will not detect clones created for other devices, resulting in trying to set twice the same unit number). */ unit = device_get_unit(sc->sc_dev) * MAX_FILTERS + filtnr; if(clone_create(&sc->demux_clones, &sms1xxx_demux_cdevsw, &unit, dev, 0)) { *dev = make_dev_credf(MAKEDEV_REF, &sms1xxx_demux_cdevsw, unit, NULL, UID_ROOT, GID_WHEEL, 0666, "dvb/adapter%d/demux0.%d", device_get_unit(sc->sc_dev), filtnr); if(*dev != NULL) { TRACE(TRACE_MODULE,"created demux0.%d device, addr=%p\n", filtnr, *dev); (*dev)->si_flags |= SI_CHEAPCLONE; (*dev)->si_drv1 = sc; (*dev)->si_drv2 = &sc->filter[filtnr]; /* map filter to device */ sc->filter[filtnr].dev = *dev; /* map device to filter */ sc->filter[filtnr].pid = PIDCLONED; } } }
/** * DEVFS event handler. */ static void vgdrvFreeBSDClone(void *pvArg, struct ucred *pCred, char *pszName, int cchName, struct cdev **ppDev) { int iUnit; int rc; Log(("vgdrvFreeBSDClone: pszName=%s ppDev=%p\n", pszName, ppDev)); /* * One device node per user, si_drv1 points to the session. * /dev/vboxguest<N> where N = {0...255}. */ if (!ppDev) return; if (strcmp(pszName, "vboxguest") == 0) iUnit = -1; else if (dev_stdclone(pszName, NULL, "vboxguest", &iUnit) != 1) return; if (iUnit >= 256) { Log(("vgdrvFreeBSDClone: iUnit=%d >= 256 - rejected\n", iUnit)); return; } Log(("vgdrvFreeBSDClone: pszName=%s iUnit=%d\n", pszName, iUnit)); rc = clone_create(&g_pvgdrvFreeBSDClones, &g_vgdrvFreeBSDChrDevSW, &iUnit, ppDev, 0); Log(("vgdrvFreeBSDClone: clone_create -> %d; iUnit=%d\n", rc, iUnit)); if (rc) { *ppDev = make_dev(&g_vgdrvFreeBSDChrDevSW, iUnit, UID_ROOT, GID_WHEEL, 0664, "vboxguest%d", iUnit); if (*ppDev) { dev_ref(*ppDev); (*ppDev)->si_flags |= SI_CHEAPCLONE; Log(("vgdrvFreeBSDClone: Created *ppDev=%p iUnit=%d si_drv1=%p si_drv2=%p\n", *ppDev, iUnit, (*ppDev)->si_drv1, (*ppDev)->si_drv2)); (*ppDev)->si_drv1 = (*ppDev)->si_drv2 = NULL; } else Log(("vgdrvFreeBSDClone: make_dev iUnit=%d failed\n", iUnit)); } else Log(("vgdrvFreeBSDClone: Existing *ppDev=%p iUnit=%d si_drv1=%p si_drv2=%p\n", *ppDev, iUnit, (*ppDev)->si_drv1, (*ppDev)->si_drv2)); }
/** * DEVFS event handler. */ static void VBoxDrvFreeBSDClone(void *pvArg, struct ucred *pCred, char *pszName, int cchName, struct cdev **ppDev) { int iUnit; int rc; Log(("VBoxDrvFreeBSDClone: pszName=%s ppDev=%p\n", pszName, ppDev)); /* * One device node per user, si_drv1 points to the session. * /dev/vboxdrv<N> where N = {0...255}. */ if (!ppDev) return; if (dev_stdclone(pszName, NULL, "vboxdrv", &iUnit) != 1) return; if (iUnit >= 256 || iUnit < 0) { Log(("VBoxDrvFreeBSDClone: iUnit=%d >= 256 - rejected\n", iUnit)); return; } Log(("VBoxDrvFreeBSDClone: pszName=%s iUnit=%d\n", pszName, iUnit)); rc = clone_create(&g_pVBoxDrvFreeBSDClones, &g_VBoxDrvFreeBSDChrDevSW, &iUnit, ppDev, 0); Log(("VBoxDrvFreeBSDClone: clone_create -> %d; iUnit=%d\n", rc, iUnit)); if (rc) { #if __FreeBSD_version > 800061 *ppDev = make_dev(&g_VBoxDrvFreeBSDChrDevSW, iUnit, UID_ROOT, GID_WHEEL, VBOXDRV_PERM, "vboxdrv%d", iUnit); #else *ppDev = make_dev(&g_VBoxDrvFreeBSDChrDevSW, unit2minor(iUnit), UID_ROOT, GID_WHEEL, VBOXDRV_PERM, "vboxdrv%d", iUnit); #endif if (*ppDev) { dev_ref(*ppDev); (*ppDev)->si_flags |= SI_CHEAPCLONE; Log(("VBoxDrvFreeBSDClone: Created *ppDev=%p iUnit=%d si_drv1=%p si_drv2=%p\n", *ppDev, iUnit, (*ppDev)->si_drv1, (*ppDev)->si_drv2)); (*ppDev)->si_drv1 = (*ppDev)->si_drv2 = NULL; } else OSDBGPRINT(("VBoxDrvFreeBSDClone: make_dev iUnit=%d failed\n", iUnit)); } else Log(("VBoxDrvFreeBSDClone: Existing *ppDev=%p iUnit=%d si_drv1=%p si_drv2=%p\n", *ppDev, iUnit, (*ppDev)->si_drv1, (*ppDev)->si_drv2)); }
static void nsmb_dev_clone(void *arg, struct ucred *cred, char *name, int namelen, struct cdev **dev) { int i, u; if (*dev != NULL) return; if (strcmp(name, NSMB_NAME) == 0) u = -1; else if (dev_stdclone(name, NULL, NSMB_NAME, &u) != 1) return; i = clone_create(&nsmb_clones, &nsmb_cdevsw, &u, dev, 0); if (i) *dev = make_dev_credf(MAKEDEV_REF, &nsmb_cdevsw, u, cred, UID_ROOT, GID_WHEEL, 0600, "%s%d", NSMB_NAME, u); }
static void nsmb_dev_clone(void *arg, struct ucred *cred, char *name, int namelen, struct cdev **dev) { int i, u; if (*dev != NULL) return; if (strcmp(name, NSMB_NAME) == 0) u = -1; else if (dev_stdclone(name, NULL, NSMB_NAME, &u) != 1) return; i = clone_create(&nsmb_clones, &nsmb_cdevsw, &u, dev, 0); if (i) { *dev = make_dev(&nsmb_cdevsw, u, UID_ROOT, GID_WHEEL, 0600, "%s%d", NSMB_NAME, u); if (*dev != NULL) { dev_ref(*dev); (*dev)->si_flags |= SI_CHEAPCLONE; } } }