Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/classes/sun/nio/fs/WindowsFileCopy.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.util.concurrent.ExecutionException;
31
import com.sun.nio.file.ExtendedCopyOption;
32
33
import static sun.nio.fs.WindowsNativeDispatcher.*;
34
import static sun.nio.fs.WindowsConstants.*;
35
36
/**
37
* Utility methods for copying and moving files.
38
*/
39
40
class WindowsFileCopy {
41
private WindowsFileCopy() {
42
}
43
44
/**
45
* Copy file from source to target
46
*/
47
static void copy(final WindowsPath source,
48
final WindowsPath target,
49
CopyOption... options)
50
throws IOException
51
{
52
// map options
53
boolean replaceExisting = false;
54
boolean copyAttributes = false;
55
boolean followLinks = true;
56
boolean interruptible = false;
57
for (CopyOption option: options) {
58
if (option == StandardCopyOption.REPLACE_EXISTING) {
59
replaceExisting = true;
60
continue;
61
}
62
if (option == LinkOption.NOFOLLOW_LINKS) {
63
followLinks = false;
64
continue;
65
}
66
if (option == StandardCopyOption.COPY_ATTRIBUTES) {
67
copyAttributes = true;
68
continue;
69
}
70
if (option == ExtendedCopyOption.INTERRUPTIBLE) {
71
interruptible = true;
72
continue;
73
}
74
if (option == null)
75
throw new NullPointerException();
76
throw new UnsupportedOperationException("Unsupported copy option");
77
}
78
79
// check permissions. If the source file is a symbolic link then
80
// later we must also check LinkPermission
81
SecurityManager sm = System.getSecurityManager();
82
if (sm != null) {
83
source.checkRead();
84
target.checkWrite();
85
}
86
87
// get attributes of source file
88
// attempt to get attributes of target file
89
// if both files are the same there is nothing to do
90
// if target exists and !replace then throw exception
91
92
WindowsFileAttributes sourceAttrs = null;
93
WindowsFileAttributes targetAttrs = null;
94
95
long sourceHandle = 0L;
96
try {
97
sourceHandle = source.openForReadAttributeAccess(followLinks);
98
} catch (WindowsException x) {
99
x.rethrowAsIOException(source);
100
}
101
try {
102
// source attributes
103
try {
104
sourceAttrs = WindowsFileAttributes.readAttributes(sourceHandle);
105
} catch (WindowsException x) {
106
x.rethrowAsIOException(source);
107
}
108
109
// open target (don't follow links)
110
long targetHandle = 0L;
111
try {
112
targetHandle = target.openForReadAttributeAccess(false);
113
try {
114
targetAttrs = WindowsFileAttributes.readAttributes(targetHandle);
115
116
// if both files are the same then nothing to do
117
if (WindowsFileAttributes.isSameFile(sourceAttrs, targetAttrs)) {
118
return;
119
}
120
121
// can't replace file
122
if (!replaceExisting) {
123
throw new FileAlreadyExistsException(
124
target.getPathForExceptionMessage());
125
}
126
127
} finally {
128
CloseHandle(targetHandle);
129
}
130
} catch (WindowsException x) {
131
// ignore
132
}
133
134
} finally {
135
CloseHandle(sourceHandle);
136
}
137
138
// if source file is a symbolic link then we must check for LinkPermission
139
if (sm != null && sourceAttrs.isSymbolicLink()) {
140
sm.checkPermission(new LinkPermission("symbolic"));
141
}
142
143
final String sourcePath = asWin32Path(source);
144
final String targetPath = asWin32Path(target);
145
146
// if target exists then delete it.
147
if (targetAttrs != null) {
148
try {
149
if (targetAttrs.isDirectory() || targetAttrs.isDirectoryLink()) {
150
RemoveDirectory(targetPath);
151
} else {
152
DeleteFile(targetPath);
153
}
154
} catch (WindowsException x) {
155
if (targetAttrs.isDirectory()) {
156
// ERROR_ALREADY_EXISTS is returned when attempting to delete
157
// non-empty directory on SAMBA servers.
158
if (x.lastError() == ERROR_DIR_NOT_EMPTY ||
159
x.lastError() == ERROR_ALREADY_EXISTS)
160
{
161
throw new DirectoryNotEmptyException(
162
target.getPathForExceptionMessage());
163
}
164
}
165
x.rethrowAsIOException(target);
166
}
167
}
168
169
// Use CopyFileEx if the file is not a directory or junction
170
if (!sourceAttrs.isDirectory() && !sourceAttrs.isDirectoryLink()) {
171
final int flags =
172
(source.getFileSystem().supportsLinks() && !followLinks) ?
173
COPY_FILE_COPY_SYMLINK : 0;
174
175
if (interruptible) {
176
// interruptible copy
177
Cancellable copyTask = new Cancellable() {
178
@Override
179
public int cancelValue() {
180
return 1; // TRUE
181
}
182
@Override
183
public void implRun() throws IOException {
184
try {
185
CopyFileEx(sourcePath, targetPath, flags,
186
addressToPollForCancel());
187
} catch (WindowsException x) {
188
x.rethrowAsIOException(source, target);
189
}
190
}
191
};
192
try {
193
Cancellable.runInterruptibly(copyTask);
194
} catch (ExecutionException e) {
195
Throwable t = e.getCause();
196
if (t instanceof IOException)
197
throw (IOException)t;
198
throw new IOException(t);
199
}
200
} else {
201
// non-interruptible copy
202
try {
203
CopyFileEx(sourcePath, targetPath, flags, 0L);
204
} catch (WindowsException x) {
205
x.rethrowAsIOException(source, target);
206
}
207
}
208
if (copyAttributes) {
209
// CopyFileEx does not copy security attributes
210
try {
211
copySecurityAttributes(source, target, followLinks);
212
} catch (IOException x) {
213
// ignore
214
}
215
}
216
return;
217
}
218
219
// copy directory or directory junction
220
try {
221
if (sourceAttrs.isDirectory()) {
222
CreateDirectory(targetPath, 0L);
223
} else {
224
String linkTarget = WindowsLinkSupport.readLink(source);
225
int flags = SYMBOLIC_LINK_FLAG_DIRECTORY;
226
CreateSymbolicLink(targetPath,
227
WindowsPath.addPrefixIfNeeded(linkTarget),
228
flags);
229
}
230
} catch (WindowsException x) {
231
x.rethrowAsIOException(target);
232
}
233
if (copyAttributes) {
234
// copy DOS/timestamps attributes
235
WindowsFileAttributeViews.Dos view =
236
WindowsFileAttributeViews.createDosView(target, false);
237
try {
238
view.setAttributes(sourceAttrs);
239
} catch (IOException x) {
240
if (sourceAttrs.isDirectory()) {
241
try {
242
RemoveDirectory(targetPath);
243
} catch (WindowsException ignore) { }
244
}
245
}
246
247
// copy security attributes. If this fail it doesn't cause the move
248
// to fail.
249
try {
250
copySecurityAttributes(source, target, followLinks);
251
} catch (IOException ignore) { }
252
}
253
}
254
255
/**
256
* Move file from source to target
257
*/
258
static void move(WindowsPath source, WindowsPath target, CopyOption... options)
259
throws IOException
260
{
261
// map options
262
boolean atomicMove = false;
263
boolean replaceExisting = false;
264
for (CopyOption option: options) {
265
if (option == StandardCopyOption.ATOMIC_MOVE) {
266
atomicMove = true;
267
continue;
268
}
269
if (option == StandardCopyOption.REPLACE_EXISTING) {
270
replaceExisting = true;
271
continue;
272
}
273
if (option == LinkOption.NOFOLLOW_LINKS) {
274
// ignore
275
continue;
276
}
277
if (option == null) throw new NullPointerException();
278
throw new UnsupportedOperationException("Unsupported copy option");
279
}
280
281
SecurityManager sm = System.getSecurityManager();
282
if (sm != null) {
283
source.checkWrite();
284
target.checkWrite();
285
}
286
287
final String sourcePath = asWin32Path(source);
288
final String targetPath = asWin32Path(target);
289
290
// atomic case
291
if (atomicMove) {
292
try {
293
MoveFileEx(sourcePath, targetPath, MOVEFILE_REPLACE_EXISTING);
294
} catch (WindowsException x) {
295
if (x.lastError() == ERROR_NOT_SAME_DEVICE) {
296
throw new AtomicMoveNotSupportedException(
297
source.getPathForExceptionMessage(),
298
target.getPathForExceptionMessage(),
299
x.errorString());
300
}
301
x.rethrowAsIOException(source, target);
302
}
303
return;
304
}
305
306
// get attributes of source file
307
// attempt to get attributes of target file
308
// if both files are the same there is nothing to do
309
// if target exists and !replace then throw exception
310
311
WindowsFileAttributes sourceAttrs = null;
312
WindowsFileAttributes targetAttrs = null;
313
314
long sourceHandle = 0L;
315
try {
316
sourceHandle = source.openForReadAttributeAccess(false);
317
} catch (WindowsException x) {
318
x.rethrowAsIOException(source);
319
}
320
try {
321
// source attributes
322
try {
323
sourceAttrs = WindowsFileAttributes.readAttributes(sourceHandle);
324
} catch (WindowsException x) {
325
x.rethrowAsIOException(source);
326
}
327
328
// open target (don't follow links)
329
long targetHandle = 0L;
330
try {
331
targetHandle = target.openForReadAttributeAccess(false);
332
try {
333
targetAttrs = WindowsFileAttributes.readAttributes(targetHandle);
334
335
// if both files are the same then nothing to do
336
if (WindowsFileAttributes.isSameFile(sourceAttrs, targetAttrs)) {
337
return;
338
}
339
340
// can't replace file
341
if (!replaceExisting) {
342
throw new FileAlreadyExistsException(
343
target.getPathForExceptionMessage());
344
}
345
346
} finally {
347
CloseHandle(targetHandle);
348
}
349
} catch (WindowsException x) {
350
// ignore
351
}
352
353
} finally {
354
CloseHandle(sourceHandle);
355
}
356
357
// if target exists then delete it.
358
if (targetAttrs != null) {
359
try {
360
if (targetAttrs.isDirectory() || targetAttrs.isDirectoryLink()) {
361
RemoveDirectory(targetPath);
362
} else {
363
DeleteFile(targetPath);
364
}
365
} catch (WindowsException x) {
366
if (targetAttrs.isDirectory()) {
367
// ERROR_ALREADY_EXISTS is returned when attempting to delete
368
// non-empty directory on SAMBA servers.
369
if (x.lastError() == ERROR_DIR_NOT_EMPTY ||
370
x.lastError() == ERROR_ALREADY_EXISTS)
371
{
372
throw new DirectoryNotEmptyException(
373
target.getPathForExceptionMessage());
374
}
375
}
376
x.rethrowAsIOException(target);
377
}
378
}
379
380
// first try MoveFileEx (no options). If target is on same volume then
381
// all attributes (including security attributes) are preserved.
382
try {
383
MoveFileEx(sourcePath, targetPath, 0);
384
return;
385
} catch (WindowsException x) {
386
if (x.lastError() != ERROR_NOT_SAME_DEVICE)
387
x.rethrowAsIOException(source, target);
388
}
389
390
// target is on different volume so use MoveFileEx with copy option
391
if (!sourceAttrs.isDirectory() && !sourceAttrs.isDirectoryLink()) {
392
try {
393
MoveFileEx(sourcePath, targetPath, MOVEFILE_COPY_ALLOWED);
394
} catch (WindowsException x) {
395
x.rethrowAsIOException(source, target);
396
}
397
// MoveFileEx does not copy security attributes when moving
398
// across volumes.
399
try {
400
copySecurityAttributes(source, target, false);
401
} catch (IOException x) {
402
// ignore
403
}
404
return;
405
}
406
407
// moving directory or directory-link to another file system
408
assert sourceAttrs.isDirectory() || sourceAttrs.isDirectoryLink();
409
410
// create new directory or directory junction
411
try {
412
if (sourceAttrs.isDirectory()) {
413
CreateDirectory(targetPath, 0L);
414
} else {
415
String linkTarget = WindowsLinkSupport.readLink(source);
416
CreateSymbolicLink(targetPath,
417
WindowsPath.addPrefixIfNeeded(linkTarget),
418
SYMBOLIC_LINK_FLAG_DIRECTORY);
419
}
420
} catch (WindowsException x) {
421
x.rethrowAsIOException(target);
422
}
423
424
// copy timestamps/DOS attributes
425
WindowsFileAttributeViews.Dos view =
426
WindowsFileAttributeViews.createDosView(target, false);
427
try {
428
view.setAttributes(sourceAttrs);
429
} catch (IOException x) {
430
// rollback
431
try {
432
RemoveDirectory(targetPath);
433
} catch (WindowsException ignore) { }
434
throw x;
435
}
436
437
// copy security attributes. If this fails it doesn't cause the move
438
// to fail.
439
try {
440
copySecurityAttributes(source, target, false);
441
} catch (IOException ignore) { }
442
443
// delete source
444
try {
445
RemoveDirectory(sourcePath);
446
} catch (WindowsException x) {
447
// rollback
448
try {
449
RemoveDirectory(targetPath);
450
} catch (WindowsException ignore) { }
451
// ERROR_ALREADY_EXISTS is returned when attempting to delete
452
// non-empty directory on SAMBA servers.
453
if (x.lastError() == ERROR_DIR_NOT_EMPTY ||
454
x.lastError() == ERROR_ALREADY_EXISTS)
455
{
456
throw new DirectoryNotEmptyException(
457
target.getPathForExceptionMessage());
458
}
459
x.rethrowAsIOException(source);
460
}
461
}
462
463
464
private static String asWin32Path(WindowsPath path) throws IOException {
465
try {
466
return path.getPathForWin32Calls();
467
} catch (WindowsException x) {
468
x.rethrowAsIOException(path);
469
return null;
470
}
471
}
472
473
/**
474
* Copy DACL/owner/group from source to target
475
*/
476
private static void copySecurityAttributes(WindowsPath source,
477
WindowsPath target,
478
boolean followLinks)
479
throws IOException
480
{
481
String path = WindowsLinkSupport.getFinalPath(source, followLinks);
482
483
// may need SeRestorePrivilege to set file owner
484
WindowsSecurity.Privilege priv =
485
WindowsSecurity.enablePrivilege("SeRestorePrivilege");
486
try {
487
int request = (DACL_SECURITY_INFORMATION |
488
OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION);
489
NativeBuffer buffer =
490
WindowsAclFileAttributeView.getFileSecurity(path, request);
491
try {
492
try {
493
SetFileSecurity(target.getPathForWin32Calls(), request,
494
buffer.address());
495
} catch (WindowsException x) {
496
x.rethrowAsIOException(target);
497
}
498
} finally {
499
buffer.release();
500
}
501
} finally {
502
priv.drop();
503
}
504
}
505
}
506
507