From b587fd008d68b754e66e29cc04fd6bcaea9a1dee Mon Sep 17 00:00:00 2001 From: Peter Wemm Date: Mon, 6 Apr 1998 17:44:40 +0000 Subject: [PATCH] Don't panic if a VOP_READ() gets through on a short link, Just Do It (because we can :-). This means you can open a link file (or pseudo-file in the case of short links where the data is stored in the inode rather than disk blocks) and read the contents. However, trap any writes from the user as it's difficult to do the right thing in all cases. A link may be short and the user may be trying to extend it beyond the limit and so on. Although.. being able to re-target a symlink without deleting it first might have been nice. This stuff is a bit perverse since symlink() and readlink() calls can end up actually being implemented as read/write vnode ops. Reviewed by: phk --- sys/ufs/ufs/ufs_readwrite.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/sys/ufs/ufs/ufs_readwrite.c b/sys/ufs/ufs/ufs_readwrite.c index be530dcae31..8822fd09300 100644 --- a/sys/ufs/ufs/ufs_readwrite.c +++ b/sys/ufs/ufs/ufs_readwrite.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)ufs_readwrite.c 8.11 (Berkeley) 5/8/95 - * $Id: ufs_readwrite.c,v 1.46 1998/03/09 22:12:52 dyson Exp $ + * $Id: ufs_readwrite.c,v 1.47 1998/03/30 09:56:31 phk Exp $ */ #define BLKSIZE(a, b, c) blksize(a, b, c) @@ -71,7 +71,7 @@ READ(ap) ufs_daddr_t lbn, nextlbn; off_t bytesinfile; long size, xfersize, blkoffset; - int error; + int error, isize; u_short mode; int seqcount; int ioflag; @@ -88,16 +88,23 @@ READ(ap) if (uio->uio_rw != UIO_READ) panic("%s: mode", READ_S); - if (vp->v_type == VLNK) { - if ((int)ip->i_size < vp->v_mount->mnt_maxsymlinklen) - panic("%s: short symlink", READ_S); - } else if (vp->v_type != VREG && vp->v_type != VDIR) + if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) panic("%s: type %d", READ_S, vp->v_type); #endif fs = ip->I_FS; if ((u_int64_t)uio->uio_offset > fs->fs_maxfilesize) return (EFBIG); + /* handle a read() on a VLNK obtained via O_NOFOLLOW */ + if (vp->v_type == VLNK) { + isize = ip->i_size; + if ((isize < vp->v_mount->mnt_maxsymlinklen) || + (ip->i_din.di_blocks == 0)) { /* XXX - for old fastlink support */ + uiomove((char *)ip->i_shortlink, isize, ap->a_uio); + return (0); + } + } + object = vp->v_object; bytesinfile = ip->i_size - uio->uio_offset; @@ -282,8 +289,11 @@ WRITE(ap) vm_object_vndeallocate(object); return (EPERM); } - /* FALLTHROUGH */ + break; case VLNK: + /* bail out if this is from the user, it's too hard */ + if (uio->uio_segflg != UIO_SYSSPACE) + return (EOPNOTSUPP); break; case VDIR: if ((ioflag & IO_SYNC) == 0)