1 /** 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 package org.apache.hadoop.fs.permission; 19 20 import java.io.DataInput; 21 import java.io.DataOutput; 22 import java.io.IOException; 23 24 import org.apache.commons.logging.Log; 25 import org.apache.commons.logging.LogFactory; 26 import org.apache.hadoop.conf.Configuration; 27 import org.apache.hadoop.io.Writable; 28 import org.apache.hadoop.io.WritableFactories; 29 import org.apache.hadoop.io.WritableFactory; 30 31 /** 32 * A class for file/directory permissions. 33 */ 34 public class FsPermission implements Writable { 35 private static final Log LOG = LogFactory.getLog(FsPermission.class); 36 37 static final WritableFactory FACTORY = new WritableFactory() { 38 public Writable newInstance() { return new FsPermission(); } 39 }; 40 static { // register a ctor WritableFactories.setFactory(FsPermission.class, FACTORY)41 WritableFactories.setFactory(FsPermission.class, FACTORY); WritableFactories.setFactory(ImmutableFsPermission.class, FACTORY)42 WritableFactories.setFactory(ImmutableFsPermission.class, FACTORY); 43 } 44 45 /** Create an immutable {@link FsPermission} object. */ createImmutable(short permission)46 public static FsPermission createImmutable(short permission) { 47 return new ImmutableFsPermission(permission); 48 } 49 50 //POSIX permission style 51 private FsAction useraction = null; 52 private FsAction groupaction = null; 53 private FsAction otheraction = null; 54 FsPermission()55 private FsPermission() {} 56 57 /** 58 * Construct by the given {@link FsAction}. 59 * @param u user action 60 * @param g group action 61 * @param o other action 62 */ FsPermission(FsAction u, FsAction g, FsAction o)63 public FsPermission(FsAction u, FsAction g, FsAction o) {set(u, g, o);} 64 65 /** 66 * Construct by the given mode. 67 * @param mode 68 * @see #toShort() 69 */ FsPermission(short mode)70 public FsPermission(short mode) { fromShort(mode); } 71 72 /** 73 * Copy constructor 74 * 75 * @param other other permission 76 */ FsPermission(FsPermission other)77 public FsPermission(FsPermission other) { 78 this.useraction = other.useraction; 79 this.groupaction = other.groupaction; 80 this.otheraction = other.otheraction; 81 } 82 83 /** 84 * Construct by given mode, either in octal or symbolic format. 85 * @param mode mode as a string, either in octal or symbolic format 86 * @throws IllegalArgumentException if <code>mode</code> is invalid 87 */ FsPermission(String mode)88 public FsPermission(String mode) { 89 this(new UmaskParser(mode).getUMask()); 90 } 91 92 /** Return user {@link FsAction}. */ getUserAction()93 public FsAction getUserAction() {return useraction;} 94 95 /** Return group {@link FsAction}. */ getGroupAction()96 public FsAction getGroupAction() {return groupaction;} 97 98 /** Return other {@link FsAction}. */ getOtherAction()99 public FsAction getOtherAction() {return otheraction;} 100 set(FsAction u, FsAction g, FsAction o)101 private void set(FsAction u, FsAction g, FsAction o) { 102 useraction = u; 103 groupaction = g; 104 otheraction = o; 105 } fromShort(short n)106 public void fromShort(short n) { 107 FsAction[] v = FsAction.values(); 108 set(v[(n >>> 6) & 7], v[(n >>> 3) & 7], v[n & 7]); 109 } 110 111 /** {@inheritDoc} */ write(DataOutput out)112 public void write(DataOutput out) throws IOException { 113 out.writeShort(toShort()); 114 } 115 116 /** {@inheritDoc} */ readFields(DataInput in)117 public void readFields(DataInput in) throws IOException { 118 fromShort(in.readShort()); 119 } 120 121 /** 122 * Create and initialize a {@link FsPermission} from {@link DataInput}. 123 */ read(DataInput in)124 public static FsPermission read(DataInput in) throws IOException { 125 FsPermission p = new FsPermission(); 126 p.readFields(in); 127 return p; 128 } 129 130 /** 131 * Encode the object to a short. 132 */ toShort()133 public short toShort() { 134 int s = (useraction.ordinal() << 6) | (groupaction.ordinal() << 3) | 135 otheraction.ordinal(); 136 return (short)s; 137 } 138 139 /** {@inheritDoc} */ equals(Object obj)140 public boolean equals(Object obj) { 141 if (obj instanceof FsPermission) { 142 FsPermission that = (FsPermission)obj; 143 return this.useraction == that.useraction 144 && this.groupaction == that.groupaction 145 && this.otheraction == that.otheraction; 146 } 147 return false; 148 } 149 150 /** {@inheritDoc} */ hashCode()151 public int hashCode() {return toShort();} 152 153 /** {@inheritDoc} */ toString()154 public String toString() { 155 return useraction.SYMBOL + groupaction.SYMBOL + otheraction.SYMBOL; 156 } 157 158 /** Apply a umask to this permission and return a new one */ applyUMask(FsPermission umask)159 public FsPermission applyUMask(FsPermission umask) { 160 return new FsPermission(useraction.and(umask.useraction.not()), 161 groupaction.and(umask.groupaction.not()), 162 otheraction.and(umask.otheraction.not())); 163 } 164 165 /** umask property label */ 166 public static final String DEPRECATED_UMASK_LABEL = "dfs.umask"; 167 public static final String UMASK_LABEL = "dfs.umaskmode"; 168 public static final int DEFAULT_UMASK = 0022; 169 170 /** 171 * Get the user file creation mask (umask) 172 * 173 * {@code UMASK_LABEL} config param has umask value that is either symbolic 174 * or octal. 175 * 176 * Symbolic umask is applied relative to file mode creation mask; 177 * the permission op characters '+' clears the corresponding bit in the mask, 178 * '-' sets bits in the mask. 179 * 180 * Octal umask, the specified bits are set in the file mode creation mask. 181 * 182 * {@code DEPRECATED_UMASK_LABEL} config param has umask value set to decimal. 183 */ getUMask(Configuration conf)184 public static FsPermission getUMask(Configuration conf) { 185 int umask = DEFAULT_UMASK; 186 187 // To ensure backward compatibility first use the deprecated key. 188 // If the deprecated key is not present then check for the new key 189 if(conf != null) { 190 int oldStyleValue = conf.getInt(DEPRECATED_UMASK_LABEL, Integer.MIN_VALUE); 191 if(oldStyleValue != Integer.MIN_VALUE) { // Property was set with old key 192 LOG.warn(DEPRECATED_UMASK_LABEL + " configuration key is deprecated. " + 193 "Convert to " + UMASK_LABEL + ", using octal or symbolic umask " + 194 "specifications."); 195 umask = oldStyleValue; 196 } else { 197 String confUmask = conf.get(UMASK_LABEL); 198 if(confUmask != null) { // UMASK_LABEL is set 199 return new FsPermission(confUmask); 200 } 201 } 202 } 203 204 return new FsPermission((short)umask); 205 } 206 207 /** Set the user file creation mask (umask) */ setUMask(Configuration conf, FsPermission umask)208 public static void setUMask(Configuration conf, FsPermission umask) { 209 conf.set(UMASK_LABEL, String.format("%1$03o", umask.toShort())); 210 } 211 212 /** Get the default permission. */ getDefault()213 public static FsPermission getDefault() { 214 return new FsPermission((short)0777); 215 } 216 217 /** 218 * Create a FsPermission from a Unix symbolic permission string 219 * @param unixSymbolicPermission e.g. "-rw-rw-rw-" 220 */ valueOf(String unixSymbolicPermission)221 public static FsPermission valueOf(String unixSymbolicPermission) { 222 if (unixSymbolicPermission == null) { 223 return null; 224 } 225 else if (unixSymbolicPermission.length() != 10) { 226 throw new IllegalArgumentException("length != 10(unixSymbolicPermission=" 227 + unixSymbolicPermission + ")"); 228 } 229 int n = 0; 230 for(int i = 1; i < unixSymbolicPermission.length(); i++) { 231 n = n << 1; 232 char c = unixSymbolicPermission.charAt(i); 233 n += (c == '-' || c == 'T' || c == 'S') ? 0: 1; 234 } 235 return new FsPermission((short)n); 236 } 237 238 private static class ImmutableFsPermission extends FsPermission { ImmutableFsPermission(short permission)239 public ImmutableFsPermission(short permission) { 240 super(permission); 241 } applyUMask(FsPermission umask)242 public FsPermission applyUMask(FsPermission umask) { 243 throw new UnsupportedOperationException(); 244 } readFields(DataInput in)245 public void readFields(DataInput in) throws IOException { 246 throw new UnsupportedOperationException(); 247 } 248 } 249 } 250