Fix warnings when compiling on MS-Windows with -std=gnu99.
[bpt/emacs.git] / src / fileio.c
index f0b3f0c..d47d7dd 100644 (file)
@@ -23,7 +23,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <setjmp.h>
 #include <unistd.h>
 
 #ifdef HAVE_PWD_H
@@ -53,6 +52,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #define NOMINMAX 1
 #include <windows.h>
 #include <fcntl.h>
+#include <sys/file.h>
+#include "w32.h"
 #endif /* not WINDOWSNT */
 
 #ifdef MSDOS
@@ -669,7 +670,6 @@ make_temp_name (Lisp_Object prefix, bool base64_p)
 
   while (1)
     {
-      struct stat ignored;
       unsigned num = make_temp_name_count;
 
       p[0] = make_temp_name_tbl[num & 63], num >>= 6;
@@ -681,7 +681,7 @@ make_temp_name (Lisp_Object prefix, bool base64_p)
       make_temp_name_count += 25229;
       make_temp_name_count %= 225307;
 
-      if (stat (data, &ignored) < 0)
+      if (!check_existing (data))
        {
          /* We want to return only if errno is ENOENT.  */
          if (errno == ENOENT)
@@ -1026,9 +1026,9 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
          memcpy (o, nm, p - nm);
          o [p - nm] = 0;
 
-         BLOCK_INPUT;
+         block_input ();
          pw = (struct passwd *) getpwnam (o + 1);
-         UNBLOCK_INPUT;
+         unblock_input ();
          if (pw)
            {
              newdir = pw->pw_dir;
@@ -1371,8 +1371,7 @@ See also the function `substitute-in-file-name'.")
       p = nm;
       while (*p)
        {
-         if (p[0] == '/' && p[1] == '/'
-             )
+         if (p[0] == '/' && p[1] == '/')
            nm = p + 1;
          if (p[0] == '/' && p[1] == '~')
            nm = p + 1, lose = 1;
@@ -1414,9 +1413,9 @@ See also the function `substitute-in-file-name'.")
        o[len] = 0;
 
        /* Look up the user name.  */
-       BLOCK_INPUT;
+       block_input ();
        pw = (struct passwd *) getpwnam (o + 1);
-       UNBLOCK_INPUT;
+       unblock_input ();
        if (!pw)
          error ("\"%s\" isn't a registered user", o + 1);
 
@@ -1511,17 +1510,16 @@ search_embedded_absfilename (char *nm, char *endp)
 
   for (p = nm + 1; p < endp; p++)
     {
-      if ((0
-          || IS_DIRECTORY_SEP (p[-1]))
+      if (IS_DIRECTORY_SEP (p[-1])
          && file_name_absolute_p (p)
 #if defined (WINDOWSNT) || defined (CYGWIN)
          /* // at start of file name is meaningful in Apollo,
             WindowsNT and Cygwin systems.  */
          && !(IS_DIRECTORY_SEP (p[0]) && p - 1 == nm)
 #endif /* not (WINDOWSNT || CYGWIN) */
-             )
+         )
        {
-         for (s = p; *s && (!IS_DIRECTORY_SEP (*s)); s++);
+         for (s = p; *s && !IS_DIRECTORY_SEP (*s); s++);
          if (p[0] == '~' && s > p + 1) /* We've got "/~something/".  */
            {
              char *o = alloca (s - p + 1);
@@ -1532,9 +1530,9 @@ search_embedded_absfilename (char *nm, char *endp)
              /* If we have ~user and `user' exists, discard
                 everything up to ~.  But if `user' does not exist, leave
                 ~user alone, it might be a literal file name.  */
-             BLOCK_INPUT;
+             block_input ();
              pw = getpwnam (o + 1);
-             UNBLOCK_INPUT;
+             unblock_input ();
              if (pw)
                return p;
            }
@@ -1736,7 +1734,7 @@ those `/' is discarded.  */)
   *x = 0;
 
   /* If /~ or // appears, discard everything through first slash.  */
-  while ((p = search_embedded_absfilename (xnm, x)))
+  while ((p = search_embedded_absfilename (xnm, x)) != NULL)
     /* This time we do not start over because we've already expanded envvars
        and replaced $$ with $.  Maybe we should start over as well, but we'd
        need to quote some $ to $$ first.  */
@@ -2170,7 +2168,7 @@ With a prefix argument, TRASH is nil.  */)
 
   encoded_file = ENCODE_FILE (filename);
 
-  if (0 > unlink (SSDATA (encoded_file)))
+  if (unlink (SSDATA (encoded_file)) < 0)
     report_file_error ("Removing old name", list1 (filename));
   return Qnil;
 }
@@ -2219,8 +2217,8 @@ This is what happens in interactive use with M-x.  */)
 #endif
       )
     {
-      Lisp_Object fname = NILP (Ffile_directory_p (file))
-       ? file : Fdirectory_file_name (file);
+      Lisp_Object fname = (NILP (Ffile_directory_p (file))
+                          ? file : Fdirectory_file_name (file));
       newname = Fexpand_file_name (Ffile_name_nondirectory (fname), newname);
     }
   else
@@ -2248,7 +2246,7 @@ This is what happens in interactive use with M-x.  */)
       || INTEGERP (ok_if_already_exists))
     barf_or_query_if_file_exists (newname, "rename to it",
                                  INTEGERP (ok_if_already_exists), 0, 0);
-  if (0 > rename (SSDATA (encoded_file), SSDATA (encoded_newname)))
+  if (rename (SSDATA (encoded_file), SSDATA (encoded_newname)) < 0)
     {
       if (errno == EXDEV)
        {
@@ -2329,7 +2327,7 @@ This is what happens in interactive use with M-x.  */)
                                  INTEGERP (ok_if_already_exists), 0, 0);
 
   unlink (SSDATA (newname));
-  if (0 > link (SSDATA (encoded_file), SSDATA (encoded_newname)))
+  if (link (SSDATA (encoded_file), SSDATA (encoded_newname)) < 0)
     report_file_error ("Adding new name", list2 (file, newname));
 
   UNGCPRO;
@@ -2386,15 +2384,14 @@ This happens for interactive use with M-x.  */)
       || INTEGERP (ok_if_already_exists))
     barf_or_query_if_file_exists (linkname, "make it a link",
                                  INTEGERP (ok_if_already_exists), 0, 0);
-  if (0 > symlink (SSDATA (encoded_filename),
-                  SSDATA (encoded_linkname)))
+  if (symlink (SSDATA (encoded_filename), SSDATA (encoded_linkname)) < 0)
     {
       /* If we didn't complain already, silently delete existing file.  */
       if (errno == EEXIST)
        {
          unlink (SSDATA (encoded_linkname));
-         if (0 <= symlink (SSDATA (encoded_filename),
-                           SSDATA (encoded_linkname)))
+         if (symlink (SSDATA (encoded_filename), SSDATA (encoded_linkname))
+             >= 0)
            {
              UNGCPRO;
              return Qnil;
@@ -2424,6 +2421,21 @@ On Unix, this is a name starting with a `/' or a `~'.  */)
   return file_name_absolute_p (SSDATA (filename)) ? Qt : Qnil;
 }
 \f
+/* Return true if FILENAME exists.  */
+bool
+check_existing (const char *filename)
+{
+#ifdef DOS_NT
+  /* The full emulation of Posix 'stat' is too expensive on
+     DOS/Windows, when all we want to know is whether the file exists.
+     So we use 'access' instead, which is much more lightweight.  */
+  return (access (filename, F_OK) >= 0);
+#else
+  struct stat st;
+  return (stat (filename, &st) >= 0);
+#endif
+}
+
 /* Return true if file FILENAME exists and can be executed.  */
 
 static bool
@@ -2491,7 +2503,6 @@ Use `file-symlink-p' to test for such links.  */)
 {
   Lisp_Object absname;
   Lisp_Object handler;
-  struct stat statbuf;
 
   CHECK_STRING (filename);
   absname = Fexpand_file_name (filename, Qnil);
@@ -2504,7 +2515,7 @@ Use `file-symlink-p' to test for such links.  */)
 
   absname = ENCODE_FILE (absname);
 
-  return (stat (SSDATA (absname), &statbuf) >= 0) ? Qt : Qnil;
+  return (check_existing (SSDATA (absname))) ? Qt : Qnil;
 }
 
 DEFUN ("file-executable-p", Ffile_executable_p, Sfile_executable_p, 1, 1, 0,
@@ -2585,7 +2596,6 @@ DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
 {
   Lisp_Object absname, dir, encoded;
   Lisp_Object handler;
-  struct stat statbuf;
 
   CHECK_STRING (filename);
   absname = Fexpand_file_name (filename, Qnil);
@@ -2597,7 +2607,7 @@ DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
     return call2 (handler, Qfile_writable_p, absname);
 
   encoded = ENCODE_FILE (absname);
-  if (stat (SSDATA (encoded), &statbuf) >= 0)
+  if (check_existing (SSDATA (encoded)))
     return (check_writable (SSDATA (encoded))
            ? Qt : Qnil);
 
@@ -2612,9 +2622,7 @@ DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
   /* The read-only attribute of the parent directory doesn't affect
      whether a file or directory can be created within it.  Some day we
      should check ACLs though, which do affect this.  */
-  if (stat (SDATA (dir), &statbuf) < 0)
-    return Qnil;
-  return S_ISDIR (statbuf.st_mode) ? Qt : Qnil;
+  return (access (SDATA (dir), D_OK) < 0) ? Qnil : Qt;
 #else
   return (check_writable (!NILP (dir) ? SSDATA (dir) : "")
          ? Qt : Qnil);
@@ -2834,9 +2842,8 @@ or if SELinux is disabled, or if Emacs lacks SELinux support.  */)
          if (context_range_get (context))
            values[3] = build_string (context_range_get (context));
          context_free (context);
+         freecon (con);
        }
-      if (con)
-       freecon (con);
     }
 #endif
 
@@ -2915,12 +2922,10 @@ compiled with SELinux support.  */)
            report_file_error ("Doing lsetfilecon", Fcons (absname, Qnil));
 
          context_free (parsed_con);
+         freecon (con);
        }
       else
        report_file_error ("Doing lgetfilecon", Fcons (absname, Qnil));
-
-      if (con)
-       freecon (con);
     }
 #endif
 
@@ -3003,10 +3008,10 @@ The value is an integer.  */)
   mode_t realmask;
   Lisp_Object value;
 
-  BLOCK_INPUT;
+  block_input ();
   realmask = umask (0);
   umask (realmask);
-  UNBLOCK_INPUT;
+  unblock_input ();
 
   XSETINT (value, (~ realmask) & 0777);
   return value;
@@ -3038,7 +3043,7 @@ Use the current time if TIMESTAMP is nil.  TIMESTAMP is in the format of
   {
     if (set_file_times (-1, SSDATA (encoded_absname), t, t))
       {
-#ifdef DOS_NT
+#ifdef MSDOS
         struct stat st;
 
         /* Setting times on a directory always fails.  */
@@ -3196,7 +3201,7 @@ emacs_lseek (int fd, EMACS_INT offset, int whence)
 {
   /* Use "&" rather than "&&" to suppress a bogus GCC warning; see
      <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43772>.  */
-  if (! ((TYPE_MINIMUM (off_t) <= offset) & (offset <= TYPE_MAXIMUM (off_t))))
+  if (! ((offset >= TYPE_MINIMUM (off_t)) & (offset <= TYPE_MAXIMUM (off_t))))
     {
       errno = EINVAL;
       return -1;
@@ -3369,7 +3374,7 @@ variable `last-coding-system-used' to the coding system actually used.  */)
 
   if (!NILP (beg))
     {
-      if (! (RANGED_INTEGERP (0, beg, TYPE_MAXIMUM (off_t))))
+      if (! RANGED_INTEGERP (0, beg, TYPE_MAXIMUM (off_t)))
        wrong_type_argument (intern ("file-offset"), beg);
       beg_offset = XFASTINT (beg);
     }
@@ -3378,7 +3383,7 @@ variable `last-coding-system-used' to the coding system actually used.  */)
 
   if (!NILP (end))
     {
-      if (! (RANGED_INTEGERP (0, end, TYPE_MAXIMUM (off_t))))
+      if (! RANGED_INTEGERP (0, end, TYPE_MAXIMUM (off_t)))
        wrong_type_argument (intern ("file-offset"), end);
       end_offset = XFASTINT (end);
     }
@@ -3414,8 +3419,8 @@ variable `last-coding-system-used' to the coding system actually used.  */)
 
       if (beg_offset < likely_end)
        {
-         ptrdiff_t buf_bytes =
-           Z_BYTE - (!NILP (replace) ? ZV_BYTE - BEGV_BYTE  : 0);
+         ptrdiff_t buf_bytes
+           Z_BYTE - (!NILP (replace) ? ZV_BYTE - BEGV_BYTE  : 0);
          ptrdiff_t buf_growth_max = BUF_BYTES_MAX - buf_bytes;
          off_t likely_growth = likely_end - beg_offset;
          if (buf_growth_max < likely_growth)
@@ -4538,6 +4543,7 @@ This calls `write-region-annotate-functions' at the start, and
   int save_errno = 0;
   const char *fn;
   struct stat st;
+  EMACS_TIME modtime;
   ptrdiff_t count = SPECPDL_INDEX ();
   int count1;
   Lisp_Object handler;
@@ -4750,12 +4756,19 @@ This calls `write-region-annotate-functions' at the start, and
     }
 #endif
 
+  modtime = invalid_emacs_time ();
+  if (visiting)
+    {
+      if (fstat (desc, &st) == 0)
+       modtime = get_stat_mtime (&st);
+      else
+       ok = 0, save_errno = errno;
+    }
+
   /* NFS can report a write failure now.  */
   if (emacs_close (desc) < 0)
     ok = 0, save_errno = errno;
 
-  stat (fn, &st);
-
   /* Discard the unwind protect for close_file_unwind.  */
   specpdl_ptr = specpdl + count1;
 
@@ -4783,9 +4796,9 @@ This calls `write-region-annotate-functions' at the start, and
   /* Do this before reporting IO error
      to avoid a "file has changed on disk" warning on
      next attempt to save.  */
-  if (visiting)
+  if (EMACS_TIME_VALID_P (modtime))
     {
-      current_buffer->modtime = get_stat_mtime (&st);
+      current_buffer->modtime = modtime;
       current_buffer->modtime_size = st.st_size;
     }
 
@@ -5035,12 +5048,12 @@ e_write (int desc, Lisp_Object string, ptrdiff_t start, ptrdiff_t end,
 
       if (coding->produced > 0)
        {
-         coding->produced -=
-           emacs_write (desc,
-                        STRINGP (coding->dst_object)
-                        ? SSDATA (coding->dst_object)
-                        : (char *) BYTE_POS_ADDR (coding->dst_pos_byte),
-                        coding->produced);
+         coding->produced
+           -= emacs_write (desc,
+                           STRINGP (coding->dst_object)
+                           ? SSDATA (coding->dst_object)
+                           : (char *) BYTE_POS_ADDR (coding->dst_pos_byte),
+                           coding->produced);
 
          if (coding->produced)
            return 0;
@@ -5219,8 +5232,8 @@ auto_save_1 (void)
       if (stat (SSDATA (BVAR (current_buffer, filename)), &st) >= 0)
        /* But make sure we can overwrite it later!  */
        auto_save_mode_bits = (st.st_mode | 0600) & 0777;
-      else if ((modes = Ffile_modes (BVAR (current_buffer, filename)),
-               INTEGERP (modes)))
+      else if (modes = Ffile_modes (BVAR (current_buffer, filename)),
+              INTEGERP (modes))
        /* Remote files don't cooperate with stat.  */
        auto_save_mode_bits = (XINT (modes) | 0600) & 0777;
     }
@@ -5239,9 +5252,9 @@ do_auto_save_unwind (Lisp_Object arg)  /* used as unwind-protect function */
   auto_saving = 0;
   if (stream != NULL)
     {
-      BLOCK_INPUT;
+      block_input ();
       fclose (stream);
-      UNBLOCK_INPUT;
+      unblock_input ();
     }
   return Qnil;
 }
@@ -5372,7 +5385,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer.  */)
        if (STRINGP (BVAR (b, auto_save_file_name))
            && stream != NULL && do_handled_files == 0)
          {
-           BLOCK_INPUT;
+           block_input ();
            if (!NILP (BVAR (b, filename)))
              {
                fwrite (SDATA (BVAR (b, filename)), 1,
@@ -5382,7 +5395,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer.  */)
            fwrite (SDATA (BVAR (b, auto_save_file_name)), 1,
                    SBYTES (BVAR (b, auto_save_file_name)), stream);
            putc ('\n', stream);
-           UNBLOCK_INPUT;
+           unblock_input ();
          }
 
        if (!NILP (current_only)
@@ -5524,7 +5537,8 @@ The return value is only relevant for a call to `read-file-name' that happens
 before any other event (mouse or keypress) is handled.  */)
   (void)
 {
-#if defined (USE_MOTIF) || defined (HAVE_NTGUI) || defined (USE_GTK)
+#if defined (USE_MOTIF) || defined (HAVE_NTGUI) || defined (USE_GTK) \
+  || defined (HAVE_NS)
   if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
       && use_dialog_box
       && use_file_dialog