emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: feature request: view part of file


From: Paul Eggert
Subject: Re: feature request: view part of file
Date: Sat, 19 Jan 2013 04:47:58 -0800
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130106 Thunderbird/17.0.2

On 01/19/2013 02:51 AM, Eli Zaretskii wrote:
> That patch calls lseek inside write-region on non-regular files as
> well, where previously we didn't.  Why is that a good idea?  (It's an
> unrelated change anyway.) 

Yes, it's unrelated; sorry, it was related in an earlier version
of the patch, but I forgot to undo that part.

It's a good idea for a couple of reasons.  First, the old code
mishandled things if the file was renamed by some other process
between the time that Emacs opened it and the time that
file-regular-p invoked stat on it.  Second, the typical GNU style
is that the behavior of a program should not depend on the type of
output device.

I looked at the old change you mentioned, and it appears that
there was a problem on DOS_NT with invoking lseek (fd, 0, SEEK_END) when
FD is not a regular file.  Here's a patch that should avoid this problem:

=== modified file 'src/ChangeLog'
--- src/ChangeLog       2013-01-19 12:29:10 +0000
+++ src/ChangeLog       2013-01-19 12:37:41 +0000
@@ -1,5 +1,16 @@
 2013-01-19  Paul Eggert  <address@hidden>
 
+       * fileio.c: Use O_APPEND to append.
+       This corresponds better to the natural interpretation of "append",
+       and avoids the need to open the output file twice, or to invoke
+       lseek when APPEND is neither nil nor a number.
+       This relies on POSIX 1003.1-1988 or later, which is OK nowadays.
+       (Fwrite_region): Simplify.  Use O_APPEND instead of opening the
+       file possibly twice, and lseeking to its end; this avoids the
+       need to lseek on non-regular files.  Do not use O_EXCL and O_TRUNC
+       at the same time: the combination is never needed and apparently
+       it doesn't work with DOS_NT.
+
        Fix size bug on DOS_NT introduced by CIFS workaround (Bug#13149).
        * fileio.c (Fwrite_region): Use O_BINARY in checking code, too.
 

=== modified file 'src/fileio.c'
--- src/fileio.c        2013-01-19 12:29:10 +0000
+++ src/fileio.c        2013-01-19 12:37:41 +0000
@@ -4741,7 +4741,9 @@
   (Lisp_Object start, Lisp_Object end, Lisp_Object filename, Lisp_Object 
append, Lisp_Object visit, Lisp_Object lockname, Lisp_Object mustbenew)
 {
   int desc;
-  off_t offset;
+  int open_flags;
+  int mode;
+  off_t offset IF_LINT (= 0);
   bool ok;
   int save_errno = 0;
   const char *fn;
@@ -4863,26 +4865,19 @@
   encoded_filename = ENCODE_FILE (filename);
 
   fn = SSDATA (encoded_filename);
-  offset = 0;
-  desc = -1;
-  if (!NILP (append))
-    {
-      if (NUMBERP (append))
-       offset = file_offset (append);
-      desc = emacs_open (fn, O_WRONLY | O_BINARY, 0);
-    }
-
-  if (desc < 0 && (NILP (append) || errno == ENOENT))
+  open_flags = O_WRONLY | O_BINARY | O_CREAT;
+  open_flags |= EQ (mustbenew, Qexcl) ? O_EXCL : O_TRUNC;
+  if (NUMBERP (append))
+    offset = file_offset (append);
+  else if (!NILP (append))
+    open_flags |= O_APPEND;
 #ifdef DOS_NT
-  desc = emacs_open (fn,
-                    O_WRONLY | O_CREAT | O_BINARY
-                    | (EQ (mustbenew, Qexcl) ? O_EXCL : O_TRUNC),
-                    S_IREAD | S_IWRITE);
-#else  /* not DOS_NT */
-  desc = emacs_open (fn, O_WRONLY | O_TRUNC | O_CREAT
-                    | (EQ (mustbenew, Qexcl) ? O_EXCL : 0),
-                    auto_saving ? auto_save_mode_bits : 0666);
-#endif /* not DOS_NT */
+  mode = S_IREAD | S_IWRITE;
+#else
+  mode = auto_saving ? auto_save_mode_bits : 0666;
+#endif
+
+  desc = emacs_open (fn, open_flags, mode);
 
   if (desc < 0)
     {
@@ -4897,9 +4892,9 @@
 
   record_unwind_protect (close_file_unwind, make_number (desc));
 
-  if (!NILP (append))
+  if (NUMBERP (append))
     {
-      off_t ret = lseek (desc, offset, NUMBERP (append) ? SEEK_SET : SEEK_END);
+      off_t ret = lseek (desc, offset, SEEK_SET);
       if (ret < 0)
        {
 #ifdef CLASH_DETECTION





reply via email to

[Prev in Thread] Current Thread [Next in Thread]