All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.hadoop.fs.permission.FsPermission Maven / Gradle / Ivy

There is a newer version: 3.4.1
Show newest version
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.hadoop.fs.permission;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputValidation;
import java.io.Serializable;

import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.CommonConfigurationKeys;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.WritableFactories;
import org.apache.hadoop.io.WritableFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A class for file/directory permissions.
 */
@InterfaceAudience.Public
@InterfaceStability.Stable
public class FsPermission implements Writable, Serializable,
    ObjectInputValidation {
  private static final Logger LOG = LoggerFactory.getLogger(FsPermission.class);
  private static final long serialVersionUID = 0x2fe08564;

  static final WritableFactory FACTORY = new WritableFactory() {
    @Override
    public Writable newInstance() { return new FsPermission(); }
  };
  static {                                      // register a ctor
    WritableFactories.setFactory(FsPermission.class, FACTORY);
    WritableFactories.setFactory(ImmutableFsPermission.class, FACTORY);
  }

  /** Maximum acceptable length of a permission string to parse */
  public static final int MAX_PERMISSION_LENGTH = 10;

  /** Create an immutable {@link FsPermission} object. */
  public static FsPermission createImmutable(short permission) {
    return new ImmutableFsPermission(permission);
  }

  //POSIX permission style
  private FsAction useraction = null;
  private FsAction groupaction = null;
  private FsAction otheraction = null;
  private Boolean stickyBit = false;

  private FsPermission() {}

  /**
   * Construct by the given {@link FsAction}.
   * @param u user action
   * @param g group action
   * @param o other action
   */
  public FsPermission(FsAction u, FsAction g, FsAction o) {
    this(u, g, o, false);
  }

  public FsPermission(FsAction u, FsAction g, FsAction o, boolean sb) {
    set(u, g, o, sb);
  }

  /**
   * Construct by the given mode.
   * @param mode
   * @see #toShort()
   */
  public FsPermission(short mode) { fromShort(mode); }

  /**
   * Construct by the given mode.
   *
   * octal mask is applied.
   *
   *
   *              before mask     after mask    file type   sticky bit
   *
   *    octal     100644            644         file          no
   *    decimal    33188            420
   *
   *    octal     101644           1644         file          yes
   *    decimal    33700           1420
   *
   *    octal      40644            644         directory     no
   *    decimal    16804            420
   *
   *    octal      41644           1644         directory     yes
   *    decimal    17316           1420
   *
* * 100644 becomes 644 while 644 remains as 644 * * @param mode Mode is supposed to come from the result of native stat() call. * It contains complete permission information: rwxrwxrwx, sticky * bit, whether it is a directory or a file, etc. Upon applying * mask, only permission and sticky bit info will be kept because * they are the only parts to be used for now. * @see #FsPermission(short mode) */ public FsPermission(int mode) { this((short)(mode & 01777)); } /** * Copy constructor * * @param other other permission */ public FsPermission(FsPermission other) { this.useraction = other.useraction; this.groupaction = other.groupaction; this.otheraction = other.otheraction; this.stickyBit = other.stickyBit; } /** * Construct by given mode, either in octal or symbolic format. * @param mode mode as a string, either in octal or symbolic format * @throws IllegalArgumentException if mode is invalid */ public FsPermission(String mode) { this(new RawParser(mode).getPermission()); } /** Return user {@link FsAction}. */ public FsAction getUserAction() {return useraction;} /** Return group {@link FsAction}. */ public FsAction getGroupAction() {return groupaction;} /** Return other {@link FsAction}. */ public FsAction getOtherAction() {return otheraction;} private void set(FsAction u, FsAction g, FsAction o, boolean sb) { useraction = u; groupaction = g; otheraction = o; stickyBit = sb; } public void fromShort(short n) { FsAction[] v = FSACTION_VALUES; set(v[(n >>> 6) & 7], v[(n >>> 3) & 7], v[n & 7], (((n >>> 9) & 1) == 1) ); } @Override @Deprecated public void write(DataOutput out) throws IOException { out.writeShort(toShort()); } @Override @Deprecated public void readFields(DataInput in) throws IOException { fromShort(in.readShort()); } /** * Get masked permission if exists. */ public FsPermission getMasked() { return null; } /** * Get unmasked permission if exists. */ public FsPermission getUnmasked() { return null; } /** * Create and initialize a {@link FsPermission} from {@link DataInput}. */ public static FsPermission read(DataInput in) throws IOException { FsPermission p = new FsPermission(); p.fromShort(in.readShort()); return p; } /** * Encode the object to a short. */ public short toShort() { int s = (stickyBit ? 1 << 9 : 0) | (useraction.ordinal() << 6) | (groupaction.ordinal() << 3) | otheraction.ordinal(); return (short)s; } /** * Encodes the object to a short. Unlike {@link #toShort()}, this method may * return values outside the fixed range 00000 - 01777 if extended features * are encoded into this permission, such as the ACL bit. * * @return short extended short representation of this permission */ @Deprecated public short toExtendedShort() { return toShort(); } /** * Returns the FsPermission in an octal format. * * @return short Unlike {@link #toShort()} which provides a binary * representation, this method returns the standard octal style permission. */ public short toOctal() { int n = this.toShort(); int octal = (n>>>9&1)*1000 + (n>>>6&7)*100 + (n>>>3&7)*10 + (n&7); return (short)octal; } @Override public boolean equals(Object obj) { if (obj instanceof FsPermission) { FsPermission that = (FsPermission)obj; return this.useraction == that.useraction && this.groupaction == that.groupaction && this.otheraction == that.otheraction && this.stickyBit.booleanValue() == that.stickyBit.booleanValue(); } return false; } @Override public int hashCode() {return toShort();} @Override public String toString() { String str = useraction.SYMBOL + groupaction.SYMBOL + otheraction.SYMBOL; if(stickyBit) { StringBuilder str2 = new StringBuilder(str); str2.replace(str2.length() - 1, str2.length(), otheraction.implies(FsAction.EXECUTE) ? "t" : "T"); str = str2.toString(); } return str; } /** * Apply a umask to this permission and return a new one. * * The umask is used by create, mkdir, and other Hadoop filesystem operations. * The mode argument for these operations is modified by removing the bits * which are set in the umask. Thus, the umask limits the permissions which * newly created files and directories get. * * @param umask The umask to use * * @return The effective permission */ public FsPermission applyUMask(FsPermission umask) { return new FsPermission(useraction.and(umask.useraction.not()), groupaction.and(umask.groupaction.not()), otheraction.and(umask.otheraction.not())); } public static final String UMASK_LABEL = CommonConfigurationKeys.FS_PERMISSIONS_UMASK_KEY; public static final int DEFAULT_UMASK = CommonConfigurationKeys.FS_PERMISSIONS_UMASK_DEFAULT; private static final FsAction[] FSACTION_VALUES = FsAction.values(); /** * Get the user file creation mask (umask) * * {@code UMASK_LABEL} config param has umask value that is either symbolic * or octal. * * Symbolic umask is applied relative to file mode creation mask; * the permission op characters '+' clears the corresponding bit in the mask, * '-' sets bits in the mask. * * Octal umask, the specified bits are set in the file mode creation mask. */ public static FsPermission getUMask(Configuration conf) { int umask = DEFAULT_UMASK; // To ensure backward compatibility first use the deprecated key. // If the deprecated key is not present then check for the new key if(conf != null) { String confUmask = conf.get(UMASK_LABEL); try { if(confUmask != null) { umask = new UmaskParser(confUmask).getUMask(); } } catch(IllegalArgumentException iae) { // Provide more explanation for user-facing message String type = iae instanceof NumberFormatException ? "decimal" : "octal or symbolic"; String error = "Unable to parse configuration " + UMASK_LABEL + " with value " + confUmask + " as " + type + " umask."; LOG.warn(error); throw new IllegalArgumentException(error); } } return new FsPermission((short)umask); } public boolean getStickyBit() { return stickyBit; } /** * Returns true if there is also an ACL (access control list). * * @return boolean true if there is also an ACL (access control list). * @deprecated Get acl bit from the {@link org.apache.hadoop.fs.FileStatus} * object. */ @Deprecated public boolean getAclBit() { // File system subclasses that support the ACL bit would override this. return false; } /** * Returns true if the file is encrypted or directory is in an encryption zone * @deprecated Get encryption bit from the * {@link org.apache.hadoop.fs.FileStatus} object. */ @Deprecated public boolean getEncryptedBit() { return false; } /** * Returns true if the file or directory is erasure coded. * @deprecated Get ec bit from the {@link org.apache.hadoop.fs.FileStatus} * object. */ @Deprecated public boolean getErasureCodedBit() { return false; } /** Set the user file creation mask (umask) */ public static void setUMask(Configuration conf, FsPermission umask) { conf.set(UMASK_LABEL, String.format("%1$03o", umask.toShort())); } /** * Get the default permission for directory and symlink. * In previous versions, this default permission was also used to * create files, so files created end up with ugo+x permission. * See HADOOP-9155 for detail. * Two new methods are added to solve this, please use * {@link FsPermission#getDirDefault()} for directory, and use * {@link FsPermission#getFileDefault()} for file. * This method is kept for compatibility. */ public static FsPermission getDefault() { return new FsPermission((short)00777); } /** * Get the default permission for directory. */ public static FsPermission getDirDefault() { return new FsPermission((short)00777); } /** * Get the default permission for file. */ public static FsPermission getFileDefault() { return new FsPermission((short)00666); } /** * Get the default permission for cache pools. */ public static FsPermission getCachePoolDefault() { return new FsPermission((short)00755); } /** * Create a FsPermission from a Unix symbolic permission string * @param unixSymbolicPermission e.g. "-rw-rw-rw-" */ public static FsPermission valueOf(String unixSymbolicPermission) { if (unixSymbolicPermission == null) { return null; } else if (unixSymbolicPermission.length() != MAX_PERMISSION_LENGTH) { throw new IllegalArgumentException(String.format( "length != %d(unixSymbolicPermission=%s)", MAX_PERMISSION_LENGTH, unixSymbolicPermission)); } int n = 0; for(int i = 1; i < unixSymbolicPermission.length(); i++) { n = n << 1; char c = unixSymbolicPermission.charAt(i); n += (c == '-' || c == 'T' || c == 'S') ? 0: 1; } // Add sticky bit value if set if(unixSymbolicPermission.charAt(9) == 't' || unixSymbolicPermission.charAt(9) == 'T') n += 01000; return new FsPermission((short)n); } private static class ImmutableFsPermission extends FsPermission { private static final long serialVersionUID = 0x1bab54bd; public ImmutableFsPermission(short permission) { super(permission); } @Override public void readFields(DataInput in) throws IOException { throw new UnsupportedOperationException(); } } @Override public void validateObject() throws InvalidObjectException { if (null == useraction || null == groupaction || null == otheraction) { throw new InvalidObjectException("Invalid mode in FsPermission"); } if (null == stickyBit) { throw new InvalidObjectException("No sticky bit in FsPermission"); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy