From 88afd96e36e62017c9c1f2229e2748b6dfbdb39a Mon Sep 17 00:00:00 2001 From: Po Lu Date: Fri, 17 Feb 2023 16:27:00 +0800 Subject: [PATCH] Fix build and running on Android 2.2 * INSTALL.android: Document that Android 2.2 is now supported, with caveats. * configure.ac (ANDROID_MIN_SDK, ANDROID_SDK_18_OR_EARLIER) (SYSTEM_TYPE, ANDROID_STUBIFY, SIZEOF_LONG): Correctly detect things missing on Android 2.2. * java/Makefile.in (ANDROID_JAR, JARSIGNER_FLAGS): * java/debug.sh (jdb, gdbserver, line): * java/org/gnu/emacs/EmacsApplication.java (findDumpFile): * java/org/gnu/emacs/EmacsService.java (onCreate): * java/org/gnu/emacs/EmacsThread.java (EmacsThread, run): Run parameter initialization on main thread. * src/android-asset.h (struct android_asset_manager) (struct android_asset, AAssetManager_fromJava, AAssetManager_open) (AAsset_close, android_asset_create_stream) (android_asset_read_internal, AAsset_openFileDescriptor) (AAsset_getLength, AAsset_getBuffer, AAsset_read): New file. * src/android.c (android_user_full_name, android_hack_asset_fd) (android_check_compressed_file): Implement for Android 2.2. * src/process.c (Fprocess_send_eof): Don't call tcdrain if unavailable. * src/sfntfont-android.c (system_font_directories): Fix compiler warning. * src/sfntfont.c (sfntfont_read_cmap): Correctly test rc of emacs_open. * src/textconv.c (handle_pending_conversion_events_1): Mark buffer UNINIT. --- INSTALL.android | 15 +- configure.ac | 23 +- java/Makefile.in | 14 +- java/debug.sh | 8 +- java/org/gnu/emacs/EmacsApplication.java | 1 + java/org/gnu/emacs/EmacsService.java | 25 +- java/org/gnu/emacs/EmacsThread.java | 9 +- src/android-asset.h | 423 +++++++++++++++++++++++ src/android.c | 72 +++- src/process.c | 2 +- src/sfntfont-android.c | 2 +- src/sfntfont.c | 2 +- src/textconv.c | 2 +- 13 files changed, 574 insertions(+), 24 deletions(-) create mode 100644 src/android-asset.h diff --git a/INSTALL.android b/INSTALL.android index a8d73331493..ab39a55eaf3 100644 --- a/INSTALL.android +++ b/INSTALL.android @@ -91,9 +91,18 @@ for, and the include directories specify the paths to the relevant Android headers. In addition, it may be necessary to specify "-gdwarf-2", due to a bug in the Android NDK. -Emacs is known to build for Android 2.2 (API version 8) or later, and -run on Android 2.3 or later. It is supposed to run on Android 2.2 as -well. +Even older versions of the Android SDK do not require the extra +`-isystem' directives. + +Emacs is known to run on Android 2.2 (API version 8) or later, with +the NDK r10b or later. We wanted to make Emacs work on even older +versions of Android, but they are missing the required JNI graphics +library that allows Emacs to display text from C code. + +Due to an extremely nasty bug in the Android 2.2 system, the generated +Emacs package cannot be compressed in builds for Android 2.2. As a +result, the Emacs package will be approximately 100 megabytes larger +than a compressed package for a newer version of Android. DEBUG AND RELEASE BUILDS diff --git a/configure.ac b/configure.ac index b4fed263cf5..a4a16ec8062 100644 --- a/configure.ac +++ b/configure.ac @@ -1044,11 +1044,18 @@ package will likely install on older systems but crash on startup.]) # Now tell java/Makefile if Emacs is being built for Android 4.3 or # earlier. ANDROID_SDK_18_OR_EARLIER= - if test "$android_sdk" -lt "18"; then + if test "$android_sdk" -le "18"; then ANDROID_SDK_18_OR_EARLIER=yes fi AC_SUBST([ANDROID_SDK_18_OR_EARLIER]) + # Likewise for Android 2.2. + ANDROID_SDK_8_OR_EARLIER= + if test "$android_sdk" -le "8"; then + ANDROID_SDK_8_OR_EARLIER=yes + fi + AC_SUBST([ANDROID_SDK_8_OR_EARLIER]) + # Save confdefs.h and config.log for now. mv -f confdefs.h _confdefs.h mv -f config.log _config.log @@ -2251,6 +2258,10 @@ AC_DEFINE_UNQUOTED([SYSTEM_TYPE], ["$SYSTEM_TYPE"], [The type of system you are compiling for; sets 'system-type'.]) AC_SUBST([SYSTEM_TYPE]) +# Check for pw_gecos in struct passwd; this is known to be missing on +# Android. + +AC_CHECK_MEMBERS([struct passwd.pw_gecos], [], [], [#include ]) pre_PKG_CONFIG_CFLAGS=$CFLAGS pre_PKG_CONFIG_LIBS=$LIBS @@ -2487,7 +2498,13 @@ for Android, but all API calls need to be stubbed out]) ANDROID_CFLAGS="$ANDROID_CFLAGS -ftree-vectorize" # Link with libraries required for Android support. - ANDROID_LIBS="-landroid -llog -ljnigraphics" + # API 9 and later require `-landroid' for the asset manager. + # API 8 uses an emulation via the JNI. + if test "$ANDROID_SDK" -lt "9"; then + ANDROID_LIBS="-llog -ljnigraphics" + else + ANDROID_LIBS="-landroid -llog -ljnigraphics" + fi # This is required to make the system load emacs.apk's libpng # (among others) instead of the system's own. But it doesn't work @@ -5610,7 +5627,7 @@ OLD_LIBS=$LIBS LIBS="$LIB_PTHREAD $LIB_MATH $LIBS" AC_CHECK_FUNCS([accept4 fchdir gethostname \ getrusage get_current_dir_name \ -lrand48 random rint trunc \ +lrand48 random rint tcdrain trunc \ select getpagesize setlocale newlocale \ getrlimit setrlimit shutdown \ pthread_sigmask strsignal setitimer \ diff --git a/java/Makefile.in b/java/Makefile.in index fc0d23980e4..92c03469c69 100644 --- a/java/Makefile.in +++ b/java/Makefile.in @@ -39,6 +39,7 @@ JARSIGNER_FLAGS = ANDROID_JAR = @ANDROID_JAR@ ANDROID_ABI = @ANDROID_ABI@ ANDROID_SDK_18_OR_EARLIER = @ANDROID_SDK_18_OR_EARLIER@ +ANDROID_SDK_8_OR_EARLIER = @ANDROID_SDK_8_OR_EARLIER@ WARN_JAVAFLAGS = -Xlint:deprecation JAVAFLAGS = -classpath "$(ANDROID_JAR):." -target 1.7 -source 1.7 \ @@ -53,6 +54,16 @@ else JARSIGNER_FLAGS = endif +# When building Emacs for Android 2.2, assets must not be compressed. +# Otherwise, the asset manager fails to extract files larger than 1 +# MB. + +ifneq (,$(ANDROID_SDK_8_OR_EARLIER)) +AAPT_ASSET_ARGS = -0 "" +else +AAPT_ASSET_ARGS = +endif + SIGN_EMACS = -keystore emacs.keystore -storepass emacs1 $(JARSIGNER_FLAGS) SIGN_EMACS_V2 = sign --v2-signing-enabled --ks emacs.keystore \ --debuggable-apk-permitted --ks-pass pass:emacs1 @@ -192,7 +203,8 @@ emacs.apk-in: install_temp install_temp/assets/directory-tree \ # of Android. Make sure not to generate R.java, as it's already been # generated. $(AM_V_AAPT) $(AAPT) p -I "$(ANDROID_JAR)" -F $@ \ - -f -M AndroidManifest.xml -A install_temp/assets \ + -f -M AndroidManifest.xml $(AAPT_ASSET_ARGS) \ + -A install_temp/assets \ -S res -J install_temp $(AM_V_SILENT) pushd install_temp &> /dev/null; \ $(AAPT) add ../$@ `find lib -type f`; \ diff --git a/java/debug.sh b/java/debug.sh index cbef7518984..30e5a94eee5 100755 --- a/java/debug.sh +++ b/java/debug.sh @@ -32,6 +32,7 @@ jdb_port=64013 jdb=no attach_existing=no gdbserver= +gdb=gdb while [ $# -gt 0 ]; do case "$1" in @@ -51,6 +52,7 @@ while [ $# -gt 0 ]; do echo " --port PORT run the GDB server on a specific port" echo " --jdb-port PORT run the JDB server on a specific port" echo " --jdb run JDB instead of GDB" + echo " --gdb use specified GDB binary" echo " --attach-existing attach to an existing process" echo " --gdbserver BINARY upload and use the specified gdbserver binary" echo " --help print this message" @@ -65,6 +67,10 @@ while [ $# -gt 0 ]; do "--jdb" ) jdb=yes ;; + "--gdb" ) + shift + gdb=$1 + ;; "--gdbserver" ) shift gdbserver=$1 @@ -355,4 +361,4 @@ fi # Finally, start gdb with any extra arguments needed. cd "$oldpwd" -gdb --eval-command "target remote localhost:$gdb_port" $gdbargs +$gdb --eval-command "target remote localhost:$gdb_port" $gdbargs diff --git a/java/org/gnu/emacs/EmacsApplication.java b/java/org/gnu/emacs/EmacsApplication.java index 96328b99d1c..6a065165eb1 100644 --- a/java/org/gnu/emacs/EmacsApplication.java +++ b/java/org/gnu/emacs/EmacsApplication.java @@ -49,6 +49,7 @@ public class EmacsApplication extends Application for a file named ``emacs-.pdmp'' and delete the rest. */ filesDirectory = context.getFilesDir (); + allFiles = filesDirectory.listFiles (new FileFilter () { @Override public boolean diff --git a/java/org/gnu/emacs/EmacsService.java b/java/org/gnu/emacs/EmacsService.java index 2acb3ead086..4d373937ab0 100644 --- a/java/org/gnu/emacs/EmacsService.java +++ b/java/org/gnu/emacs/EmacsService.java @@ -180,11 +180,11 @@ public class EmacsService extends Service public void onCreate () { - AssetManager manager; + final AssetManager manager; Context app_context; - String filesDir, libDir, cacheDir, classPath; - double pixelDensityX; - double pixelDensityY; + final String filesDir, libDir, cacheDir, classPath; + final double pixelDensityX; + final double pixelDensityY; SERVICE = this; handler = new Handler (Looper.getMainLooper ()); @@ -210,13 +210,18 @@ public class EmacsService extends Service Log.d (TAG, "Initializing Emacs, where filesDir = " + filesDir + ", libDir = " + libDir + ", and classPath = " + classPath); - EmacsNative.setEmacsParams (manager, filesDir, libDir, - cacheDir, (float) pixelDensityX, - (float) pixelDensityY, - classPath, this); - /* Start the thread that runs Emacs. */ - thread = new EmacsThread (this, needDashQ); + thread = new EmacsThread (this, new Runnable () { + @Override + public void + run () + { + EmacsNative.setEmacsParams (manager, filesDir, libDir, + cacheDir, (float) pixelDensityX, + (float) pixelDensityY, + classPath, EmacsService.this); + } + }, needDashQ); thread.start (); } catch (IOException exception) diff --git a/java/org/gnu/emacs/EmacsThread.java b/java/org/gnu/emacs/EmacsThread.java index 2724d838d41..30484710651 100644 --- a/java/org/gnu/emacs/EmacsThread.java +++ b/java/org/gnu/emacs/EmacsThread.java @@ -28,11 +28,16 @@ public class EmacsThread extends Thread /* Whether or not Emacs should be started -Q. */ private boolean startDashQ; + /* Runnable run to initialize Emacs. */ + private Runnable paramsClosure; + public - EmacsThread (EmacsService service, boolean startDashQ) + EmacsThread (EmacsService service, Runnable paramsClosure, + boolean startDashQ) { super ("Emacs main thread"); this.startDashQ = startDashQ; + this.paramsClosure = paramsClosure; } @Override @@ -46,6 +51,8 @@ public class EmacsThread extends Thread else args = new String[] { "libandroid-emacs.so", "-Q", }; + paramsClosure.run (); + /* Run the native code now. */ EmacsNative.initEmacs (args, EmacsApplication.dumpFileName, Build.VERSION.SDK_INT); diff --git a/src/android-asset.h b/src/android-asset.h new file mode 100644 index 00000000000..b0e83bbf424 --- /dev/null +++ b/src/android-asset.h @@ -0,0 +1,423 @@ +/* Android initialization for GNU Emacs. + +Copyright (C) 2023 Free Software Foundation, Inc. + +This file is part of GNU Emacs. + +GNU Emacs is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or (at +your option) any later version. + +GNU Emacs is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Emacs. If not, see . */ + +#include + +/* This file contains an emulation of the Android asset manager API + used on builds for Android 2.2. It is included by android.c + whenever appropriate. + + The replacements in this file are not thread safe and must only be + called from the creating thread. */ + +struct android_asset_manager +{ + /* JNI environment. */ + JNIEnv *env; + + /* Asset manager class and functions. */ + jclass class; + jmethodID open_fd; + + /* Asset file descriptor class and functions. */ + jclass fd_class; + jmethodID get_length; + jmethodID create_input_stream; + jmethodID close; + + /* Input stream class and functions. */ + jclass input_stream_class; + jmethodID read; + jmethodID stream_close; + + /* Associated asset manager object. */ + jobject asset_manager; +}; + +typedef struct android_asset_manager AAssetManager; + +struct android_asset +{ + /* The asset manager. */ + AAssetManager *manager; + + /* The length of the asset, or -1. */ + jlong length; + + /* The asset file descriptor and input stream. */ + jobject fd, stream; + + /* The mode. */ + int mode; +}; + +typedef struct android_asset AAsset; + +static AAssetManager * +AAssetManager_fromJava (JNIEnv *env, jobject java_manager) +{ + AAssetManager *manager; + jclass temp; + + manager = malloc (sizeof *manager); + + if (!manager) + return NULL; + + manager->env = env; + manager->asset_manager + = (*env)->NewGlobalRef (env, java_manager); + + if (!manager->asset_manager) + { + free (manager); + return NULL; + } + + manager->class + = (*env)->FindClass (env, "android/content/res/AssetManager"); + assert (manager->class); + + manager->open_fd + = (*env)->GetMethodID (env, manager->class, "openFd", + "(Ljava/lang/String;)" + "Landroid/content/res/AssetFileDescriptor;"); + assert (manager->open); + + manager->fd_class + = (*env)->FindClass (env, "android/content/res/AssetFileDescriptor"); + assert (manager->fd_class); + + manager->get_length + = (*env)->GetMethodID (env, manager->fd_class, "getLength", + "()J"); + assert (manager->get_length); + + manager->create_input_stream + = (*env)->GetMethodID (env, manager->fd_class, + "createInputStream", + "()Ljava/io/FileInputStream;"); + assert (manager->create_input_stream); + + manager->close + = (*env)->GetMethodID (env, manager->fd_class, + "close", "()V"); + assert (manager->close); + + manager->input_stream_class + = (*env)->FindClass (env, "java/io/InputStream"); + assert (manager->input_stream_class); + + manager->read + = (*env)->GetMethodID (env, manager->input_stream_class, + "read", "([B)I"); + assert (manager->read); + + manager->stream_close + = (*env)->GetMethodID (env, manager->input_stream_class, + "close", "()V"); + assert (manager->stream_close); + + /* Now convert all the class references to global ones. */ + temp = manager->class; + manager->class + = (*env)->NewGlobalRef (env, temp); + assert (manager->class); + (*env)->DeleteLocalRef (env, temp); + temp = manager->fd_class; + manager->fd_class + = (*env)->NewGlobalRef (env, temp); + assert (manager->fd_class); + (*env)->DeleteLocalRef (env, temp); + temp = manager->input_stream_class; + manager->input_stream_class + = (*env)->NewGlobalRef (env, temp); + assert (manager->input_stream_class); + (*env)->DeleteLocalRef (env, temp); + + /* Return the asset manager. */ + return manager; +} + +enum + { + AASSET_MODE_STREAMING = 0, + AASSET_MODE_BUFFER = 1, + }; + +static AAsset * +AAssetManager_open (AAssetManager *manager, const char *c_name, + int mode) +{ + jobject desc; + jstring name; + AAsset *asset; + + /* Push a local frame. */ + asset = NULL; + + (*(manager->env))->PushLocalFrame (manager->env, 3); + + if ((*(manager->env))->ExceptionCheck (manager->env)) + goto fail; + + /* Encoding issues can be ignored for now as there are only ASCII + file names in Emacs. */ + name = (*(manager->env))->NewStringUTF (manager->env, c_name); + + if (!name) + goto fail; + + /* Now try to open an ``AssetFileDescriptor''. */ + desc = (*(manager->env))->CallObjectMethod (manager->env, + manager->asset_manager, + manager->open_fd, + name); + + if (!desc) + goto fail; + + /* Allocate the asset. */ + asset = calloc (1, sizeof *asset); + + if (!asset) + { + (*(manager->env))->CallVoidMethod (manager->env, + desc, + manager->close); + goto fail; + } + + /* Pop the local frame and return desc. */ + desc = (*(manager->env))->NewGlobalRef (manager->env, desc); + + if (!desc) + goto fail; + + (*(manager->env))->PopLocalFrame (manager->env, NULL); + + asset->manager = manager; + asset->length = -1; + asset->fd = desc; + asset->mode = mode; + + return asset; + + fail: + (*(manager->env))->ExceptionClear (manager->env); + (*(manager->env))->PopLocalFrame (manager->env, NULL); + free (asset); + + return NULL; +} + +static AAsset * +AAsset_close (AAsset *asset) +{ + JNIEnv *env; + + env = asset->manager->env; + + (*env)->CallVoidMethod (asset->manager->env, + asset->fd, + asset->manager->close); + (*env)->DeleteGlobalRef (asset->manager->env, + asset->fd); + + if (asset->stream) + { + (*env)->CallVoidMethod (asset->manager->env, + asset->stream, + asset->manager->stream_close); + (*env)->DeleteGlobalRef (asset->manager->env, + asset->stream); + } + + free (asset); +} + +/* Create an input stream associated with the given ASSET. Set + ASSET->stream to its global reference. + + Value is 1 upon failure, else 0. ASSET must not already have an + input stream. */ + +static int +android_asset_create_stream (AAsset *asset) +{ + jobject stream; + JNIEnv *env; + + env = asset->manager->env; + stream + = (*env)->CallObjectMethod (env, asset->fd, + asset->manager->create_input_stream); + + if (!stream) + { + (*env)->ExceptionClear (env); + return 1; + } + + asset->stream + = (*env)->NewGlobalRef (env, stream); + + if (!asset->stream) + { + (*env)->ExceptionClear (env); + (*env)->DeleteLocalRef (env, stream); + return 1; + } + + (*env)->DeleteLocalRef (env, stream); + return 0; +} + +/* Read NBYTES from the specified asset into the given BUFFER; + + Internally, allocate a Java byte array containing 4096 elements and + copy the data to and from that array. + + Value is the number of bytes actually read, 0 at EOF, or -1 upon + failure, in which case errno is set accordingly. If NBYTES is + zero, behavior is undefined. */ + +static int +android_asset_read_internal (AAsset *asset, int nbytes, char *buffer) +{ + jbyteArray stash; + JNIEnv *env; + jint bytes_read, total; + + /* Allocate a suitable amount of storage. Either nbytes or 4096, + whichever is larger. */ + env = asset->manager->env; + stash = (*env)->NewByteArray (env, MIN (nbytes, 4096)); + + if (!stash) + { + (*env)->ExceptionClear (env); + errno = ENOMEM; + return -1; + } + + /* Try to create an input stream. */ + + if (!asset->stream + && android_asset_create_stream (asset)) + { + (*env)->DeleteLocalRef (env, stash); + errno = ENOMEM; + return -1; + } + + /* Start reading. */ + + total = 0; + + while (nbytes) + { + bytes_read = (*env)->CallIntMethod (env, asset->stream, + asset->manager->read, + stash); + + /* Detect error conditions. */ + + if ((*env)->ExceptionCheck (env)) + goto out; + + /* Detect EOF. */ + + if (bytes_read == -1) + goto out; + + /* Finally write out the amount that was read. */ + bytes_read = MIN (bytes_read, nbytes); + (*env)->GetByteArrayRegion (env, stash, 0, bytes_read, buffer); + + buffer += bytes_read; + total += bytes_read; + nbytes -= bytes_read; + } + + /* Make sure the value of nbytes still makes sense. */ + assert (nbytes >= 0); + + out: + (*env)->ExceptionClear (env); + (*env)->DeleteLocalRef (env, stash); + return total; +} + +static int +AAsset_openFileDescriptor (AAsset *asset, off_t *out_start, + off_t *out_end) +{ + *out_start = 0; + *out_end = 0; + return -1; +} + +static long +AAsset_getLength (AAsset *asset) +{ + JNIEnv *env; + + if (asset->length != -1) + return asset->length; + + env = asset->manager->env; + asset->length + = (*env)->CallLongMethod (env, asset->fd, + asset->manager->get_length); + return asset->length; +} + +static char * +AAsset_getBuffer (AAsset *asset) +{ + long length; + char *buffer; + + length = AAsset_getLength (asset); + + if (!length) + return NULL; + + buffer = malloc (length); + + if (!buffer) + return NULL; + + if (android_asset_read_internal (asset, length, buffer) + != length) + { + xfree (buffer); + return NULL; + } + + return buffer; +} + +static size_t +AAsset_read (AAsset *asset, void *buffer, size_t size) +{ + return android_asset_read_internal (asset, MIN (size, INT_MAX), + buffer); +} diff --git a/src/android.c b/src/android.c index 8f446224dab..09b9001b45d 100644 --- a/src/android.c +++ b/src/android.c @@ -32,6 +32,9 @@ along with GNU Emacs. If not, see . */ #include #include +/* Old NDK versions lack MIN and MAX. */ +#include + #include #include @@ -49,8 +52,13 @@ bool android_init_gui; #ifndef ANDROID_STUBIFY +#if __ANDROID_API__ >= 9 #include #include +#else +#include "android-asset.h" +#endif + #include #include @@ -907,10 +915,14 @@ android_is_directory (const char *dir) char * android_user_full_name (struct passwd *pw) { +#ifdef HAVE_STRUCT_PASSWD_PW_GECOS if (!pw->pw_gecos) return (char *) "Android user"; return pw->pw_gecos; +#else + return "Android user"; +#endif } /* Given a real file name, return the part that describes its asset @@ -1048,6 +1060,60 @@ android_file_access_p (const char *name, int amode) static int android_hack_asset_fd (AAsset *asset) { +#if __ANDROID_API__ < 9 + int fd; + char filename[PATH_MAX]; + size_t size; + void *mem; + + /* Assets must be small enough to fit in size_t, if off_t is + larger. */ + size = AAsset_getLength (asset); + + /* Get an unlinked file descriptor from a file in the cache + directory, which is guaranteed to only be written to by Emacs. + Creating an asset file descriptor doesn't work on these old + Android versions. */ + + snprintf (filename, PATH_MAX, "%s/%s.%d", + android_cache_dir, "temp-unlinked", + getpid ()); + fd = open (filename, O_CREAT | O_RDWR | O_TRUNC, + S_IRUSR | S_IWUSR); + + if (fd < 1) + return -1; + + if (unlink (filename)) + goto fail; + + if (ftruncate (fd, size)) + goto fail; + + mem = mmap (NULL, size, PROT_WRITE, MAP_SHARED, fd, 0); + if (mem == MAP_FAILED) + { + __android_log_print (ANDROID_LOG_ERROR, __func__, + "mmap: %s", strerror (errno)); + goto fail; + } + + if (AAsset_read (asset, mem, size) != size) + { + /* Too little was read. Close the file descriptor and + report an error. */ + __android_log_print (ANDROID_LOG_ERROR, __func__, + "AAsset_read: %s", strerror (errno)); + goto fail; + } + + munmap (mem, size); + return fd; + + fail: + close (fd); + return -1; +#else int fd, rc; unsigned char *mem; size_t size; @@ -1172,10 +1238,11 @@ android_hack_asset_fd (AAsset *asset) /* Return anyway even if munmap fails. */ munmap (mem, size); return fd; +#endif } /* Read two bytes from FD and see if they are ``PK'', denoting ZIP - archive compressed data. + archive compressed data. If FD is -1, return -1. If they are not, rewind the file descriptor to offset 0. @@ -1187,6 +1254,9 @@ android_check_compressed_file (int fd) { char bytes[2]; + if (fd == -1) + return -1; + if (read (fd, bytes, 2) != 2) goto lseek_back; diff --git a/src/process.c b/src/process.c index e7ccb2c604e..bdaaba70fea 100644 --- a/src/process.c +++ b/src/process.c @@ -7248,7 +7248,7 @@ process has been transmitted to the serial port. */) send_process (proc, "\004", 1, Qnil); else if (EQ (XPROCESS (proc)->type, Qserial)) { -#ifndef WINDOWSNT +#if !defined WINDOWSNT && defined HAVE_TCDRAIN if (tcdrain (XPROCESS (proc)->outfd) != 0) report_file_error ("Failed tcdrain", Qnil); #endif /* not WINDOWSNT */ diff --git a/src/sfntfont-android.c b/src/sfntfont-android.c index c28a911bfba..8324185cc6f 100644 --- a/src/sfntfont-android.c +++ b/src/sfntfont-android.c @@ -51,7 +51,7 @@ struct sfntfont_android_scanline_buffer /* Array of directories to search for system fonts. */ static char *system_font_directories[] = { - "/system/fonts", + (char *) "/system/fonts", /* This should be filled in by init_sfntfont_android. */ (char[PATH_MAX]) { }, }; diff --git a/src/sfntfont.c b/src/sfntfont.c index f9344067f1a..20c109f2401 100644 --- a/src/sfntfont.c +++ b/src/sfntfont.c @@ -953,7 +953,7 @@ sfntfont_read_cmap (struct sfnt_font_desc *desc, /* Pick a character map and place it in *CMAP. */ fd = emacs_open (desc->path, O_RDONLY, 0); - if (fd < 1) + if (fd < 0) return; font = sfnt_read_table_directory (fd); diff --git a/src/textconv.c b/src/textconv.c index 5090b0a33b6..8f5a4987d5a 100644 --- a/src/textconv.c +++ b/src/textconv.c @@ -989,7 +989,7 @@ handle_pending_conversion_events_1 (struct frame *f, { Lisp_Object data; enum text_conversion_operation operation; - struct buffer *buffer; + struct buffer *buffer UNINIT; struct window *w; specpdl_ref count; unsigned long token; -- 2.39.5