diff -Nur php.orig/main/streams/plain_wrapper.c php.aix/main/streams/plain_wrapper.c
--- php.orig/main/streams/plain_wrapper.c	2019-09-24 11:20:18 +0200
+++ php.aix/main/streams/plain_wrapper.c	2019-12-11 14:14:11 +0100
@@ -1040,6 +1040,20 @@
 	}
 #ifdef PHP_WIN32
 	fd = php_win32_ioutil_open(realpath, open_flags, 0666);
+#elif defined _AIX
+	/*
+	On AIX, open() does not raise an error if the file name ends with a slash, it opens/creates
+	the file without the trailing slash.
+	For consistency with Linux, check if the name ends with a slash and simulate Linux behavior
+	in this case.
+	*/
+	if (realpath[strlen(realpath) - 1] == '/') {
+		fd = -1;
+		errno = EISDIR;	
+	}
+	else {
+		fd = open(realpath, open_flags, 0666);
+	}
 #else
 	fd = open(realpath, open_flags, 0666);
 #endif
--- ./Zend/zend_virtual_cwd.h.ORIG	2020-01-21 12:35:33 +0100
+++ ./Zend/zend_virtual_cwd.h	2020-01-29 17:23:12 +0100
@@ -130,6 +130,20 @@
 #	define CWD_API
 #endif
 
+#ifdef _AIX
+CWD_API int stat_aix(const char *path, struct stat *buf);
+CWD_API int lstat_aix(const char *path, struct stat *buf);
+CWD_API int rename_aix(const char *oldname, const char *newname);
+CWD_API int access_aix(const char *path, int mode);
+CWD_API int unlink_aix(const char *path);
+CWD_API FILE *fopen_aix(const char *path, const char *type);
+CWD_API int open_aix(const char *path, int flag);
+CWD_API int open_mode_aix(const char *path, int flag, mode_t mode);
+CWD_API int creat_aix(const char *path, mode_t mode);
+CWD_API int utime_aix(const char *path, const struct utimbuf *times);
+CWD_API FILE *popen_aix(const char *path, const char *type);
+#endif
+
 #ifdef ZEND_WIN32
 # define php_sys_stat_ex php_win32_ioutil_stat_ex
 # define php_sys_stat php_win32_ioutil_stat
@@ -138,6 +152,17 @@
 # define php_sys_readlink php_win32_ioutil_readlink
 # define php_sys_symlink php_win32_ioutil_symlink
 # define php_sys_link php_win32_ioutil_link
+
+#elif defined(_AIX)
+# define php_sys_stat(path, buf) stat_aix(path, buf)
+# define php_sys_lstat(path, buf) lstat_aix(path, buf)
+# define php_sys_fstat fstat
+# ifdef HAVE_SYMLINK
+# define php_sys_readlink(link, target, target_len) readlink(link, target, target_len)
+# define php_sys_symlink symlink
+# define php_sys_link link
+# endif
+
 #else
 # define php_sys_stat stat
 # define php_sys_lstat lstat
@@ -286,7 +311,6 @@
 
 #else
 
-#define VCWD_CREAT(path, mode) creat(path, mode)
 /* rename on windows will fail if newname already exists.
    MoveFileEx has to be used */
 #if defined(ZEND_WIN32)
@@ -302,15 +326,30 @@
 #define VCWD_GETCWD(buff, size) php_win32_ioutil_getcwd(buff, size)
 #define VCWD_CHMOD(path, mode) php_win32_ioutil_chmod(path, mode)
 #else
+
+#ifdef _AIX
+#define VCWD_FOPEN(path, mode)  fopen_aix(path, mode)
+#define VCWD_OPEN(path, flags) open_aix(path, flags)
+#define VCWD_OPEN_MODE(path, flags, mode)	open_mode_aix(path, flags, mode)
+#define VCWD_RENAME(oldname, newname) rename_aix(oldname, newname)
+#define VCWD_UNLINK(path) unlink_aix(path)
+#define VCWD_ACCESS(pathname, mode) access_aix(pathname, mode)
+#else
+
 #define VCWD_FOPEN(path, mode)  fopen(path, mode)
 #define VCWD_OPEN(path, flags) open(path, flags)
 #define VCWD_OPEN_MODE(path, flags, mode)	open(path, flags, mode)
 # define VCWD_RENAME(oldname, newname) rename(oldname, newname)
+
+#define VCWD_UNLINK(path) unlink(path)
+#define VCWD_ACCESS(pathname, mode) access(pathname, mode)
+#endif
+
 #define VCWD_MKDIR(pathname, mode) mkdir(pathname, mode)
 #define VCWD_RMDIR(pathname) rmdir(pathname)
-#define VCWD_UNLINK(path) unlink(path)
+
 #define VCWD_CHDIR(path) chdir(path)
-#define VCWD_ACCESS(pathname, mode) access(pathname, mode)
+
 #define VCWD_GETCWD(buff, size) getcwd(buff, size)
 #define VCWD_CHMOD(path, mode) chmod(path, mode)
 #endif
--- ./Zend/zend_virtual_cwd.c.orig	2022-12-05 00:13:14 +0000
+++ ./Zend/zend_virtual_cwd.c	2022-12-05 00:14:46 +0000
@@ -73,6 +73,10 @@
 # include <winnt.h>
 #endif
 
+#ifdef _AIX
+#include <sys/vnode.h>
+#endif
+
 #define VIRTUAL_CWD_DEBUG 0
 
 #include "TSRM.h"
--- ./Zend/zend_virtual_cwd.c.orig	2026-01-02 01:02:37.218908600 -0600
+++ ./Zend/zend_virtual_cwd.c	2026-01-02 01:05:33.206227119 -0600
@@ -122,6 +122,105 @@
 # define CWD_STATE_FREE_ERR(state) CWD_STATE_FREE(state)
 #endif
 
+#ifdef _AIX
+/*
+The AIX file operations accepts a regular fine name appended with a trailing
+slash.
+To ensure a consitent behavior on Linux and AIX, check if a path with a trailing
+slash is a directory and simulate Linux behavior if not.
+*/
+#define ERROR_IF_FILE_WITH_TRAILING_SLASH(path, retval, set_errno, retval_if_not_exists, errno_if_not_exists) \
+       if (path[strlen(path) - 1] == '/') {\
+               if (access(path, F_OK) == 0) {\
+                       struct stat buf;\
+                       if (stat(path, &buf) == 0 && buf.st_type != VDIR) {\
+                               if (set_errno != -1) {\
+                                       errno = set_errno;\
+                               }\
+                               return retval;\
+                       }\
+               }\
+               else if (errno_if_not_exists > 0) {\
+                       errno = errno_if_not_exists;\
+                       return retval_if_not_exists;\
+               }\
+       }
+
+CWD_API int stat_aix(const char *path, struct stat *buf) /* {{{ */
+{
+       ERROR_IF_FILE_WITH_TRAILING_SLASH(path, -1, ENOTDIR, 0, 0);
+       return stat(path, buf);
+}
+
+CWD_API int lstat_aix(const char *path, struct stat *buf) /* {{{ */
+{
+       ERROR_IF_FILE_WITH_TRAILING_SLASH(path, -1, ENOTDIR, 0, 0);
+       return lstat(path, buf);
+}
+
+CWD_API int rename_aix(const char *oldname, const char *newname) /* {{{ */
+{
+       ERROR_IF_FILE_WITH_TRAILING_SLASH(oldname, -1, ENOTDIR, 0, 0);
+       return rename(oldname, newname);
+}
+
+CWD_API int access_aix(const char *path, int mode) /* {{{ */
+{
+       ERROR_IF_FILE_WITH_TRAILING_SLASH(path, -1, ENOTDIR, 0, 0);
+       return access(path, mode);
+}
+
+CWD_API int unlink_aix(const char *path) /* {{{ */
+{
+       ERROR_IF_FILE_WITH_TRAILING_SLASH(path, -1, ENOTDIR, 0, 0);
+       return unlink(path);
+}
+
+CWD_API FILE *fopen_aix(const char *path, const char *type) /* {{{ */
+{
+       ERROR_IF_FILE_WITH_TRAILING_SLASH(path, 0, ENOTDIR, NULL, EISDIR);
+       return fopen(path, type);
+}
+
+CWD_API FILE *popen_aix(const char *path, const char *type) /* {{{ */
+{
+       ERROR_IF_FILE_WITH_TRAILING_SLASH(path, 0, ENOTDIR, NULL, EISDIR);
+       /*
+       On Linux, popen does not allow r and w simultaneously
+       */
+       if (strchr(type, 'r') != NULL && strchr(type, 'w') != NULL) {
+               errno = EINVAL;
+               return NULL;
+       }
+       return popen(path, type);
+}
+
+CWD_API int open_aix(const char *path, int flag) /* {{{ */
+{
+       ERROR_IF_FILE_WITH_TRAILING_SLASH(path, 0, ENOTDIR, -1, EISDIR);
+       return open(path, flag);
+}
+
+CWD_API int open_mode_aix(const char *path, int flag, mode_t mode) /* {{{ */
+{
+       ERROR_IF_FILE_WITH_TRAILING_SLASH(path, 0, ENOTDIR, -1, EISDIR);
+       return open(path, flag, mode);
+}
+
+CWD_API int creat_aix(const char *path, mode_t mode) /* {{{ */
+{
+       ERROR_IF_FILE_WITH_TRAILING_SLASH(path, 0, ENOTDIR, -1, EISDIR);
+       return creat(path, mode);
+}
+
+CWD_API int utime_aix(const char *path, const struct utimbuf *times) /* {{{ */
+{
+       ERROR_IF_FILE_WITH_TRAILING_SLASH(path, -1, ENOTDIR, 0, 0);
+       return utime(path, times);
+}
+#endif
+
+
 static int php_is_dir_ok(const cwd_state *state)  /* {{{ */
 {
 	zend_stat_t buf = {0};
--- ./Zend/zend_virtual_cwd.h.orig	2026-01-02 01:05:55.254417741 -0600
+++ ./Zend/zend_virtual_cwd.h	2026-01-02 01:08:46.753902173 -0600
@@ -373,15 +373,30 @@
 #define VCWD_CHDIR_FILE(path) virtual_chdir_file(path, chdir)
 #define VCWD_GETWD(buf) getwd(buf)
 #define VCWD_STAT(path, buff) php_sys_stat(path, buff)
+
+#ifdef _AIX
+#define VCWD_CREAT(path, mode) creat_aix(path, mode)
+#define VCWD_LSTAT(path, buff) lstat_aix(path, buff)
+#define VCWD_POPEN(command, type) popen_aix(command, type)
+#else
+#define VCWD_CREAT(path, mode) creat(path, mode)
+
 #define VCWD_LSTAT(path, buff) lstat(path, buff)
-#define VCWD_OPENDIR(pathname) opendir(pathname)
+
 #define VCWD_POPEN(command, type) popen(command, type)
 
+#endif
+#define VCWD_OPENDIR(pathname) opendir(pathname)
+
 #define VCWD_REALPATH(path, real_path) tsrm_realpath(path, real_path)
 
 #ifdef HAVE_UTIME
 # ifdef ZEND_WIN32
 #  define VCWD_UTIME(path, time) win32_utime(path, time)
+
+# elif defined(_AIX)
+#  define VCWD_UTIME(path, time) utime_aix(path, time)
+
 # else
 #  define VCWD_UTIME(path, time) utime(path, time)
 # endif
