summaryrefslogtreecommitdiff
path: root/src/dired.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dired.c')
-rw-r--r--src/dired.c76
1 files changed, 60 insertions, 16 deletions
diff --git a/src/dired.c b/src/dired.c
index e7eafc6ea5d..bfbacf70917 100644
--- a/src/dired.c
+++ b/src/dired.c
@@ -44,6 +44,21 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "msdos.h" /* for fstatat */
#endif
+#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
+typedef DIR emacs_dir;
+#define emacs_readdir readdir
+#define emacs_closedir closedir
+#else
+
+#include "android.h"
+
+/* The Android emulation of dirent stuff is required to be able to
+ list the /assets special directory. */
+typedef struct android_vdir emacs_dir;
+#define emacs_readdir android_readdir
+#define emacs_closedir android_closedir
+#endif
+
#ifdef WINDOWSNT
extern int is_slow_fs (const char *);
#endif
@@ -78,19 +93,42 @@ dirent_type (struct dirent *dp)
#endif
}
-static DIR *
+static emacs_dir *
open_directory (Lisp_Object dirname, Lisp_Object encoded_dirname, int *fdp)
{
char *name = SSDATA (encoded_dirname);
- DIR *d;
+ emacs_dir *d;
int fd, opendir_errno;
-#ifdef DOS_NT
- /* Directories cannot be opened. The emulation assumes that any
- file descriptor other than AT_FDCWD corresponds to the most
- recently opened directory. This hack is good enough for Emacs. */
+#if defined DOS_NT || (defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
+ /* On DOS_NT, directories cannot be opened. The emulation assumes
+ that any file descriptor other than AT_FDCWD corresponds to the
+ most recently opened directory. This hack is good enough for
+ Emacs.
+
+ This code is also used on Android for a different reason: a
+ special `assets' directory outside the normal file system is used
+ to open assets inside the Android application package, and must
+ be listed using the opendir-like interface provided in
+ android.h. */
fd = 0;
+#ifndef HAVE_ANDROID
d = opendir (name);
+#else
+ /* `android_opendir' can return EINTR if DIRNAME designates a file
+ within a slow-to-respond document provider. */
+
+ again:
+ d = android_opendir (name);
+
+ if (d)
+ fd = android_dirfd (d);
+ else if (errno == EINTR)
+ {
+ maybe_quit ();
+ goto again;
+ }
+#endif
opendir_errno = errno;
#else
fd = emacs_open (name, O_RDONLY | O_DIRECTORY, 0);
@@ -125,7 +163,7 @@ directory_files_internal_w32_unwind (Lisp_Object arg)
static void
directory_files_internal_unwind (void *d)
{
- closedir (d);
+ emacs_closedir (d);
}
/* Return the next directory entry from DIR; DIR's name is DIRNAME.
@@ -133,12 +171,12 @@ directory_files_internal_unwind (void *d)
Signal any unrecoverable errors. */
static struct dirent *
-read_dirent (DIR *dir, Lisp_Object dirname)
+read_dirent (emacs_dir *dir, Lisp_Object dirname)
{
while (true)
{
errno = 0;
- struct dirent *dp = readdir (dir);
+ struct dirent *dp = emacs_readdir (dir);
if (dp || errno == 0)
return dp;
if (! (errno == EAGAIN || errno == EINTR))
@@ -190,7 +228,10 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
Lisp_Object encoded_dirfilename = ENCODE_FILE (dirfilename);
int fd;
- DIR *d = open_directory (dirfilename, encoded_dirfilename, &fd);
+
+ /* Keep in mind that FD is not always a real file descriptor on
+ Android. */
+ emacs_dir *d = open_directory (dirfilename, encoded_dirfilename, &fd);
/* Unfortunately, we can now invoke expand-file-name and
file-attributes on filenames, both of which can throw, so we must
@@ -300,7 +341,7 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
list = Fcons (attrs ? Fcons (finalname, fileattrs) : finalname, list);
}
- closedir (d);
+ emacs_closedir (d);
#ifdef WINDOWSNT
if (attrs)
Vw32_get_true_file_attributes = w32_save;
@@ -310,7 +351,7 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
specpdl_ptr = specpdl_ref_to_ptr (count);
if (NILP (nosort))
- list = Fsort (Fnreverse (list),
+ list = CALLN (Fsort, Fnreverse (list),
attrs ? Qfile_attributes_lessp : Qstring_lessp);
(void) directory_volatile;
@@ -514,7 +555,7 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
}
}
int fd;
- DIR *d = open_directory (dirname, encoded_dir, &fd);
+ emacs_dir *d = open_directory (dirname, encoded_dir, &fd);
record_unwind_protect_ptr (directory_files_internal_unwind, d);
/* Loop reading directory entries. */
@@ -855,7 +896,9 @@ file_name_completion_dirp (int fd, struct dirent *dp, ptrdiff_t len)
char *subdir_name = SAFE_ALLOCA (len + 2);
memcpy (subdir_name, dp->d_name, len);
strcpy (subdir_name + len, "/");
- bool dirp = faccessat (fd, subdir_name, F_OK, AT_EACCESS) == 0;
+
+ bool dirp = sys_faccessat (fd, subdir_name,
+ F_OK, AT_EACCESS) == 0;
SAFE_FREE ();
return dirp;
}
@@ -979,14 +1022,15 @@ file_attributes (int fd, char const *name,
int err = EINVAL;
-#if defined O_PATH && !defined HAVE_CYGWIN_O_PATH_BUG
+#if defined O_PATH && !defined HAVE_CYGWIN_O_PATH_BUG \
+ && !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
int namefd = emacs_openat (fd, name, O_PATH | O_CLOEXEC | O_NOFOLLOW, 0);
if (namefd < 0)
err = errno;
else
{
record_unwind_protect_int (close_file_unwind, namefd);
- if (fstat (namefd, &s) != 0)
+ if (sys_fstat (namefd, &s) != 0)
{
err = errno;
/* The Linux kernel before version 3.6 does not support