]> code.delx.au - gnu-emacs/blobdiff - src/msdos.c
Merge from emacs-24; up to 2014-04-16T15:28:26Z!monnier@iro.umontreal.ca
[gnu-emacs] / src / msdos.c
index 6b677bb2f02b68911dfa07dfdf4b7c8eedf3daca..217943412223cf2016ca0a0e90f0ce4f5c91c75a 100644 (file)
@@ -50,6 +50,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <unistd.h>     /* for chdir, dup, dup2, etc. */
 #include <dir.h>        /* for getdisk */
 #pragma pack(0)                 /* dir.h does a pack(4), which isn't GCC's default */
+#undef opendir
+#include <dirent.h>     /* for opendir */
 #include <fcntl.h>
 #include <io.h>                 /* for setmode */
 #include <dpmi.h>       /* for __dpmi_xxx stuff */
@@ -1883,18 +1885,6 @@ dos_get_saved_screen (char **screen, int *rows, int *cols)
 #endif
 }
 
-#ifndef HAVE_X_WINDOWS
-
-/* We are not X, but we can emulate it well enough for our needs... */
-void
-check_window_system (void)
-{
-  if (! FRAME_MSDOS_P (SELECTED_FRAME ()))
-    error ("Not running under a window system");
-}
-
-#endif
-
 \f
 /* ----------------------- Keyboard control ----------------------
  *
@@ -3875,6 +3865,9 @@ int setpgid (int pid, int pgid) { return 0; }
 int setpriority (int x, int y, int z) { return 0; }
 pid_t setsid (void) { return 0; }
 
+\f
+/* Gnulib support and emulation.  */
+
 #if __DJGPP__ == 2 && __DJGPP_MINOR__ < 4
 ssize_t
 readlink (const char *name, char *dummy1, size_t dummy2)
@@ -3886,6 +3879,38 @@ readlink (const char *name, char *dummy1, size_t dummy2)
 }
 #endif
 
+/* dir_pathname is set by sys_opendir and used in readlinkat and in
+   fstatat, when they get a special FD of zero, which means use the
+   last directory opened by opendir.  */
+static char dir_pathname[MAXPATHLEN];
+DIR *
+sys_opendir (const char *dirname)
+{
+  _fixpath (dirname, dir_pathname);
+  return opendir (dirname);
+}
+
+ssize_t
+readlinkat (int fd, char const *name, char *buffer, size_t buffer_size)
+{
+  /* Rely on a hack: an open directory is modeled as file descriptor 0,
+     as in fstatat.  FIXME: Add proper support for readlinkat.  */
+  char fullname[MAXPATHLEN];
+
+  if (fd != AT_FDCWD)
+    {
+      if (strlen (dir_pathname) + strlen (name) + 1 >= MAXPATHLEN)
+       {
+         errno = ENAMETOOLONG;
+         return -1;
+       }
+      sprintf (fullname, "%s/%s", dir_pathname, name);
+      name = fullname;
+    }
+
+  return readlink (name, buffer, buffer_size);
+}
+
 char *
 careadlinkat (int fd, char const *filename,
               char *buffer, size_t buffer_size,
@@ -3913,6 +3938,82 @@ careadlinkat (int fd, char const *filename,
   return buffer;
 }
 
+/* Emulate faccessat(2).  */
+int
+faccessat (int dirfd, const char * path, int mode, int flags)
+{
+  /* We silently ignore FLAGS.  */
+  flags = flags;
+
+  if (dirfd != AT_FDCWD
+      && !(IS_DIRECTORY_SEP (path[0])
+          || IS_DEVICE_SEP (path[1])))
+    {
+      errno = EBADF;
+      return -1;
+    }
+
+  return access (path, mode);
+}
+
+/* Emulate fstatat.  */
+int
+fstatat (int fd, char const *name, struct stat *st, int flags)
+{
+  /* Rely on a hack: an open directory is modeled as file descriptor 0.
+     This is good enough for the current usage in Emacs, but is fragile.
+
+     FIXME: Add proper support for fdopendir, fstatat, readlinkat.
+     Gnulib does this and can serve as a model.  */
+  char fullname[MAXPATHLEN];
+
+  flags = flags;
+
+  if (fd != AT_FDCWD)
+    {
+      char lastc = dir_pathname[strlen (dir_pathname) - 1];
+
+      if (strlen (dir_pathname) + strlen (name) + IS_DIRECTORY_SEP (lastc)
+         >= MAXPATHLEN)
+       {
+         errno = ENAMETOOLONG;
+         return -1;
+       }
+
+      sprintf (fullname, "%s%s%s",
+              dir_pathname, IS_DIRECTORY_SEP (lastc) ? "" : "/", name);
+      name = fullname;
+    }
+
+#if __DJGPP__ > 2 || __DJGPP_MINOR__ > 3
+  return (flags & AT_SYMLINK_NOFOLLOW) ? lstat (name, st) : stat (name, st);
+#else
+  return stat (name, st);
+#endif
+}
+
+#if __DJGPP__ == 2 && __DJGPP_MINOR__ < 4
+/* Emulate the Posix unsetenv.  DJGPP v2.04 has this in the library.  */
+int
+unsetenv (const char *name)
+{
+  char *var;
+  size_t name_len;
+  int retval;
+
+  if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  /* DJGPP's 'putenv' deletes the entry if it doesn't include '='.  */
+  putenv (name);
+
+  return 0;
+}
+#endif
+
 \f
 #if __DJGPP__ == 2 && __DJGPP_MINOR__ < 2
 
@@ -4038,7 +4139,7 @@ dos_yield_time_slice (void)
 /* We don't have to call timer_check here
    because wait_reading_process_output takes care of that.  */
 int
-sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
+sys_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds,
            struct timespec *timeout, void *ignored)
 {
   int check_input;