Path: blob/master/src/java.base/linux/classes/sun/nio/fs/LinuxDosFileAttributeView.java
40948 views
/*1* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.nio.fs;2627import java.nio.file.attribute.*;28import java.util.Map;29import java.util.Set;30import java.io.IOException;31import jdk.internal.misc.Unsafe;3233import static sun.nio.fs.UnixNativeDispatcher.*;34import static sun.nio.fs.UnixConstants.*;3536/**37* Linux implementation of DosFileAttributeView for use on file systems such38* as ext3 that have extended attributes enabled and SAMBA configured to store39* DOS attributes.40*/4142class LinuxDosFileAttributeView43extends UnixFileAttributeViews.Basic implements DosFileAttributeView44{45private static final Unsafe unsafe = Unsafe.getUnsafe();4647private static final String READONLY_NAME = "readonly";48private static final String ARCHIVE_NAME = "archive";49private static final String SYSTEM_NAME = "system";50private static final String HIDDEN_NAME = "hidden";5152private static final String DOS_XATTR_NAME = "user.DOSATTRIB";53private static final byte[] DOS_XATTR_NAME_AS_BYTES = Util.toBytes(DOS_XATTR_NAME);5455private static final int DOS_XATTR_READONLY = 0x01;56private static final int DOS_XATTR_HIDDEN = 0x02;57private static final int DOS_XATTR_SYSTEM = 0x04;58private static final int DOS_XATTR_ARCHIVE = 0x20;5960// the names of the DOS attributes (includes basic)61private static final Set<String> dosAttributeNames =62Util.newSet(basicAttributeNames, READONLY_NAME, ARCHIVE_NAME, SYSTEM_NAME, HIDDEN_NAME);6364LinuxDosFileAttributeView(UnixPath file, boolean followLinks) {65super(file, followLinks);66}6768@Override69public String name() {70return "dos";71}7273@Override74public void setAttribute(String attribute, Object value)75throws IOException76{77if (attribute.equals(READONLY_NAME)) {78setReadOnly((Boolean)value);79return;80}81if (attribute.equals(ARCHIVE_NAME)) {82setArchive((Boolean)value);83return;84}85if (attribute.equals(SYSTEM_NAME)) {86setSystem((Boolean)value);87return;88}89if (attribute.equals(HIDDEN_NAME)) {90setHidden((Boolean)value);91return;92}93super.setAttribute(attribute, value);94}9596@Override97public Map<String,Object> readAttributes(String[] attributes)98throws IOException99{100AttributesBuilder builder =101AttributesBuilder.create(dosAttributeNames, attributes);102DosFileAttributes attrs = readAttributes();103addRequestedBasicAttributes(attrs, builder);104if (builder.match(READONLY_NAME))105builder.add(READONLY_NAME, attrs.isReadOnly());106if (builder.match(ARCHIVE_NAME))107builder.add(ARCHIVE_NAME, attrs.isArchive());108if (builder.match(SYSTEM_NAME))109builder.add(SYSTEM_NAME, attrs.isSystem());110if (builder.match(HIDDEN_NAME))111builder.add(HIDDEN_NAME, attrs.isHidden());112return builder.unmodifiableMap();113}114115@Override116public DosFileAttributes readAttributes() throws IOException {117file.checkRead();118119int fd = -1;120try {121fd = file.openForAttributeAccess(followLinks);122final UnixFileAttributes attrs = UnixFileAttributes.get(fd);123final int dosAttribute = getDosAttribute(fd);124125return new DosFileAttributes() {126@Override127public FileTime lastModifiedTime() {128return attrs.lastModifiedTime();129}130@Override131public FileTime lastAccessTime() {132return attrs.lastAccessTime();133}134@Override135public FileTime creationTime() {136return attrs.creationTime();137}138@Override139public boolean isRegularFile() {140return attrs.isRegularFile();141}142@Override143public boolean isDirectory() {144return attrs.isDirectory();145}146@Override147public boolean isSymbolicLink() {148return attrs.isSymbolicLink();149}150@Override151public boolean isOther() {152return attrs.isOther();153}154@Override155public long size() {156return attrs.size();157}158@Override159public Object fileKey() {160return attrs.fileKey();161}162@Override163public boolean isReadOnly() {164return (dosAttribute & DOS_XATTR_READONLY) != 0;165}166@Override167public boolean isHidden() {168return (dosAttribute & DOS_XATTR_HIDDEN) != 0;169}170@Override171public boolean isArchive() {172return (dosAttribute & DOS_XATTR_ARCHIVE) != 0;173}174@Override175public boolean isSystem() {176return (dosAttribute & DOS_XATTR_SYSTEM) != 0;177}178};179180} catch (UnixException x) {181x.rethrowAsIOException(file);182return null; // keep compiler happy183} finally {184close(fd);185}186}187188@Override189public void setReadOnly(boolean value) throws IOException {190updateDosAttribute(DOS_XATTR_READONLY, value);191}192193@Override194public void setHidden(boolean value) throws IOException {195updateDosAttribute(DOS_XATTR_HIDDEN, value);196}197198@Override199public void setArchive(boolean value) throws IOException {200updateDosAttribute(DOS_XATTR_ARCHIVE, value);201}202203@Override204public void setSystem(boolean value) throws IOException {205updateDosAttribute(DOS_XATTR_SYSTEM, value);206}207208/**209* Reads the value of the user.DOSATTRIB extended attribute210*/211private int getDosAttribute(int fd) throws UnixException {212final int size = 24;213214NativeBuffer buffer = NativeBuffers.getNativeBuffer(size);215try {216int len = LinuxNativeDispatcher217.fgetxattr(fd, DOS_XATTR_NAME_AS_BYTES, buffer.address(), size);218219if (len > 0) {220// ignore null terminator221if (unsafe.getByte(buffer.address()+len-1) == 0)222len--;223224// convert to String and parse225byte[] buf = new byte[len];226unsafe.copyMemory(null, buffer.address(), buf,227Unsafe.ARRAY_BYTE_BASE_OFFSET, len);228String value = Util.toString(buf);229230// should be something like 0x20231if (value.length() >= 3 && value.startsWith("0x")) {232try {233return Integer.parseInt(value.substring(2), 16);234} catch (NumberFormatException x) {235// ignore236}237}238}239throw new UnixException("Value of " + DOS_XATTR_NAME + " attribute is invalid");240} catch (UnixException x) {241// default value when attribute does not exist242if (x.errno() == ENODATA)243return 0;244throw x;245} finally {246buffer.release();247}248}249250/**251* Updates the value of the user.DOSATTRIB extended attribute252*/253private void updateDosAttribute(int flag, boolean enable) throws IOException {254file.checkWrite();255256int fd = -1;257try {258fd = file.openForAttributeAccess(followLinks);259int oldValue = getDosAttribute(fd);260int newValue = oldValue;261if (enable) {262newValue |= flag;263} else {264newValue &= ~flag;265}266if (newValue != oldValue) {267byte[] value = Util.toBytes("0x" + Integer.toHexString(newValue));268NativeBuffer buffer = NativeBuffers.asNativeBuffer(value);269try {270LinuxNativeDispatcher.fsetxattr(fd, DOS_XATTR_NAME_AS_BYTES,271buffer.address(), value.length+1);272} finally {273buffer.release();274}275}276} catch (UnixException x) {277x.rethrowAsIOException(file);278} finally {279close(fd);280}281}282}283284285