From b1bd40dce197d2938426d1ec33cebd3d51ccc8cf Mon Sep 17 00:00:00 2001 From: Po Lu Date: Thu, 8 Jun 2023 14:04:31 +0800 Subject: [PATCH] Update Android port * src/android.c (android_is_special_directory): New function. (android_get_asset_name, android_content_name_p) (android_get_content_name): * src/android.h (android_is_special_directory) (JNI_STACK_ALIGNMENT_PROLOGUE): * src/fileio.c (check_mutable_filename): * src/filelock.c (WTMP_FILE, make_lock_file_name): * src/inotify.c (IN_ONLYDIR, Finotify_add_watch): Factor out checks against asset and content directories to that function. --- src/android.c | 90 ++++++++++++++++++++++++++++++++++++++++---------- src/android.h | 11 ++++-- src/fileio.c | 18 +++++----- src/filelock.c | 14 ++++---- src/inotify.c | 14 ++++---- 5 files changed, 104 insertions(+), 43 deletions(-) diff --git a/src/android.c b/src/android.c index f59c0d9e5d2..92aab548180 100644 --- a/src/android.c +++ b/src/android.c @@ -1045,19 +1045,72 @@ android_user_full_name (struct passwd *pw) #endif } + + +/* Determine whether or not the specified file NAME describes a file + in the directory DIR, which should be an absolute file name. NAME + must be in canonical form. + + Value is NULL if not. Otherwise, it is a pointer to the first + character in NAME after the part containing DIR and its trailing + directory separator. */ + +const char * +android_is_special_directory (const char *name, const char *dir) +{ + size_t len; + + /* Compare up to strlen (DIR) bytes of NAME with DIR. */ + + len = strlen (dir); + if (strncmp (name, dir, len)) + return NULL; + + /* Now see if the character of NAME after len is either a directory + separator or a terminating NULL. */ + + name += len; + switch (*name) + { + case '\0': + /* Return the empty string if this is the end of the file + name. */ + return name; + + case '/': + /* Return NAME (with the separator removed) if it describes a + file. */ + return name + 1; + + default: + /* The file name doesn't match. */ + return NULL; + } +} + /* Given a real file name, return the part that describes its asset - path, or NULL if it is not an asset. */ + path, or NULL if it is not an asset. + + If FILENAME contains only `/assets', return `/' to indicate the + root of the assets hierarchy. */ static const char * android_get_asset_name (const char *filename) { - if (!strcmp (filename, "/assets") || !strcmp (filename, "/assets/")) - return "/"; + const char *name; - if (!strncmp (filename, "/assets/", sizeof "/assets/" - 1)) - return filename + (sizeof "/assets/" - 1); + name = android_is_special_directory (filename, "/assets"); - return NULL; + if (!name) + return NULL; + + /* If NAME is empty, return /. Otherwise, return the name relative + to /assets/. */ + + if (*name) + return name; + + return "/"; } /* Return whether or not the specified FILENAME actually resolves to a @@ -1072,9 +1125,9 @@ android_content_name_p (const char *filename) if (android_api_level < 19) return false; - return (!strcmp (filename, "/content") - || !strncmp (filename, "/content/", - sizeof "/content/" - 1)); + return (android_is_special_directory (filename, + "/content") + != NULL); } /* Return the content URI corresponding to a `/content' file name, @@ -1091,20 +1144,21 @@ android_get_content_name (const char *filename) n = PATH_MAX; - /* First handle content ``URIs'' without a provider. */ + /* Find the file name described if it starts with `/content'. If + just the directory is described, return content://. */ - if (!strcmp (filename, "/content") - || !strcmp (filename, "/content/")) - return "content://"; + filename = android_is_special_directory (filename, "/content"); - /* Next handle ordinary file names. */ - - if (strncmp (filename, "/content/", sizeof "/content/" - 1)) + if (!filename) return NULL; - /* Forward past the first directory specifying the schema. */ + if (!*filename) + return "content://"; + + /* Now copy FILENAME into a buffer and convert it into a content + URI. */ - copy = xstrdup (filename + sizeof "/content"); + copy = xstrdup (filename); token = saveptr = NULL; head = stpcpy (buffer, "content:/"); diff --git a/src/android.h b/src/android.h index d0440259161..c748d99a09a 100644 --- a/src/android.h +++ b/src/android.h @@ -48,6 +48,7 @@ extern int android_select (int, fd_set *, fd_set *, fd_set *, extern int android_open (const char *, int, mode_t); extern char *android_user_full_name (struct passwd *); +extern const char *android_is_special_directory (const char *, const char *); extern int android_fstat (int, struct stat *); extern int android_fstatat (int, const char *restrict, struct stat *restrict, int); @@ -195,7 +196,13 @@ extern unsigned int event_serial; /* Process related functions. */ extern int android_rewrite_spawn_argv (const char ***); -#endif +#else /* ANDROID_STUBIFY */ + +/* Define a substitute for use during Emacs compilation. */ + +#define android_is_special_directory(name, dir) ((const char *) NULL) + +#endif /* !ANDROID_STUBIFY */ /* JNI functions should not be built when Emacs is stubbed out for the build. These should be documented in EmacsNative.java. */ @@ -227,5 +234,5 @@ extern void *unused_pointer; #define JNI_STACK_ALIGNMENT_PROLOGUE ((void) 0) #endif /* __i386__ */ -#endif +#endif /* !ANDROID_STUBIFY */ #endif /* _ANDROID_H_ */ diff --git a/src/fileio.c b/src/fileio.c index f2f440d0a3b..fbccd796751 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -56,9 +56,9 @@ along with GNU Emacs. If not, see . */ #include "region-cache.h" #include "frame.h" -#if defined HAVE_ANDROID +#ifdef HAVE_ANDROID #include "android.h" -#endif +#endif /* HAVE_ANDROID */ #ifdef HAVE_LINUX_FS_H # include @@ -193,9 +193,11 @@ static void check_mutable_filename (Lisp_Object encoded, bool write) { #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY - if (!strcmp (SSDATA (encoded), "/assets") - || !strncmp (SSDATA (encoded), "/assets/", - sizeof "/assets/" - 1)) + const char *name; + + name = SSDATA (encoded); + + if (android_is_special_directory (name, "/assets")) xsignal2 (Qfile_error, build_string ("File lies on read-only directory"), encoded); @@ -203,13 +205,11 @@ check_mutable_filename (Lisp_Object encoded, bool write) if (write) return; - if (!strcmp (SSDATA (encoded), "/content") - || !strncmp (SSDATA (encoded), "/content/", - sizeof "/content/" - 1)) + if (android_is_special_directory (name, "/content")) xsignal2 (Qfile_error, build_string ("File lies on read-only directory"), encoded); -#endif +#endif /* defined HAVE_ANDROID && !defined ANDROID_STUBIFY */ } diff --git a/src/filelock.c b/src/filelock.c index be551fc876f..cbbcc016b27 100644 --- a/src/filelock.c +++ b/src/filelock.c @@ -75,6 +75,10 @@ along with GNU Emacs. If not, see . */ #define WTMP_FILE "/var/log/wtmp" #endif +#ifdef HAVE_ANDROID +#include "android.h" /* For `android_is_special_directory'. */ +#endif /* HAVE_ANDROID */ + /* Normally use a symbolic link to represent a lock. The strategy: to lock a file FN, create a symlink .#FN in FN's directory, with link data USER@HOST.PID:BOOT. This avoids a single @@ -673,14 +677,10 @@ make_lock_file_name (Lisp_Object fn) name = SSDATA (fn); - if (strcmp (name, "/assets") - || strcmp (name, "/assets/") - || strcmp (name, "/content") - || strcmp (name, "/content/") - || strncmp (name, "/assets/", sizeof "/assets") - || strncmp (name, "/content/", sizeof "/content")) + if (android_is_special_directory (name, "/assets") + || android_is_special_directory (name, "/content")) return Qnil; -#endif +#endif /* defined HAVE_ANDROID && !defined ANDROID_STUBIFY */ lock_file_name = call1 (Qmake_lock_file_name, fn); diff --git a/src/inotify.c b/src/inotify.c index 844bf54105c..105ff5a9d8a 100644 --- a/src/inotify.c +++ b/src/inotify.c @@ -40,6 +40,10 @@ along with GNU Emacs. If not, see . */ # define IN_ONLYDIR 0 #endif +#ifdef HAVE_ANDROID +#include "android.h" /* For `android_is_special_directory'. */ +#endif /* HAVE_ANDROID */ + /* File handle for inotify. */ static int inotifyfd = -1; @@ -440,14 +444,10 @@ IN_ONESHOT */) instead of letting inotify fail. These directories cannot receive file notifications as they are read only. */ - if (strcmp (name, "/assets") - || strcmp (name, "/assets/") - || strcmp (name, "/content") - || strcmp (name, "/content/") - || strncmp (name, "/assets/", sizeof "/assets") - || strncmp (name, "/content/", sizeof "/content")) + if (android_is_special_directory (name, "/assets") + || android_is_special_directory (name, "/content")) return Qnil; -#endif +#endif /* defined HAVE_ANDROID && !defined ANDROID_STUBIFY */ wd = inotify_add_watch (inotifyfd, name, mask); if (wd < 0) -- 2.39.2