Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/classes/sun/nio/fs/UnixCopyFile.java
32288 views
1
/*
2
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.nio.fs;
27
28
import java.nio.file.*;
29
import java.io.IOException;
30
import java.security.AccessController;
31
import java.security.PrivilegedAction;
32
import java.util.concurrent.ExecutionException;
33
import java.util.concurrent.TimeUnit;
34
import com.sun.nio.file.ExtendedCopyOption;
35
36
import static sun.nio.fs.UnixNativeDispatcher.*;
37
import static sun.nio.fs.UnixConstants.*;
38
39
40
/**
41
* Unix implementation of Path#copyTo and Path#moveTo methods.
42
*/
43
44
class UnixCopyFile {
45
private UnixCopyFile() { }
46
47
// The flags that control how a file is copied or moved
48
private static class Flags {
49
boolean replaceExisting;
50
boolean atomicMove;
51
boolean followLinks;
52
boolean interruptible;
53
54
// the attributes to copy
55
boolean copyBasicAttributes;
56
boolean copyPosixAttributes;
57
boolean copyNonPosixAttributes;
58
59
// flags that indicate if we should fail if attributes cannot be copied
60
boolean failIfUnableToCopyBasic;
61
boolean failIfUnableToCopyPosix;
62
boolean failIfUnableToCopyNonPosix;
63
64
static Flags fromCopyOptions(CopyOption... options) {
65
Flags flags = new Flags();
66
flags.followLinks = true;
67
for (CopyOption option: options) {
68
if (option == StandardCopyOption.REPLACE_EXISTING) {
69
flags.replaceExisting = true;
70
continue;
71
}
72
if (option == LinkOption.NOFOLLOW_LINKS) {
73
flags.followLinks = false;
74
continue;
75
}
76
if (option == StandardCopyOption.COPY_ATTRIBUTES) {
77
// copy all attributes but only fail if basic attributes
78
// cannot be copied
79
flags.copyBasicAttributes = true;
80
flags.copyPosixAttributes = true;
81
flags.copyNonPosixAttributes = true;
82
flags.failIfUnableToCopyBasic = true;
83
continue;
84
}
85
if (option == ExtendedCopyOption.INTERRUPTIBLE) {
86
flags.interruptible = true;
87
continue;
88
}
89
if (option == null)
90
throw new NullPointerException();
91
throw new UnsupportedOperationException("Unsupported copy option");
92
}
93
return flags;
94
}
95
96
static Flags fromMoveOptions(CopyOption... options) {
97
Flags flags = new Flags();
98
for (CopyOption option: options) {
99
if (option == StandardCopyOption.ATOMIC_MOVE) {
100
flags.atomicMove = true;
101
continue;
102
}
103
if (option == StandardCopyOption.REPLACE_EXISTING) {
104
flags.replaceExisting = true;
105
continue;
106
}
107
if (option == LinkOption.NOFOLLOW_LINKS) {
108
// ignore
109
continue;
110
}
111
if (option == null)
112
throw new NullPointerException();
113
throw new UnsupportedOperationException("Unsupported copy option");
114
}
115
116
// a move requires that all attributes be copied but only fail if
117
// the basic attributes cannot be copied
118
flags.copyBasicAttributes = true;
119
flags.copyPosixAttributes = true;
120
flags.copyNonPosixAttributes = true;
121
flags.failIfUnableToCopyBasic = true;
122
return flags;
123
}
124
}
125
126
// copy directory from source to target
127
private static void copyDirectory(UnixPath source,
128
UnixFileAttributes attrs,
129
UnixPath target,
130
Flags flags)
131
throws IOException
132
{
133
try {
134
mkdir(target, attrs.mode());
135
} catch (UnixException x) {
136
x.rethrowAsIOException(target);
137
}
138
139
// no attributes to copy
140
if (!flags.copyBasicAttributes &&
141
!flags.copyPosixAttributes &&
142
!flags.copyNonPosixAttributes) return;
143
144
// open target directory if possible (this can fail when copying a
145
// directory for which we don't have read access).
146
int dfd = -1;
147
try {
148
dfd = open(target, O_RDONLY, 0);
149
} catch (UnixException x) {
150
// access to target directory required to copy named attributes
151
if (flags.copyNonPosixAttributes && flags.failIfUnableToCopyNonPosix) {
152
try { rmdir(target); } catch (UnixException ignore) { }
153
x.rethrowAsIOException(target);
154
}
155
}
156
157
boolean done = false;
158
try {
159
// copy owner/group/permissions
160
if (flags.copyPosixAttributes){
161
try {
162
if (dfd >= 0) {
163
fchown(dfd, attrs.uid(), attrs.gid());
164
fchmod(dfd, attrs.mode());
165
} else {
166
chown(target, attrs.uid(), attrs.gid());
167
chmod(target, attrs.mode());
168
}
169
} catch (UnixException x) {
170
// unable to set owner/group
171
if (flags.failIfUnableToCopyPosix)
172
x.rethrowAsIOException(target);
173
}
174
}
175
// copy other attributes
176
if (flags.copyNonPosixAttributes && (dfd >= 0)) {
177
int sfd = -1;
178
try {
179
sfd = open(source, O_RDONLY, 0);
180
} catch (UnixException x) {
181
if (flags.failIfUnableToCopyNonPosix)
182
x.rethrowAsIOException(source);
183
}
184
if (sfd >= 0) {
185
source.getFileSystem().copyNonPosixAttributes(sfd, dfd);
186
close(sfd);
187
}
188
}
189
// copy time stamps last
190
if (flags.copyBasicAttributes) {
191
try {
192
if (dfd >= 0 && futimesSupported()) {
193
futimes(dfd,
194
attrs.lastAccessTime().to(TimeUnit.MICROSECONDS),
195
attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS));
196
} else {
197
utimes(target,
198
attrs.lastAccessTime().to(TimeUnit.MICROSECONDS),
199
attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS));
200
}
201
} catch (UnixException x) {
202
// unable to set times
203
if (flags.failIfUnableToCopyBasic)
204
x.rethrowAsIOException(target);
205
}
206
}
207
done = true;
208
} finally {
209
if (dfd >= 0)
210
close(dfd);
211
if (!done) {
212
// rollback
213
try { rmdir(target); } catch (UnixException ignore) { }
214
}
215
}
216
}
217
218
// copy regular file from source to target
219
private static void copyFile(UnixPath source,
220
UnixFileAttributes attrs,
221
UnixPath target,
222
Flags flags,
223
long addressToPollForCancel)
224
throws IOException
225
{
226
int fi = -1;
227
try {
228
fi = open(source, O_RDONLY, 0);
229
} catch (UnixException x) {
230
x.rethrowAsIOException(source);
231
}
232
233
try {
234
// open new file
235
int fo = -1;
236
try {
237
fo = open(target,
238
(O_WRONLY |
239
O_CREAT |
240
O_EXCL),
241
attrs.mode());
242
} catch (UnixException x) {
243
x.rethrowAsIOException(target);
244
}
245
246
// set to true when file and attributes copied
247
boolean complete = false;
248
try {
249
// transfer bytes to target file
250
try {
251
transfer(fo, fi, addressToPollForCancel);
252
} catch (UnixException x) {
253
x.rethrowAsIOException(source, target);
254
}
255
// copy owner/permissions
256
if (flags.copyPosixAttributes) {
257
try {
258
fchown(fo, attrs.uid(), attrs.gid());
259
fchmod(fo, attrs.mode());
260
} catch (UnixException x) {
261
if (flags.failIfUnableToCopyPosix)
262
x.rethrowAsIOException(target);
263
}
264
}
265
// copy non POSIX attributes (depends on file system)
266
if (flags.copyNonPosixAttributes) {
267
source.getFileSystem().copyNonPosixAttributes(fi, fo);
268
}
269
// copy time attributes
270
if (flags.copyBasicAttributes) {
271
try {
272
if (futimesSupported()) {
273
futimes(fo,
274
attrs.lastAccessTime().to(TimeUnit.MICROSECONDS),
275
attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS));
276
} else {
277
utimes(target,
278
attrs.lastAccessTime().to(TimeUnit.MICROSECONDS),
279
attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS));
280
}
281
} catch (UnixException x) {
282
if (flags.failIfUnableToCopyBasic)
283
x.rethrowAsIOException(target);
284
}
285
}
286
complete = true;
287
} finally {
288
close(fo);
289
290
// copy of file or attributes failed so rollback
291
if (!complete) {
292
try {
293
unlink(target);
294
} catch (UnixException ignore) { }
295
}
296
}
297
} finally {
298
close(fi);
299
}
300
}
301
302
// copy symbolic link from source to target
303
private static void copyLink(UnixPath source,
304
UnixFileAttributes attrs,
305
UnixPath target,
306
Flags flags)
307
throws IOException
308
{
309
byte[] linktarget = null;
310
try {
311
linktarget = readlink(source);
312
} catch (UnixException x) {
313
x.rethrowAsIOException(source);
314
}
315
try {
316
symlink(linktarget, target);
317
318
if (flags.copyPosixAttributes) {
319
try {
320
lchown(target, attrs.uid(), attrs.gid());
321
} catch (UnixException x) {
322
// ignore since link attributes not required to be copied
323
}
324
}
325
} catch (UnixException x) {
326
x.rethrowAsIOException(target);
327
}
328
}
329
330
// copy special file from source to target
331
private static void copySpecial(UnixPath source,
332
UnixFileAttributes attrs,
333
UnixPath target,
334
Flags flags)
335
throws IOException
336
{
337
try {
338
mknod(target, attrs.mode(), attrs.rdev());
339
} catch (UnixException x) {
340
x.rethrowAsIOException(target);
341
}
342
boolean done = false;
343
try {
344
if (flags.copyPosixAttributes) {
345
try {
346
chown(target, attrs.uid(), attrs.gid());
347
chmod(target, attrs.mode());
348
} catch (UnixException x) {
349
if (flags.failIfUnableToCopyPosix)
350
x.rethrowAsIOException(target);
351
}
352
}
353
if (flags.copyBasicAttributes) {
354
try {
355
utimes(target,
356
attrs.lastAccessTime().to(TimeUnit.MICROSECONDS),
357
attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS));
358
} catch (UnixException x) {
359
if (flags.failIfUnableToCopyBasic)
360
x.rethrowAsIOException(target);
361
}
362
}
363
done = true;
364
} finally {
365
if (!done) {
366
try { unlink(target); } catch (UnixException ignore) { }
367
}
368
}
369
}
370
371
// move file from source to target
372
static void move(UnixPath source, UnixPath target, CopyOption... options)
373
throws IOException
374
{
375
// permission check
376
SecurityManager sm = System.getSecurityManager();
377
if (sm != null) {
378
source.checkWrite();
379
target.checkWrite();
380
}
381
382
// translate options into flags
383
Flags flags = Flags.fromMoveOptions(options);
384
385
// handle atomic rename case
386
if (flags.atomicMove) {
387
try {
388
rename(source, target);
389
} catch (UnixException x) {
390
if (x.errno() == EXDEV) {
391
throw new AtomicMoveNotSupportedException(
392
source.getPathForExceptionMessage(),
393
target.getPathForExceptionMessage(),
394
x.errorString());
395
}
396
x.rethrowAsIOException(source, target);
397
}
398
return;
399
}
400
401
// move using rename or copy+delete
402
UnixFileAttributes sourceAttrs = null;
403
UnixFileAttributes targetAttrs = null;
404
405
// get attributes of source file (don't follow links)
406
try {
407
sourceAttrs = UnixFileAttributes.get(source, false);
408
} catch (UnixException x) {
409
x.rethrowAsIOException(source);
410
}
411
412
// get attributes of target file (don't follow links)
413
try {
414
targetAttrs = UnixFileAttributes.get(target, false);
415
} catch (UnixException x) {
416
// ignore
417
}
418
boolean targetExists = (targetAttrs != null);
419
420
// if the target exists:
421
// 1. check if source and target are the same file
422
// 2. throw exception if REPLACE_EXISTING option is not set
423
// 3. delete target if REPLACE_EXISTING option set
424
if (targetExists) {
425
if (sourceAttrs.isSameFile(targetAttrs))
426
return; // nothing to do as files are identical
427
if (!flags.replaceExisting) {
428
throw new FileAlreadyExistsException(
429
target.getPathForExceptionMessage());
430
}
431
432
// attempt to delete target
433
try {
434
if (targetAttrs.isDirectory()) {
435
rmdir(target);
436
} else {
437
unlink(target);
438
}
439
} catch (UnixException x) {
440
// target is non-empty directory that can't be replaced.
441
if (targetAttrs.isDirectory() &&
442
(x.errno() == EEXIST || x.errno() == ENOTEMPTY))
443
{
444
throw new DirectoryNotEmptyException(
445
target.getPathForExceptionMessage());
446
}
447
x.rethrowAsIOException(target);
448
}
449
}
450
451
// first try rename
452
try {
453
rename(source, target);
454
return;
455
} catch (UnixException x) {
456
if (x.errno() != EXDEV && x.errno() != EISDIR) {
457
x.rethrowAsIOException(source, target);
458
}
459
}
460
461
// copy source to target
462
if (sourceAttrs.isDirectory()) {
463
copyDirectory(source, sourceAttrs, target, flags);
464
} else {
465
if (sourceAttrs.isSymbolicLink()) {
466
copyLink(source, sourceAttrs, target, flags);
467
} else {
468
if (sourceAttrs.isDevice()) {
469
copySpecial(source, sourceAttrs, target, flags);
470
} else {
471
copyFile(source, sourceAttrs, target, flags, 0L);
472
}
473
}
474
}
475
476
// delete source
477
try {
478
if (sourceAttrs.isDirectory()) {
479
rmdir(source);
480
} else {
481
unlink(source);
482
}
483
} catch (UnixException x) {
484
// file was copied but unable to unlink the source file so attempt
485
// to remove the target and throw a reasonable exception
486
try {
487
if (sourceAttrs.isDirectory()) {
488
rmdir(target);
489
} else {
490
unlink(target);
491
}
492
} catch (UnixException ignore) { }
493
494
if (sourceAttrs.isDirectory() &&
495
(x.errno() == EEXIST || x.errno() == ENOTEMPTY))
496
{
497
throw new DirectoryNotEmptyException(
498
source.getPathForExceptionMessage());
499
}
500
x.rethrowAsIOException(source);
501
}
502
}
503
504
// copy file from source to target
505
static void copy(final UnixPath source,
506
final UnixPath target,
507
CopyOption... options) throws IOException
508
{
509
// permission checks
510
SecurityManager sm = System.getSecurityManager();
511
if (sm != null) {
512
source.checkRead();
513
target.checkWrite();
514
}
515
516
// translate options into flags
517
final Flags flags = Flags.fromCopyOptions(options);
518
519
UnixFileAttributes sourceAttrs = null;
520
UnixFileAttributes targetAttrs = null;
521
522
// get attributes of source file
523
try {
524
sourceAttrs = UnixFileAttributes.get(source, flags.followLinks);
525
} catch (UnixException x) {
526
x.rethrowAsIOException(source);
527
}
528
529
// if source file is symbolic link then we must check LinkPermission
530
if (sm != null && sourceAttrs.isSymbolicLink()) {
531
sm.checkPermission(new LinkPermission("symbolic"));
532
}
533
534
// get attributes of target file (don't follow links)
535
try {
536
targetAttrs = UnixFileAttributes.get(target, false);
537
} catch (UnixException x) {
538
// ignore
539
}
540
boolean targetExists = (targetAttrs != null);
541
542
// if the target exists:
543
// 1. check if source and target are the same file
544
// 2. throw exception if REPLACE_EXISTING option is not set
545
// 3. try to unlink the target
546
if (targetExists) {
547
if (sourceAttrs.isSameFile(targetAttrs))
548
return; // nothing to do as files are identical
549
if (!flags.replaceExisting)
550
throw new FileAlreadyExistsException(
551
target.getPathForExceptionMessage());
552
try {
553
if (targetAttrs.isDirectory()) {
554
rmdir(target);
555
} else {
556
unlink(target);
557
}
558
} catch (UnixException x) {
559
// target is non-empty directory that can't be replaced.
560
if (targetAttrs.isDirectory() &&
561
(x.errno() == EEXIST || x.errno() == ENOTEMPTY))
562
{
563
throw new DirectoryNotEmptyException(
564
target.getPathForExceptionMessage());
565
}
566
x.rethrowAsIOException(target);
567
}
568
}
569
570
// do the copy
571
if (sourceAttrs.isDirectory()) {
572
copyDirectory(source, sourceAttrs, target, flags);
573
return;
574
}
575
if (sourceAttrs.isSymbolicLink()) {
576
copyLink(source, sourceAttrs, target, flags);
577
return;
578
}
579
if (!flags.interruptible) {
580
// non-interruptible file copy
581
copyFile(source, sourceAttrs, target, flags, 0L);
582
return;
583
}
584
585
// interruptible file copy
586
final UnixFileAttributes attrsToCopy = sourceAttrs;
587
Cancellable copyTask = new Cancellable() {
588
@Override public void implRun() throws IOException {
589
copyFile(source, attrsToCopy, target, flags,
590
addressToPollForCancel());
591
}
592
};
593
try {
594
Cancellable.runInterruptibly(copyTask);
595
} catch (ExecutionException e) {
596
Throwable t = e.getCause();
597
if (t instanceof IOException)
598
throw (IOException)t;
599
throw new IOException(t);
600
}
601
}
602
603
// -- native methods --
604
605
static native void transfer(int dst, int src, long addressToPollForCancel)
606
throws UnixException;
607
608
static {
609
AccessController.doPrivileged(new PrivilegedAction<Void>() {
610
@Override
611
public Void run() {
612
System.loadLibrary("nio");
613
return null;
614
}});
615
}
616
617
}
618
619