Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/fs/udf Posix requires the va_size of a symlink to be pat...
details: https://anonhg.NetBSD.org/src/rev/cf10db1691d3
branches: trunk
changeset: 331057:cf10db1691d3
user: reinoud <reinoud%NetBSD.org@localhost>
date: Tue Jul 29 15:48:22 2014 +0000
description:
Posix requires the va_size of a symlink to be pathlength for symbolic links.
This fixes yet another atf case.
diffstat:
sys/fs/udf/udf_vnops.c | 109 ++++++++++++++++++++++++++++++++----------------
1 files changed, 73 insertions(+), 36 deletions(-)
diffs (206 lines):
diff -r 8bf394916789 -r cf10db1691d3 sys/fs/udf/udf_vnops.c
--- a/sys/fs/udf/udf_vnops.c Tue Jul 29 15:36:43 2014 +0000
+++ b/sys/fs/udf/udf_vnops.c Tue Jul 29 15:48:22 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: udf_vnops.c,v 1.93 2014/07/29 11:10:12 reinoud Exp $ */
+/* $NetBSD: udf_vnops.c,v 1.94 2014/07/29 15:48:22 reinoud Exp $ */
/*
* Copyright (c) 2006, 2008 Reinoud Zandijk
@@ -32,7 +32,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__KERNEL_RCSID(0, "$NetBSD: udf_vnops.c,v 1.93 2014/07/29 11:10:12 reinoud Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udf_vnops.c,v 1.94 2014/07/29 15:48:22 reinoud Exp $");
#endif /* not lint */
@@ -67,6 +67,9 @@
#define VTOI(vnode) ((struct udf_node *) (vnode)->v_data)
+/* forward declarations */
+static int udf_do_readlink(struct udf_node *udf_node, uint64_t filesize,
+ uint8_t *targetbuf, int *length);
/* externs */
extern int prtactive;
@@ -865,10 +868,10 @@
uint64_t filesize, blkssize;
uint32_t nlink;
uint32_t offset, a_l;
- uint8_t *filedata;
+ uint8_t *filedata, *targetbuf;
uid_t uid;
gid_t gid;
- int error;
+ int length, error;
DPRINTF(CALL, ("udf_getattr called\n"));
@@ -939,6 +942,22 @@
if (vap->va_type == VDIR)
vap->va_nlink++;
+ /*
+ * BUG-ALERT: Posix requires the va_size to be pathlength for symbolic
+ * links.
+ */
+ if (vap->va_type == VLNK) {
+ /* claim temporary buffers for translation */
+ targetbuf = malloc(PATH_MAX+1, M_UDFTEMP, M_WAITOK);
+ error = udf_do_readlink(udf_node, filesize, targetbuf, &length);
+ if (!error) {
+ vap->va_size = length;
+ KASSERT(length == strlen(targetbuf));
+ }
+ free(targetbuf, M_UDFTEMP);
+ /* XXX return error? */
+ }
+
/* access times */
udf_timestamp_to_timespec(ump, atime, &vap->va_atime);
udf_timestamp_to_timespec(ump, mtime, &vap->va_mtime);
@@ -1730,49 +1749,30 @@
/* --------------------------------------------------------------------- */
-int
-udf_readlink(void *v)
+static int
+udf_do_readlink(struct udf_node *udf_node, uint64_t filesize,
+ uint8_t *targetbuf, int *length)
{
- struct vop_readlink_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- kauth_cred_t a_cred;
- } */ *ap = v;
- struct vnode *vp = ap->a_vp;
- struct uio *uio = ap->a_uio;
- kauth_cred_t cred = ap->a_cred;
- struct udf_node *udf_node;
struct pathcomp pathcomp;
- struct vattr vattr;
- uint8_t *pathbuf, *targetbuf, *tmpname;
+ uint8_t *pathbuf, *tmpname;
uint8_t *pathpos, *targetpos;
char *mntonname;
int pathlen, targetlen, namelen, mntonnamelen, len, l_ci;
int first, error;
- DPRINTF(CALL, ("udf_readlink called\n"));
-
- udf_node = VTOI(vp);
- error = VOP_GETATTR(vp, &vattr, cred);
- if (error)
- return error;
-
- /* claim temporary buffers for translation */
pathbuf = malloc(UDF_SYMLINKBUFLEN, M_UDFTEMP, M_WAITOK);
- targetbuf = malloc(PATH_MAX+1, M_UDFTEMP, M_WAITOK);
tmpname = malloc(PATH_MAX+1, M_UDFTEMP, M_WAITOK);
memset(pathbuf, 0, UDF_SYMLINKBUFLEN);
memset(targetbuf, 0, PATH_MAX);
/* read contents of file in our temporary buffer */
error = vn_rdwr(UIO_READ, udf_node->vnode,
- pathbuf, vattr.va_size, 0,
+ pathbuf, filesize, 0,
UIO_SYSSPACE, IO_NODELOCKED | IO_ALTSEMANTICS,
FSCRED, NULL, NULL);
if (error) {
/* failed to read in symlink contents */
free(pathbuf, M_UDFTEMP);
- free(targetbuf, M_UDFTEMP);
free(tmpname, M_UDFTEMP);
return error;
}
@@ -1787,7 +1787,7 @@
error = 0;
first = 1;
- while (vattr.va_size - pathlen >= UDF_PATH_COMP_SIZE) {
+ while (filesize - pathlen >= UDF_PATH_COMP_SIZE) {
len = UDF_PATH_COMP_SIZE;
memcpy(&pathcomp, pathpos, len);
l_ci = pathcomp.l_ci;
@@ -1808,7 +1808,7 @@
}
memcpy(targetpos, mntonname, mntonnamelen);
targetpos += mntonnamelen; targetlen -= mntonnamelen;
- if (vattr.va_size-pathlen > UDF_PATH_COMP_SIZE+l_ci) {
+ if (filesize-pathlen > UDF_PATH_COMP_SIZE+l_ci) {
/* more follows, so must be directory */
*targetpos++ = '/'; targetlen--;
}
@@ -1849,7 +1849,7 @@
}
memcpy(targetpos, tmpname, namelen);
targetpos += namelen; targetlen -= namelen;
- if (vattr.va_size-pathlen > UDF_PATH_COMP_SIZE+l_ci) {
+ if (filesize-pathlen > UDF_PATH_COMP_SIZE+l_ci) {
/* more follows, so must be directory */
*targetpos++ = '/'; targetlen--;
}
@@ -1866,17 +1866,54 @@
}
/* all processed? */
- if (vattr.va_size - pathlen > 0)
+ if (filesize - pathlen > 0)
error = EINVAL;
+ free(pathbuf, M_UDFTEMP);
+ free(tmpname, M_UDFTEMP);
+
+ *length = PATH_MAX - targetlen;
+ return error;
+}
+
+
+int
+udf_readlink(void *v)
+{
+ struct vop_readlink_args /* {
+ struct vnode *a_vp;
+ struct uio *a_uio;
+ kauth_cred_t a_cred;
+ } */ *ap = v;
+ struct vnode *vp = ap->a_vp;
+ struct udf_node *udf_node = VTOI(vp);
+ struct file_entry *fe = udf_node->fe;
+ struct extfile_entry *efe = udf_node->efe;
+ struct uio *uio = ap->a_uio;
+ uint64_t filesize;
+ uint8_t *targetbuf;
+ int length;
+ int error;
+
+ DPRINTF(CALL, ("udf_readlink called\n"));
+
+ if (fe) {
+ filesize = udf_rw64(fe->inf_len);
+ } else {
+ assert(udf_node->efe);
+ filesize = udf_rw64(efe->inf_len);
+ }
+
+ /* claim temporary buffers for translation */
+ targetbuf = malloc(PATH_MAX+1, M_UDFTEMP, M_WAITOK);
+
+ error = udf_do_readlink(udf_node, filesize, targetbuf, &length);
+
/* uiomove() to destination */
if (!error)
- uiomove(targetbuf, PATH_MAX - targetlen, uio);
+ uiomove(targetbuf, length, uio);
- free(pathbuf, M_UDFTEMP);
free(targetbuf, M_UDFTEMP);
- free(tmpname, M_UDFTEMP);
-
return error;
}
Home |
Main Index |
Thread Index |
Old Index