34
34
import java .nio .file .CopyOption ;
35
35
import java .nio .file .FileAlreadyExistsException ;
36
36
import java .nio .file .Files ;
37
+ import java .nio .file .FileStore ;
37
38
import java .nio .file .LinkOption ;
38
39
import java .nio .file .Path ;
39
40
import java .nio .file .attribute .PosixFilePermission ;
@@ -68,19 +69,21 @@ enum PathType {
68
69
}
69
70
70
71
private static final boolean SUPPORTS_POSIX_PERMISSIONS ;
72
+ private static final String TMP_DIR =
73
+ System .getProperty ("copymove.tmp.dir" , "." );
71
74
72
75
static {
73
- Path currentDir = null ;
76
+ Path tempFile = null ;
74
77
try {
75
- currentDir = Files .createTempFile (Path .of ("." ), "this" , "that" );
78
+ tempFile = Files .createTempFile (Path .of (TMP_DIR ), "this" , "that" );
76
79
SUPPORTS_POSIX_PERMISSIONS =
77
- Files .getFileStore (currentDir ).supportsFileAttributeView ("posix" );
80
+ Files .getFileStore (tempFile ).supportsFileAttributeView ("posix" );
78
81
} catch (IOException cause ) {
79
82
throw new UncheckedIOException (cause );
80
83
} finally {
81
- if (currentDir != null ) {
84
+ if (tempFile != null ) {
82
85
try {
83
- Files .delete (currentDir );
86
+ Files .delete (tempFile );
84
87
} catch (IOException ignore ) {
85
88
}
86
89
}
@@ -91,6 +94,13 @@ private static boolean supportsPosixPermissions() {
91
94
return SUPPORTS_POSIX_PERMISSIONS ;
92
95
}
93
96
97
+ private static boolean isSameFileStore (Path p1 , Path p2 )
98
+ throws IOException {
99
+ FileStore fs1 = p1 .getFileSystem ().provider ().getFileStore (p1 );
100
+ FileStore fs2 = p2 .getFileSystem ().provider ().getFileStore (p2 );
101
+ return fs1 .equals (fs2 );
102
+ }
103
+
94
104
private static Stream <Arguments > params () {
95
105
List <Arguments > list = new ArrayList <Arguments >();
96
106
@@ -142,15 +152,15 @@ void op(OpType op, PathType type, String mode, boolean replaceExisting,
142
152
Path source = null ;
143
153
Path target = null ;
144
154
Path linkTarget = null ;
145
- Path currentDir = Path .of ("." );
155
+ Path tmpDir = Path .of (TMP_DIR );
146
156
try {
147
157
switch (type ) {
148
158
case FILE ->
149
- source = Files .createTempFile (currentDir , "file" , "dat" );
159
+ source = Files .createTempFile (tmpDir , "file" , "dat" );
150
160
case DIR ->
151
- source = Files .createTempDirectory (currentDir , "dir" );
161
+ source = Files .createTempDirectory (tmpDir , "dir" );
152
162
case LINK -> {
153
- linkTarget = Files .createTempFile (currentDir , "link" , "target" );
163
+ linkTarget = Files .createTempFile (tmpDir , "link" , "target" );
154
164
Path link = Path .of ("link" );
155
165
source = Files .createSymbolicLink (link , linkTarget );
156
166
}
@@ -164,7 +174,7 @@ void op(OpType op, PathType type, String mode, boolean replaceExisting,
164
174
Files .setPosixFilePermissions (source , perms );
165
175
166
176
if (targetExists )
167
- target = Files .createTempFile (currentDir , "file" , "target" );
177
+ target = Files .createTempFile (tmpDir , "file" , "target" );
168
178
else
169
179
target = Path .of ("target" );
170
180
@@ -193,7 +203,11 @@ void op(OpType op, PathType type, String mode, boolean replaceExisting,
193
203
assertThrows (FileAlreadyExistsException .class ,
194
204
() -> Files .move (src , dst , options ));
195
205
} else {
196
- Files .move (source , target , options );
206
+ try {
207
+ Files .move (source , target , options );
208
+ } catch (AccessDeniedException ade ) {
209
+ assertTrue (mode .charAt (0 ) != 'r' );
210
+ }
197
211
assert Files .exists (target );
198
212
}
199
213
} else if (type == PathType .DIR ) {
@@ -213,7 +227,20 @@ void op(OpType op, PathType type, String mode, boolean replaceExisting,
213
227
Files .move (source , target , options );
214
228
assert Files .exists (target );
215
229
} catch (AccessDeniedException ade ) {
216
- assertTrue (mode .charAt (1 ) != 'w' );
230
+ Path other = target .getParent ();
231
+ if (other == null )
232
+ other = Path .of (System .getProperty ("user.dir" ));
233
+ if (isSameFileStore (source , other )) {
234
+ // directories on same store should be renamed
235
+ assertTrue (mode .charAt (1 ) != 'w' );
236
+ } else {
237
+ // directories on different stores will likely be
238
+ // moved by a copy which requires read permission
239
+ if (mode .charAt (1 ) == 'w' )
240
+ assertTrue (mode .charAt (0 ) != 'r' );
241
+ else
242
+ assertTrue (mode .charAt (1 ) != 'w' );
243
+ }
217
244
} catch (FileAlreadyExistsException faee ) {
218
245
assertTrue (targetExists && !replaceExisting );
219
246
}
0 commit comments