Add rudimentary support for symbolic links on UDF. Links are stored as a
sequence of pathname components. We walk the list building a string in the caller's passed in buffer. Currently this only handles path names in CS8 (character set 8) as that is what mkisofs generates for UDF images. MFC after: 1 month
This commit is contained in:
parent
643f85c491
commit
e3024df2e0
@ -354,6 +354,18 @@ struct file_entry {
|
||||
#define UDF_FENTRY_PERM_GRP_MASK 0xE0
|
||||
#define UDF_FENTRY_PERM_OWNER_MASK 0x1C00
|
||||
|
||||
/* Path Component [4/14.16.1] */
|
||||
struct path_component {
|
||||
uint8_t type;
|
||||
uint8_t length;
|
||||
uint16_t version;
|
||||
uint8_t identifier[0];
|
||||
} __packed;
|
||||
#define UDF_PATH_ROOT 2
|
||||
#define UDF_PATH_DOTDOT 3
|
||||
#define UDF_PATH_DOT 4
|
||||
#define UDF_PATH_PATH 5
|
||||
|
||||
union dscrptr {
|
||||
struct desc_tag tag;
|
||||
struct anchor_vdp avdp;
|
||||
|
@ -859,12 +859,121 @@ udf_readdir(struct vop_readdir_args *a)
|
||||
return (error);
|
||||
}
|
||||
|
||||
/* Are there any implementations out there that do soft-links? */
|
||||
static int
|
||||
udf_readlink(struct vop_readlink_args *ap)
|
||||
{
|
||||
printf("%s called\n", __func__);
|
||||
return (EOPNOTSUPP);
|
||||
struct path_component *pc, *end;
|
||||
struct vnode *vp;
|
||||
struct uio uio;
|
||||
struct iovec iov[1];
|
||||
struct udf_node *node;
|
||||
void *buf;
|
||||
char *cp;
|
||||
int error, len, root;
|
||||
|
||||
/*
|
||||
* A symbolic link in UDF is a list of variable-length path
|
||||
* component structures. We build a pathname in the caller's
|
||||
* uio by traversing this list.
|
||||
*/
|
||||
vp = ap->a_vp;
|
||||
node = VTON(vp);
|
||||
len = le64toh(node->fentry->inf_len);
|
||||
buf = malloc(iov[0].iov_len, M_DEVBUF, M_WAITOK);
|
||||
iov[0].iov_base = buf;
|
||||
iov[0].iov_len = len;
|
||||
uio.uio_iov = iov;
|
||||
uio.uio_iovcnt = 1;
|
||||
uio.uio_offset = 0;
|
||||
uio.uio_resid = iov[0].iov_len;
|
||||
uio.uio_segflg = UIO_SYSSPACE;
|
||||
uio.uio_rw = UIO_READ;
|
||||
uio.uio_td = curthread;
|
||||
error = VOP_READ(vp, &uio, 0, ap->a_cred);
|
||||
if (error)
|
||||
goto error;
|
||||
|
||||
pc = buf;
|
||||
end = (void *)((char *)buf + len);
|
||||
root = 0;
|
||||
while (pc < end) {
|
||||
switch (pc->type) {
|
||||
case UDF_PATH_ROOT:
|
||||
/* Only allow this at the beginning of a path. */
|
||||
if ((void *)pc != buf) {
|
||||
error = EINVAL;
|
||||
goto error;
|
||||
}
|
||||
cp = "/";
|
||||
len = 1;
|
||||
root = 1;
|
||||
break;
|
||||
case UDF_PATH_DOT:
|
||||
cp = ".";
|
||||
len = 1;
|
||||
break;
|
||||
case UDF_PATH_DOTDOT:
|
||||
cp = "..";
|
||||
len = 2;
|
||||
break;
|
||||
case UDF_PATH_PATH:
|
||||
if (pc->length == 0) {
|
||||
error = EINVAL;
|
||||
goto error;
|
||||
}
|
||||
/*
|
||||
* XXX: We only support CS8 which appears to map
|
||||
* to ASCII directly.
|
||||
*/
|
||||
switch (pc->identifier[0]) {
|
||||
case 8:
|
||||
cp = pc->identifier + 1;
|
||||
len = pc->length - 1;
|
||||
break;
|
||||
default:
|
||||
error = EOPNOTSUPP;
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is not the first component, insert a path
|
||||
* separator.
|
||||
*/
|
||||
if (pc != buf) {
|
||||
/* If we started with root we already have a "/". */
|
||||
if (root)
|
||||
goto skipslash;
|
||||
root = 0;
|
||||
if (ap->a_uio->uio_resid < 1) {
|
||||
error = ENAMETOOLONG;
|
||||
goto error;
|
||||
}
|
||||
error = uiomove("/", 1, ap->a_uio);
|
||||
if (error)
|
||||
break;
|
||||
}
|
||||
skipslash:
|
||||
|
||||
/* Append string at 'cp' of length 'len' to our path. */
|
||||
if (len > ap->a_uio->uio_resid) {
|
||||
error = ENAMETOOLONG;
|
||||
goto error;
|
||||
}
|
||||
error = uiomove(cp, len, ap->a_uio);
|
||||
if (error)
|
||||
break;
|
||||
|
||||
/* Advance to next component. */
|
||||
pc = (void *)((char *)pc + 4 + pc->length);
|
||||
}
|
||||
error:
|
||||
free(buf, M_DEVBUF);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
|
Loading…
x
Reference in New Issue
Block a user