Path: blob/master/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java
41137 views
/*1* Copyright (c) 2008, 2021, 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.*;28import java.nio.file.attribute.*;29import java.util.*;30import java.util.concurrent.TimeUnit;31import java.io.IOException;3233import static sun.nio.fs.UnixNativeDispatcher.*;3435class UnixFileAttributeViews {3637static class Basic extends AbstractBasicFileAttributeView {38protected final UnixPath file;39protected final boolean followLinks;4041Basic(UnixPath file, boolean followLinks) {42this.file = file;43this.followLinks = followLinks;44}4546@Override47public BasicFileAttributes readAttributes() throws IOException {48file.checkRead();49try {50UnixFileAttributes attrs =51UnixFileAttributes.get(file, followLinks);52return attrs.asBasicFileAttributes();53} catch (UnixException x) {54x.rethrowAsIOException(file);55return null; // keep compiler happy56}57}5859@Override60public void setTimes(FileTime lastModifiedTime,61FileTime lastAccessTime,62FileTime createTime) throws IOException63{64// null => don't change65if (lastModifiedTime == null && lastAccessTime == null) {66// no effect67return;68}6970// permission check71file.checkWrite();7273boolean haveFd = false;74boolean useFutimes = false;75boolean useFutimens = false;76boolean useLutimes = false;77int fd = -1;78try {79if (!followLinks) {80useLutimes = lutimesSupported() &&81UnixFileAttributes.get(file, false).isSymbolicLink();82}83if (!useLutimes) {84fd = file.openForAttributeAccess(followLinks);85if (fd != -1) {86haveFd = true;87if (!(useFutimens = futimensSupported())) {88useFutimes = futimesSupported();89}90}91}92} catch (UnixException x) {93if (!(x.errno() == UnixConstants.ENXIO ||94(x.errno() == UnixConstants.ELOOP && useLutimes))) {95x.rethrowAsIOException(file);96}97}9899try {100// assert followLinks || !UnixFileAttributes.get(fd).isSymbolicLink();101102// if not changing both attributes then need existing attributes103if (lastModifiedTime == null || lastAccessTime == null) {104try {105UnixFileAttributes attrs = haveFd ?106UnixFileAttributes.get(fd) :107UnixFileAttributes.get(file, followLinks);108if (lastModifiedTime == null)109lastModifiedTime = attrs.lastModifiedTime();110if (lastAccessTime == null)111lastAccessTime = attrs.lastAccessTime();112} catch (UnixException x) {113x.rethrowAsIOException(file);114}115}116117// update times118TimeUnit timeUnit = useFutimens ?119TimeUnit.NANOSECONDS : TimeUnit.MICROSECONDS;120long modValue = lastModifiedTime.to(timeUnit);121long accessValue= lastAccessTime.to(timeUnit);122123boolean retry = false;124try {125if (useFutimens) {126futimens(fd, accessValue, modValue);127} else if (useFutimes) {128futimes(fd, accessValue, modValue);129} else if (useLutimes) {130lutimes(file, accessValue, modValue);131} else {132utimes(file, accessValue, modValue);133}134} catch (UnixException x) {135// if futimes/utimes fails with EINVAL and one/both of the times is136// negative then we adjust the value to the epoch and retry.137if (x.errno() == UnixConstants.EINVAL &&138(modValue < 0L || accessValue < 0L)) {139retry = true;140} else {141x.rethrowAsIOException(file);142}143}144if (retry) {145if (modValue < 0L) modValue = 0L;146if (accessValue < 0L) accessValue= 0L;147try {148if (useFutimens) {149futimens(fd, accessValue, modValue);150} else if (useFutimes) {151futimes(fd, accessValue, modValue);152} else if (useLutimes) {153lutimes(file, accessValue, modValue);154} else {155utimes(file, accessValue, modValue);156}157} catch (UnixException x) {158x.rethrowAsIOException(file);159}160}161} finally {162close(fd);163}164}165}166167private static class Posix extends Basic implements PosixFileAttributeView {168private static final String PERMISSIONS_NAME = "permissions";169private static final String OWNER_NAME = "owner";170private static final String GROUP_NAME = "group";171172// the names of the posix attributes (includes basic)173static final Set<String> posixAttributeNames =174Util.newSet(basicAttributeNames, PERMISSIONS_NAME, OWNER_NAME, GROUP_NAME);175176Posix(UnixPath file, boolean followLinks) {177super(file, followLinks);178}179180final void checkReadExtended() {181@SuppressWarnings("removal")182SecurityManager sm = System.getSecurityManager();183if (sm != null) {184file.checkRead();185sm.checkPermission(new RuntimePermission("accessUserInformation"));186}187}188189final void checkWriteExtended() {190@SuppressWarnings("removal")191SecurityManager sm = System.getSecurityManager();192if (sm != null) {193file.checkWrite();194sm.checkPermission(new RuntimePermission("accessUserInformation"));195}196}197198@Override199public String name() {200return "posix";201}202203@Override204@SuppressWarnings("unchecked")205public void setAttribute(String attribute, Object value)206throws IOException207{208if (attribute.equals(PERMISSIONS_NAME)) {209setPermissions((Set<PosixFilePermission>)value);210return;211}212if (attribute.equals(OWNER_NAME)) {213setOwner((UserPrincipal)value);214return;215}216if (attribute.equals(GROUP_NAME)) {217setGroup((GroupPrincipal)value);218return;219}220super.setAttribute(attribute, value);221}222223/**224* Invoked by readAttributes or sub-classes to add all matching posix225* attributes to the builder226*/227final void addRequestedPosixAttributes(PosixFileAttributes attrs,228AttributesBuilder builder)229{230addRequestedBasicAttributes(attrs, builder);231if (builder.match(PERMISSIONS_NAME))232builder.add(PERMISSIONS_NAME, attrs.permissions());233if (builder.match(OWNER_NAME))234builder.add(OWNER_NAME, attrs.owner());235if (builder.match(GROUP_NAME))236builder.add(GROUP_NAME, attrs.group());237}238239@Override240public Map<String,Object> readAttributes(String[] requested)241throws IOException242{243AttributesBuilder builder =244AttributesBuilder.create(posixAttributeNames, requested);245PosixFileAttributes attrs = readAttributes();246addRequestedPosixAttributes(attrs, builder);247return builder.unmodifiableMap();248}249250@Override251public UnixFileAttributes readAttributes() throws IOException {252checkReadExtended();253try {254return UnixFileAttributes.get(file, followLinks);255} catch (UnixException x) {256x.rethrowAsIOException(file);257return null; // keep compiler happy258}259}260261// chmod262final void setMode(int mode) throws IOException {263checkWriteExtended();264try {265if (followLinks) {266chmod(file, mode);267} else {268int fd = file.openForAttributeAccess(false);269try {270fchmod(fd, mode);271} finally {272close(fd);273}274}275} catch (UnixException x) {276x.rethrowAsIOException(file);277}278}279280// chown281final void setOwners(int uid, int gid) throws IOException {282checkWriteExtended();283try {284if (followLinks) {285chown(file, uid, gid);286} else {287lchown(file, uid, gid);288}289} catch (UnixException x) {290x.rethrowAsIOException(file);291}292}293294@Override295public void setPermissions(Set<PosixFilePermission> perms)296throws IOException297{298setMode(UnixFileModeAttribute.toUnixMode(perms));299}300301@Override302public void setOwner(UserPrincipal owner)303throws IOException304{305if (owner == null)306throw new NullPointerException("'owner' is null");307if (!(owner instanceof UnixUserPrincipals.User))308throw new ProviderMismatchException();309if (owner instanceof UnixUserPrincipals.Group)310throw new IOException("'owner' parameter can't be a group");311int uid = ((UnixUserPrincipals.User)owner).uid();312setOwners(uid, -1);313}314315@Override316public UserPrincipal getOwner() throws IOException {317return readAttributes().owner();318}319320@Override321public void setGroup(GroupPrincipal group)322throws IOException323{324if (group == null)325throw new NullPointerException("'owner' is null");326if (!(group instanceof UnixUserPrincipals.Group))327throw new ProviderMismatchException();328int gid = ((UnixUserPrincipals.Group)group).gid();329setOwners(-1, gid);330}331}332333private static class Unix extends Posix {334private static final String MODE_NAME = "mode";335private static final String INO_NAME = "ino";336private static final String DEV_NAME = "dev";337private static final String RDEV_NAME = "rdev";338private static final String NLINK_NAME = "nlink";339private static final String UID_NAME = "uid";340private static final String GID_NAME = "gid";341private static final String CTIME_NAME = "ctime";342343// the names of the unix attributes (including posix)344static final Set<String> unixAttributeNames =345Util.newSet(posixAttributeNames,346MODE_NAME, INO_NAME, DEV_NAME, RDEV_NAME,347NLINK_NAME, UID_NAME, GID_NAME, CTIME_NAME);348349Unix(UnixPath file, boolean followLinks) {350super(file, followLinks);351}352353@Override354public String name() {355return "unix";356}357358@Override359public void setAttribute(String attribute, Object value)360throws IOException361{362if (attribute.equals(MODE_NAME)) {363setMode((Integer)value);364return;365}366if (attribute.equals(UID_NAME)) {367setOwners((Integer)value, -1);368return;369}370if (attribute.equals(GID_NAME)) {371setOwners(-1, (Integer)value);372return;373}374super.setAttribute(attribute, value);375}376377@Override378public Map<String,Object> readAttributes(String[] requested)379throws IOException380{381AttributesBuilder builder =382AttributesBuilder.create(unixAttributeNames, requested);383UnixFileAttributes attrs = readAttributes();384addRequestedPosixAttributes(attrs, builder);385if (builder.match(MODE_NAME))386builder.add(MODE_NAME, attrs.mode());387if (builder.match(INO_NAME))388builder.add(INO_NAME, attrs.ino());389if (builder.match(DEV_NAME))390builder.add(DEV_NAME, attrs.dev());391if (builder.match(RDEV_NAME))392builder.add(RDEV_NAME, attrs.rdev());393if (builder.match(NLINK_NAME))394builder.add(NLINK_NAME, attrs.nlink());395if (builder.match(UID_NAME))396builder.add(UID_NAME, attrs.uid());397if (builder.match(GID_NAME))398builder.add(GID_NAME, attrs.gid());399if (builder.match(CTIME_NAME))400builder.add(CTIME_NAME, attrs.ctime());401return builder.unmodifiableMap();402}403}404405static Basic createBasicView(UnixPath file, boolean followLinks) {406return new Basic(file, followLinks);407}408409static Posix createPosixView(UnixPath file, boolean followLinks) {410return new Posix(file, followLinks);411}412413static Unix createUnixView(UnixPath file, boolean followLinks) {414return new Unix(file, followLinks);415}416417static FileOwnerAttributeViewImpl createOwnerView(UnixPath file, boolean followLinks) {418return new FileOwnerAttributeViewImpl(createPosixView(file, followLinks));419}420}421422423