1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-02-06 18:29:47 +00:00

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
This commit is contained in:
Peter Wemm 1998-04-06 17:44:40 +00:00
parent 7e3426aa1f
commit b587fd008d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=35083

View File

@ -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)