* 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.
#endif
}
+\f
+
+/* 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
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,
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:/");
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);
/* 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. */
#define JNI_STACK_ALIGNMENT_PROLOGUE ((void) 0)
#endif /* __i386__ */
-#endif
+#endif /* !ANDROID_STUBIFY */
#endif /* _ANDROID_H_ */
#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 <sys/ioctl.h>
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);
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 */
}
\f
#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
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);
# 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;
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)