]> code.delx.au - gnu-emacs/blobdiff - src/fileio.c
* editfns.c, systime.h (mktime_z) [!HAVE_TZALLOC]: Now static.
[gnu-emacs] / src / fileio.c
index 39514ee18e619ad45964042e3fa4cf8b8034bc05..d4e12cbe277fb130f6a71c7c9c2ec39d28da3ffa 100644 (file)
@@ -1,6 +1,6 @@
 /* File IO for GNU Emacs.
 
-Copyright (C) 1985-1988, 1993-2014 Free Software Foundation, Inc.
+Copyright (C) 1985-1988, 1993-2015 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -86,6 +86,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <careadlinkat.h>
 #include <stat-time.h>
 
+#include <binary-io.h>
+
 #ifdef HPUX
 #include <netio.h>
 #endif
@@ -113,50 +115,10 @@ static bool auto_save_error_occurred;
 static bool valid_timestamp_file_system;
 static dev_t timestamp_file_system;
 
-/* The symbol bound to coding-system-for-read when
-   insert-file-contents is called for recovering a file.  This is not
-   an actual coding system name, but just an indicator to tell
-   insert-file-contents to use `emacs-mule' with a special flag for
-   auto saving and recovering a file.  */
-static Lisp_Object Qauto_save_coding;
-
-/* Property name of a file name handler,
-   which gives a list of operations it handles..  */
-static Lisp_Object Qoperations;
-
-/* Lisp functions for translating file formats.  */
-static Lisp_Object Qformat_decode, Qformat_annotate_function;
-
-/* Lisp function for setting buffer-file-coding-system and the
-   multibyteness of the current buffer after inserting a file.  */
-static Lisp_Object Qafter_insert_file_set_coding;
-
-static Lisp_Object Qwrite_region_annotate_functions;
 /* Each time an annotation function changes the buffer, the new buffer
    is added here.  */
 static Lisp_Object Vwrite_region_annotation_buffers;
 
-static Lisp_Object Qdelete_by_moving_to_trash;
-
-/* Lisp function for moving files to trash.  */
-static Lisp_Object Qmove_file_to_trash;
-
-/* Lisp function for recursively copying directories.  */
-static Lisp_Object Qcopy_directory;
-
-/* Lisp function for recursively deleting directories.  */
-static Lisp_Object Qdelete_directory;
-
-static Lisp_Object Qsubstitute_env_in_file_name;
-static Lisp_Object Qget_buffer_window_list;
-
-Lisp_Object Qfile_error, Qfile_notify_error;
-static Lisp_Object Qfile_already_exists, Qfile_date_error;
-static Lisp_Object Qexcl;
-Lisp_Object Qfile_name_history;
-
-static Lisp_Object Qcar_less_than_car;
-
 static bool a_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t,
                     Lisp_Object *, struct coding_system *);
 static bool e_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t,
@@ -224,37 +186,17 @@ void
 report_file_errno (char const *string, Lisp_Object name, int errorno)
 {
   Lisp_Object data = CONSP (name) || NILP (name) ? name : list1 (name);
-  Lisp_Object errstring;
-  char *str;
-
   synchronize_system_messages_locale ();
-  str = strerror (errorno);
-  errstring = code_convert_string_norecord (build_unibyte_string (str),
-                                           Vlocale_coding_system, 0);
-
-  while (1)
-    switch (errorno)
-      {
-      case EEXIST:
-       xsignal (Qfile_already_exists, Fcons (errstring, data));
-       break;
-      default:
-       /* System error messages are capitalized.  Downcase the initial
-          unless it is followed by a slash.  (The slash case caters to
-          error messages that begin with "I/O" or, in German, "E/A".)  */
-       if (STRING_MULTIBYTE (errstring)
-           && ! EQ (Faref (errstring, make_number (1)), make_number ('/')))
-         {
-           int c;
-
-           str = SSDATA (errstring);
-           c = STRING_CHAR ((unsigned char *) str);
-           Faset (errstring, make_number (0), make_number (downcase (c)));
-         }
-
-       xsignal (Qfile_error,
-                Fcons (build_string (string), Fcons (errstring, data)));
-      }
+  char *str = strerror (errorno);
+  Lisp_Object errstring
+    = code_convert_string_norecord (build_unibyte_string (str),
+                                   Vlocale_coding_system, 0);
+  Lisp_Object errdata = Fcons (errstring, data);
+
+  if (errorno == EEXIST)
+    xsignal (Qfile_already_exists, errdata);
+  else
+    xsignal (Qfile_error, Fcons (build_string (string), errdata));
 }
 
 /* Signal a file-access failure that set errno.  STRING describes the
@@ -291,43 +233,6 @@ restore_point_unwind (Lisp_Object location)
 }
 
 \f
-static Lisp_Object Qexpand_file_name;
-static Lisp_Object Qsubstitute_in_file_name;
-static Lisp_Object Qdirectory_file_name;
-static Lisp_Object Qfile_name_directory;
-static Lisp_Object Qfile_name_nondirectory;
-static Lisp_Object Qunhandled_file_name_directory;
-static Lisp_Object Qfile_name_as_directory;
-static Lisp_Object Qcopy_file;
-static Lisp_Object Qmake_directory_internal;
-static Lisp_Object Qmake_directory;
-static Lisp_Object Qdelete_directory_internal;
-Lisp_Object Qdelete_file;
-static Lisp_Object Qrename_file;
-static Lisp_Object Qadd_name_to_file;
-static Lisp_Object Qmake_symbolic_link;
-Lisp_Object Qfile_exists_p;
-static Lisp_Object Qfile_executable_p;
-static Lisp_Object Qfile_readable_p;
-static Lisp_Object Qfile_writable_p;
-static Lisp_Object Qfile_symlink_p;
-static Lisp_Object Qaccess_file;
-Lisp_Object Qfile_directory_p;
-static Lisp_Object Qfile_regular_p;
-static Lisp_Object Qfile_accessible_directory_p;
-static Lisp_Object Qfile_modes;
-static Lisp_Object Qset_file_modes;
-static Lisp_Object Qset_file_times;
-static Lisp_Object Qfile_selinux_context;
-static Lisp_Object Qset_file_selinux_context;
-static Lisp_Object Qfile_acl;
-static Lisp_Object Qset_file_acl;
-static Lisp_Object Qfile_newer_than_file_p;
-Lisp_Object Qinsert_file_contents;
-Lisp_Object Qwrite_region;
-static Lisp_Object Qverify_visited_file_modtime;
-static Lisp_Object Qset_visited_file_modtime;
-
 DEFUN ("find-file-name-handler", Ffind_file_name_handler,
        Sfind_file_name_handler, 2, 2, 0,
        doc: /* Return FILENAME's handler function for OPERATION, if it has one.
@@ -599,8 +504,6 @@ For a Unix-syntax file name, just appends a slash.  */)
   USE_SAFE_ALLOCA;
 
   CHECK_STRING (file);
-  if (NILP (file))
-    return Qnil;
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
@@ -668,9 +571,6 @@ In Unix-syntax, this function just removes the final slash.  */)
 
   CHECK_STRING (directory);
 
-  if (NILP (directory))
-    return Qnil;
-
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
   handler = Ffind_file_name_handler (directory, Qdirectory_file_name);
@@ -824,20 +724,16 @@ make_temp_name (Lisp_Object prefix, bool base64_p)
 
 DEFUN ("make-temp-name", Fmake_temp_name, Smake_temp_name, 1, 1, 0,
        doc: /* Generate temporary file name (string) starting with PREFIX (a string).
-The Emacs process number forms part of the result,
-so there is no danger of generating a name being used by another process.
+The Emacs process number forms part of the result, so there is no
+danger of generating a name being used by another Emacs process
+\(so long as only a single host can access the containing directory...).
 
-In addition, this function makes an attempt to choose a name
-which has no existing file.  To make this work,
-PREFIX should be an absolute file name.
+This function tries to choose a name that has no existing file.
+For this to work, PREFIX should be an absolute file name.
 
 There is a race condition between calling `make-temp-name' and creating the
-file which opens all kinds of security holes.  For that reason, you should
-probably use `make-temp-file' instead, except in three circumstances:
-
-* If you are creating the file in the user's home directory.
-* If you are creating a directory rather than an ordinary file.
-* If you are taking special precautions as `make-temp-file' does.  */)
+file, which opens all kinds of security holes.  For that reason, you should
+normally use `make-temp-file' instead.  */)
   (Lisp_Object prefix)
 {
   return make_temp_name (prefix, 0);
@@ -2892,7 +2788,8 @@ or if SELinux is disabled, or if Emacs lacks SELinux support.  */)
   (Lisp_Object filename)
 {
   Lisp_Object absname;
-  Lisp_Object values[4];
+  Lisp_Object user = Qnil, role = Qnil, type = Qnil, range = Qnil;
+
   Lisp_Object handler;
 #if HAVE_LIBSELINUX
   security_context_t con;
@@ -2910,10 +2807,6 @@ or if SELinux is disabled, or if Emacs lacks SELinux support.  */)
 
   absname = ENCODE_FILE (absname);
 
-  values[0] = Qnil;
-  values[1] = Qnil;
-  values[2] = Qnil;
-  values[3] = Qnil;
 #if HAVE_LIBSELINUX
   if (is_selinux_enabled ())
     {
@@ -2922,20 +2815,20 @@ or if SELinux is disabled, or if Emacs lacks SELinux support.  */)
        {
          context = context_new (con);
          if (context_user_get (context))
-           values[0] = build_string (context_user_get (context));
+           user = build_string (context_user_get (context));
          if (context_role_get (context))
-           values[1] = build_string (context_role_get (context));
+           role = build_string (context_role_get (context));
          if (context_type_get (context))
-           values[2] = build_string (context_type_get (context));
+           type = build_string (context_type_get (context));
          if (context_range_get (context))
-           values[3] = build_string (context_range_get (context));
+           range = build_string (context_range_get (context));
          context_free (context);
          freecon (con);
        }
     }
 #endif
 
-  return Flist (ARRAYELTS (values), values);
+  return list4 (user, role, type, range);
 }
 \f
 DEFUN ("set-file-selinux-context", Fset_file_selinux_context,
@@ -3753,11 +3646,9 @@ by calling `format-decode', which see.  */)
            {
              /* If we have not yet decided a coding system, check
                  file-coding-system-alist.  */
-             Lisp_Object args[6];
-
-             args[0] = Qinsert_file_contents, args[1] = orig_filename;
-             args[2] = visit, args[3] = beg, args[4] = end, args[5] = replace;
-             coding_system = Ffind_operation_coding_system (6, args);
+             coding_system = CALLN (Ffind_operation_coding_system,
+                                    Qinsert_file_contents, orig_filename,
+                                    visit, beg, end, replace);
              if (CONSP (coding_system))
                coding_system = XCAR (coding_system);
            }
@@ -4334,11 +4225,9 @@ by calling `format-decode', which see.  */)
            {
              /* If the coding system is not yet decided, check
                 file-coding-system-alist.  */
-             Lisp_Object args[6];
-
-             args[0] = Qinsert_file_contents, args[1] = orig_filename;
-             args[2] = visit, args[3] = beg, args[4] = end, args[5] = Qnil;
-             coding_system = Ffind_operation_coding_system (6, args);
+             coding_system = CALLN (Ffind_operation_coding_system,
+                                    Qinsert_file_contents, orig_filename,
+                                    visit, beg, end, Qnil);
              if (CONSP (coding_system))
                coding_system = XCAR (coding_system);
            }
@@ -4666,12 +4555,9 @@ choose_write_coding_system (Lisp_Object start, Lisp_Object end, Lisp_Object file
       if (NILP (val))
        {
          /* Check file-coding-system-alist.  */
-         Lisp_Object args[7], coding_systems;
-
-         args[0] = Qwrite_region; args[1] = start; args[2] = end;
-         args[3] = filename; args[4] = append; args[5] = visit;
-         args[6] = lockname;
-         coding_systems = Ffind_operation_coding_system (7, args);
+         Lisp_Object coding_systems
+           = CALLN (Ffind_operation_coding_system, Qwrite_region, start, end,
+                    filename, append, visit, lockname);
          if (CONSP (coding_systems) && !NILP (XCDR (coding_systems)))
            val = XCDR (coding_systems);
        }
@@ -4741,8 +4627,8 @@ Optional fifth argument VISIT, if t or a string, means
 If VISIT is a string, it is a second file name;
   the output goes to FILENAME, but the buffer is marked as visiting VISIT.
   VISIT is also the file name to lock and unlock for clash detection.
-If VISIT is neither t nor nil nor a string,
-  that means do not display the \"Wrote file\" message.
+If VISIT is neither t nor nil nor a string, or if Emacs is in batch mode,
+  do not display the \"Wrote file\" message.
 The optional sixth arg LOCKNAME, if non-nil, specifies the name to
   use for locking and unlocking, overriding FILENAME and VISIT.
 The optional seventh arg MUSTBENEW, if non-nil, insists on a check
@@ -5109,7 +4995,7 @@ write_region (Lisp_Object start, Lisp_Object end, Lisp_Object filename,
       return Qnil;
     }
 
-  if (!auto_saving)
+  if (!auto_saving && !noninteractive)
     message_with_string ((NUMBERP (append)
                          ? "Updated %s"
                          : ! NILP (append)
@@ -5124,10 +5010,7 @@ DEFUN ("car-less-than-car", Fcar_less_than_car, Scar_less_than_car, 2, 2, 0,
        doc: /* Return t if (car A) is numerically less than (car B).  */)
   (Lisp_Object a, Lisp_Object b)
 {
-  Lisp_Object args[2];
-  args[0] = Fcar (a);
-  args[1] = Fcar (b);
-  return Flss (2, args);
+  return CALLN (Flss, Fcar (a), Fcar (b));
 }
 
 /* Build the complete list of annotations appropriate for writing out
@@ -5146,7 +5029,7 @@ build_annotations (Lisp_Object start, Lisp_Object end)
   struct gcpro gcpro1, gcpro2;
   Lisp_Object original_buffer;
   int i;
-  bool used_global = 0;
+  bool used_global = false;
 
   XSETBUFFER (original_buffer, current_buffer);
 
@@ -5158,11 +5041,10 @@ build_annotations (Lisp_Object start, Lisp_Object end)
       struct buffer *given_buffer = current_buffer;
       if (EQ (Qt, XCAR (p)) && !used_global)
        { /* Use the global value of the hook.  */
-         Lisp_Object arg[2];
-         used_global = 1;
-         arg[0] = Fdefault_value (Qwrite_region_annotate_functions);
-         arg[1] = XCDR (p);
-         p = Fappend (2, arg);
+         used_global = true;
+         p = CALLN (Fappend,
+                    Fdefault_value (Qwrite_region_annotate_functions),
+                    XCDR (p));
          continue;
        }
       Vwrite_region_annotations_so_far = annotations;
@@ -5491,9 +5373,8 @@ auto_save_error (Lisp_Object error_val)
   ring_bell (XFRAME (selected_frame));
 
   AUTO_STRING (format, "Auto-saving %s: %s");
-  msg = Fformat (3, ((Lisp_Object [])
-                    {format, BVAR (current_buffer, name),
-                     Ferror_message_string (error_val)}));
+  msg = CALLN (Fformat, format, BVAR (current_buffer, name),
+              Ferror_message_string (error_val));
   GCPRO1 (msg);
 
   for (i = 0; i < 3; ++i)
@@ -5815,8 +5696,8 @@ then any auto-save counts as "recent".  */)
      they're never autosaved.  */
   return (SAVE_MODIFF < BUF_AUTOSAVE_MODIFF (current_buffer) ? Qt : Qnil);
 }
-\f
-/* Reading and completing file names */
+
+/* Reading and completing file names */
 
 DEFUN ("next-read-file-uses-dialog-p", Fnext_read_file_uses_dialog_p,
        Snext_read_file_uses_dialog_p, 0, 0, 0,
@@ -5825,8 +5706,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) \
-  || defined (HAVE_NS)
+#if (defined USE_GTK || defined USE_MOTIF \
+     || defined HAVE_NS || defined HAVE_NTGUI)
   if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
       && use_dialog_box
       && use_file_dialog
@@ -5836,6 +5717,48 @@ before any other event (mouse or keypress) is handled.  */)
   return Qnil;
 }
 
+\f
+DEFUN ("set-binary-mode", Fset_binary_mode, Sset_binary_mode, 2, 2, 0,
+       doc: /* Switch STREAM to binary I/O mode or text I/O mode.
+STREAM can be one of the symbols `stdin', `stdout', or `stderr'.
+If MODE is non-nil, switch STREAM to binary mode, otherwise switch
+it to text mode.
+
+As a side effect, this function flushes any pending STREAM's data.
+
+Value is the previous value of STREAM's I/O mode, nil for text mode,
+non-nil for binary mode.
+
+On MS-Windows and MS-DOS, binary mode is needed to read or write
+arbitrary binary data, and for disabling translation between CR-LF
+pairs and a single newline character.  Examples include generation
+of text files with Unix-style end-of-line format using `princ' in
+batch mode, with standard output redirected to a file.
+
+On Posix systems, this function always returns non-nil, and has no
+effect except for flushing STREAM's data.  */)
+  (Lisp_Object stream, Lisp_Object mode)
+{
+  FILE *fp = NULL;
+  int binmode;
+
+  CHECK_SYMBOL (stream);
+  if (EQ (stream, Qstdin))
+    fp = stdin;
+  else if (EQ (stream, Qstdout))
+    fp = stdout;
+  else if (EQ (stream, Qstderr))
+    fp = stderr;
+  else
+    xsignal2 (Qerror, build_string ("unsupported stream"), stream);
+
+  binmode = NILP (mode) ? O_TEXT : O_BINARY;
+  if (fp != stdin)
+    fflush (fp);
+
+  return (set_binary_mode (fileno (fp), binmode) == O_BINARY) ? Qt : Qnil;
+}
+\f
 void
 init_fileio (void)
 {
@@ -5866,7 +5789,10 @@ init_fileio (void)
 void
 syms_of_fileio (void)
 {
+  /* Property name of a file name handler,
+     which gives a list of operations it handles.  */
   DEFSYM (Qoperations, "operations");
+
   DEFSYM (Qexpand_file_name, "expand-file-name");
   DEFSYM (Qsubstitute_in_file_name, "substitute-in-file-name");
   DEFSYM (Qdirectory_file_name, "directory-file-name");
@@ -5903,6 +5829,12 @@ syms_of_fileio (void)
   DEFSYM (Qwrite_region, "write-region");
   DEFSYM (Qverify_visited_file_modtime, "verify-visited-file-modtime");
   DEFSYM (Qset_visited_file_modtime, "set-visited-file-modtime");
+
+  /* The symbol bound to coding-system-for-read when
+     insert-file-contents is called for recovering a file.  This is not
+     an actual coding system name, but just an indicator to tell
+     insert-file-contents to use `emacs-mule' with a special flag for
+     auto saving and recovering a file.  */
   DEFSYM (Qauto_save_coding, "auto-save-coding");
 
   DEFSYM (Qfile_name_history, "file-name-history");
@@ -5938,9 +5870,14 @@ On MS-Windows, the value of this variable is largely ignored if
 behaves as if file names were encoded in `utf-8'.  */);
   Vdefault_file_name_coding_system = Qnil;
 
+  /* Lisp functions for translating file formats.  */
   DEFSYM (Qformat_decode, "format-decode");
   DEFSYM (Qformat_annotate_function, "format-annotate-function");
+
+  /* Lisp function for setting buffer-file-coding-system and the
+     multibyteness of the current buffer after inserting a file.  */
   DEFSYM (Qafter_insert_file_set_coding, "after-insert-file-set-coding");
+
   DEFSYM (Qcar_less_than_car, "car-less-than-car");
 
   Fput (Qfile_error, Qerror_conditions,
@@ -6094,14 +6031,24 @@ When non-nil, certain file deletion commands use the function
 This includes interactive calls to `delete-file' and
 `delete-directory' and the Dired deletion commands.  */);
   delete_by_moving_to_trash = 0;
-  Qdelete_by_moving_to_trash = intern_c_string ("delete-by-moving-to-trash");
+  DEFSYM (Qdelete_by_moving_to_trash, "delete-by-moving-to-trash");
 
+  /* Lisp function for moving files to trash.  */
   DEFSYM (Qmove_file_to_trash, "move-file-to-trash");
+
+  /* Lisp function for recursively copying directories.  */
   DEFSYM (Qcopy_directory, "copy-directory");
+
+  /* Lisp function for recursively deleting directories.  */
   DEFSYM (Qdelete_directory, "delete-directory");
+
   DEFSYM (Qsubstitute_env_in_file_name, "substitute-env-in-file-name");
   DEFSYM (Qget_buffer_window_list, "get-buffer-window-list");
 
+  DEFSYM (Qstdin, "stdin");
+  DEFSYM (Qstdout, "stdout");
+  DEFSYM (Qstderr, "stderr");
+
   defsubr (&Sfind_file_name_handler);
   defsubr (&Sfile_name_directory);
   defsubr (&Sfile_name_nondirectory);
@@ -6151,6 +6098,8 @@ This includes interactive calls to `delete-file' and
 
   defsubr (&Snext_read_file_uses_dialog_p);
 
+  defsubr (&Sset_binary_mode);
+
 #ifdef HAVE_SYNC
   defsubr (&Sunix_sync);
 #endif