+/*
+ * Function: devfs_make_node
+ *
+ * Purpose
+ * Create a device node with the given pathname in the devfs namespace.
+ *
+ * Parameters:
+ * dev - the dev_t value to associate
+ * chrblk - block or character device (DEVFS_CHAR or DEVFS_BLOCK)
+ * uid, gid - ownership
+ * perms - permissions
+ * clone - minor number cloning function
+ * fmt, ... - path format string with printf args to format the path name
+ * Returns:
+ * A handle to a device node if successful, NULL otherwise.
+ */
+void *
+devfs_make_node_clone(dev_t dev, int chrblk, uid_t uid,
+ gid_t gid, int perms, int (*clone)(dev_t dev, int action),
+ const char *fmt, ...)
+{
+ devdirent_t * new_dev = NULL;
+ devnode_t * dnp; /* devnode for parent directory */
+ devnode_type_t typeinfo;
+
+ char *name, buf[256]; /* XXX */
+ const char *path;
+ int i;
+ va_list ap;
+
+
+ DEVFS_LOCK();
+
+ if (!devfs_ready) {
+ printf("devfs_make_node: not ready for devices!\n");
+ goto out;
+ }
+ if (chrblk != DEVFS_CHAR && chrblk != DEVFS_BLOCK)
+ goto out;
+
+ DEVFS_UNLOCK();
+
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+
+ name = NULL;
+
+ for(i=strlen(buf); i>0; i--)
+ if(buf[i] == '/') {
+ name=&buf[i];
+ buf[i]=0;
+ break;
+ }
+
+ if (name) {
+ *name++ = '\0';
+ path = buf;
+ } else {
+ name = buf;
+ path = "/";
+ }
+ DEVFS_LOCK();
+
+ /* find/create directory path ie. mkdir -p */
+ if (dev_finddir(path, NULL, DEVFS_CREATE, &dnp) == 0) {
+ typeinfo.dev = dev;
+ if (dev_add_entry(name, dnp,
+ (chrblk == DEVFS_CHAR) ? DEV_CDEV : DEV_BDEV,
+ &typeinfo, NULL, NULL, &new_dev) == 0) {
+ new_dev->de_dnp->dn_gid = gid;
+ new_dev->de_dnp->dn_uid = uid;
+ new_dev->de_dnp->dn_mode |= perms;
+ new_dev->de_dnp->dn_clone = clone;
+ devfs_propogate(dnp->dn_typeinfo.Dir.myname, new_dev);
+ }
+ }
+out:
+ DEVFS_UNLOCK();
+
+ return new_dev;
+}
+
+