hadoop FsShellPermissions 源码

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

haddop FsShellPermissions 代码

文件路径:/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FsShellPermissions.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;

import java.io.IOException;
import java.util.LinkedList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.fs.permission.ChmodParser;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.fs.shell.CommandFactory;
import org.apache.hadoop.fs.shell.CommandFormat;
import org.apache.hadoop.fs.shell.FsCommand;
import org.apache.hadoop.fs.shell.PathData;
import org.apache.hadoop.util.Shell;
import org.slf4j.Logger;

/**
 * This class is the home for file permissions related commands.
 * Moved to this separate class since FsShell is getting too large.
 */
@InterfaceAudience.Private
@InterfaceStability.Unstable
public class FsShellPermissions extends FsCommand {

  static final Logger LOG = FsShell.LOG;
  
  /**
   * Register the permission related commands with the factory
   * @param factory the command factory
   */
  public static void registerCommands(CommandFactory factory) {
    factory.addClass(Chmod.class, "-chmod");
    factory.addClass(Chown.class, "-chown");
    factory.addClass(Chgrp.class, "-chgrp");
  }

  /**
   * The pattern is almost as flexible as mode allowed by chmod shell command.
   * The main restriction is that we recognize only rwxXt. To reduce errors we
   * also enforce octal mode specifications of either 3 digits without a sticky
   * bit setting or four digits with a sticky bit setting.
   */
  public static class Chmod extends FsShellPermissions {
    public static final String NAME = "chmod";
    public static final String USAGE = "[-R] <MODE[,MODE]... | OCTALMODE> PATH...";
    public static final String DESCRIPTION =
      "Changes permissions of a file. " +
      "This works similar to the shell's chmod command with a few exceptions.\n" +
      "-R: modifies the files recursively. This is the only option" +
      " currently supported.\n" +
      "<MODE>: Mode is the same as mode used for the shell's command. " +
      "The only letters recognized are 'rwxXt', e.g. +t,a+r,g-w,+rwx,o=r.\n" +
      "<OCTALMODE>: Mode specifed in 3 or 4 digits. If 4 digits, the first " +
      "may be 1 or 0 to turn the sticky bit on or off, respectively.  Unlike " +
      "the shell command, it is not possible to specify only part of the " +
      "mode, e.g. 754 is same as u=rwx,g=rx,o=r.\n\n" +
      "If none of 'augo' is specified, 'a' is assumed and unlike the " +
      "shell command, no umask is applied.";

    protected ChmodParser pp;

    @Override
    protected void processOptions(LinkedList<String> args) throws IOException {
      CommandFormat cf = new CommandFormat(2, Integer.MAX_VALUE, "R", null);
      cf.parse(args);
      setRecursive(cf.getOpt("R"));

      String modeStr = args.removeFirst();
      try {
        pp = new ChmodParser(modeStr);
      } catch (IllegalArgumentException iea) {
        // TODO: remove "chmod : " so it's not doubled up in output, but it's
        // here for backwards compatibility...
        throw new IllegalArgumentException(
            "chmod : mode '" + modeStr + "' does not match the expected pattern.");      
      }
    }
    
    @Override
    protected void processPath(PathData item) throws IOException {
      short newperms = pp.applyNewPermission(item.stat);
      if (item.stat.getPermission().toShort() != newperms) {
        try {
          item.fs.setPermission(item.path, new FsPermission(newperms));
        } catch (IOException e) {
          LOG.debug("Error changing permissions of " + item, e);
          throw new IOException(
              "changing permissions of '" + item + "': " + e.getMessage());
        }
      }
    }    
  }
  
  // used by chown/chgrp
  static private String allowedChars = Shell.WINDOWS ? "[-_./@a-zA-Z0-9 ]" :
    "[-+_./@a-zA-Z0-9]";

  /**
   * Used to change owner and/or group of files 
   */
  public static class Chown extends FsShellPermissions {
    public static final String NAME = "chown";
    public static final String USAGE = "[-R] [OWNER][:[GROUP]] PATH...";
    public static final String DESCRIPTION =
      "Changes owner and group of a file. " +
      "This is similar to the shell's chown command with a few exceptions.\n" +
      "-R: modifies the files recursively. This is the only option " +
      "currently supported.\n\n" +
      "If only the owner or group is specified, then only the owner or " +
      "group is modified. " +
      "The owner and group names may only consist of digits, alphabet, "+
      "and any of " + allowedChars + ". The names are case sensitive.\n\n" +
      "WARNING: Avoid using '.' to separate user name and group though " +
      "Linux allows it. If user names have dots in them and you are " +
      "using local file system, you might see surprising results since " +
      "the shell command 'chown' is used for local files.";

    ///allows only "allowedChars" above in names for owner and group
    static private final Pattern chownPattern = Pattern.compile(
        "^\\s*(" + allowedChars + "+)?([:](" + allowedChars + "*))?\\s*$");

    protected String owner = null;
    protected String group = null;

    @Override
    protected void processOptions(LinkedList<String> args) throws IOException {
      CommandFormat cf = new CommandFormat(2, Integer.MAX_VALUE, "R");
      cf.parse(args);
      setRecursive(cf.getOpt("R"));
      parseOwnerGroup(args.removeFirst());
    }
    
    /**
     * Parse the first argument into an owner and group
     * @param ownerStr string describing new ownership
     */
    protected void parseOwnerGroup(String ownerStr) {
      Matcher matcher = chownPattern.matcher(ownerStr);
      if (!matcher.matches()) {
        throw new IllegalArgumentException(
            "'" + ownerStr + "' does not match expected pattern for [owner][:group].");
      }
      owner = matcher.group(1);
      group = matcher.group(3);
      if (group != null && group.length() == 0) {
        group = null;
      }
      if (owner == null && group == null) {
        throw new IllegalArgumentException(
            "'" + ownerStr + "' does not specify owner or group.");
      }    
    }
    
    @Override
    protected void processPath(PathData item) throws IOException {
      //Should we do case insensitive match?
      String newOwner = (owner == null || owner.equals(item.stat.getOwner())) ?
                        null : owner;
      String newGroup = (group == null || group.equals(item.stat.getGroup())) ?
                        null : group;

      if (newOwner != null || newGroup != null) {
        try {
          item.fs.setOwner(item.path, newOwner, newGroup);
        } catch (IOException e) {
          LOG.debug("Error changing ownership of " + item, e);
          throw new IOException(
              "changing ownership of '" + item + "': " + e.getMessage());
        }
      }
    }
  }

  /**
   * Used to change group of files 
   */
  public static class Chgrp extends Chown {
    public static final String NAME = "chgrp";
    public static final String USAGE = "[-R] GROUP PATH...";
    public static final String DESCRIPTION =
      "This is equivalent to -chown ... :GROUP ...";

    static private final Pattern chgrpPattern = 
      Pattern.compile("^\\s*(" + allowedChars + "+)\\s*$");

    @Override
    protected void parseOwnerGroup(String groupStr) {
      Matcher matcher = chgrpPattern.matcher(groupStr);
      if (!matcher.matches()) {
        throw new IllegalArgumentException(
            "'" + groupStr + "' does not match expected pattern for group");
      }
      owner = null;
      group = matcher.group(1);
    }
  }
}

相关信息

hadoop 源码目录

相关文章

hadoop Abortable 源码

hadoop AbstractFileSystem 源码

hadoop AvroFSInput 源码

hadoop BBPartHandle 源码

hadoop BBUploadHandle 源码

hadoop BatchListingOperations 源码

hadoop BatchedRemoteIterator 源码

hadoop BlockLocation 源码

hadoop BlockStoragePolicySpi 源码

hadoop BufferedFSInputStream 源码

0  赞