hadoop FsPermission 源码

  • 2022-10-20
  • 浏览 (421)

haddop FsPermission 代码

文件路径:/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/permission/FsPermission.java

/**
 * 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.
   * @param permission permission.
   * @return FsPermission.
   */
  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 mode.
   * @see #toShort()
   */
  public FsPermission(short mode) { fromShort(mode); }

  /**
   * Construct by the given mode.
   *
   * octal mask is applied.
   *
   *<pre>
   *              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
   *</pre>
   *
   * 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 <code>mode</code> is invalid
   */
  public FsPermission(String mode) {
    this(new RawParser(mode).getPermission());
  }

  /**
   * @return Return user {@link FsAction}.
   */
  public FsAction getUserAction() {return useraction;}

  /**
   * @return Return group {@link FsAction}.
   */
  public FsAction getGroupAction() {return groupaction;}

  /**
   * @return 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.
   * @return masked.
   */
  public FsPermission getMasked() {
    return null;
  }

  /**
   * Get unmasked permission if exists.
   * @return unmasked.
   */
  public FsPermission getUnmasked() {
    return null;
  }

  /**
   * Create and initialize a {@link FsPermission} from {@link DataInput}.
   *
   * @param in data input.
   * @throws IOException raised on errors performing I/O.
   * @return FsPermission.
   */
  public static FsPermission read(DataInput in) throws IOException {
    FsPermission p = new FsPermission();
    p.fromShort(in.readShort());
    return p;
  }

  /**
   * Encode the object to a short.
   * @return 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.
   *
   * @param conf configuration.
   * @return FsPermission UMask.
   */
  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.
   *
   * @return if the file is encrypted or directory
   * is in an encryption zone true, not false.
   *
   * @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.
   *
   * @return if the file or directory is
   * erasure coded true, not false.
   * @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)
   * @param conf configuration.
   * @param umask 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.
   *
   * @return Default FsPermission.
   */
  public static FsPermission getDefault() {
    return new FsPermission((short)00777);
  }

  /**
   * Get the default permission for directory.
   *
   * @return DirDefault FsPermission.
   */
  public static FsPermission getDirDefault() {
    return new FsPermission((short)00777);
  }

  /**
   * Get the default permission for file.
   *
   * @return FileDefault FsPermission.
   */
  public static FsPermission getFileDefault() {
    return new FsPermission((short)00666);
  }

  /**
   * Get the default permission for cache pools.
   *
   * @return CachePoolDefault FsPermission.
   */
  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-"
   * @return FsPermission.
   */
  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");
    }
  }
}

相关信息

hadoop 源码目录

相关文章

hadoop AclEntry 源码

hadoop AclEntryScope 源码

hadoop AclEntryType 源码

hadoop AclStatus 源码

hadoop AclUtil 源码

hadoop ChmodParser 源码

hadoop FsAction 源码

hadoop FsCreateModes 源码

hadoop PermissionParser 源码

hadoop PermissionStatus 源码

0  赞