From 22f7ad1057e1a1e20933e0a1ff2a858ecd9e3fec Mon Sep 17 00:00:00 2001 From: Po Lu Date: Thu, 26 Jan 2023 19:54:38 +0800 Subject: [PATCH] Update Android port * INSTALL.android: Document how to install sqlite3. * build-aux/ndk-build-helper-1.mk (SYSTEM_LIBRARIES): * build-aux/ndk-build-helper-2.mk (SYSTEM_LIBRARIES): Add liblog and libandroid. * configure.ac (SQLITE3_LIBS, HAVE_SQLITE3) (HAVE_SQLITE3_LOAD_EXTENSION): Support on Android. (APKSIGNER): Look for this new required binary. * cross/ndk-build/ndk-build-shared-library.mk (objname): * cross/ndk-build/ndk-build-static-library.mk (objname): Avoid duplicate rules by prefixing objects with module type. * cross/ndk-build/ndk-build.mk.in (NDK_BUILD_SHARED): Fix definition. * cross/ndk-build/ndk-resolve.mk: (NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE)): Handle new system libraries. * doc/emacs/android.texi (Android File System): Document Android 10 system restriction. * java/AndroidManifest.xml.in: Target Android 33, not 28. * java/Makefile.in (SIGN_EMACS_V2, APKSIGNER): New variables. ($(APK_NAME)): Make sure to apply a ``version 2 signature'' to the package as well. * java/org/gnu/emacs/EmacsNative.java (EmacsNative): New argument apiLevel. * java/org/gnu/emacs/EmacsNoninteractive.java (main): * java/org/gnu/emacs/EmacsThread.java (run): Pass API level. * m4/ndk-build.m4 (ndk_package_mape): Add package mapping for sqlite3. * src/Makefile.in (SQLITE3_CFLAGS): New substition. (EMACS_CFLAGS): Add that variable. * src/android.c (android_api_level): New variable. (initEmacs): Set it. (android_file_access_p): Make static. (android_hack_asset_fd): Adjust for restrictions in Android 29 and later. (android_close_on_exec): New function. (android_open): Adjust to not duplicate file descriptor even if CLOEXEC. (android_faccessat): Use fstatat at-func emulation. * src/android.h: Update prototypes. * src/dired.c (file_name_completion_dirp): * src/fileio.c (file_access_p, Faccess_file): Now that sys_faccessat takes care of everything, stop calling android_file_access_p. --- INSTALL.android | 18 ++ build-aux/ndk-build-helper-1.mk | 2 +- build-aux/ndk-build-helper-2.mk | 2 +- configure.ac | 69 ++++-- cross/ndk-build/ndk-build-shared-library.mk | 7 +- cross/ndk-build/ndk-build-static-library.mk | 2 +- cross/ndk-build/ndk-build.mk.in | 2 +- cross/ndk-build/ndk-resolve.mk | 30 ++- doc/emacs/android.texi | 28 ++- java/AndroidManifest.xml.in | 2 +- java/Makefile.in | 9 +- java/org/gnu/emacs/EmacsNative.java | 7 +- java/org/gnu/emacs/EmacsNoninteractive.java | 3 +- java/org/gnu/emacs/EmacsThread.java | 5 +- m4/ndk-build.m4 | 1 + src/Makefile.in | 3 +- src/android.c | 220 ++++++++++++++------ src/android.h | 1 - src/dired.c | 6 - src/fileio.c | 12 -- 20 files changed, 305 insertions(+), 124 deletions(-) diff --git a/INSTALL.android b/INSTALL.android index ed0bd0f68dc..06211e5ec93 100644 --- a/INSTALL.android +++ b/INSTALL.android @@ -165,6 +165,9 @@ work, along with what has to be patched to make them work: and apply the patch at the end of this file.) icu4c - https://android.googlesource.com/platform/external/icu/ (You must apply the patch at the end of this file.) + sqlite3 - https://android.googlesource.com/platform/external/sqlite/ + (You must apply the patch at the end of this file, and add the `dist' + directory to ``--with-ndk-path''.) Many of these dependencies have been migrated over to the ``Android.bp'' build system now used to build Android itself. @@ -592,3 +595,18 @@ index 8e5f757..44bb130 100644 LOCAL_MODULE_TAGS := optional LOCAL_MODULE := libicuuc LOCAL_RTTI_FLAG := -frtti + +PATCH FOR SQLITE3 + +diff --git a/dist/Android.mk b/dist/Android.mk +index bf277d2..36734d9 100644 +--- a/dist/Android.mk ++++ b/dist/Android.mk +@@ -141,6 +141,7 @@ include $(BUILD_HOST_EXECUTABLE) + include $(CLEAR_VARS) + LOCAL_SRC_FILES := $(common_src_files) + LOCAL_CFLAGS += $(minimal_sqlite_flags) ++LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH) + LOCAL_MODULE:= libsqlite_static_minimal + LOCAL_SDK_VERSION := 23 + include $(BUILD_STATIC_LIBRARY) diff --git a/build-aux/ndk-build-helper-1.mk b/build-aux/ndk-build-helper-1.mk index 4ffe0d423e4..9035b5ca59a 100644 --- a/build-aux/ndk-build-helper-1.mk +++ b/build-aux/ndk-build-helper-1.mk @@ -77,7 +77,7 @@ endef # dependencies can be ignored while building a shared library, as they # will be linked in to the resulting shared object file later. -SYSTEM_LIBRARIES = z libz libc c libdl dl stdc++ libstdc++ +SYSTEM_LIBRARIES = z libz libc c libdl dl stdc++ libstdc++ log liblog android libandroid $(foreach module,$(filter-out $(SYSTEM_LIBRARIES), $(LOCAL_SHARED_LIBRARIES)),$(eval $(call add-so-name,$(module)))) $(foreach module,$(filter-out $(SYSTEM_LIBRARIES), $(LOCAL_SHARED_LIBRARIES) $(LOCAL_STATIC_LIBRARIES) $(LOCAL_WHOLE_LIBRARIES)),$(eval $(call add-includes,$(module)))) diff --git a/build-aux/ndk-build-helper-2.mk b/build-aux/ndk-build-helper-2.mk index 9c9e7cf09a9..8f2f397e534 100644 --- a/build-aux/ndk-build-helper-2.mk +++ b/build-aux/ndk-build-helper-2.mk @@ -87,7 +87,7 @@ endef # Resolve additional dependencies based on LOCAL_STATIC_LIBRARIES and # LOCAL_SHARED_LIBRARIES. -SYSTEM_LIBRARIES = z libz libc c libdl dl libstdc++ stdc++ +SYSTEM_LIBRARIES = z libz libc c libdl dl libstdc++ stdc++ log liblog android libandroid $(foreach module,$(filter-out $(SYSTEM_LIBRARIES), $(LOCAL_STATIC_LIBRARIES) $(LOCAL_WHOLE_STATIC_LIBRARIES)),$(eval $(call add-a-name,$(module)))) $(foreach module,$(filter-out $(SYSTEM_LIBRARIES), $(LOCAL_SHARED_LIBRARIES)),$(eval $(call add-so-name,$(module)))) diff --git a/configure.ac b/configure.ac index 95bb0cfca88..879e4ab74aa 100644 --- a/configure.ac +++ b/configure.ac @@ -752,6 +752,7 @@ ANDROID= JAVAC= AAPT= JARSIGNER= +APKSIGNER= ZIPALIGN= DX= ANDROID_JAR= @@ -763,6 +764,7 @@ android_makefiles="lib/Makefile lib/gnulib.mk lib-src/Makefile src/Makefile" AC_ARG_VAR([JAVAC], [Java compiler path. Used for Android.]) AC_ARG_VAR([JARSIGNER], [Java package signer path. Used for Android.]) +AC_ARG_VAR([APKSIGNER], [Android package signer path. Used for Android.]) AC_ARG_VAR([SDK_BULD_TOOLS], [Path to the Android SDK build tools.]) if test "$with_android" = "yes"; then @@ -792,6 +794,7 @@ the path to your Java compiler before configuring Emacs, like so: JAVAC=/opt/jdk/bin/javac ./configure --with-android]) fi + AC_CHECK_PROGS([JARSIGNER], [jarsigner]) if test "$JARSIGNER" = ""; then AC_MSG_ERROR([The Java package signing utility was not found. @@ -861,6 +864,12 @@ Android 13 (Tiramisu) or later.]) Please verify that the path to the SDK build tools you specified is correct]) fi + AC_PATH_PROGS([APKSIGNER], [apksigner], [], "${SDK_BUILD_TOOLS}:$PATH") + if test "$APKSIGNER" = ""; then + AC_MSG_ERROR([The Android package signing tool was not found. +Please verify that the path to the SDK build tools you specified is correct]) + fi + AC_PATH_PROGS([D8], [d8], [], "${SDK_BUILD_TOOLS}:$PATH") if test "D8" = ""; then AC_MSG_ERROR([The Android dexer was not found. @@ -1051,6 +1060,7 @@ package will likely install on older systems but crash on startup.]) passthrough="$passthrough --with-json=$with_json" passthrough="$passthrough --with-jpeg=$with_jpeg" passthrough="$passthrough --with-xml2=$with_xml2" + passthrough="$passthrough --with-sqlite3=$with_sqlite3" AS_IF([XCONFIGURE=android ANDROID_CC="$ANDROID_CC" \ ANDROID_SDK="$android_sdk" android_abi=$android_abi \ @@ -1120,10 +1130,10 @@ if test "$ANDROID" = "yes"; then with_json=no with_jpeg=no with_xml2=no + with_sqlite3=no fi with_rsvg=no - with_sqlite3=no with_lcms2=no with_libsystemd=no with_cairo=no @@ -3348,30 +3358,49 @@ fi ### Use -lsqlite3 if available, unless '--with-sqlite3=no' HAVE_SQLITE3=no +SQLITE3_LIBS= +SQLITE3_CFLAGS= if test "${with_sqlite3}" != "no"; then - AC_CHECK_LIB([sqlite3], [sqlite3_open_v2], - [HAVE_SQLITE3=yes], - [HAVE_SQLITE3=no]) - if test "$HAVE_SQLITE3" = "yes"; then - SQLITE3_LIBS=-lsqlite3 - AC_SUBST([SQLITE3_LIBS]) - LIBS="$SQLITE3_LIBS $LIBS" - AC_DEFINE([HAVE_SQLITE3], [1], - [Define to 1 if you have the libsqlite3 library (-lsqlite).]) - # Windows loads libsqlite dynamically - if test "${opsys}" = "mingw32"; then - SQLITE3_LIBS= + if test "${REALLY_ANDROID}" = "yes"; then + ndk_SEARCH_MODULE([sqlite3], [SQLITE3], [HAVE_SQLITE3=yes]) + + if test "$HAVE_SQLITE3" = "yes"; then + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $SQLITE3_CFLAGS" + AC_CHECK_DECL([sqlite3_open_v2], [HAVE_SQLITE=yes], + [HAVE_SQLITE3=no], [#include ]) + CFLAGS="$SAVE_CFLAGS" fi - AC_CHECK_LIB([sqlite3], [sqlite3_load_extension], - [HAVE_SQLITE3_LOAD_EXTENSION=yes], - [HAVE_SQLITE3_LOAD_EXTENSION=no]) - if test "$HAVE_SQLITE3_LOAD_EXTENSION" = "yes"; then - AC_DEFINE([HAVE_SQLITE3_LOAD_EXTENSION], [1], - [Define to 1 if sqlite3 supports loading extensions.]) + else + AC_CHECK_LIB([sqlite3], [sqlite3_open_v2], + [HAVE_SQLITE3=yes], + [HAVE_SQLITE3=no]) + if test "$HAVE_SQLITE3" = "yes"; then + SQLITE3_LIBS=-lsqlite3 + LIBS="$SQLITE3_LIBS $LIBS" + # Windows loads libsqlite dynamically + if test "${opsys}" = "mingw32"; then + SQLITE3_LIBS= + fi + AC_CHECK_LIB([sqlite3], [sqlite3_load_extension], + [HAVE_SQLITE3_LOAD_EXTENSION=yes], + [HAVE_SQLITE3_LOAD_EXTENSION=no]) + if test "$HAVE_SQLITE3_LOAD_EXTENSION" = "yes"; then + AC_DEFINE([HAVE_SQLITE3_LOAD_EXTENSION], [1], + [Define to 1 if sqlite3 supports loading extensions.]) + fi fi - fi + fi + + if test "$HAVE_SQLITE3" = "yes"; then + AC_DEFINE([HAVE_SQLITE3], [1], + [Define to 1 if you have the libsqlite3 library (-lsqlite).]) + fi fi +AC_SUBST([SQLITE3_LIBS]) +AC_SUBST([SQLITE3_CFLAGS]) + HAVE_IMAGEMAGICK=no if test "${HAVE_X11}" = "yes" || test "${HAVE_NS}" = "yes" || test "${HAVE_W32}" = "yes" || \ test "${HAVE_BE_APP}" = "yes" || test "${window_system}" = "pgtk"; then diff --git a/cross/ndk-build/ndk-build-shared-library.mk b/cross/ndk-build/ndk-build-shared-library.mk index a4b7b47f749..b69641ba9b0 100644 --- a/cross/ndk-build/ndk-build-shared-library.mk +++ b/cross/ndk-build/ndk-build-shared-library.mk @@ -20,7 +20,12 @@ # which actually builds targets. eq = $(and $(findstring $(1),$(2)),$(findstring $(2),$(1))) -objname = $(1)-$(subst /,_,$(2).o) + +# Objects for shared libraries are prefixed with `-shared-' in +# addition to the name of the module, because a common practice in +# Android.mk files written by Google is to define two modules with the +# same name but of different types. +objname = $(1)-shared-$(subst /,_,$(2).o) # Here are the default flags to link shared libraries with. NDK_SO_DEFAULT_LDFLAGS := -lc -lm diff --git a/cross/ndk-build/ndk-build-static-library.mk b/cross/ndk-build/ndk-build-static-library.mk index 4d16d81330c..349b9242b1f 100644 --- a/cross/ndk-build/ndk-build-static-library.mk +++ b/cross/ndk-build/ndk-build-static-library.mk @@ -20,7 +20,7 @@ # which actually builds targets. eq = $(and $(findstring $(1),$(2)),$(findstring $(2),$(1))) -objname = $(1)-$(subst /,_,$(2).o) +objname = $(1)-static-$(subst /,_,$(2).o) define single-object-target diff --git a/cross/ndk-build/ndk-build.mk.in b/cross/ndk-build/ndk-build.mk.in index 798dcf6c19e..5b0aa82856d 100644 --- a/cross/ndk-build/ndk-build.mk.in +++ b/cross/ndk-build/ndk-build.mk.in @@ -38,7 +38,7 @@ NDK_BUILD_MODULES := $(call uniqify,$(NDK_BUILD_MODULES)) # requires the C++ standard library. ifneq ($(NDK_BUILD_ANY_CXX_MODULE),) -NDK_BUILD_SHARED += $(NDK_BUILD_ANY_CXX_SHARED) +NDK_BUILD_SHARED += $(NDK_BUILD_CXX_SHARED) endif define subr-1 diff --git a/cross/ndk-build/ndk-resolve.mk b/cross/ndk-build/ndk-resolve.mk index 910be8dab53..c2e281c53ba 100644 --- a/cross/ndk-build/ndk-resolve.mk +++ b/cross/ndk-build/ndk-resolve.mk @@ -43,32 +43,50 @@ NDK_CFLAGS_$(LOCAL_MODULE) += $(addprefix -I,$(NDK_LOCAL_EXPORT_C_INCLUDES_$(1)) # If the module happens to be zlib, then add -lz to the shared library # flags. -ifneq ($(strip $(1)),libz) +ifeq ($(strip $(1)),libz) NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += -lz endif -ifneq ($(strip $(1)),z) +ifeq ($(strip $(1)),z) NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += -lz endif # Likewise for libdl. -ifneq ($(strip $(1)),libdl) +ifeq ($(strip $(1)),libdl) NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += -ldl endif -ifneq ($(strip $(1)),dl) +ifeq ($(strip $(1)),dl) NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += -ldl endif # Likewise for libstdc++. -ifneq ($(strip $(1)),libstdc++) +ifeq ($(strip $(1)),libstdc++) NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += -lstdc++ endif -ifneq ($(strip $(1)),dl) +ifeq ($(strip $(1)),dl) NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += -lstdc++ endif +# Likewise for liblog. +ifeq ($(strip $(1)),liblog) +NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += -llog +endif + +ifeq ($(strip $(1)),log) +NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += -llog +endif + +# Likewise for libandroid. +ifeq ($(strip $(1)),libandroid) +NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += -landroid +endif + +ifeq ($(strip $(1)),android) +NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += -landroid +endif + ifneq ($(2),) ifneq ($(findstring lib,$(1)),) NDK_LOCAL_A_NAMES_$(LOCAL_MODULE) += $(1).a diff --git a/doc/emacs/android.texi b/doc/emacs/android.texi index e910e482ad8..98d7f1e1d9e 100644 --- a/doc/emacs/android.texi +++ b/doc/emacs/android.texi @@ -160,13 +160,35 @@ The @dfn{app library} directory. This is automatically appended to @item The @dfn{external storage} directory. This is accessible to Emacs -when the user grants the @code{Files and media} permission to Emacs -via system settings. +when the user grants the ``Files and Media'' permission to Emacs via +system settings. @end itemize -The external storage directory is found at @file{/sdcard}; the other + The external storage directory is found at @file{/sdcard}; the other directories are not found at any fixed location. +@cindex file system limitations, Android 10 + On Android 10 and later, the Android system restricts applications +from accessing files in the @file{/sdcard} directory using +file-related system calls such as @code{open} and @code{readdir}. + + This restriction is known as ``Scoped Storage'', and supposedly +makes the system more secure. Unfortunately, it also means that Emacs +cannot access files in those directories, despite holding the +necessary permissions. Thankfully, the Open Handset Alliance's +version of Android allows this restriction to be disabled on a +per-program basis; the corresponding option in the system settings +panel is: + +@indentedblock +System -> Developer Options -> App Compatibility Changes -> Emacs -> +DEFAULT_SCOPED_STORAGE +@end indentedblock + + After you disable this setting and grant Emacs the ``Files and +Media'' permission, it will be able to access files under +@file{/sdcard} as usual. + @node Android Environment @section Running Emacs under Android diff --git a/java/AndroidManifest.xml.in b/java/AndroidManifest.xml.in index c4a9d1f5177..527ce74c474 100644 --- a/java/AndroidManifest.xml.in +++ b/java/AndroidManifest.xml.in @@ -53,7 +53,7 @@ along with GNU Emacs. If not, see . --> + android:targetSdkVersion="33"/> = ANDROID_MAX_ASSET_FD || fd < 0) { - /* Too bad. You lose. */ + /* Too bad. Pretend this is an out of memory error. */ errno = ENOMEM; if (fd >= 0) @@ -1713,7 +1791,7 @@ android_init_emacs_window (void) extern JNIEXPORT void JNICALL NATIVE_NAME (initEmacs) (JNIEnv *env, jobject object, jarray argv, - jobject dump_file_object) + jobject dump_file_object, jint api_level) { char **c_argv; jsize nelements, i; @@ -1732,6 +1810,9 @@ NATIVE_NAME (initEmacs) (JNIEnv *env, jobject object, jarray argv, /* Trick GCC into not optimizing this variable away. */ unused_pointer = buffer; + /* Set the Android API level. */ + android_api_level = api_level; + android_java_env = env; nelements = (*env)->GetArrayLength (env, argv); @@ -4214,34 +4295,47 @@ android_window_updated (android_window window, unsigned long serial) -#if __ANDROID_API__ >= 16 +/* When calling the system's faccessat, make sure to clear the flag + AT_EACCESS. -/* Replace the system faccessat with one which understands AT_EACCESS. Android's faccessat simply fails upon using AT_EACCESS, so replace - it with zero here. This isn't caught during configuration. + it with zero here. This isn't caught during configuration as Emacs + is being cross compiled. This replacement is only done when building for Android 16 or later, because earlier versions use the gnulib replacement that - lacks these issues. */ + lacks these issues. + + This is unnecessary on earlier API versions, as gnulib's + rpl_faccessat will be used instead, which lacks these problems. */ + +/* Like faccessat, except it also understands DIRFD opened using + android_dirfd. */ int android_faccessat (int dirfd, const char *pathname, int mode, int flags) { - return faccessat (dirfd, pathname, mode, flags & ~AT_EACCESS); -} + const char *asset; -#else /* __ANDROID_API__ < 16 */ + if (dirfd != AT_FDCWD) + dirfd + = android_lookup_asset_directory_fd (dirfd, &pathname, + pathname); -/* This is unnecessary on earlier API versions, as gnulib's - rpl_faccessat will be used instead. */ + /* Check if pathname is actually an asset. If that is the case, + simply fall back to android_file_access_p. */ -int -android_faccessat (int dirfd, const char *pathname, int mode, int flags) -{ - return faccessat (dirfd, pathname, mode, flags); -} + if (dirfd == AT_FDCWD + && asset_manager + && (asset = android_get_asset_name (pathname))) + return !android_file_access_p (asset, mode); +#if __ANDROID_API__ >= 16 + return faccessat (dirfd, pathname, mode, flags & ~AT_EACCESS); +#else + return faccessat (dirfd, pathname, mode, flags); #endif +} @@ -4468,10 +4562,10 @@ android_closedir (struct android_dir *dir) xfree (dir); } -/* Subroutine used by android_fstatat. If DIRFD belongs to an open - asset directory and FILE is a relative file name, then return - AT_FDCWD and the absolute file name of the directory prepended to - FILE in *PATHNAME. Else, return DIRFD. */ +/* Subroutine used by android_fstatat and android_faccessat. If DIRFD + belongs to an open asset directory and FILE is a relative file + name, then return AT_FDCWD and the absolute file name of the + directory prepended to FILE in *PATHNAME. Else, return DIRFD. */ int android_lookup_asset_directory_fd (int dirfd, diff --git a/src/android.h b/src/android.h index 33fad512d4a..8234dbb07c0 100644 --- a/src/android.h +++ b/src/android.h @@ -46,7 +46,6 @@ extern int android_emacs_init (int, char **, char *); extern int android_select (int, fd_set *, fd_set *, fd_set *, struct timespec *); -extern bool android_file_access_p (const char *, int); extern int android_open (const char *, int, int); extern char *android_user_full_name (struct passwd *); extern int android_fstat (int, struct stat *); diff --git a/src/dired.c b/src/dired.c index b38416e981a..93487d552e2 100644 --- a/src/dired.c +++ b/src/dired.c @@ -888,12 +888,6 @@ file_name_completion_dirp (int fd, struct dirent *dp, ptrdiff_t len) memcpy (subdir_name, dp->d_name, len); strcpy (subdir_name + len, "/"); -#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY - /* Check if subdir_name lies in the assets directory. */ - if (android_file_access_p (subdir_name, F_OK)) - return true; -#endif - bool dirp = sys_faccessat (fd, subdir_name, F_OK, AT_EACCESS) == 0; SAFE_FREE (); diff --git a/src/fileio.c b/src/fileio.c index 6f25506dbc2..71f83ea6daf 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -182,12 +182,6 @@ file_access_p (char const *file, int amode) } #endif -#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY - /* FILE may be some kind of special Android file. */ - if (android_file_access_p (file, amode)) - return true; -#endif - if (sys_faccessat (AT_FDCWD, file, amode, AT_EACCESS) == 0) return true; @@ -3018,12 +3012,6 @@ If there is no error, returns nil. */) encoded_filename = ENCODE_FILE (absname); -#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY - /* FILE may be some kind of special Android file. */ - if (android_file_access_p (SSDATA (encoded_filename), R_OK)) - return Qnil; -#endif - if (sys_faccessat (AT_FDCWD, SSDATA (encoded_filename), R_OK, AT_EACCESS) != 0) report_file_error (SSDATA (string), filename); -- 2.39.5