jdk/src/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java
changeset 2057 3acf8e5e2ca0
child 5506 202f599c92aa
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java	Sun Feb 15 12:25:54 2009 +0000
@@ -0,0 +1,293 @@
+/*
+ * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.nio.fs;
+
+import java.nio.file.*;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.io.IOException;
+import java.util.*;
+
+import static sun.nio.fs.UnixNativeDispatcher.*;
+import static sun.nio.fs.UnixConstants.*;
+import static sun.nio.fs.SolarisConstants.*;
+
+/**
+ * Solaris emulation of NamedAttributeView using extended attributes.
+ */
+
+class SolarisUserDefinedFileAttributeView
+    extends AbstractUserDefinedFileAttributeView
+{
+    private byte[] nameAsBytes(UnixPath file, String name) throws IOException {
+        byte[] bytes = name.getBytes();
+        //  "", "." and ".." not allowed
+        if (bytes.length == 0 || bytes[0] == '.') {
+            if (bytes.length <= 1 ||
+                (bytes.length == 2 && bytes[1] == '.'))
+            {
+                throw new FileSystemException(file.getPathForExecptionMessage(),
+                    null, "'" + name + "' is not a valid name");
+            }
+        }
+        return bytes;
+    }
+
+    private final UnixPath file;
+    private final boolean followLinks;
+
+    SolarisUserDefinedFileAttributeView(UnixPath file, boolean followLinks) {
+        this.file = file;
+        this.followLinks = followLinks;
+    }
+
+    @Override
+    public List<String> list() throws IOException  {
+        if (System.getSecurityManager() != null)
+            checkAccess(file.getPathForPermissionCheck(), true, false);
+
+        int fd = file.openForAttributeAccess(followLinks);
+        try {
+            try {
+                // open extended attribute directory
+                int dfd = openat(fd, ".".getBytes(), (O_RDONLY|O_XATTR), 0);
+                long dp;
+                try {
+                    dp = fdopendir(dfd);
+                } catch (UnixException x) {
+                    close(dfd);
+                    throw x;
+                }
+
+                // read list of extended attributes
+                final List<String> list = new ArrayList<String>();
+                try {
+                    byte[] name;
+                    while ((name = readdir(dp)) != null) {
+                        String s = new String(name);
+                        if (!s.equals(".") && !s.equals(".."))
+                            list.add(s);
+                    }
+                } finally {
+                    closedir(dp);
+                }
+                return Collections.unmodifiableList(list);
+            } catch (UnixException x) {
+                throw new FileSystemException(file.getPathForExecptionMessage(),
+                    null, "Unable to get list of extended attributes: " +
+                    x.getMessage());
+            }
+        } finally {
+            close(fd);
+        }
+    }
+
+    @Override
+    public int size(String name) throws IOException  {
+        if (System.getSecurityManager() != null)
+            checkAccess(file.getPathForPermissionCheck(), true, false);
+
+        int fd = file.openForAttributeAccess(followLinks);
+        try {
+            try {
+                // open attribute file
+                int afd = openat(fd, nameAsBytes(file,name), (O_RDONLY|O_XATTR), 0);
+                try {
+                    // read attribute's attributes
+                    UnixFileAttributes attrs = UnixFileAttributes.get(afd);
+                    long size = attrs.size();
+                    if (size > Integer.MAX_VALUE)
+                        throw new ArithmeticException("Extended attribute value too large");
+                    return (int)size;
+                } finally {
+                    close(afd);
+                }
+            } catch (UnixException x) {
+                throw new FileSystemException(file.getPathForExecptionMessage(),
+                    null, "Unable to get size of extended attribute '" + name +
+                    "': " + x.getMessage());
+            }
+        } finally {
+            close(fd);
+        }
+    }
+
+    @Override
+    public int read(String name, ByteBuffer dst) throws IOException {
+        if (System.getSecurityManager() != null)
+            checkAccess(file.getPathForPermissionCheck(), true, false);
+
+        int fd = file.openForAttributeAccess(followLinks);
+        try {
+            try {
+                // open attribute file
+                int afd = openat(fd, nameAsBytes(file,name), (O_RDONLY|O_XATTR), 0);
+
+                // wrap with channel
+                FileChannel fc = UnixChannelFactory.newFileChannel(afd, true, false);
+
+                // read to EOF (nothing we can do if I/O error occurs)
+                try {
+                    if (fc.size() > dst.remaining())
+                        throw new IOException("Extended attribute file too large");
+                    int total = 0;
+                    while (dst.hasRemaining()) {
+                        int n = fc.read(dst);
+                        if (n < 0)
+                            break;
+                        total += n;
+                    }
+                    return total;
+                } finally {
+                    fc.close();
+                }
+            } catch (UnixException x) {
+                throw new FileSystemException(file.getPathForExecptionMessage(),
+                    null, "Unable to read extended attribute '" + name +
+                    "': " + x.getMessage());
+            }
+        } finally {
+            close(fd);
+        }
+    }
+
+    @Override
+    public int write(String name, ByteBuffer src) throws IOException {
+        if (System.getSecurityManager() != null)
+            checkAccess(file.getPathForPermissionCheck(), false, true);
+
+        int fd = file.openForAttributeAccess(followLinks);
+        try {
+            try {
+                // open/create attribute file
+                int afd = openat(fd, nameAsBytes(file,name),
+                                 (O_CREAT|O_WRONLY|O_TRUNC|O_XATTR),
+                                 UnixFileModeAttribute.ALL_PERMISSIONS);
+
+                // wrap with channel
+                FileChannel fc = UnixChannelFactory.newFileChannel(afd, false, true);
+
+                // write value (nothing we can do if I/O error occurs)
+                try {
+                    int rem = src.remaining();
+                    while (src.hasRemaining()) {
+                        fc.write(src);
+                    }
+                    return rem;
+                } finally {
+                    fc.close();
+                }
+            } catch (UnixException x) {
+                throw new FileSystemException(file.getPathForExecptionMessage(),
+                    null, "Unable to write extended attribute '" + name +
+                    "': " + x.getMessage());
+            }
+        } finally {
+            close(fd);
+        }
+    }
+
+    @Override
+    public void delete(String name) throws IOException {
+        if (System.getSecurityManager() != null)
+            checkAccess(file.getPathForPermissionCheck(), false, true);
+
+        int fd = file.openForAttributeAccess(followLinks);
+        try {
+            int dfd = openat(fd, ".".getBytes(), (O_RDONLY|O_XATTR), 0);
+            try {
+                unlinkat(dfd, nameAsBytes(file,name), 0);
+            } finally {
+                close(dfd);
+            }
+        } catch (UnixException x) {
+            throw new FileSystemException(file.getPathForExecptionMessage(),
+                null, "Unable to delete extended attribute '" + name +
+                "': " + x.getMessage());
+        } finally {
+            close(fd);
+        }
+    }
+
+    /**
+     * Used by copyTo/moveTo to copy extended attributes from source to target.
+     *
+     * @param   ofd
+     *          file descriptor for source file
+     * @param   nfd
+     *          file descriptor for target file
+     */
+    static void copyExtendedAttributes(int ofd, int nfd) {
+        try {
+            // open extended attribute directory
+            int dfd = openat(ofd, ".".getBytes(), (O_RDONLY|O_XATTR), 0);
+            long dp = 0L;
+            try {
+                dp = fdopendir(dfd);
+            } catch (UnixException x) {
+                close(dfd);
+                throw x;
+            }
+
+            // copy each extended attribute
+            try {
+                byte[] name;
+                while ((name = readdir(dp)) != null) {
+                    // ignore "." and ".."
+                    if (name[0] == '.') {
+                        if (name.length == 1)
+                            continue;
+                        if (name.length == 2 && name[1] == '.')
+                            continue;
+                    }
+                    copyExtendedAttribute(ofd, name, nfd);
+                }
+            } finally {
+                closedir(dp);
+            }
+        } catch (UnixException ignore) {
+        }
+    }
+
+    private static void copyExtendedAttribute(int ofd, byte[] name, int nfd)
+        throws UnixException
+    {
+        // open source attribute file
+        int src = openat(ofd, name, (O_RDONLY|O_XATTR), 0);
+        try {
+            // create target attribute file
+            int dst = openat(nfd, name, (O_CREAT|O_WRONLY|O_TRUNC|O_XATTR),
+                UnixFileModeAttribute.ALL_PERMISSIONS);
+            try {
+                UnixCopyFile.transfer(dst, src, 0L);
+            } finally {
+                close(dst);
+            }
+        } finally {
+            close(src);
+        }
+    }
+}