Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/main/java/org/perlonjava/core/Configuration.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public final class Configuration {
* Automatically populated by Gradle/Maven during build.
* DO NOT EDIT MANUALLY - this value is replaced at build time.
*/
public static final String gitCommitId = "36ce11560";
public static final String gitCommitId = "bebebd07e";

/**
* Git commit date of the build (ISO format: YYYY-MM-DD).
Expand All @@ -48,7 +48,7 @@ public final class Configuration {
* Parsed by App::perlbrew and other tools via: perl -V | grep "Compiled at"
* DO NOT EDIT MANUALLY - this value is replaced at build time.
*/
public static final String buildTimestamp = "Apr 29 2026 11:48:26";
public static final String buildTimestamp = "Apr 29 2026 12:11:44";

// Prevent instantiation
private Configuration() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,14 @@ public interface FFMPosixInterface {
* @return 0 on success, -1 on error
*/
int link(String oldPath, String newPath);

/**
* Create a FIFO (named pipe).
* @param path Path of the FIFO to create
* @param mode Permission mode (modified by umask)
* @return 0 on success, -1 on error (check errno)
*/
int mkfifo(String path, int mode);

/**
* Set file access and modification times.
Expand Down
34 changes: 34 additions & 0 deletions src/main/java/org/perlonjava/runtime/nativ/ffm/FFMPosixLinux.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public class FFMPosixLinux implements FFMPosixInterface {
// Method handles that need errno capture
private static MethodHandle killHandle;
private static MethodHandle chmodHandle;
private static MethodHandle mkfifoHandle;
private static MethodHandle statHandle;
private static MethodHandle lstatHandle;

Expand Down Expand Up @@ -213,6 +214,16 @@ private static synchronized void ensureInitialized() {
FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS, ValueLayout.JAVA_INT),
captureErrno
);

// mkfifo is optional — not every libc exposes it (it always does on
// Linux/macOS; this guard just keeps initialization robust).
stdlib.find("mkfifo").ifPresent(addr ->
mkfifoHandle = linker.downcallHandle(
addr,
FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS, ValueLayout.JAVA_INT),
captureErrno
)
);

// stat and lstat - take path pointer and stat buffer pointer
statHandle = linker.downcallHandle(
Expand Down Expand Up @@ -805,6 +816,29 @@ public int link(String oldPath, String newPath) {
return -1;
}
}

@Override
public int mkfifo(String path, int mode) {
ensureInitialized();
if (mkfifoHandle == null) {
// libc has no mkfifo on this platform
setErrno(38); // ENOSYS - function not implemented
return -1;
}
try (Arena arena = Arena.ofConfined()) {
MemorySegment pathSegment = arena.allocateFrom(path);
MemorySegment capturedState = arena.allocate(Linker.Option.captureStateLayout());
int result = (int) mkfifoHandle.invokeExact(capturedState, pathSegment, mode);
if (result == -1) {
int err = capturedState.get(ValueLayout.JAVA_INT, errnoOffset);
setErrno(err);
}
return result;
} catch (Throwable e) {
setErrno(1); // EPERM
return -1;
}
}

@Override
public int utimes(String path, long atime, long mtime) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,13 @@ public int link(String oldPath, String newPath) {
return -1;
}
}

@Override
public int mkfifo(String path, int mode) {
// Windows has no POSIX FIFOs (named pipes use a different API).
setErrno(38); // ENOSYS
return -1;
}

@Override
public int utimes(String path, long atime, long mtime) {
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/org/perlonjava/runtime/perlmodule/Encode.java
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ public class Encode extends PerlModuleBase {
CHARSET_ALIASES.put("UCS-2LE", StandardCharsets.UTF_16LE);
CHARSET_ALIASES.put("ucs-2le", StandardCharsets.UTF_16LE);

// ISO-10646-1 is an Encode alias for UCS-2 (used by File::BOM, etc.)
CHARSET_ALIASES.put("iso-10646-1", StandardCharsets.UTF_16BE);
CHARSET_ALIASES.put("ISO-10646-1", StandardCharsets.UTF_16BE);

// Shift_JIS aliases
try {
Charset shiftJIS = Charset.forName("Shift_JIS");
Expand Down
23 changes: 23 additions & 0 deletions src/main/java/org/perlonjava/runtime/perlmodule/POSIX.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public static void initialize() {
module.registerMethod("_getcwd", "getcwd", null);
module.registerMethod("_strerror", "strerror", null);
module.registerMethod("_access", "access", null);
module.registerMethod("_mkfifo", "posix_mkfifo", null);
module.registerMethod("_dup2", "dup2", null);

// Low-level FD operations
Expand Down Expand Up @@ -951,6 +952,28 @@ public static RuntimeList access(RuntimeArray args, int ctx) {
return new RuntimeScalar("0 but true").getList();
}

/**
* POSIX mkfifo() - create a named pipe (FIFO).
* Arguments: path, mode (e.g. 0700)
* Returns true on success, undef on failure (and sets $!).
*/
public static RuntimeList posix_mkfifo(RuntimeArray args, int ctx) {
if (args.size() < 2) {
GlobalVariable.getGlobalVariable("main::!").set("Bad arguments to mkfifo");
return RuntimeScalarCache.scalarUndef.getList();
}
String path = args.get(0).toString();
int mode = args.get(1).getInt();
var posix = FFMPosix.get();
int result = posix.mkfifo(path, mode);
if (result == -1) {
GlobalVariable.getGlobalVariable("main::!").set(posix.strerror(posix.errno()));
return RuntimeScalarCache.scalarUndef.getList();
}
// Real Perl returns "0 but true" — true in boolean, 0 numerically.
return new RuntimeScalar("0 but true").getList();
}

// ==================== Low-level FD Operations ====================

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,13 @@ public void dynamicSaveState() {
errnoStack.push(new int[]{errno});
messageStack.push(message);
super.dynamicSaveState();
// After saving, reset to the default "no error" state so that
// `local $!;` actually clears the variable inside the dynamic scope,
// matching Perl's semantics.
this.errno = 0;
this.message = "";
this.type = RuntimeScalarType.DUALVAR;
this.value = new DualVar(new RuntimeScalar(0), new RuntimeScalar(""));
}

@Override
Expand Down
1 change: 1 addition & 0 deletions src/main/perl/lib/POSIX.pm
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ sub unlink { POSIX::_unlink(@_) }
sub link { POSIX::_link(@_) }
sub rename { POSIX::_rename(@_) }
sub mkdir { POSIX::_mkdir(@_) }
sub mkfifo { POSIX::_mkfifo(@_) }
sub rmdir { POSIX::_rmdir(@_) }
sub getcwd { POSIX::_getcwd() }
sub chdir { POSIX::_chdir(@_) }
Expand Down
Loading