Crossfire JXClient, Trunk
Chmod.java
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * - Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * - Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * - Neither the name of Oracle nor the names of its
16  * contributors may be used to endorse or promote products derived
17  * from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  * This source code is provided to illustrate the usage of a given feature
34  * or technique and has been deliberately simplified. Additional steps
35  * required for a production-quality application, such as security checks,
36  * input validation and proper error handling, might not be present in
37  * this sample code.
38  */
39 
40 
41 import java.nio.file.*;
42 import java.nio.file.attribute.*;
43 import static java.nio.file.attribute.PosixFilePermission.*;
44 import static java.nio.file.FileVisitResult.*;
45 import java.io.IOException;
46 import java.util.*;
47 
53 public class Chmod {
54 
115  public static Changer compile(String exprs) {
116  // minimum is who and operator (u= for example)
117  if (exprs.length() < 2)
118  throw new IllegalArgumentException("Invalid mode");
119 
120  // permissions that the changer will add or remove
121  final Set<PosixFilePermission> toAdd = new HashSet<PosixFilePermission>();
122  final Set<PosixFilePermission> toRemove = new HashSet<PosixFilePermission>();
123 
124  // iterate over each of expression modes
125  for (String expr: exprs.split(",")) {
126  // minimum of who and operator
127  if (expr.length() < 2)
128  throw new IllegalArgumentException("Invalid mode");
129 
130  int pos = 0;
131 
132  // who
133  boolean u = false;
134  boolean g = false;
135  boolean o = false;
136  boolean done = false;
137  for (;;) {
138  switch (expr.charAt(pos)) {
139  case 'u' : u = true; break;
140  case 'g' : g = true; break;
141  case 'o' : o = true; break;
142  case 'a' : u = true; g = true; o = true; break;
143  default : done = true;
144  }
145  if (done)
146  break;
147  pos++;
148  }
149  if (!u && !g && !o)
150  throw new IllegalArgumentException("Invalid mode");
151 
152  // get operator and permissions
153  char op = expr.charAt(pos++);
154  String mask = (expr.length() == pos) ? "" : expr.substring(pos);
155 
156  // operator
157  boolean add = (op == '+');
158  boolean remove = (op == '-');
159  boolean assign = (op == '=');
160  if (!add && !remove && !assign)
161  throw new IllegalArgumentException("Invalid mode");
162 
163  // who= means remove all
164  if (assign && mask.length() == 0) {
165  assign = false;
166  remove = true;
167  mask = "rwx";
168  }
169 
170  // permissions
171  boolean r = false;
172  boolean w = false;
173  boolean x = false;
174  for (int i=0; i<mask.length(); i++) {
175  switch (mask.charAt(i)) {
176  case 'r' : r = true; break;
177  case 'w' : w = true; break;
178  case 'x' : x = true; break;
179  default:
180  throw new IllegalArgumentException("Invalid mode");
181  }
182  }
183 
184  // update permissions set
185  if (add) {
186  if (u) {
187  if (r) toAdd.add(OWNER_READ);
188  if (w) toAdd.add(OWNER_WRITE);
189  if (x) toAdd.add(OWNER_EXECUTE);
190  }
191  if (g) {
192  if (r) toAdd.add(GROUP_READ);
193  if (w) toAdd.add(GROUP_WRITE);
194  if (x) toAdd.add(GROUP_EXECUTE);
195  }
196  if (o) {
197  if (r) toAdd.add(OTHERS_READ);
198  if (w) toAdd.add(OTHERS_WRITE);
199  if (x) toAdd.add(OTHERS_EXECUTE);
200  }
201  }
202  if (remove) {
203  if (u) {
204  if (r) toRemove.add(OWNER_READ);
205  if (w) toRemove.add(OWNER_WRITE);
206  if (x) toRemove.add(OWNER_EXECUTE);
207  }
208  if (g) {
209  if (r) toRemove.add(GROUP_READ);
210  if (w) toRemove.add(GROUP_WRITE);
211  if (x) toRemove.add(GROUP_EXECUTE);
212  }
213  if (o) {
214  if (r) toRemove.add(OTHERS_READ);
215  if (w) toRemove.add(OTHERS_WRITE);
216  if (x) toRemove.add(OTHERS_EXECUTE);
217  }
218  }
219  if (assign) {
220  if (u) {
221  if (r) toAdd.add(OWNER_READ);
222  else toRemove.add(OWNER_READ);
223  if (w) toAdd.add(OWNER_WRITE);
224  else toRemove.add(OWNER_WRITE);
225  if (x) toAdd.add(OWNER_EXECUTE);
226  else toRemove.add(OWNER_EXECUTE);
227  }
228  if (g) {
229  if (r) toAdd.add(GROUP_READ);
230  else toRemove.add(GROUP_READ);
231  if (w) toAdd.add(GROUP_WRITE);
232  else toRemove.add(GROUP_WRITE);
233  if (x) toAdd.add(GROUP_EXECUTE);
234  else toRemove.add(GROUP_EXECUTE);
235  }
236  if (o) {
237  if (r) toAdd.add(OTHERS_READ);
238  else toRemove.add(OTHERS_READ);
239  if (w) toAdd.add(OTHERS_WRITE);
240  else toRemove.add(OTHERS_WRITE);
241  if (x) toAdd.add(OTHERS_EXECUTE);
242  else toRemove.add(OTHERS_EXECUTE);
243  }
244  }
245  }
246 
247  // return changer
248  return new Changer() {
249  @Override
250  public Set<PosixFilePermission> change(Set<PosixFilePermission> perms) {
251  perms.addAll(toAdd);
252  perms.removeAll(toRemove);
253  return perms;
254  }
255  };
256  }
257 
261  public interface Changer {
270  Set<PosixFilePermission> change(Set<PosixFilePermission> perms);
271  }
272 
276  static void chmod(Path file, Changer changer) {
277  try {
278  Set<PosixFilePermission> perms = Files.getPosixFilePermissions(file);
279  Files.setPosixFilePermissions(file, changer.change(perms));
280  } catch (IOException x) {
281  System.err.println(x);
282  }
283  }
284 
288  static class TreeVisitor implements FileVisitor<Path> {
289  private final Changer changer;
290 
292  this.changer = changer;
293  }
294 
295  @Override
296  public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
297  chmod(dir, changer);
298  return CONTINUE;
299  }
300 
301  @Override
302  public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
303  chmod(file, changer);
304  return CONTINUE;
305  }
306 
307  @Override
308  public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
309  if (exc != null)
310  System.err.println("WARNING: " + exc);
311  return CONTINUE;
312  }
313 
314  @Override
315  public FileVisitResult visitFileFailed(Path file, IOException exc) {
316  System.err.println("WARNING: " + exc);
317  return CONTINUE;
318  }
319  }
320 
321  static void usage() {
322  System.err.println("java Chmod [-R] symbolic-mode-list file...");
323  System.exit(-1);
324  }
325 
326  public static void main(String[] args) throws IOException {
327  if (args.length < 2)
328  usage();
329  int argi = 0;
330  int maxDepth = 0;
331  if (args[argi].equals("-R")) {
332  if (args.length < 3)
333  usage();
334  argi++;
335  maxDepth = Integer.MAX_VALUE;
336  }
337 
338  // compile the symbolic mode expressions
339  Changer changer = compile(args[argi++]);
340  TreeVisitor visitor = new TreeVisitor(changer);
341 
342  Set<FileVisitOption> opts = Collections.emptySet();
343  while (argi < args.length) {
344  Path file = Paths.get(args[argi]);
345  Files.walkFileTree(file, opts, maxDepth, visitor);
346  argi++;
347  }
348  }
349 }
Chmod.usage
static void usage()
Definition: Chmod.java:321
file
Once a FileSystem is created then classes in the java nio file package can be used to access files in the zip JAR file
Definition: README.txt:19
Chmod.TreeVisitor
Definition: Chmod.java:288
Chmod.compile
static Changer compile(String exprs)
Definition: Chmod.java:115
Chmod.TreeVisitor.visitFileFailed
FileVisitResult visitFileFailed(Path file, IOException exc)
Definition: Chmod.java:315
Chmod.Changer
Definition: Chmod.java:261
Chmod.TreeVisitor.changer
final Changer changer
Definition: Chmod.java:289
Chmod.Changer.change
Set< PosixFilePermission > change(Set< PosixFilePermission > perms)
Chmod.chmod
static void chmod(Path file, Changer changer)
Definition: Chmod.java:276
Chmod
Definition: Chmod.java:53
Chmod.TreeVisitor.postVisitDirectory
FileVisitResult postVisitDirectory(Path dir, IOException exc)
Definition: Chmod.java:308
Chmod.TreeVisitor.preVisitDirectory
FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
Definition: Chmod.java:296
Chmod.TreeVisitor.visitFile
FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
Definition: Chmod.java:302
Chmod.TreeVisitor.TreeVisitor
TreeVisitor(Changer changer)
Definition: Chmod.java:291
Chmod.main
static void main(String[] args)
Definition: Chmod.java:326