From ed9a71b7fc714f25f9c8682e0e88eee0960326f4 Mon Sep 17 00:00:00 2001 From: Julian Elischer Date: Tue, 13 Aug 1996 07:21:45 +0000 Subject: [PATCH] symlink support in devfs. it only barely works so don't get too carried away.. I noticed that teh symlink is length 0.. I guess I'll fix that tomorrow.. it also sometimes panics with "cleaned vnode isn't" but it's not more broken than it was before.. I really want to go over it with someone who understands the lifecycle of a vnode better than I do.. terry? kirk? david? john? --- sys/miscfs/devfs/devfs_tree.c | 79 ++++++++++++++++++++++------------ sys/miscfs/devfs/devfs_vnops.c | 55 ++++++++++++++++++----- 2 files changed, 96 insertions(+), 38 deletions(-) diff --git a/sys/miscfs/devfs/devfs_tree.c b/sys/miscfs/devfs/devfs_tree.c index 6342ceff0488..192ec5469126 100644 --- a/sys/miscfs/devfs/devfs_tree.c +++ b/sys/miscfs/devfs/devfs_tree.c @@ -2,7 +2,7 @@ /* * Written by Julian Elischer (julian@DIALix.oz.au) * - * $Header: /home/ncvs/src/sys/miscfs/devfs/devfs_tree.c,v 1.26 1996/07/24 21:22:36 phk Exp $ + * $Header: /home/ncvs/src/sys/miscfs/devfs/devfs_tree.c,v 1.27 1996/07/30 18:00:32 bde Exp $ */ #include "param.h" @@ -157,25 +157,21 @@ dev_finddir(char *orig_path, dn_p dirnode, int create, dn_p *dn_pp) * find the next segment of the name * \***************************************/ cp = name = path; - while((*cp != '/') && (*cp != 0)) - { + while((*cp != '/') && (*cp != 0)) { cp++; } /***********************************************\ * Check to see if it's the last component * \***********************************************/ - if(*cp) - { + if(*cp) { path = cp + 1; /* path refers to the rest */ *cp = 0; /* name is now a separate string */ if(!(*path)) { path = (char *)0; /* was trailing slash */ } - } - else - { + } else { path = (char *)0; /* no more to do */ } @@ -183,13 +179,10 @@ dev_finddir(char *orig_path, dn_p dirnode, int create, dn_p *dn_pp) * Start scanning along the linked list * \***************************************/ devnmp = dev_findname(dirnode,name); - if(devnmp) - { /* check it's a directory */ + if(devnmp) { /* check it's a directory */ dnp = devnmp->dnp; if(dnp->type != DEV_DIR) return ENOTDIR; - } - else - { + } else { /***************************************\ * The required element does not exist * * So we will add it if asked to. * @@ -203,12 +196,9 @@ dev_finddir(char *orig_path, dn_p dirnode, int create, dn_p *dn_pp) } dnp = devnmp->dnp; } - if(path) /* decide whether to recurse more or return */ - { + if(path) { /* decide whether to recurse more or return */ return (dev_finddir(path,dnp,create,dn_pp)); - } - else - { + } else { *dn_pp = dnp; return 0; } @@ -246,8 +236,7 @@ dev_add_name(char *name, dn_p dirnode, devnm_p back, dn_p dnp, * Allocate and fill out a new directory entry */ if(!(devnmp = (devnm_p)malloc(sizeof(devnm_t), - M_DEVFSNAME, M_NOWAIT))) - { + M_DEVFSNAME, M_NOWAIT))) { return ENOMEM; } bzero(devnmp,sizeof(devnm_t)); @@ -365,6 +354,10 @@ dev_add_node(int entrytype, union typeinfo *by, dn_p proto, dn_p *dn_pp) { return ENOMEM; } + /* + * If we have a proto, that means that we are duplicating some + * other device, which can only happen if we are not at the back plane + */ if(proto) { /* XXX should check that we are NOT copying a device node */ bcopy(proto, dnp, sizeof(devnode_t)); @@ -374,6 +367,9 @@ dev_add_node(int entrytype, union typeinfo *by, dn_p proto, dn_p *dn_pp) dnp->vn = NULL; dnp->len = 0; } else { + /* + * We have no prototype, so start off with a clean slate + */ bzero(dnp,sizeof(devnode_t)); dnp->type = entrytype; TIMEVAL_TO_TIMESPEC(&time,&(dnp->ctime)) @@ -403,6 +399,26 @@ dev_add_node(int entrytype, union typeinfo *by, dn_p proto, dn_p *dn_pp) dnp->ops = &devfs_vnodeop_p; dnp->mode |= 0555; /* default perms */ break; + case DEV_SLNK: + /* + * As it's a symlink allocate and store the link info + * Symlinks should only ever be created by the user, + * so they are not on the back plane and should not be + * propogated forward.. a bit like directories in that way.. + * A symlink only exists on one plane and has it's own + * node.. therefore we might be on any random plane. + */ + dnp->by.Slnk.name = malloc(by->Slnk.namelen+1, + M_DEVFSNODE, M_NOWAIT); + if (!dnp->by.Slnk.name) { + free(dnp,M_DEVFSNODE); + return ENOMEM; + } + strncpy(dnp->by.Slnk.name,by->Slnk.name,by->Slnk.namelen); + dnp->by.Slnk.namelen = by->Slnk.namelen; + dnp->ops = &devfs_vnodeop_p; + dnp->mode |= 0555; /* default perms */ + break; /*******************************************************\ * The rest of these can't happen except in the back plane* \*******************************************************/ @@ -461,6 +477,9 @@ devfs_dn_free(dn_p dnp) if(--dnp->links <= 0 ) /* can be -1 for initial free, on error */ { /*probably need to do other cleanups XXX */ + if(dnp->type == DEV_SLNK) { + free(dnp->by.Slnk.name,M_DEVFSNODE); + } devfs_dropvnode(dnp); free (dnp, M_DEVFSNODE); } @@ -500,7 +519,8 @@ devfs_add_fronts(devnm_p parent,devnm_p child) for (falias = parent->next_front; falias; falias = falias->next_front) { /* - * If a Dir (XXX symlink too one day) + * If a Dir (XXX symlink too one day?) + * (...Nope, symlinks don't propogate..) * Make the node, using the original as a prototype) */ if(type == DEV_DIR) { @@ -601,6 +621,7 @@ devfs_free_plane(struct devfsmount *devfs_mp_p) * Create and link in a new front element.. * * Parent can be 0 for a root node * * Not presently usable to make a symlink XXX * +* (Ok, symlinks don't propogate) * recursively will create subnodes corresponding to equivalent * * child nodes in the base level * \***************************************************************/ @@ -703,7 +724,7 @@ dev_free_name(devnm_p devnmp) */ if(parent) /* if not fs root */ { - if( *devnmp->prevp = devnmp->next)/* yes, assign */ + if( (*devnmp->prevp = devnmp->next) )/* yes, assign */ { devnmp->next->prevp = devnmp->prevp; } @@ -721,9 +742,9 @@ dev_free_name(devnm_p devnmp) * from that.. * Remember that we may not HAVE a backing node. */ - if (back = devnmp->as.front.realthing) /* yes an assign */ + if ( (back = devnmp->as.front.realthing) ) /* yes an assign */ { - if( *devnmp->prev_frontp = devnmp->next_front)/* yes, assign */ + if((*devnmp->prev_frontp = devnmp->next_front))/* yes, assign */ { devnmp->next_front->prev_frontp = devnmp->prev_frontp; } @@ -773,9 +794,12 @@ DBPRINT((" vntodn ")); printf("No references! "); } #endif - if((vn_p->v_type == VBAD) || (vn_p->v_type == VNON)) - { - printf("bad-type2 "); + switch(vn_p->v_type) { + case VBAD: + printf("bad-type2 (VBAD)"); + return(EINVAL); + case VNON: + printf("bad-type2 (VNON)"); return(EINVAL); } *dn_pp = (dn_p)vn_p->v_data; @@ -888,6 +912,7 @@ DBPRINT(("(New vnode)")); switch(dnp->type) { case DEV_SLNK: + vn_p->v_type = VLNK; break; case DEV_DIR: if(dnp->by.Dir.parent == dnp) diff --git a/sys/miscfs/devfs/devfs_vnops.c b/sys/miscfs/devfs/devfs_vnops.c index 14afa0c4b967..3b6352c8a98f 100644 --- a/sys/miscfs/devfs/devfs_vnops.c +++ b/sys/miscfs/devfs/devfs_vnops.c @@ -1,7 +1,7 @@ /* * Written by Julian Elischer (julian@DIALix.oz.au) * - * $Header: /home/ncvs/src/sys/miscfs/devfs/devfs_vnops.c,v 1.20 1996/04/07 01:15:02 joerg Exp $ + * $Header: /home/ncvs/src/sys/miscfs/devfs/devfs_vnops.c,v 1.21 1996/06/12 05:08:34 gpalmer Exp $ * * symlinks can wait 'til later. */ @@ -102,7 +102,7 @@ DBPRINT(("lookup\n")); /* * Check accessiblity of directory. */ - if (dir_node->type != DEV_DIR) + if (dir_node->type != DEV_DIR) /* XXX or symlink? */ { return (ENOTDIR); } @@ -272,7 +272,7 @@ DBPRINT(("MKACCESS ")); if ((dir_node->mode & ISVTX) && cnp->cn_cred->cr_uid != 0 && cnp->cn_cred->cr_uid != dir_node->uid && - new_node->uid != cnp->cn_cred->cr_uid) { + cnp->cn_cred->cr_uid != new_node->uid) { VOP_UNLOCK((*result_vnode)); return (EPERM); } @@ -974,8 +974,7 @@ DBPRINT(("link\n")); /* * Check we are doing legal things WRT the new flags */ - if ((fp->flags & (IMMUTABLE | APPEND)) - || (tdp->flags & APPEND) /*XXX eh?*/ ) { + if (fp->flags & (IMMUTABLE | APPEND)) { error = EPERM; goto abortit; } @@ -1101,7 +1100,6 @@ devfs_rename(struct vop_rename_args *ap) */ if ((tp && (tp->flags & (IMMUTABLE | APPEND))) || (fp->flags & (IMMUTABLE | APPEND)) - || (tdp->flags & APPEND) /*XXX eh?*/ || (fdp->flags & APPEND)) { error = EPERM; goto abortit; @@ -1264,6 +1262,7 @@ devfs_rmdir(struct vop_rmdir_args *ap) DBPRINT(("rmdir\n")); return 0; } +#endif static int devfs_symlink(struct vop_symlink_args *ap) @@ -1275,10 +1274,27 @@ devfs_symlink(struct vop_symlink_args *ap) char *a_target; } */ { - return EINVAL; + int err; + dn_p dnp; + union typeinfo by; + devnm_p nm_p; + struct vnode *vp; + DBPRINT(("symlink\n")); + if(err = devfs_vntodn(ap->a_dvp,&dnp)) { + return err; + } + + by.Slnk.name = ap->a_target; + by.Slnk.namelen = strlen(ap->a_target); + dev_add_entry( ap->a_cnp->cn_nameptr, dnp, DEV_SLNK, &by, &nm_p); + if(err = devfs_dntovn(nm_p->dnp,&vp) ) { + return err; + } + *ap->a_vpp = vp; + VOP_SETATTR(vp, ap->a_vap, ap->a_cnp->cn_cred, ap->a_cnp->cn_proc); + return 0; } -#endif /* * Vnode op for readdir @@ -1389,7 +1405,6 @@ DBPRINT(("readdir\n")); /* */ -#ifdef notyet static int devfs_readlink(struct vop_readlink_args *ap) /*struct vop_readlink_args { @@ -1398,10 +1413,26 @@ devfs_readlink(struct vop_readlink_args *ap) struct ucred *a_cred; } */ { + struct vnode *vp = ap->a_vp; + struct uio *uio = ap->a_uio; + dn_p lnk_node; + int error = 0; + + DBPRINT(("readlink\n")); - return 0; +/* set up refs to dir */ + if (error = devfs_vntodn(vp,&lnk_node)) + return error; + if(lnk_node->type != DEV_SLNK) + return(EINVAL); + if (error = VOP_ACCESS(vp, VREAD, ap->a_cred, NULL)) { /* XXX */ + return error; + } + error = uiomove(lnk_node->by.Slnk.name, lnk_node->by.Slnk.namelen, uio); + return error; } +#ifdef notyet static int devfs_abortop(struct vop_abortop_args *ap) /*struct vop_abortop_args { @@ -1638,9 +1669,11 @@ devfs_dropvnode(dn_p dnp) #define devfs_seek ((int (*) __P((struct vop_seek_args *)))nullop) #define devfs_mkdir ((int (*) __P((struct vop_mkdir_args *)))devfs_enotsupp) #define devfs_rmdir ((int (*) __P((struct vop_rmdir_args *)))devfs_enotsupp) +/* #define devfs_symlink ((int (*) __P((struct vop_symlink_args *)))devfs_enotsupp) #define devfs_readlink \ ((int (*) __P((struct vop_readlink_args *)))devfs_enotsupp) +*/ #define devfs_abortop ((int (*) __P((struct vop_abortop_args *)))nullop) #define devfs_lock ((int (*) __P((struct vop_lock_args *)))nullop) #define devfs_unlock ((int (*) __P((struct vop_unlock_args *)))nullop) @@ -1775,7 +1808,7 @@ static struct vnodeopv_entry_desc dev_spec_vnodeop_entries[] = { { &vop_rename_desc, (vop_t *)spec_rename }, /* rename */ { &vop_mkdir_desc, (vop_t *)spec_mkdir }, /* mkdir */ { &vop_rmdir_desc, (vop_t *)spec_rmdir }, /* rmdir */ - { &vop_symlink_desc, (vop_t *)spec_symlink }, /* symlink */ + { &vop_symlink_desc, (vop_t *)devfs_symlink }, /* symlink */ { &vop_readdir_desc, (vop_t *)spec_readdir }, /* readdir */ { &vop_readlink_desc, (vop_t *)spec_readlink }, /* readlink */ { &vop_abortop_desc, (vop_t *)spec_abortop }, /* abortop */