Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/sample/nio/file/Chmod.java
38829 views
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
48
/**
49
* Sample code that changes the permissions of files in a similar manner to the
50
* chmod(1) program.
51
*/
52
53
public class Chmod {
54
55
/**
56
* Compiles a list of one or more <em>symbolic mode expressions</em> that
57
* may be used to change a set of file permissions. This method is
58
* intended for use where file permissions are required to be changed in
59
* a manner similar to the UNIX <i>chmod</i> program.
60
*
61
* <p> The {@code exprs} parameter is a comma separated list of expressions
62
* where each takes the form:
63
* <blockquote>
64
* <i>who operator</i> [<i>permissions</i>]
65
* </blockquote>
66
* where <i>who</i> is one or more of the characters {@code 'u'}, {@code 'g'},
67
* {@code 'o'}, or {@code 'a'} meaning the owner (user), group, others, or
68
* all (owner, group, and others) respectively.
69
*
70
* <p> <i>operator</i> is the character {@code '+'}, {@code '-'}, or {@code
71
* '='} signifying how permissions are to be changed. {@code '+'} means the
72
* permissions are added, {@code '-'} means the permissions are removed, and
73
* {@code '='} means the permissions are assigned absolutely.
74
*
75
* <p> <i>permissions</i> is a sequence of zero or more of the following:
76
* {@code 'r'} for read permission, {@code 'w'} for write permission, and
77
* {@code 'x'} for execute permission. If <i>permissions</i> is omitted
78
* when assigned absolutely, then the permissions are cleared for
79
* the owner, group, or others as identified by <i>who</i>. When omitted
80
* when adding or removing then the expression is ignored.
81
*
82
* <p> The following examples demonstrate possible values for the {@code
83
* exprs} parameter:
84
*
85
* <table border="0">
86
* <tr>
87
* <td> {@code u=rw} </td>
88
* <td> Sets the owner permissions to be read and write. </td>
89
* </tr>
90
* <tr>
91
* <td> {@code ug+w} </td>
92
* <td> Sets the owner write and group write permissions. </td>
93
* </tr>
94
* <tr>
95
* <td> {@code u+w,o-rwx} </td>
96
* <td> Sets the owner write, and removes the others read, others write
97
* and others execute permissions. </td>
98
* </tr>
99
* <tr>
100
* <td> {@code o=} </td>
101
* <td> Sets the others permission to none (others read, others write and
102
* others execute permissions are removed if set) </td>
103
* </tr>
104
* </table>
105
*
106
* @param exprs
107
* List of one or more <em>symbolic mode expressions</em>
108
*
109
* @return A {@code Changer} that may be used to changer a set of
110
* file permissions
111
*
112
* @throws IllegalArgumentException
113
* If the value of the {@code exprs} parameter is invalid
114
*/
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
258
/**
259
* A task that <i>changes</i> a set of {@link PosixFilePermission} elements.
260
*/
261
public interface Changer {
262
/**
263
* Applies the changes to the given set of permissions.
264
*
265
* @param perms
266
* The set of permissions to change
267
*
268
* @return The {@code perms} parameter
269
*/
270
Set<PosixFilePermission> change(Set<PosixFilePermission> perms);
271
}
272
273
/**
274
* Changes the permissions of the file using the given Changer.
275
*/
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
285
/**
286
* Changes the permission of each file and directory visited
287
*/
288
static class TreeVisitor implements FileVisitor<Path> {
289
private final Changer changer;
290
291
TreeVisitor(Changer changer) {
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
}
350
351