|
16 | 16 | import java.nio.file.Path; |
17 | 17 | import java.nio.file.Paths; |
18 | 18 | import java.nio.file.attribute.BasicFileAttributes; |
| 19 | +import java.nio.file.attribute.PosixFilePermission; |
19 | 20 | import java.nio.file.attribute.PosixFilePermissions; |
20 | 21 | import java.time.Instant; |
21 | 22 | import java.time.temporal.ChronoUnit; |
22 | 23 | import java.util.Set; |
23 | 24 | import java.util.concurrent.CountDownLatch; |
24 | 25 | import java.util.concurrent.TimeUnit; |
| 26 | +import java.util.concurrent.atomic.AtomicReference; |
25 | 27 | import java.util.regex.Pattern; |
26 | 28 | import java.util.stream.Stream; |
27 | 29 | import org.slf4j.Logger; |
@@ -219,6 +221,7 @@ boolean await(long timeout, TimeUnit unit) throws Throwable { |
219 | 221 | } |
220 | 222 | } |
221 | 223 |
|
| 224 | + private final boolean isPosixFs; |
222 | 225 | private final Path baseTempDir; |
223 | 226 | private final Path tempDir; |
224 | 227 | private final long cutoffSeconds; |
@@ -262,6 +265,9 @@ private TempLocationManager() { |
262 | 265 | ConfigProvider configProvider, boolean runStartupCleanup, CleanupHook testHook) { |
263 | 266 | cleanupTestHook = testHook; |
264 | 267 |
|
| 268 | + Set<String> supportedViews = FileSystems.getDefault().supportedFileAttributeViews(); |
| 269 | + isPosixFs = supportedViews.contains("posix"); |
| 270 | + |
265 | 271 | // In order to avoid racy attempts to clean up files which are currently being processed in a |
266 | 272 | // JVM which is being shut down (the JVMs far in the shutdown routine may not be reported by |
267 | 273 | // 'jps' but still can be eg. processing JFR chunks) we will not clean up any files not older |
@@ -317,6 +323,8 @@ private TempLocationManager() { |
317 | 323 | }, |
318 | 324 | "Temp Location Manager Cleanup"); |
319 | 325 | Runtime.getRuntime().addShutdownHook(selfCleanup); |
| 326 | + |
| 327 | + createTempDir(tempDir); |
320 | 328 | } |
321 | 329 |
|
322 | 330 | // @VisibleForTesting |
@@ -362,21 +370,7 @@ public Path getTempDir(Path subPath, boolean create) { |
362 | 370 | Path rslt = |
363 | 371 | subPath != null && !subPath.toString().isEmpty() ? tempDir.resolve(subPath) : tempDir; |
364 | 372 | if (create && !Files.exists(rslt)) { |
365 | | - try { |
366 | | - Set<String> supportedViews = FileSystems.getDefault().supportedFileAttributeViews(); |
367 | | - if (supportedViews.contains("posix")) { |
368 | | - Files.createDirectories( |
369 | | - rslt, |
370 | | - PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rwx------"))); |
371 | | - } else { |
372 | | - // non-posix, eg. Windows - let's rely on the created folders being world-writable |
373 | | - Files.createDirectories(rslt); |
374 | | - } |
375 | | - |
376 | | - } catch (Exception e) { |
377 | | - log.warn(SEND_TELEMETRY, "Failed to create temp directory: {}", tempDir, e); |
378 | | - throw new IllegalStateException("Failed to create temp directory: " + tempDir, e); |
379 | | - } |
| 373 | + createTempDir(rslt); |
380 | 374 | } |
381 | 375 | return rslt; |
382 | 376 | } |
@@ -454,4 +448,79 @@ boolean waitForCleanup(long timeout, TimeUnit unit) { |
454 | 448 | void createDirStructure() throws IOException { |
455 | 449 | Files.createDirectories(baseTempDir); |
456 | 450 | } |
| 451 | + |
| 452 | + private void createTempDir(Path tempDir) { |
| 453 | + String msg = "Failed to create temp directory: " + tempDir; |
| 454 | + try { |
| 455 | + if (isPosixFs) { |
| 456 | + Files.createDirectories( |
| 457 | + tempDir, |
| 458 | + PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rwx------"))); |
| 459 | + } else { |
| 460 | + Files.createDirectories(tempDir); |
| 461 | + } |
| 462 | + } catch (IOException e) { |
| 463 | + log.error("Failed to create temp directory {}", tempDir, e); |
| 464 | + // if on a posix fs, let's check the expected permissions |
| 465 | + // we will find the first offender not having the expected permissions and fail the check |
| 466 | + if (isPosixFs) { |
| 467 | + // take the first subfolder below the base temp dir |
| 468 | + Path root = baseTempDir.resolve(baseTempDir.relativize(tempDir).getRoot()); |
| 469 | + try { |
| 470 | + AtomicReference<Path> failed = new AtomicReference<>(); |
| 471 | + Files.walkFileTree( |
| 472 | + root, |
| 473 | + new FileVisitor<Path>() { |
| 474 | + @Override |
| 475 | + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) |
| 476 | + throws IOException { |
| 477 | + Set<PosixFilePermission> perms = Files.getPosixFilePermissions(dir); |
| 478 | + if (!perms.contains(PosixFilePermission.OWNER_READ) |
| 479 | + || !perms.contains(PosixFilePermission.OWNER_WRITE) |
| 480 | + || !perms.contains(PosixFilePermission.OWNER_EXECUTE)) { |
| 481 | + failed.set(dir); |
| 482 | + return FileVisitResult.TERMINATE; |
| 483 | + } |
| 484 | + return FileVisitResult.CONTINUE; |
| 485 | + } |
| 486 | + |
| 487 | + @Override |
| 488 | + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) |
| 489 | + throws IOException { |
| 490 | + return FileVisitResult.SKIP_SIBLINGS; |
| 491 | + } |
| 492 | + |
| 493 | + @Override |
| 494 | + public FileVisitResult visitFileFailed(Path file, IOException exc) |
| 495 | + throws IOException { |
| 496 | + return FileVisitResult.TERMINATE; |
| 497 | + } |
| 498 | + |
| 499 | + @Override |
| 500 | + public FileVisitResult postVisitDirectory(Path dir, IOException exc) |
| 501 | + throws IOException { |
| 502 | + return FileVisitResult.CONTINUE; |
| 503 | + } |
| 504 | + }); |
| 505 | + Path failedDir = failed.get(); |
| 506 | + |
| 507 | + if (failedDir != null) { |
| 508 | + msg += |
| 509 | + " (offender: " |
| 510 | + + failedDir |
| 511 | + + ", permissions: " |
| 512 | + + PosixFilePermissions.toString(Files.getPosixFilePermissions(failedDir)) |
| 513 | + + ")"; |
| 514 | + log.warn(SEND_TELEMETRY, msg, e); |
| 515 | + } |
| 516 | + } catch (IOException ignored) { |
| 517 | + // should not happen, but let's ignore it anyway' |
| 518 | + } |
| 519 | + throw new IllegalStateException(msg, e); |
| 520 | + } else { |
| 521 | + log.warn(SEND_TELEMETRY, msg, e); |
| 522 | + throw new IllegalStateException(msg, e); |
| 523 | + } |
| 524 | + } |
| 525 | + } |
457 | 526 | } |
0 commit comments