diff options
| author | Eli Zaretskii | 2013-02-25 19:36:03 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2013-02-25 19:36:03 +0200 |
| commit | 343a2aefb528ce3c978ba2145705b9e37bfbe02a (patch) | |
| tree | 4672030eea98dfc9bd077ac58400271d1c812918 | |
| parent | aec32f66d0db82b562e904dfe7bb6d54796fe773 (diff) | |
| download | emacs-343a2aefb528ce3c978ba2145705b9e37bfbe02a.tar.gz emacs-343a2aefb528ce3c978ba2145705b9e37bfbe02a.zip | |
Implement CLASH_DETECTION for MS-Windows.
src/filelock.c [WINDOWSNT]: Include w32.h.
(MAKE_LOCK_NAME): Don't use 'lock', it clashes with MS runtime
function of that name. Up-case the macro arguments.
(IS_LOCK_FILE): New macro.
(fill_in_lock_file_name): Use IS_LOCK_FILE instead of S_ISLNK.
(create_lock_file): New function, with body extracted from
lock_file_1.
[WINDOWSNT]: Implement lock files by writing a regular file with
the lock information as its contents.
(read_lock_data): New function, on Posix platforms just calls
emacs_readlinkat.
[WINDOWSNT]: Read the lock info from the file.
(current_lock_owner): Call read_lock_data instead of calling
emacs_readlinkat directly.
(lock_file) [WINDOWSNT]: Run the file name through
dostounix_filename.
src/w32proc.c (sys_kill): Support the case of SIG = 0, in which case
just check if the process by that PID exists.
src/w32.c (sys_open): Don't reset the _O_CREAT flag if _O_EXCL is
also present, as doing so will fail to error out if the file
already exists.
src/makefile.w32-in ($(BLD)/filelock.$(O)): Depend on src/w32.h.
nt/inc/ms-w32.h (BOOT_TIME_FILE): Define.
nt/config.nt (CLASH_DETECTION): Define to 1.
lisp/emacs-lisp/bytecomp.el (byte-recompile-directory): Reject files
that match "\`\.#", to avoid compiling lock files, even if they
are readable (as they are on MS-Windows).
doc/emacs/files.texi (Interlocking): Don't refer to symlinks as the
exclusive means of locking files.
etc/NEWS: Mention support for lock files on MS-Windows.
| -rw-r--r-- | doc/emacs/ChangeLog | 5 | ||||
| -rw-r--r-- | doc/emacs/files.texi | 24 | ||||
| -rw-r--r-- | etc/NEWS | 7 | ||||
| -rw-r--r-- | lisp/ChangeLog | 6 | ||||
| -rw-r--r-- | lisp/emacs-lisp/bytecomp.el | 2 | ||||
| -rw-r--r-- | nt/ChangeLog | 6 | ||||
| -rw-r--r-- | nt/config.nt | 2 | ||||
| -rw-r--r-- | nt/inc/ms-w32.h | 12 | ||||
| -rw-r--r-- | src/ChangeLog | 28 | ||||
| -rw-r--r-- | src/filelock.c | 113 | ||||
| -rw-r--r-- | src/makefile.w32-in | 1 | ||||
| -rw-r--r-- | src/w32.c | 11 | ||||
| -rw-r--r-- | src/w32proc.c | 32 |
13 files changed, 215 insertions, 34 deletions
diff --git a/doc/emacs/ChangeLog b/doc/emacs/ChangeLog index 33f530cbadc..44245441791 100644 --- a/doc/emacs/ChangeLog +++ b/doc/emacs/ChangeLog | |||
| @@ -1,3 +1,8 @@ | |||
| 1 | 2013-02-25 Eli Zaretskii <eliz@gnu.org> | ||
| 2 | |||
| 3 | * files.texi (Interlocking): Don't refer to symlinks as the | ||
| 4 | exclusive means of locking files. | ||
| 5 | |||
| 1 | 2013-02-22 Glenn Morris <rgm@gnu.org> | 6 | 2013-02-22 Glenn Morris <rgm@gnu.org> |
| 2 | 7 | ||
| 3 | * ack.texi (Acknowledgments): | 8 | * ack.texi (Acknowledgments): |
diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi index 7f7ae483cd5..1f78747eaa6 100644 --- a/doc/emacs/files.texi +++ b/doc/emacs/files.texi | |||
| @@ -734,10 +734,10 @@ file. | |||
| 734 | @cindex locking files | 734 | @cindex locking files |
| 735 | When you make the first modification in an Emacs buffer that is | 735 | When you make the first modification in an Emacs buffer that is |
| 736 | visiting a file, Emacs records that the file is @dfn{locked} by you. | 736 | visiting a file, Emacs records that the file is @dfn{locked} by you. |
| 737 | (It does this by creating a specially-named symbolic link in the same | 737 | (It does this by creating a specially-named symbolic link or regular |
| 738 | directory.) Emacs removes the lock when you save the changes. The | 738 | file with special contents in the same directory.) Emacs removes the |
| 739 | idea is that the file is locked whenever an Emacs buffer visiting it | 739 | lock when you save the changes. The idea is that the file is locked |
| 740 | has unsaved changes. | 740 | whenever an Emacs buffer visiting it has unsaved changes. |
| 741 | 741 | ||
| 742 | @vindex create-lockfiles | 742 | @vindex create-lockfiles |
| 743 | You can prevent the creation of lock files by setting the variable | 743 | You can prevent the creation of lock files by setting the variable |
| @@ -774,14 +774,14 @@ multiple names, Emacs does not prevent two users from editing it | |||
| 774 | simultaneously under different names. | 774 | simultaneously under different names. |
| 775 | 775 | ||
| 776 | A lock file cannot be written in some circumstances, e.g., if Emacs | 776 | A lock file cannot be written in some circumstances, e.g., if Emacs |
| 777 | lacks the system permissions or the system does not support symbolic | 777 | lacks the system permissions or cannot create lock files for some |
| 778 | links. In these cases, Emacs can still detect the collision when you | 778 | other reason. In these cases, Emacs can still detect the collision |
| 779 | try to save a file, by checking the file's last-modification date. If | 779 | when you try to save a file, by checking the file's last-modification |
| 780 | the file has changed since the last time Emacs visited or saved it, | 780 | date. If the file has changed since the last time Emacs visited or |
| 781 | that implies that changes have been made in some other way, and will | 781 | saved it, that implies that changes have been made in some other way, |
| 782 | be lost if Emacs proceeds with saving. Emacs then displays a warning | 782 | and will be lost if Emacs proceeds with saving. Emacs then displays a |
| 783 | message and asks for confirmation before saving; answer @kbd{yes} to | 783 | warning message and asks for confirmation before saving; answer |
| 784 | save, and @kbd{no} or @kbd{C-g} cancel the save. | 784 | @kbd{yes} to save, and @kbd{no} or @kbd{C-g} cancel the save. |
| 785 | 785 | ||
| 786 | If you are notified that simultaneous editing has already taken | 786 | If you are notified that simultaneous editing has already taken |
| 787 | place, one way to compare the buffer to its file is the @kbd{M-x | 787 | place, one way to compare the buffer to its file is the @kbd{M-x |
| @@ -348,6 +348,13 @@ Setting it has no effect, and %t in the mode-line format is ignored. | |||
| 348 | Likewise, `file-name-buffer-file-type-alist' is now obsolete, and | 348 | Likewise, `file-name-buffer-file-type-alist' is now obsolete, and |
| 349 | modifying it has no effect. | 349 | modifying it has no effect. |
| 350 | 350 | ||
| 351 | --- | ||
| 352 | ** Lock files now work on MS-Windows. | ||
| 353 | This allows to avoid losing your edits if the same file is being | ||
| 354 | edited in another Emacs session or by another user. See the node | ||
| 355 | "Interlocking" in the Emacs User Manual for the details. To disable | ||
| 356 | file locking, customize `create-lockfiles' to nil. | ||
| 357 | |||
| 351 | ** Improved fullscreen support on Mac OS X. | 358 | ** Improved fullscreen support on Mac OS X. |
| 352 | Both native (>= OSX 10.7) and "old style" fullscreen are supported. | 359 | Both native (>= OSX 10.7) and "old style" fullscreen are supported. |
| 353 | Customize `ns-use-native-fullscreen' to change style. For >= 10.7 | 360 | Customize `ns-use-native-fullscreen' to change style. For >= 10.7 |
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 07c3df9e279..c8fb65e89e8 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,9 @@ | |||
| 1 | 2013-02-25 Eli Zaretskii <eliz@gnu.org> | ||
| 2 | |||
| 3 | * emacs-lisp/bytecomp.el (byte-recompile-directory): Reject files | ||
| 4 | that match "\`\.#", to avoid compiling lock files, even if they | ||
| 5 | are readable (as they are on MS-Windows). | ||
| 6 | |||
| 1 | 2013-02-25 Stefan Monnier <monnier@iro.umontreal.ca> | 7 | 2013-02-25 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 8 | ||
| 3 | * files.el (basic-save-buffer): Remove redundant directory-creation. | 9 | * files.el (basic-save-buffer): Remove redundant directory-creation. |
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index f5861550c9a..e0837033c74 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el | |||
| @@ -1594,7 +1594,9 @@ that already has a `.elc' file." | |||
| 1594 | (setq directories (nconc directories (list source)))) | 1594 | (setq directories (nconc directories (list source)))) |
| 1595 | ;; It is an ordinary file. Decide whether to compile it. | 1595 | ;; It is an ordinary file. Decide whether to compile it. |
| 1596 | (if (and (string-match emacs-lisp-file-regexp source) | 1596 | (if (and (string-match emacs-lisp-file-regexp source) |
| 1597 | ;; The next 2 tests avoid compiling lock files | ||
| 1597 | (file-readable-p source) | 1598 | (file-readable-p source) |
| 1599 | (not (string-match "\\`\\.#" file)) | ||
| 1598 | (not (auto-save-file-name-p source)) | 1600 | (not (auto-save-file-name-p source)) |
| 1599 | (not (string-equal dir-locals-file | 1601 | (not (string-equal dir-locals-file |
| 1600 | (file-name-nondirectory source)))) | 1602 | (file-name-nondirectory source)))) |
diff --git a/nt/ChangeLog b/nt/ChangeLog index a8bb8c74c91..fab143fcddc 100644 --- a/nt/ChangeLog +++ b/nt/ChangeLog | |||
| @@ -1,3 +1,9 @@ | |||
| 1 | 2013-02-25 Eli Zaretskii <eliz@gnu.org> | ||
| 2 | |||
| 3 | * inc/ms-w32.h (BOOT_TIME_FILE): Define. | ||
| 4 | |||
| 5 | * config.nt (CLASH_DETECTION): Define to 1. | ||
| 6 | |||
| 1 | 2013-02-16 Eli Zaretskii <eliz@gnu.org> | 7 | 2013-02-16 Eli Zaretskii <eliz@gnu.org> |
| 2 | 8 | ||
| 3 | * inc/ms-w32.h (__STDC__): Fiddle with value only for MSVC. | 9 | * inc/ms-w32.h (__STDC__): Fiddle with value only for MSVC. |
diff --git a/nt/config.nt b/nt/config.nt index 61e56174bb4..cc4e91d9af0 100644 --- a/nt/config.nt +++ b/nt/config.nt | |||
| @@ -75,7 +75,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 75 | /* Define if you want lock files to be written, so that Emacs can tell | 75 | /* Define if you want lock files to be written, so that Emacs can tell |
| 76 | instantly when you try to modify a file that someone else has modified in | 76 | instantly when you try to modify a file that someone else has modified in |
| 77 | his/her Emacs. */ | 77 | his/her Emacs. */ |
| 78 | #undef CLASH_DETECTION | 78 | #define CLASH_DETECTION 1 |
| 79 | 79 | ||
| 80 | /* Short copyright string for this version of Emacs. */ | 80 | /* Short copyright string for this version of Emacs. */ |
| 81 | #define COPYRIGHT "Copyright (C) 2013 Free Software Foundation, Inc." | 81 | #define COPYRIGHT "Copyright (C) 2013 Free Software Foundation, Inc." |
diff --git a/nt/inc/ms-w32.h b/nt/inc/ms-w32.h index 66f586a4f76..9473fbe3ca6 100644 --- a/nt/inc/ms-w32.h +++ b/nt/inc/ms-w32.h | |||
| @@ -70,6 +70,18 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 70 | #define HAVE___BUILTIN_UNWIND_INIT 1 | 70 | #define HAVE___BUILTIN_UNWIND_INIT 1 |
| 71 | #endif | 71 | #endif |
| 72 | 72 | ||
| 73 | /* This isn't perfect, as some systems might have the page file in | ||
| 74 | another place. Also, I suspect that the time stamp of that file | ||
| 75 | might also change when Windows enlarges the file due to | ||
| 76 | insufficient VM. Still, this seems to be the most reliable way; | ||
| 77 | the alternative (of using GetSystemTimes) won't work on laptops | ||
| 78 | that hibernate, because the system clock is stopped then. Other | ||
| 79 | possibility would be to run "net statistics workstation" and parse | ||
| 80 | the output, but that's gross. So this should do; if the file is | ||
| 81 | not there, the boot time will be returned as zero, and filelock.c | ||
| 82 | already handles that. */ | ||
| 83 | #define BOOT_TIME_FILE "C:/pagefile.sys" | ||
| 84 | |||
| 73 | /* ============================================================ */ | 85 | /* ============================================================ */ |
| 74 | 86 | ||
| 75 | /* Here, add any special hacks needed to make Emacs work on this | 87 | /* Here, add any special hacks needed to make Emacs work on this |
diff --git a/src/ChangeLog b/src/ChangeLog index dc9b97c3c03..135d4d48b41 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,5 +1,33 @@ | |||
| 1 | 2013-02-25 Eli Zaretskii <eliz@gnu.org> | 1 | 2013-02-25 Eli Zaretskii <eliz@gnu.org> |
| 2 | 2 | ||
| 3 | Implement CLASH_DETECTION for MS-Windows. | ||
| 4 | |||
| 5 | * filelock.c [WINDOWSNT]: Include w32.h. | ||
| 6 | (MAKE_LOCK_NAME): Don't use 'lock', it clashes with MS runtime | ||
| 7 | function of that name. Up-case the macro arguments. | ||
| 8 | (IS_LOCK_FILE): New macro. | ||
| 9 | (fill_in_lock_file_name): Use IS_LOCK_FILE instead of S_ISLNK. | ||
| 10 | (create_lock_file): New function, with body extracted from | ||
| 11 | lock_file_1. | ||
| 12 | [WINDOWSNT]: Implement lock files by writing a regular file with | ||
| 13 | the lock information as its contents. | ||
| 14 | (read_lock_data): New function, on Posix platforms just calls | ||
| 15 | emacs_readlinkat. | ||
| 16 | [WINDOWSNT]: Read the lock info from the file. | ||
| 17 | (current_lock_owner): Call read_lock_data instead of calling | ||
| 18 | emacs_readlinkat directly. | ||
| 19 | (lock_file) [WINDOWSNT]: Run the file name through | ||
| 20 | dostounix_filename. | ||
| 21 | |||
| 22 | * w32proc.c (sys_kill): Support the case of SIG = 0, in which case | ||
| 23 | just check if the process by that PID exists. | ||
| 24 | |||
| 25 | * w32.c (sys_open): Don't reset the _O_CREAT flag if _O_EXCL is | ||
| 26 | also present, as doing so will fail to error out if the file | ||
| 27 | already exists. | ||
| 28 | |||
| 29 | * makefile.w32-in ($(BLD)/filelock.$(O)): Depend on src/w32.h. | ||
| 30 | |||
| 3 | * textprop.c (Fadd_text_properties, Fremove_text_properties) | 31 | * textprop.c (Fadd_text_properties, Fremove_text_properties) |
| 4 | (Fremove_list_of_text_properties): Skip all of the intervals in | 32 | (Fremove_list_of_text_properties): Skip all of the intervals in |
| 5 | the region between START and END that already have resp. don't | 33 | the region between START and END that already have resp. don't |
diff --git a/src/filelock.c b/src/filelock.c index cd2cd2e53a2..4d556de2454 100644 --- a/src/filelock.c +++ b/src/filelock.c | |||
| @@ -43,6 +43,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 43 | #include "buffer.h" | 43 | #include "buffer.h" |
| 44 | #include "coding.h" | 44 | #include "coding.h" |
| 45 | #include "systime.h" | 45 | #include "systime.h" |
| 46 | #ifdef WINDOWSNT | ||
| 47 | #include "w32.h" /* for dostounix_filename */ | ||
| 48 | #endif | ||
| 46 | 49 | ||
| 47 | #ifdef CLASH_DETECTION | 50 | #ifdef CLASH_DETECTION |
| 48 | 51 | ||
| @@ -288,13 +291,22 @@ typedef struct | |||
| 288 | #define FREE_LOCK_INFO(i) do { xfree ((i).user); xfree ((i).host); } while (0) | 291 | #define FREE_LOCK_INFO(i) do { xfree ((i).user); xfree ((i).host); } while (0) |
| 289 | 292 | ||
| 290 | 293 | ||
| 291 | /* Write the name of the lock file for FN into LFNAME. Length will be | 294 | /* Write the name of the lock file for FNAME into LOCKNAME. Length |
| 292 | that of FN plus two more for the leading `.#' plus 1 for the | 295 | will be that of FN plus two more for the leading `.#' plus 1 for |
| 293 | trailing period plus one for the digit after it plus one for the | 296 | the trailing period plus one for the digit after it plus one for |
| 294 | null. */ | 297 | the null. */ |
| 295 | #define MAKE_LOCK_NAME(lock, file) \ | 298 | #define MAKE_LOCK_NAME(LOCKNAME, FNAME) \ |
| 296 | (lock = alloca (SBYTES (file) + 2 + 1 + 1 + 1), \ | 299 | (LOCKNAME = alloca (SBYTES (FNAME) + 2 + 1 + 1 + 1), \ |
| 297 | fill_in_lock_file_name (lock, (file))) | 300 | fill_in_lock_file_name (LOCKNAME, (FNAME))) |
| 301 | |||
| 302 | #ifdef WINDOWSNT | ||
| 303 | /* 256 chars for user, 1024 chars for host, 10 digits for each of 2 int's. */ | ||
| 304 | #define MAX_LFINFO (256 + 1024 + 10 + 10 + 2) | ||
| 305 | /* min size: .@PID */ | ||
| 306 | #define IS_LOCK_FILE(ST) (MAX_LFINFO >= (ST).st_size && (ST).st_size >= 3) | ||
| 307 | #else | ||
| 308 | #define IS_LOCK_FILE(ST) S_ISLNK ((ST).st_mode) | ||
| 309 | #endif | ||
| 298 | 310 | ||
| 299 | static void | 311 | static void |
| 300 | fill_in_lock_file_name (register char *lockfile, register Lisp_Object fn) | 312 | fill_in_lock_file_name (register char *lockfile, register Lisp_Object fn) |
| @@ -318,7 +330,7 @@ fill_in_lock_file_name (register char *lockfile, register Lisp_Object fn) | |||
| 318 | 330 | ||
| 319 | p = lockfile + length + 2; | 331 | p = lockfile + length + 2; |
| 320 | 332 | ||
| 321 | while (lstat (lockfile, &st) == 0 && !S_ISLNK (st.st_mode)) | 333 | while (lstat (lockfile, &st) == 0 && !IS_LOCK_FILE (st)) |
| 322 | { | 334 | { |
| 323 | if (count > 9) | 335 | if (count > 9) |
| 324 | { | 336 | { |
| @@ -329,6 +341,49 @@ fill_in_lock_file_name (register char *lockfile, register Lisp_Object fn) | |||
| 329 | } | 341 | } |
| 330 | } | 342 | } |
| 331 | 343 | ||
| 344 | static int | ||
| 345 | create_lock_file (char *lfname, char *lock_info_str, bool force) | ||
| 346 | { | ||
| 347 | int err; | ||
| 348 | |||
| 349 | #ifdef WINDOWSNT | ||
| 350 | /* Symlinks are supported only by latest versions of Windows, and | ||
| 351 | creating them is a privileged operation that often triggers UAC | ||
| 352 | elevation prompts. Therefore, instead of using symlinks, we | ||
| 353 | create a regular file with the lock info written as its | ||
| 354 | contents. */ | ||
| 355 | { | ||
| 356 | int fd = emacs_open (lfname, O_WRONLY | O_BINARY | O_CREAT | O_EXCL, | ||
| 357 | S_IREAD | S_IWRITE); | ||
| 358 | |||
| 359 | if (fd < 0 && errno == EEXIST && force) | ||
| 360 | fd = emacs_open (lfname, O_WRONLY | O_BINARY | O_TRUNC, | ||
| 361 | S_IREAD | S_IWRITE); | ||
| 362 | if (fd >= 0) | ||
| 363 | { | ||
| 364 | ssize_t lock_info_len = strlen (lock_info_str); | ||
| 365 | |||
| 366 | err = 0; | ||
| 367 | if (emacs_write (fd, lock_info_str, lock_info_len) != lock_info_len) | ||
| 368 | err = -1; | ||
| 369 | if (emacs_close (fd)) | ||
| 370 | err = -1; | ||
| 371 | } | ||
| 372 | else | ||
| 373 | err = -1; | ||
| 374 | } | ||
| 375 | #else | ||
| 376 | err = symlink (lock_info_str, lfname); | ||
| 377 | if (errno == EEXIST && force) | ||
| 378 | { | ||
| 379 | unlink (lfname); | ||
| 380 | err = symlink (lock_info_str, lfname); | ||
| 381 | } | ||
| 382 | #endif | ||
| 383 | |||
| 384 | return err; | ||
| 385 | } | ||
| 386 | |||
| 332 | /* Lock the lock file named LFNAME. | 387 | /* Lock the lock file named LFNAME. |
| 333 | If FORCE, do so even if it is already locked. | 388 | If FORCE, do so even if it is already locked. |
| 334 | Return true if successful. */ | 389 | Return true if successful. */ |
| @@ -355,13 +410,7 @@ lock_file_1 (char *lfname, bool force) | |||
| 355 | 410 | ||
| 356 | esprintf (lock_info_str, boot ? "%s@%s.%"pMd":%"pMd : "%s@%s.%"pMd, | 411 | esprintf (lock_info_str, boot ? "%s@%s.%"pMd":%"pMd : "%s@%s.%"pMd, |
| 357 | user_name, host_name, pid, boot); | 412 | user_name, host_name, pid, boot); |
| 358 | 413 | err = create_lock_file (lfname, lock_info_str, force); | |
| 359 | err = symlink (lock_info_str, lfname); | ||
| 360 | if (errno == EEXIST && force) | ||
| 361 | { | ||
| 362 | unlink (lfname); | ||
| 363 | err = symlink (lock_info_str, lfname); | ||
| 364 | } | ||
| 365 | 414 | ||
| 366 | symlink_errno = errno; | 415 | symlink_errno = errno; |
| 367 | SAFE_FREE (); | 416 | SAFE_FREE (); |
| @@ -377,6 +426,32 @@ within_one_second (time_t a, time_t b) | |||
| 377 | return (a - b >= -1 && a - b <= 1); | 426 | return (a - b >= -1 && a - b <= 1); |
| 378 | } | 427 | } |
| 379 | 428 | ||
| 429 | static Lisp_Object | ||
| 430 | read_lock_data (char *lfname) | ||
| 431 | { | ||
| 432 | #ifndef WINDOWSNT | ||
| 433 | return emacs_readlinkat (AT_FDCWD, lfname); | ||
| 434 | #else | ||
| 435 | int fd = emacs_open (lfname, O_RDONLY | O_BINARY, S_IREAD); | ||
| 436 | ssize_t nbytes; | ||
| 437 | char lfinfo[MAX_LFINFO + 1]; | ||
| 438 | |||
| 439 | if (fd < 0) | ||
| 440 | return Qnil; | ||
| 441 | |||
| 442 | nbytes = emacs_read (fd, lfinfo, MAX_LFINFO); | ||
| 443 | emacs_close (fd); | ||
| 444 | |||
| 445 | if (nbytes > 0) | ||
| 446 | { | ||
| 447 | lfinfo[nbytes] = '\0'; | ||
| 448 | return build_string (lfinfo); | ||
| 449 | } | ||
| 450 | else | ||
| 451 | return Qnil; | ||
| 452 | #endif | ||
| 453 | } | ||
| 454 | |||
| 380 | /* Return 0 if nobody owns the lock file LFNAME or the lock is obsolete, | 455 | /* Return 0 if nobody owns the lock file LFNAME or the lock is obsolete, |
| 381 | 1 if another process owns it (and set OWNER (if non-null) to info), | 456 | 1 if another process owns it (and set OWNER (if non-null) to info), |
| 382 | 2 if the current process owns it, | 457 | 2 if the current process owns it, |
| @@ -390,7 +465,7 @@ current_lock_owner (lock_info_type *owner, char *lfname) | |||
| 390 | lock_info_type local_owner; | 465 | lock_info_type local_owner; |
| 391 | intmax_t n; | 466 | intmax_t n; |
| 392 | char *at, *dot, *colon; | 467 | char *at, *dot, *colon; |
| 393 | Lisp_Object lfinfo_object = emacs_readlinkat (AT_FDCWD, lfname); | 468 | Lisp_Object lfinfo_object = read_lock_data (lfname); |
| 394 | char *lfinfo; | 469 | char *lfinfo; |
| 395 | struct gcpro gcpro1; | 470 | struct gcpro gcpro1; |
| 396 | 471 | ||
| @@ -552,6 +627,12 @@ lock_file (Lisp_Object fn) | |||
| 552 | orig_fn = fn; | 627 | orig_fn = fn; |
| 553 | GCPRO1 (fn); | 628 | GCPRO1 (fn); |
| 554 | fn = Fexpand_file_name (fn, Qnil); | 629 | fn = Fexpand_file_name (fn, Qnil); |
| 630 | #ifdef WINDOWSNT | ||
| 631 | /* Ensure we have only '/' separators, to avoid problems with | ||
| 632 | looking (inside fill_in_lock_file_name) for backslashes in file | ||
| 633 | names encoded by some DBCS codepage. */ | ||
| 634 | dostounix_filename (SSDATA (fn), 1); | ||
| 635 | #endif | ||
| 555 | encoded_fn = ENCODE_FILE (fn); | 636 | encoded_fn = ENCODE_FILE (fn); |
| 556 | 637 | ||
| 557 | /* Create the name of the lock-file for file fn */ | 638 | /* Create the name of the lock-file for file fn */ |
diff --git a/src/makefile.w32-in b/src/makefile.w32-in index d60331198db..93f12900dde 100644 --- a/src/makefile.w32-in +++ b/src/makefile.w32-in | |||
| @@ -864,6 +864,7 @@ $(BLD)/fileio.$(O) : \ | |||
| 864 | 864 | ||
| 865 | $(BLD)/filelock.$(O) : \ | 865 | $(BLD)/filelock.$(O) : \ |
| 866 | $(SRC)/filelock.c \ | 866 | $(SRC)/filelock.c \ |
| 867 | $(SRC)/w32.h \ | ||
| 867 | $(NT_INC)/pwd.h \ | 868 | $(NT_INC)/pwd.h \ |
| 868 | $(NT_INC)/sys/file.h \ | 869 | $(NT_INC)/sys/file.h \ |
| 869 | $(NT_INC)/sys/stat.h \ | 870 | $(NT_INC)/sys/stat.h \ |
| @@ -3402,10 +3402,13 @@ int | |||
| 3402 | sys_open (const char * path, int oflag, int mode) | 3402 | sys_open (const char * path, int oflag, int mode) |
| 3403 | { | 3403 | { |
| 3404 | const char* mpath = map_w32_filename (path, NULL); | 3404 | const char* mpath = map_w32_filename (path, NULL); |
| 3405 | /* Try to open file without _O_CREAT, to be able to write to hidden | 3405 | int res = -1; |
| 3406 | and system files. Force all file handles to be | 3406 | |
| 3407 | non-inheritable. */ | 3407 | /* If possible, try to open file without _O_CREAT, to be able to |
| 3408 | int res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode); | 3408 | write to existing hidden and system files. Force all file |
| 3409 | handles to be non-inheritable. */ | ||
| 3410 | if ((oflag & (_O_CREAT | _O_EXCL)) != (_O_CREAT | _O_EXCL)) | ||
| 3411 | res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode); | ||
| 3409 | if (res < 0) | 3412 | if (res < 0) |
| 3410 | res = _open (mpath, oflag | _O_NOINHERIT, mode); | 3413 | res = _open (mpath, oflag | _O_NOINHERIT, mode); |
| 3411 | if (res >= 0 && res < MAXDESC) | 3414 | if (res >= 0 && res < MAXDESC) |
diff --git a/src/w32proc.c b/src/w32proc.c index 961791a40ed..84589388cd7 100644 --- a/src/w32proc.c +++ b/src/w32proc.c | |||
| @@ -2263,12 +2263,42 @@ sys_kill (pid_t pid, int sig) | |||
| 2263 | pid = -pid; | 2263 | pid = -pid; |
| 2264 | 2264 | ||
| 2265 | /* Only handle signals that will result in the process dying */ | 2265 | /* Only handle signals that will result in the process dying */ |
| 2266 | if (sig != SIGINT && sig != SIGKILL && sig != SIGQUIT && sig != SIGHUP) | 2266 | if (sig != 0 |
| 2267 | && sig != SIGINT && sig != SIGKILL && sig != SIGQUIT && sig != SIGHUP) | ||
| 2267 | { | 2268 | { |
| 2268 | errno = EINVAL; | 2269 | errno = EINVAL; |
| 2269 | return -1; | 2270 | return -1; |
| 2270 | } | 2271 | } |
| 2271 | 2272 | ||
| 2273 | if (sig == 0) | ||
| 2274 | { | ||
| 2275 | /* It will take _some_ time before PID 4 or less on Windows will | ||
| 2276 | be Emacs... */ | ||
| 2277 | if (pid <= 4) | ||
| 2278 | { | ||
| 2279 | errno = EPERM; | ||
| 2280 | return -1; | ||
| 2281 | } | ||
| 2282 | proc_hand = OpenProcess (PROCESS_QUERY_INFORMATION, 0, pid); | ||
| 2283 | if (proc_hand == NULL) | ||
| 2284 | { | ||
| 2285 | DWORD err = GetLastError (); | ||
| 2286 | |||
| 2287 | switch (err) | ||
| 2288 | { | ||
| 2289 | case ERROR_ACCESS_DENIED: /* existing process, but access denied */ | ||
| 2290 | errno = EPERM; | ||
| 2291 | return -1; | ||
| 2292 | case ERROR_INVALID_PARAMETER: /* process PID does not exist */ | ||
| 2293 | errno = ESRCH; | ||
| 2294 | return -1; | ||
| 2295 | } | ||
| 2296 | } | ||
| 2297 | else | ||
| 2298 | CloseHandle (proc_hand); | ||
| 2299 | return 0; | ||
| 2300 | } | ||
| 2301 | |||
| 2272 | cp = find_child_pid (pid); | 2302 | cp = find_child_pid (pid); |
| 2273 | if (cp == NULL) | 2303 | if (cp == NULL) |
| 2274 | { | 2304 | { |