diff options
| author | Joakim Verona | 2013-01-20 00:03:45 +0100 |
|---|---|---|
| committer | Joakim Verona | 2013-01-20 00:03:45 +0100 |
| commit | 6a5f23571aa7c6e13c0ad97b1bde086e7f95a65e (patch) | |
| tree | 24145f7884f301dde3608b78853e2868c817d1de /src | |
| parent | 19ea867b2ed4dca4e460d1f347a4ff39d31705f1 (diff) | |
| parent | ee271528bfa645727f03c2a3e04db73b72a76077 (diff) | |
| download | emacs-6a5f23571aa7c6e13c0ad97b1bde086e7f95a65e.tar.gz emacs-6a5f23571aa7c6e13c0ad97b1bde086e7f95a65e.zip | |
auto upstream
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 73 | ||||
| -rw-r--r-- | src/buffer.c | 7 | ||||
| -rw-r--r-- | src/editfns.c | 5 | ||||
| -rw-r--r-- | src/emacs.c | 12 | ||||
| -rw-r--r-- | src/fileio.c | 137 | ||||
| -rw-r--r-- | src/fns.c | 5 | ||||
| -rw-r--r-- | src/lisp.h | 10 | ||||
| -rw-r--r-- | src/w32.c | 27 |
8 files changed, 207 insertions, 69 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index a7b8ab7855b..1383b12ed68 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,76 @@ | |||
| 1 | 2013-01-19 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | * lisp.h (eabs): Define unconditionally (Bug#13419). | ||
| 4 | The old "#if !defined (eabs)" was an unnecessary revenant of back | ||
| 5 | when this macro was called "abs". Document 'eabs' better. | ||
| 6 | |||
| 7 | 2013-01-19 Glenn Morris <rgm@gnu.org> | ||
| 8 | |||
| 9 | * fns.c (Frandom): Doc fix. | ||
| 10 | |||
| 11 | 2013-01-19 Eli Zaretskii <eliz@gnu.org> | ||
| 12 | |||
| 13 | * editfns.c (get_pos_property): Use SAFE_ALLOCA_LISP, to avoid | ||
| 14 | segfault when there are lots of overlays. | ||
| 15 | |||
| 16 | * buffer.c (sort_overlays): Use SAFE_NALLOCA, to avoid segfault | ||
| 17 | when there are lots of overlays. See | ||
| 18 | http://lists.gnu.org/archive/html/emacs-devel/2013-01/msg00421.html | ||
| 19 | for the details and a way to reproduce. | ||
| 20 | |||
| 21 | 2013-01-19 Paul Eggert <eggert@cs.ucla.edu> | ||
| 22 | |||
| 23 | * fileio.c: Use O_APPEND to append. | ||
| 24 | This corresponds better to the natural interpretation of "append", | ||
| 25 | and avoids the need to open the output file twice, or to invoke | ||
| 26 | lseek when APPEND is neither nil nor a number. | ||
| 27 | This relies on POSIX 1003.1-1988 or later, which is OK nowadays. | ||
| 28 | (Fwrite_region): Simplify. Use O_APPEND instead of opening the | ||
| 29 | file possibly twice, and lseeking to its end; this avoids the | ||
| 30 | need to lseek on non-regular files. Do not use O_EXCL and O_TRUNC | ||
| 31 | at the same time: the combination is never needed and apparently | ||
| 32 | it doesn't work with DOS_NT. | ||
| 33 | |||
| 34 | Fix size bug on DOS_NT introduced by CIFS workaround (Bug#13149). | ||
| 35 | * fileio.c (Fwrite_region): Use O_BINARY in checking code, too. | ||
| 36 | |||
| 37 | Allow floating-point file offsets. | ||
| 38 | Problem reported by Vitalie Spinu in | ||
| 39 | <http://lists.gnu.org/archive/html/emacs-devel/2013-01/msg00411.html>. | ||
| 40 | * fileio.c (emacs_lseek): Remove. | ||
| 41 | (file_offset): New function. | ||
| 42 | (Finsert_file_contents, Fwrite_region): Use it. | ||
| 43 | |||
| 44 | 2013-01-19 Chong Yidong <cyd@gnu.org> | ||
| 45 | |||
| 46 | * emacs.c (Fkill_emacs): Set waiting_for_input to 0 to avoid | ||
| 47 | aborting on Fsignal (Bug#13289). | ||
| 48 | |||
| 49 | 2013-01-19 Eli Zaretskii <eliz@gnu.org> | ||
| 50 | |||
| 51 | * w32.c (acl_set_file): Treat ERROR_ACCESS_DENIED from | ||
| 52 | set_file_security as failure due to insufficient privileges. | ||
| 53 | Reported by Fabrice Popineau <fabrice.popineau@supelec.fr>. | ||
| 54 | (fstat): Return owner and group like 'stat' and 'lstat' do. | ||
| 55 | |||
| 56 | 2013-01-19 Paul Eggert <eggert@cs.ucla.edu> | ||
| 57 | |||
| 58 | Work around bug in CIFS and vboxsf file systems (Bug#13149). | ||
| 59 | The bug was observed on Ubuntu operating inside a virtual machine, | ||
| 60 | editing files mounted via CIFS or vboxsf from the MS Windows 7 host. | ||
| 61 | The workaround introduces a race condition on non-buggy hosts, | ||
| 62 | but it's an unlikely race and anyway there's a nearly identical | ||
| 63 | nearby race that can't be fixed. | ||
| 64 | * fileio.c (valid_timestamp_file_system, timestamp_file_system): | ||
| 65 | New static vars. | ||
| 66 | (Fwrite_region): Test for file system time stamp bug. | ||
| 67 | (init_fileio): New function. | ||
| 68 | * lisp.h (init_fileio): Declare it. | ||
| 69 | * emacs.c (main): Call it. | ||
| 70 | |||
| 71 | * fileio.c (Finsert_file_contents): Simplify new diagnostic | ||
| 72 | and make it more consistent with other stat-failure diagnostics. | ||
| 73 | |||
| 1 | 2013-01-18 Dmitry Antipov <dmantipov@yandex.ru> | 74 | 2013-01-18 Dmitry Antipov <dmantipov@yandex.ru> |
| 2 | 75 | ||
| 3 | Fix crash when inserting data from non-regular files. See | 76 | Fix crash when inserting data from non-regular files. See |
diff --git a/src/buffer.c b/src/buffer.c index 66581cb7828..aa3fcf8c234 100644 --- a/src/buffer.c +++ b/src/buffer.c | |||
| @@ -3151,7 +3151,10 @@ ptrdiff_t | |||
| 3151 | sort_overlays (Lisp_Object *overlay_vec, ptrdiff_t noverlays, struct window *w) | 3151 | sort_overlays (Lisp_Object *overlay_vec, ptrdiff_t noverlays, struct window *w) |
| 3152 | { | 3152 | { |
| 3153 | ptrdiff_t i, j; | 3153 | ptrdiff_t i, j; |
| 3154 | struct sortvec *sortvec = alloca (noverlays * sizeof *sortvec); | 3154 | USE_SAFE_ALLOCA; |
| 3155 | struct sortvec *sortvec; | ||
| 3156 | |||
| 3157 | SAFE_NALLOCA (sortvec, 1, noverlays); | ||
| 3155 | 3158 | ||
| 3156 | /* Put the valid and relevant overlays into sortvec. */ | 3159 | /* Put the valid and relevant overlays into sortvec. */ |
| 3157 | 3160 | ||
| @@ -3197,6 +3200,8 @@ sort_overlays (Lisp_Object *overlay_vec, ptrdiff_t noverlays, struct window *w) | |||
| 3197 | 3200 | ||
| 3198 | for (i = 0; i < noverlays; i++) | 3201 | for (i = 0; i < noverlays; i++) |
| 3199 | overlay_vec[i] = sortvec[i].overlay; | 3202 | overlay_vec[i] = sortvec[i].overlay; |
| 3203 | |||
| 3204 | SAFE_FREE (); | ||
| 3200 | return (noverlays); | 3205 | return (noverlays); |
| 3201 | } | 3206 | } |
| 3202 | 3207 | ||
diff --git a/src/editfns.c b/src/editfns.c index 197950517b7..020285cf4ec 100644 --- a/src/editfns.c +++ b/src/editfns.c | |||
| @@ -386,6 +386,7 @@ get_pos_property (Lisp_Object position, register Lisp_Object prop, Lisp_Object o | |||
| 386 | ptrdiff_t noverlays; | 386 | ptrdiff_t noverlays; |
| 387 | Lisp_Object *overlay_vec, tem; | 387 | Lisp_Object *overlay_vec, tem; |
| 388 | struct buffer *obuf = current_buffer; | 388 | struct buffer *obuf = current_buffer; |
| 389 | USE_SAFE_ALLOCA; | ||
| 389 | 390 | ||
| 390 | set_buffer_temp (XBUFFER (object)); | 391 | set_buffer_temp (XBUFFER (object)); |
| 391 | 392 | ||
| @@ -398,7 +399,7 @@ get_pos_property (Lisp_Object position, register Lisp_Object prop, Lisp_Object o | |||
| 398 | make enough space for all, and try again. */ | 399 | make enough space for all, and try again. */ |
| 399 | if (noverlays > 40) | 400 | if (noverlays > 40) |
| 400 | { | 401 | { |
| 401 | overlay_vec = alloca (noverlays * sizeof *overlay_vec); | 402 | SAFE_ALLOCA_LISP (overlay_vec, noverlays); |
| 402 | noverlays = overlays_around (posn, overlay_vec, noverlays); | 403 | noverlays = overlays_around (posn, overlay_vec, noverlays); |
| 403 | } | 404 | } |
| 404 | noverlays = sort_overlays (overlay_vec, noverlays, NULL); | 405 | noverlays = sort_overlays (overlay_vec, noverlays, NULL); |
| @@ -421,10 +422,12 @@ get_pos_property (Lisp_Object position, register Lisp_Object prop, Lisp_Object o | |||
| 421 | ; /* The overlay will not cover a char inserted at point. */ | 422 | ; /* The overlay will not cover a char inserted at point. */ |
| 422 | else | 423 | else |
| 423 | { | 424 | { |
| 425 | SAFE_FREE (); | ||
| 424 | return tem; | 426 | return tem; |
| 425 | } | 427 | } |
| 426 | } | 428 | } |
| 427 | } | 429 | } |
| 430 | SAFE_FREE (); | ||
| 428 | 431 | ||
| 429 | { /* Now check the text properties. */ | 432 | { /* Now check the text properties. */ |
| 430 | int stickiness = text_property_stickiness (prop, position, object); | 433 | int stickiness = text_property_stickiness (prop, position, object); |
diff --git a/src/emacs.c b/src/emacs.c index d1eeb97980a..564084ec610 100644 --- a/src/emacs.c +++ b/src/emacs.c | |||
| @@ -136,7 +136,7 @@ Lisp_Object Qfile_name_handler_alist; | |||
| 136 | 136 | ||
| 137 | Lisp_Object Qrisky_local_variable; | 137 | Lisp_Object Qrisky_local_variable; |
| 138 | 138 | ||
| 139 | Lisp_Object Qkill_emacs; | 139 | Lisp_Object Qkill_emacs, Qkill_emacs_hook; |
| 140 | 140 | ||
| 141 | /* If true, Emacs should not attempt to use a window-specific code, | 141 | /* If true, Emacs should not attempt to use a window-specific code, |
| 142 | but instead should use the virtual terminal under which it was started. */ | 142 | but instead should use the virtual terminal under which it was started. */ |
| @@ -1320,6 +1320,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem | |||
| 1320 | } | 1320 | } |
| 1321 | 1321 | ||
| 1322 | init_callproc (); /* Must follow init_cmdargs but not init_sys_modes. */ | 1322 | init_callproc (); /* Must follow init_cmdargs but not init_sys_modes. */ |
| 1323 | init_fileio (); | ||
| 1323 | init_lread (); | 1324 | init_lread (); |
| 1324 | #ifdef WINDOWSNT | 1325 | #ifdef WINDOWSNT |
| 1325 | /* Check to see if Emacs has been installed correctly. */ | 1326 | /* Check to see if Emacs has been installed correctly. */ |
| @@ -1846,7 +1847,6 @@ all of which are called before Emacs is actually killed. */) | |||
| 1846 | (Lisp_Object arg) | 1847 | (Lisp_Object arg) |
| 1847 | { | 1848 | { |
| 1848 | struct gcpro gcpro1; | 1849 | struct gcpro gcpro1; |
| 1849 | Lisp_Object hook; | ||
| 1850 | int exit_code; | 1850 | int exit_code; |
| 1851 | 1851 | ||
| 1852 | GCPRO1 (arg); | 1852 | GCPRO1 (arg); |
| @@ -1854,9 +1854,10 @@ all of which are called before Emacs is actually killed. */) | |||
| 1854 | if (feof (stdin)) | 1854 | if (feof (stdin)) |
| 1855 | arg = Qt; | 1855 | arg = Qt; |
| 1856 | 1856 | ||
| 1857 | hook = intern ("kill-emacs-hook"); | 1857 | /* Fsignal calls emacs_abort () if it sees that waiting_for_input is |
| 1858 | Frun_hooks (1, &hook); | 1858 | set. */ |
| 1859 | 1859 | waiting_for_input = 0; | |
| 1860 | Frun_hooks (1, &Qkill_emacs_hook); | ||
| 1860 | UNGCPRO; | 1861 | UNGCPRO; |
| 1861 | 1862 | ||
| 1862 | #ifdef HAVE_X_WINDOWS | 1863 | #ifdef HAVE_X_WINDOWS |
| @@ -2268,6 +2269,7 @@ syms_of_emacs (void) | |||
| 2268 | DEFSYM (Qfile_name_handler_alist, "file-name-handler-alist"); | 2269 | DEFSYM (Qfile_name_handler_alist, "file-name-handler-alist"); |
| 2269 | DEFSYM (Qrisky_local_variable, "risky-local-variable"); | 2270 | DEFSYM (Qrisky_local_variable, "risky-local-variable"); |
| 2270 | DEFSYM (Qkill_emacs, "kill-emacs"); | 2271 | DEFSYM (Qkill_emacs, "kill-emacs"); |
| 2272 | DEFSYM (Qkill_emacs_hook, "kill-emacs-hook"); | ||
| 2271 | 2273 | ||
| 2272 | #ifndef CANNOT_DUMP | 2274 | #ifndef CANNOT_DUMP |
| 2273 | defsubr (&Sdump_emacs); | 2275 | defsubr (&Sdump_emacs); |
diff --git a/src/fileio.c b/src/fileio.c index 4c54fd822ae..51f966787b9 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -103,6 +103,11 @@ static mode_t auto_save_mode_bits; | |||
| 103 | /* Set by auto_save_1 if an error occurred during the last auto-save. */ | 103 | /* Set by auto_save_1 if an error occurred during the last auto-save. */ |
| 104 | static bool auto_save_error_occurred; | 104 | static bool auto_save_error_occurred; |
| 105 | 105 | ||
| 106 | /* If VALID_TIMESTAMP_FILE_SYSTEM, then TIMESTAMP_FILE_SYSTEM is the device | ||
| 107 | number of a file system where time stamps were observed to to work. */ | ||
| 108 | static bool valid_timestamp_file_system; | ||
| 109 | static dev_t timestamp_file_system; | ||
| 110 | |||
| 106 | /* The symbol bound to coding-system-for-read when | 111 | /* The symbol bound to coding-system-for-read when |
| 107 | insert-file-contents is called for recovering a file. This is not | 112 | insert-file-contents is called for recovering a file. This is not |
| 108 | an actual coding system name, but just an indicator to tell | 113 | an actual coding system name, but just an indicator to tell |
| @@ -3438,19 +3443,25 @@ read_contents_quit (Lisp_Object ignore) | |||
| 3438 | return Qnil; | 3443 | return Qnil; |
| 3439 | } | 3444 | } |
| 3440 | 3445 | ||
| 3441 | /* Reposition FD to OFFSET, based on WHENCE. This acts like lseek | 3446 | /* Return the file offset that VAL represents, checking for type |
| 3442 | except that it also tests for OFFSET being out of lseek's range. */ | 3447 | errors and overflow. */ |
| 3443 | static off_t | 3448 | static off_t |
| 3444 | emacs_lseek (int fd, EMACS_INT offset, int whence) | 3449 | file_offset (Lisp_Object val) |
| 3445 | { | 3450 | { |
| 3446 | /* Use "&" rather than "&&" to suppress a bogus GCC warning; see | 3451 | if (RANGED_INTEGERP (0, val, TYPE_MAXIMUM (off_t))) |
| 3447 | <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43772>. */ | 3452 | return XINT (val); |
| 3448 | if (! ((offset >= TYPE_MINIMUM (off_t)) & (offset <= TYPE_MAXIMUM (off_t)))) | 3453 | |
| 3454 | if (FLOATP (val)) | ||
| 3449 | { | 3455 | { |
| 3450 | errno = EINVAL; | 3456 | double v = XFLOAT_DATA (val); |
| 3451 | return -1; | 3457 | if (0 <= v |
| 3458 | && (sizeof (off_t) < sizeof v | ||
| 3459 | ? v <= TYPE_MAXIMUM (off_t) | ||
| 3460 | : v < TYPE_MAXIMUM (off_t))) | ||
| 3461 | return v; | ||
| 3452 | } | 3462 | } |
| 3453 | return lseek (fd, offset, whence); | 3463 | |
| 3464 | wrong_type_argument (intern ("file-offset"), val); | ||
| 3454 | } | 3465 | } |
| 3455 | 3466 | ||
| 3456 | /* Return a special time value indicating the error number ERRNUM. */ | 3467 | /* Return a special time value indicating the error number ERRNUM. */ |
| @@ -3574,8 +3585,7 @@ by calling `format-decode', which see. */) | |||
| 3574 | record_unwind_protect (close_file_unwind, make_number (fd)); | 3585 | record_unwind_protect (close_file_unwind, make_number (fd)); |
| 3575 | 3586 | ||
| 3576 | if (fstat (fd, &st) != 0) | 3587 | if (fstat (fd, &st) != 0) |
| 3577 | report_file_error ("Getting input file status", | 3588 | report_file_error ("Input file status", Fcons (orig_filename, Qnil)); |
| 3578 | Fcons (orig_filename, Qnil)); | ||
| 3579 | mtime = get_stat_mtime (&st); | 3589 | mtime = get_stat_mtime (&st); |
| 3580 | 3590 | ||
| 3581 | /* This code will need to be changed in order to work on named | 3591 | /* This code will need to be changed in order to work on named |
| @@ -3602,20 +3612,12 @@ by calling `format-decode', which see. */) | |||
| 3602 | } | 3612 | } |
| 3603 | 3613 | ||
| 3604 | if (!NILP (beg)) | 3614 | if (!NILP (beg)) |
| 3605 | { | 3615 | beg_offset = file_offset (beg); |
| 3606 | if (! RANGED_INTEGERP (0, beg, TYPE_MAXIMUM (off_t))) | ||
| 3607 | wrong_type_argument (intern ("file-offset"), beg); | ||
| 3608 | beg_offset = XFASTINT (beg); | ||
| 3609 | } | ||
| 3610 | else | 3616 | else |
| 3611 | beg_offset = 0; | 3617 | beg_offset = 0; |
| 3612 | 3618 | ||
| 3613 | if (!NILP (end)) | 3619 | if (!NILP (end)) |
| 3614 | { | 3620 | end_offset = file_offset (end); |
| 3615 | if (! RANGED_INTEGERP (0, end, TYPE_MAXIMUM (off_t))) | ||
| 3616 | wrong_type_argument (intern ("file-offset"), end); | ||
| 3617 | end_offset = XFASTINT (end); | ||
| 3618 | } | ||
| 3619 | else | 3621 | else |
| 3620 | { | 3622 | { |
| 3621 | if (not_regular) | 3623 | if (not_regular) |
| @@ -4710,7 +4712,7 @@ If START is a string, then output that string to the file | |||
| 4710 | instead of any buffer contents; END is ignored. | 4712 | instead of any buffer contents; END is ignored. |
| 4711 | 4713 | ||
| 4712 | Optional fourth argument APPEND if non-nil means | 4714 | Optional fourth argument APPEND if non-nil means |
| 4713 | append to existing file contents (if any). If it is an integer, | 4715 | append to existing file contents (if any). If it is a number, |
| 4714 | seek to that offset in the file before writing. | 4716 | seek to that offset in the file before writing. |
| 4715 | Optional fifth argument VISIT, if t or a string, means | 4717 | Optional fifth argument VISIT, if t or a string, means |
| 4716 | set the last-save-file-modtime of buffer to this file's modtime | 4718 | set the last-save-file-modtime of buffer to this file's modtime |
| @@ -4739,6 +4741,9 @@ This calls `write-region-annotate-functions' at the start, and | |||
| 4739 | (Lisp_Object start, Lisp_Object end, Lisp_Object filename, Lisp_Object append, Lisp_Object visit, Lisp_Object lockname, Lisp_Object mustbenew) | 4741 | (Lisp_Object start, Lisp_Object end, Lisp_Object filename, Lisp_Object append, Lisp_Object visit, Lisp_Object lockname, Lisp_Object mustbenew) |
| 4740 | { | 4742 | { |
| 4741 | int desc; | 4743 | int desc; |
| 4744 | int open_flags; | ||
| 4745 | int mode; | ||
| 4746 | off_t offset IF_LINT (= 0); | ||
| 4742 | bool ok; | 4747 | bool ok; |
| 4743 | int save_errno = 0; | 4748 | int save_errno = 0; |
| 4744 | const char *fn; | 4749 | const char *fn; |
| @@ -4858,27 +4863,20 @@ This calls `write-region-annotate-functions' at the start, and | |||
| 4858 | #endif /* CLASH_DETECTION */ | 4863 | #endif /* CLASH_DETECTION */ |
| 4859 | 4864 | ||
| 4860 | encoded_filename = ENCODE_FILE (filename); | 4865 | encoded_filename = ENCODE_FILE (filename); |
| 4861 | |||
| 4862 | fn = SSDATA (encoded_filename); | 4866 | fn = SSDATA (encoded_filename); |
| 4863 | desc = -1; | 4867 | open_flags = O_WRONLY | O_BINARY | O_CREAT; |
| 4864 | if (!NILP (append)) | 4868 | open_flags |= EQ (mustbenew, Qexcl) ? O_EXCL : !NILP (append) ? 0 : O_TRUNC; |
| 4869 | if (NUMBERP (append)) | ||
| 4870 | offset = file_offset (append); | ||
| 4871 | else if (!NILP (append)) | ||
| 4872 | open_flags |= O_APPEND; | ||
| 4865 | #ifdef DOS_NT | 4873 | #ifdef DOS_NT |
| 4866 | desc = emacs_open (fn, O_WRONLY | O_BINARY, 0); | 4874 | mode = S_IREAD | S_IWRITE; |
| 4867 | #else /* not DOS_NT */ | 4875 | #else |
| 4868 | desc = emacs_open (fn, O_WRONLY, 0); | 4876 | mode = auto_saving ? auto_save_mode_bits : 0666; |
| 4869 | #endif /* not DOS_NT */ | 4877 | #endif |
| 4870 | 4878 | ||
| 4871 | if (desc < 0 && (NILP (append) || errno == ENOENT)) | 4879 | desc = emacs_open (fn, open_flags, mode); |
| 4872 | #ifdef DOS_NT | ||
| 4873 | desc = emacs_open (fn, | ||
| 4874 | O_WRONLY | O_CREAT | O_BINARY | ||
| 4875 | | (EQ (mustbenew, Qexcl) ? O_EXCL : O_TRUNC), | ||
| 4876 | S_IREAD | S_IWRITE); | ||
| 4877 | #else /* not DOS_NT */ | ||
| 4878 | desc = emacs_open (fn, O_WRONLY | O_TRUNC | O_CREAT | ||
| 4879 | | (EQ (mustbenew, Qexcl) ? O_EXCL : 0), | ||
| 4880 | auto_saving ? auto_save_mode_bits : 0666); | ||
| 4881 | #endif /* not DOS_NT */ | ||
| 4882 | 4880 | ||
| 4883 | if (desc < 0) | 4881 | if (desc < 0) |
| 4884 | { | 4882 | { |
| @@ -4893,14 +4891,9 @@ This calls `write-region-annotate-functions' at the start, and | |||
| 4893 | 4891 | ||
| 4894 | record_unwind_protect (close_file_unwind, make_number (desc)); | 4892 | record_unwind_protect (close_file_unwind, make_number (desc)); |
| 4895 | 4893 | ||
| 4896 | if (!NILP (append) && !NILP (Ffile_regular_p (filename))) | 4894 | if (NUMBERP (append)) |
| 4897 | { | 4895 | { |
| 4898 | off_t ret; | 4896 | off_t ret = lseek (desc, offset, SEEK_SET); |
| 4899 | |||
| 4900 | if (NUMBERP (append)) | ||
| 4901 | ret = emacs_lseek (desc, XINT (append), SEEK_CUR); | ||
| 4902 | else | ||
| 4903 | ret = lseek (desc, 0, SEEK_END); | ||
| 4904 | if (ret < 0) | 4897 | if (ret < 0) |
| 4905 | { | 4898 | { |
| 4906 | #ifdef CLASH_DETECTION | 4899 | #ifdef CLASH_DETECTION |
| @@ -4972,6 +4965,48 @@ This calls `write-region-annotate-functions' at the start, and | |||
| 4972 | /* Discard the unwind protect for close_file_unwind. */ | 4965 | /* Discard the unwind protect for close_file_unwind. */ |
| 4973 | specpdl_ptr = specpdl + count1; | 4966 | specpdl_ptr = specpdl + count1; |
| 4974 | 4967 | ||
| 4968 | /* Some file systems have a bug where st_mtime is not updated | ||
| 4969 | properly after a write. For example, CIFS might not see the | ||
| 4970 | st_mtime change until after the file is opened again. | ||
| 4971 | |||
| 4972 | Attempt to detect this file system bug, and update MODTIME to the | ||
| 4973 | newer st_mtime if the bug appears to be present. This introduces | ||
| 4974 | a race condition, so to avoid most instances of the race condition | ||
| 4975 | on non-buggy file systems, skip this check if the most recently | ||
| 4976 | encountered non-buggy file system was the current file system. | ||
| 4977 | |||
| 4978 | A race condition can occur if some other process modifies the | ||
| 4979 | file between the fstat above and the fstat below, but the race is | ||
| 4980 | unlikely and a similar race between the last write and the fstat | ||
| 4981 | above cannot possibly be closed anyway. */ | ||
| 4982 | |||
| 4983 | if (EMACS_TIME_VALID_P (modtime) | ||
| 4984 | && ! (valid_timestamp_file_system && st.st_dev == timestamp_file_system)) | ||
| 4985 | { | ||
| 4986 | int desc1 = emacs_open (fn, O_WRONLY | O_BINARY, 0); | ||
| 4987 | if (0 <= desc1) | ||
| 4988 | { | ||
| 4989 | struct stat st1; | ||
| 4990 | if (fstat (desc1, &st1) == 0 | ||
| 4991 | && st.st_dev == st1.st_dev && st.st_ino == st1.st_ino) | ||
| 4992 | { | ||
| 4993 | EMACS_TIME modtime1 = get_stat_mtime (&st1); | ||
| 4994 | if (EMACS_TIME_EQ (modtime, modtime1) | ||
| 4995 | && st.st_size == st1.st_size) | ||
| 4996 | { | ||
| 4997 | timestamp_file_system = st.st_dev; | ||
| 4998 | valid_timestamp_file_system = 1; | ||
| 4999 | } | ||
| 5000 | else | ||
| 5001 | { | ||
| 5002 | st.st_size = st1.st_size; | ||
| 5003 | modtime = modtime1; | ||
| 5004 | } | ||
| 5005 | } | ||
| 5006 | emacs_close (desc1); | ||
| 5007 | } | ||
| 5008 | } | ||
| 5009 | |||
| 4975 | /* Call write-region-post-annotation-function. */ | 5010 | /* Call write-region-post-annotation-function. */ |
| 4976 | while (CONSP (Vwrite_region_annotation_buffers)) | 5011 | while (CONSP (Vwrite_region_annotation_buffers)) |
| 4977 | { | 5012 | { |
| @@ -5024,7 +5059,7 @@ This calls `write-region-annotate-functions' at the start, and | |||
| 5024 | } | 5059 | } |
| 5025 | 5060 | ||
| 5026 | if (!auto_saving) | 5061 | if (!auto_saving) |
| 5027 | message_with_string ((INTEGERP (append) | 5062 | message_with_string ((NUMBERP (append) |
| 5028 | ? "Updated %s" | 5063 | ? "Updated %s" |
| 5029 | : ! NILP (append) | 5064 | : ! NILP (append) |
| 5030 | ? "Added to %s" | 5065 | ? "Added to %s" |
| @@ -5769,6 +5804,12 @@ Fread_file_name (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filena | |||
| 5769 | 5804 | ||
| 5770 | 5805 | ||
| 5771 | void | 5806 | void |
| 5807 | init_fileio (void) | ||
| 5808 | { | ||
| 5809 | valid_timestamp_file_system = 0; | ||
| 5810 | } | ||
| 5811 | |||
| 5812 | void | ||
| 5772 | syms_of_fileio (void) | 5813 | syms_of_fileio (void) |
| 5773 | { | 5814 | { |
| 5774 | DEFSYM (Qoperations, "operations"); | 5815 | DEFSYM (Qoperations, "operations"); |
| @@ -66,7 +66,10 @@ and `most-positive-fixnum', inclusive, are equally likely. | |||
| 66 | 66 | ||
| 67 | With positive integer LIMIT, return random number in interval [0,LIMIT). | 67 | With positive integer LIMIT, return random number in interval [0,LIMIT). |
| 68 | With argument t, set the random number seed from the current time and pid. | 68 | With argument t, set the random number seed from the current time and pid. |
| 69 | Other values of LIMIT are ignored. */) | 69 | With a string argument, set the seed based on the string's contents. |
| 70 | Other values of LIMIT are ignored. | ||
| 71 | |||
| 72 | See Info node `(elisp)Random Numbers' for more details. */) | ||
| 70 | (Lisp_Object limit) | 73 | (Lisp_Object limit) |
| 71 | { | 74 | { |
| 72 | EMACS_INT val; | 75 | EMACS_INT val; |
diff --git a/src/lisp.h b/src/lisp.h index cf4dd22e364..ca5fa6c3454 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -3304,6 +3304,7 @@ extern _Noreturn void report_file_error (const char *, Lisp_Object); | |||
| 3304 | extern bool internal_delete_file (Lisp_Object); | 3304 | extern bool internal_delete_file (Lisp_Object); |
| 3305 | extern bool file_directory_p (const char *); | 3305 | extern bool file_directory_p (const char *); |
| 3306 | extern bool file_accessible_directory_p (const char *); | 3306 | extern bool file_accessible_directory_p (const char *); |
| 3307 | extern void init_fileio (void); | ||
| 3307 | extern void syms_of_fileio (void); | 3308 | extern void syms_of_fileio (void); |
| 3308 | extern Lisp_Object make_temp_name (Lisp_Object, bool); | 3309 | extern Lisp_Object make_temp_name (Lisp_Object, bool); |
| 3309 | extern Lisp_Object Qdelete_file; | 3310 | extern Lisp_Object Qdelete_file; |
| @@ -3715,12 +3716,11 @@ extern char *egetenv (const char *); | |||
| 3715 | /* Set up the name of the machine we're running on. */ | 3716 | /* Set up the name of the machine we're running on. */ |
| 3716 | extern void init_system_name (void); | 3717 | extern void init_system_name (void); |
| 3717 | 3718 | ||
| 3718 | /* We used to use `abs', but that clashes with system headers on some | 3719 | /* Return the absolute value of X. X should be a signed integer |
| 3719 | platforms, and using a name reserved by Standard C is a bad idea | 3720 | expression without side effects, and X's absolute value should not |
| 3720 | anyway. */ | 3721 | exceed the maximum for its promoted type. This is called 'eabs' |
| 3721 | #if !defined (eabs) | 3722 | because 'abs' is reserved by the C standard. */ |
| 3722 | #define eabs(x) ((x) < 0 ? -(x) : (x)) | 3723 | #define eabs(x) ((x) < 0 ? -(x) : (x)) |
| 3723 | #endif | ||
| 3724 | 3724 | ||
| 3725 | /* Return a fixnum or float, depending on whether VAL fits in a Lisp | 3725 | /* Return a fixnum or float, depending on whether VAL fits in a Lisp |
| 3726 | fixnum. */ | 3726 | fixnum. */ |
| @@ -4164,13 +4164,23 @@ fstat (int desc, struct stat * buf) | |||
| 4164 | else | 4164 | else |
| 4165 | buf->st_ino = fake_inode; | 4165 | buf->st_ino = fake_inode; |
| 4166 | 4166 | ||
| 4167 | /* Consider files to belong to current user. | 4167 | /* If the caller so requested, get the true file owner and group. |
| 4168 | FIXME: this should use GetSecurityInfo API, but it is only | 4168 | Otherwise, consider the file to belong to the current user. */ |
| 4169 | available for _WIN32_WINNT >= 0x501. */ | 4169 | if (!w32_stat_get_owner_group || is_windows_9x () == TRUE) |
| 4170 | buf->st_uid = dflt_passwd.pw_uid; | 4170 | get_file_owner_and_group (NULL, buf); |
| 4171 | buf->st_gid = dflt_passwd.pw_gid; | 4171 | else |
| 4172 | strcpy (buf->st_uname, dflt_passwd.pw_name); | 4172 | { |
| 4173 | strcpy (buf->st_gname, dflt_group.gr_name); | 4173 | PSECURITY_DESCRIPTOR psd = NULL; |
| 4174 | |||
| 4175 | psd = get_file_security_desc_by_handle (fh); | ||
| 4176 | if (psd) | ||
| 4177 | { | ||
| 4178 | get_file_owner_and_group (psd, buf); | ||
| 4179 | LocalFree (psd); | ||
| 4180 | } | ||
| 4181 | else | ||
| 4182 | get_file_owner_and_group (NULL, buf); | ||
| 4183 | } | ||
| 4174 | 4184 | ||
| 4175 | buf->st_dev = info.dwVolumeSerialNumber; | 4185 | buf->st_dev = info.dwVolumeSerialNumber; |
| 4176 | buf->st_rdev = info.dwVolumeSerialNumber; | 4186 | buf->st_rdev = info.dwVolumeSerialNumber; |
| @@ -4875,7 +4885,8 @@ acl_set_file (const char *fname, acl_type_t type, acl_t acl) | |||
| 4875 | retval = 0; | 4885 | retval = 0; |
| 4876 | errno = e; | 4886 | errno = e; |
| 4877 | } | 4887 | } |
| 4878 | else if (err == ERROR_INVALID_OWNER || err == ERROR_NOT_ALL_ASSIGNED) | 4888 | else if (err == ERROR_INVALID_OWNER || err == ERROR_NOT_ALL_ASSIGNED |
| 4889 | || err == ERROR_ACCESS_DENIED) | ||
| 4879 | { | 4890 | { |
| 4880 | /* Maybe the requested ACL and the one the file already has are | 4891 | /* Maybe the requested ACL and the one the file already has are |
| 4881 | identical, in which case we can silently ignore the | 4892 | identical, in which case we can silently ignore the |