#endif
#include "devfsdefs.h"
+#include "devfs.h"
+
+#if FDESC
+#include "fdesc.h"
+#endif /* FDESC */
static int devfs_update(struct vnode *vp, struct timeval *access,
struct timeval *modify);
+void devfs_rele_node(devnode_t *);
/*
switch (file_node->dn_type)
{
case DEV_DIR:
- VATTR_RETURN(vap, va_rdev, (dev_t)file_node->dn_dvm);
+#if FDESC
+ case DEV_DEVFD: /* Like a directory */
+#endif /* FDESC */
+ VATTR_RETURN(vap, va_rdev, 0);
vap->va_mode |= (S_IFDIR);
break;
case DEV_CDEV:
VATTR_RETURN(vap, va_uid, file_node->dn_uid);
VATTR_RETURN(vap, va_gid, file_node->dn_gid);
VATTR_RETURN(vap, va_fsid, (uintptr_t)file_node->dn_dvm);
- VATTR_RETURN(vap, va_fileid, (uintptr_t)file_node);
+ VATTR_RETURN(vap, va_fileid, (uintptr_t)file_node->dn_ino);
VATTR_RETURN(vap, va_data_size, file_node->dn_len);
/* return an override block size (advisory) */
VATTR_RETURN(vap, va_modify_time, file_node->dn_mtime);
VATTR_RETURN(vap, va_access_time, file_node->dn_atime);
VATTR_RETURN(vap, va_gen, 0);
- VATTR_RETURN(vap, va_flags, 0);
VATTR_RETURN(vap, va_filerev, 0);
VATTR_RETURN(vap, va_acl, NULL);
+ /* Hide the root so Finder doesn't display it */
+ if (vnode_isvroot(vp)) {
+ VATTR_RETURN(vap, va_flags, UF_HIDDEN);
+ } else {
+ VATTR_RETURN(vap, va_flags, 0);
+ }
+
DEVFS_UNLOCK();
return 0;
struct vnode * vp = ap->a_vp;
register devnode_t * dnp;
struct timeval now;
- int ref = 1;
-
- if (vp->v_type == VBLK)
- ref = 0;
- if (vnode_isinuse(vp, ref)) {
+ if (vnode_isinuse(vp, 0)) {
DEVFS_LOCK();
microtime(&now);
dnp = VTODN(vp);
return 0; /* not reached */
}
+/*
+ * Deviates from UFS naming convention because there is a KPI function
+ * called devfs_remove().
+ */
static int
-devfs_remove(struct vnop_remove_args *ap)
+devfs_vnop_remove(struct vnop_remove_args *ap)
/* struct vnop_remove_args {
struct vnode *a_dvp;
struct vnode *a_vp;
ra.a_flags = 0; /* XXX */
ra.a_context = ap->a_context;
- return devfs_remove(&ra);
+ return devfs_vnop_remove(&ra);
}
vfs_context_t a_context;
} */
{
- struct componentname * cnp = ap->a_cnp;
- vfs_context_t ctx = cnp->cn_context;
- struct proc *p = vfs_context_proc(ctx);
+ int error;
+ devdirent_t *newent;
+
+ DEVFS_LOCK();
+ error = devfs_make_symlink(VTODN(ap->a_dvp), ap->a_cnp->cn_nameptr, ap->a_vap->va_mode, ap->a_target, &newent);
+
+ if (error == 0) {
+ error = devfs_dntovn(newent->de_dnp, ap->a_vpp, vfs_context_proc(ap->a_context));
+ }
+
+ DEVFS_UNLOCK();
+
+ return error;
+
+}
+
+/* Called with devfs locked */
+int
+devfs_make_symlink(devnode_t *dir_p, char *name, int mode, char *target, devdirent_t **newent)
+{
int error = 0;
- devnode_t * dir_p;
devnode_type_t typeinfo;
devdirent_t * nm_p;
devnode_t * dev_p;
- struct vnode_attr * vap = ap->a_vap;
- struct vnode * * vpp = ap->a_vpp;
- typeinfo.Slnk.name = ap->a_target;
- typeinfo.Slnk.namelen = strlen(ap->a_target);
+ typeinfo.Slnk.name = target;
+ typeinfo.Slnk.namelen = strlen(target);
- DEVFS_LOCK();
-
- dir_p = VTODN(ap->a_dvp);
-
- error = dev_add_entry(cnp->cn_nameptr, dir_p, DEV_SLNK,
+ error = dev_add_entry(name, dir_p, DEV_SLNK,
&typeinfo, NULL, NULL, &nm_p);
if (error) {
goto failure;
dev_p = nm_p->de_dnp;
dev_p->dn_uid = dir_p->dn_uid;
dev_p->dn_gid = dir_p->dn_gid;
- dev_p->dn_mode = vap->va_mode;
+ dev_p->dn_mode = mode;
dn_copy_times(dev_p, dir_p);
- error = devfs_dntovn(dev_p, vpp, p);
+ if (newent) {
+ *newent = nm_p;
+ }
+
failure:
- DEVFS_UNLOCK();
return error;
}
switch(nodenumber)
{
case 0:
- dirent.d_fileno = (int32_t)(void *)dir_node;
+ dirent.d_fileno = dir_node->dn_ino;
name = ".";
dirent.d_namlen = 1;
dirent.d_type = DT_DIR;
break;
case 1:
if(dir_node->dn_typeinfo.Dir.parent)
- dirent.d_fileno
- = (int32_t)dir_node->dn_typeinfo.Dir.parent;
+ dirent.d_fileno = dir_node->dn_typeinfo.Dir.parent->dn_ino;
else
- dirent.d_fileno = (u_int32_t)dir_node;
+ dirent.d_fileno = dir_node->dn_ino;
name = "..";
dirent.d_namlen = 2;
dirent.d_type = DT_DIR;
break;
default:
- dirent.d_fileno = (int32_t)(void *)name_node->de_dnp;
+ dirent.d_fileno = name_node->de_dnp->dn_ino;
dirent.d_namlen = strlen(name_node->de_name);
name = name_node->de_name;
switch(name_node->de_dnp->dn_type) {
dnp = VTODN(vp);
if (dnp) {
- /*
- * do the same as devfs_inactive in case it is not called
- * before us (can that ever happen?)
- */
+ /* If this is a cloning device, it didn't have a dn_vn anyway */
dnp->dn_vn = NULL;
- vp->v_data = NULL;
+ vnode_clearfsnode(vp);
- if (dnp->dn_delete) {
- devnode_free(dnp);
- }
+ /* This could delete the node, if we are the last vnode */
+ devfs_rele_node(dnp);
}
DEVFS_UNLOCK();
static int
devfs_inactive(__unused struct vnop_inactive_args *ap)
{
- return (0);
+ vnode_t vp = ap->a_vp;
+ devnode_t *dnp = VTODN(vp);
+
+ /*
+ * Cloned vnodes are not linked in anywhere, so they
+ * can just be recycled.
+ */
+ if (dnp->dn_clone != NULL) {
+ vnode_recycle(vp);
+ }
+
+ return (0);
}
/*
{ &vnop_revoke_desc, (VOPFUNC)err_revoke }, /* revoke */
{ &vnop_mmap_desc, (VOPFUNC)err_mmap }, /* mmap */
{ &vnop_fsync_desc, (VOPFUNC)nop_fsync }, /* fsync */
- { &vnop_remove_desc, (VOPFUNC)devfs_remove }, /* remove */
+ { &vnop_remove_desc, (VOPFUNC)devfs_vnop_remove }, /* remove */
{ &vnop_link_desc, (VOPFUNC)devfs_link }, /* link */
{ &vnop_rename_desc, (VOPFUNC)devfs_rename }, /* rename */
{ &vnop_mkdir_desc, (VOPFUNC)devfs_mkdir }, /* mkdir */
{ &vnop_revoke_desc, (VOPFUNC)spec_revoke }, /* revoke */
{ &vnop_mmap_desc, (VOPFUNC)spec_mmap }, /* mmap */
{ &vnop_fsync_desc, (VOPFUNC)spec_fsync }, /* fsync */
- { &vnop_remove_desc, (VOPFUNC)devfs_remove }, /* remove */
+ { &vnop_remove_desc, (VOPFUNC)devfs_vnop_remove }, /* remove */
{ &vnop_link_desc, (VOPFUNC)devfs_link }, /* link */
{ &vnop_rename_desc, (VOPFUNC)spec_rename }, /* rename */
{ &vnop_mkdir_desc, (VOPFUNC)spec_mkdir }, /* mkdir */
};
struct vnodeopv_desc devfs_spec_vnodeop_opv_desc =
{ &devfs_spec_vnodeop_p, devfs_spec_vnodeop_entries };
+
+
+#if FDESC
+int (**devfs_devfd_vnodeop_p)(void*);
+static struct vnodeopv_entry_desc devfs_devfd_vnodeop_entries[] = {
+ { &vnop_default_desc, (VOPFUNC)vn_default_error },
+ { &vnop_lookup_desc, (VOPFUNC)devfs_devfd_lookup}, /* lookup */
+ { &vnop_open_desc, (VOPFUNC)nop_open }, /* open */
+ { &vnop_close_desc, (VOPFUNC)devfs_close }, /* close */
+ { &vnop_getattr_desc, (VOPFUNC)devfs_getattr }, /* getattr */
+ { &vnop_setattr_desc, (VOPFUNC)devfs_setattr }, /* setattr */
+ { &vnop_revoke_desc, (VOPFUNC)err_revoke }, /* revoke */
+ { &vnop_fsync_desc, (VOPFUNC)nop_fsync }, /* fsync */
+ { &vnop_readdir_desc, (VOPFUNC)devfs_devfd_readdir}, /* readdir */
+ { &vnop_inactive_desc, (VOPFUNC)devfs_inactive }, /* inactive */
+ { &vnop_reclaim_desc, (VOPFUNC)devfs_reclaim }, /* reclaim */
+ { &vnop_pathconf_desc, (VOPFUNC)devs_vnop_pathconf }, /* pathconf */
+#if CONFIG_MACF
+ { &vnop_setlabel_desc, (VOPFUNC)devfs_setlabel }, /* setlabel */
+#endif
+ { (struct vnodeop_desc*)NULL, (int(*)())NULL }
+};
+struct vnodeopv_desc devfs_devfd_vnodeop_opv_desc =
+ { &devfs_devfd_vnodeop_p, devfs_devfd_vnodeop_entries};
+#endif /* FDESC */
+
+