Author: jhb
Date: Fri Feb  6 22:24:03 2009
New Revision: 188251
URL: http://svn.freebsd.org/changeset/base/188251

Log:
  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

Modified:
  head/sys/fs/udf/ecma167-udf.h
  head/sys/fs/udf/udf_vnops.c

Modified: head/sys/fs/udf/ecma167-udf.h
==============================================================================
--- head/sys/fs/udf/ecma167-udf.h       Fri Feb  6 22:22:08 2009        
(r188250)
+++ head/sys/fs/udf/ecma167-udf.h       Fri Feb  6 22:24:03 2009        
(r188251)
@@ -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;

Modified: head/sys/fs/udf/udf_vnops.c
==============================================================================
--- head/sys/fs/udf/udf_vnops.c Fri Feb  6 22:22:08 2009        (r188250)
+++ head/sys/fs/udf/udf_vnops.c Fri Feb  6 22:24:03 2009        (r188251)
@@ -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
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to