From 7d9fabfe5c6da56ae0ba4bcde5a26fa3c2d364b9 Mon Sep 17 00:00:00 2001 From: "Flavio S. Glock" Date: Mon, 16 Mar 2026 11:30:57 +0100 Subject: [PATCH] Fix mkdir to set $! errno correctly (EEXIST) - Use Files.createDirectory() instead of Files.createDirectories() so it throws FileAlreadyExistsException when directory already exists - Use handleIOException() which properly maps exceptions to errno values (e.g., FileAlreadyExistsException -> EEXIST=17) This fixes jcpan failing on re-run when build directories exist. The CPAN::Distribution module relies on mkdir returning false with $! set to EEXIST to increment the suffix number for build directories. Before: $!+0 returned 0 regardless of error type After: $!+0 returns 17 (EEXIST) when mkdir fails on existing directory Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin --- .../org/perlonjava/runtime/operators/Directory.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/perlonjava/runtime/operators/Directory.java b/src/main/java/org/perlonjava/runtime/operators/Directory.java index f75a70017..95cc77eb4 100644 --- a/src/main/java/org/perlonjava/runtime/operators/Directory.java +++ b/src/main/java/org/perlonjava/runtime/operators/Directory.java @@ -252,7 +252,10 @@ public static RuntimeScalar mkdir(RuntimeList args) { try { Path path = RuntimeIO.resolvePath(fileName); - Files.createDirectories(path); + // Use createDirectory (not createDirectories) so it throws FileAlreadyExistsException + // when the directory exists. This matches Perl's behavior where mkdir() fails + // with EEXIST if the directory already exists. + Files.createDirectory(path); // Set permissions only if the file system supports POSIX permissions if (FileSystems.getDefault().supportedFileAttributeViews().contains("posix")) { @@ -263,9 +266,9 @@ public static RuntimeScalar mkdir(RuntimeList args) { return scalarTrue; } catch (IOException e) { - // Set $! (errno) in case of failure - getGlobalVariable("main::!").set(e.getMessage()); - return scalarFalse; + // Set $! (errno) properly using handleIOException which maps + // FileAlreadyExistsException to EEXIST (17), etc. + return handleIOException(e, fileName, 0); } } }