diff options
| author | Paul Eggert | 2022-01-11 08:58:18 -0800 |
|---|---|---|
| committer | Paul Eggert | 2022-01-11 08:58:39 -0800 |
| commit | a980795fd0bd2ae5fb0dba27fafbb811bc2ff75d (patch) | |
| tree | 875f7b4859be26f4f5dd70655b2cba8c777cdcfe /src/filelock.c | |
| parent | 68f2d772e51a0f436559bbfe26868eaca23af390 (diff) | |
| download | emacs-a980795fd0bd2ae5fb0dba27fafbb811bc2ff75d.tar.gz emacs-a980795fd0bd2ae5fb0dba27fafbb811bc2ff75d.zip | |
Clean up filelock code related to errno
Reduce dependency on Haiku internals, by not assuming that
Haiku errno values (which are negative) are neither -1 nor -2.
This removes an #ifdef HAIKU while still maintaining
portability to Haiku.
* src/filelock.c (NEGATIVE_ERRNO, ANOTHER_OWNS_IT, I_OWN_IT):
New constants, which should work regardless of whether
we are on Haiku or B_USE_POSITIVE_POSIX_ERRORS is defined.
(current_lock_owner, lock_if_free, lock_file, unlock_file)
(Ffile_locked_p): Use them, without assuming anything about errno
value sign.
Diffstat (limited to 'src/filelock.c')
| -rw-r--r-- | src/filelock.c | 69 |
1 files changed, 38 insertions, 31 deletions
diff --git a/src/filelock.c b/src/filelock.c index 3555cfc2519..eb8d9ab5e01 100644 --- a/src/filelock.c +++ b/src/filelock.c | |||
| @@ -490,15 +490,29 @@ read_lock_data (char *lfname, char lfinfo[MAX_LFINFO + 1]) | |||
| 490 | return nbytes; | 490 | return nbytes; |
| 491 | } | 491 | } |
| 492 | 492 | ||
| 493 | /* True if errno values are negative. Although the C standard | ||
| 494 | requires them to be positive, they are negative in Haiku. */ | ||
| 495 | enum { NEGATIVE_ERRNO = EDOM < 0 }; | ||
| 496 | |||
| 497 | /* Nonzero values that are not errno values. */ | ||
| 498 | enum | ||
| 499 | { | ||
| 500 | /* Another process on this machine owns it. */ | ||
| 501 | ANOTHER_OWNS_IT = NEGATIVE_ERRNO ? 1 : -1, | ||
| 502 | |||
| 503 | /* This Emacs process owns it. */ | ||
| 504 | I_OWN_IT = 2 * ANOTHER_OWNS_IT | ||
| 505 | }; | ||
| 506 | |||
| 493 | /* Return 0 if nobody owns the lock file LFNAME or the lock is obsolete, | 507 | /* Return 0 if nobody owns the lock file LFNAME or the lock is obsolete, |
| 494 | -1 if another process owns it (and set OWNER (if non-null) to info), | 508 | ANOTHER_OWNS_IT if another process owns it |
| 495 | -2 if the current process owns it, | 509 | (and set OWNER (if non-null) to info), |
| 510 | I_OWN_IT if the current process owns it, | ||
| 496 | or an errno value if something is wrong with the locking mechanism. */ | 511 | or an errno value if something is wrong with the locking mechanism. */ |
| 497 | 512 | ||
| 498 | static int | 513 | static int |
| 499 | current_lock_owner (lock_info_type *owner, char *lfname) | 514 | current_lock_owner (lock_info_type *owner, char *lfname) |
| 500 | { | 515 | { |
| 501 | int ret; | ||
| 502 | lock_info_type local_owner; | 516 | lock_info_type local_owner; |
| 503 | ptrdiff_t lfinfolen; | 517 | ptrdiff_t lfinfolen; |
| 504 | intmax_t pid, boot_time; | 518 | intmax_t pid, boot_time; |
| @@ -571,13 +585,13 @@ current_lock_owner (lock_info_type *owner, char *lfname) | |||
| 571 | && memcmp (at + 1, SSDATA (system_name), SBYTES (system_name)) == 0) | 585 | && memcmp (at + 1, SSDATA (system_name), SBYTES (system_name)) == 0) |
| 572 | { | 586 | { |
| 573 | if (pid == getpid ()) | 587 | if (pid == getpid ()) |
| 574 | ret = -2; /* We own it. */ | 588 | return I_OWN_IT; |
| 575 | else if (0 < pid && pid <= TYPE_MAXIMUM (pid_t) | 589 | else if (0 < pid && pid <= TYPE_MAXIMUM (pid_t) |
| 576 | && (kill (pid, 0) >= 0 || errno == EPERM) | 590 | && (kill (pid, 0) >= 0 || errno == EPERM) |
| 577 | && (boot_time == 0 | 591 | && (boot_time == 0 |
| 578 | || (boot_time <= TYPE_MAXIMUM (time_t) | 592 | || (boot_time <= TYPE_MAXIMUM (time_t) |
| 579 | && within_one_second (boot_time, get_boot_time ())))) | 593 | && within_one_second (boot_time, get_boot_time ())))) |
| 580 | ret = -1; /* An existing process on this machine owns it. */ | 594 | return ANOTHER_OWNS_IT; |
| 581 | /* The owner process is dead or has a strange pid, so try to | 595 | /* The owner process is dead or has a strange pid, so try to |
| 582 | zap the lockfile. */ | 596 | zap the lockfile. */ |
| 583 | else | 597 | else |
| @@ -586,18 +600,16 @@ current_lock_owner (lock_info_type *owner, char *lfname) | |||
| 586 | else | 600 | else |
| 587 | { /* If we wanted to support the check for stale locks on remote machines, | 601 | { /* If we wanted to support the check for stale locks on remote machines, |
| 588 | here's where we'd do it. */ | 602 | here's where we'd do it. */ |
| 589 | ret = -1; | 603 | return ANOTHER_OWNS_IT; |
| 590 | } | 604 | } |
| 591 | |||
| 592 | return ret; | ||
| 593 | } | 605 | } |
| 594 | 606 | ||
| 595 | 607 | ||
| 596 | /* Lock the lock named LFNAME if possible. | 608 | /* Lock the lock named LFNAME if possible. |
| 597 | Return 0 in that case. | 609 | Return 0 in that case. |
| 598 | Return negative if some other process owns the lock, and info about | 610 | Return ANOTHER_OWNS_IT if some other process owns the lock, and info about |
| 599 | that process in CLASHER. | 611 | that process in CLASHER. |
| 600 | Return positive errno value if cannot lock for any other reason. */ | 612 | Return errno value if cannot lock for any other reason. */ |
| 601 | 613 | ||
| 602 | static int | 614 | static int |
| 603 | lock_if_free (lock_info_type *clasher, char *lfname) | 615 | lock_if_free (lock_info_type *clasher, char *lfname) |
| @@ -606,24 +618,17 @@ lock_if_free (lock_info_type *clasher, char *lfname) | |||
| 606 | while ((err = lock_file_1 (lfname, 0)) == EEXIST) | 618 | while ((err = lock_file_1 (lfname, 0)) == EEXIST) |
| 607 | { | 619 | { |
| 608 | err = current_lock_owner (clasher, lfname); | 620 | err = current_lock_owner (clasher, lfname); |
| 621 | |||
| 622 | /* Return if we locked it, or another process owns it, or it is | ||
| 623 | a strange error. */ | ||
| 609 | if (err != 0) | 624 | if (err != 0) |
| 610 | { | 625 | return err == I_OWN_IT ? 0 : err; |
| 611 | if (err == -1 || err == -2) | ||
| 612 | return -2 - err; /* We locked it, or someone else has it. */ | ||
| 613 | break; /* current_lock_owner returned strange error. */ | ||
| 614 | } | ||
| 615 | 626 | ||
| 616 | /* We deleted a stale lock; try again to lock the file. */ | 627 | /* We deleted a stale lock or some other process deleted the lock; |
| 628 | try again to lock the file. */ | ||
| 617 | } | 629 | } |
| 618 | 630 | ||
| 619 | #if !defined HAIKU \ | ||
| 620 | || defined B_USE_POSITIVE_POSIX_ERRORS | ||
| 621 | return err; | 631 | return err; |
| 622 | #else | ||
| 623 | /* On Haiku, POSIX errno values are negative by default, but this | ||
| 624 | code's callers assume that all errno values are positive. */ | ||
| 625 | return -err; | ||
| 626 | #endif | ||
| 627 | } | 632 | } |
| 628 | 633 | ||
| 629 | static Lisp_Object | 634 | static Lisp_Object |
| @@ -681,12 +686,12 @@ lock_file (Lisp_Object fn) | |||
| 681 | if (!NILP (subject_buf) | 686 | if (!NILP (subject_buf) |
| 682 | && NILP (Fverify_visited_file_modtime (subject_buf)) | 687 | && NILP (Fverify_visited_file_modtime (subject_buf)) |
| 683 | && !NILP (Ffile_exists_p (fn)) | 688 | && !NILP (Ffile_exists_p (fn)) |
| 684 | && current_lock_owner (NULL, lfname) != -2) | 689 | && current_lock_owner (NULL, lfname) != I_OWN_IT) |
| 685 | call1 (intern ("userlock--ask-user-about-supersession-threat"), fn); | 690 | call1 (intern ("userlock--ask-user-about-supersession-threat"), fn); |
| 686 | 691 | ||
| 687 | /* Try to lock the lock. FIXME: This ignores errors when | 692 | /* Try to lock the lock. FIXME: This ignores errors when |
| 688 | lock_if_free returns a positive errno value. */ | 693 | lock_if_free returns an errno value. */ |
| 689 | if (lock_if_free (&lock_info, lfname) < 0) | 694 | if (lock_if_free (&lock_info, lfname) == ANOTHER_OWNS_IT) |
| 690 | { | 695 | { |
| 691 | /* Someone else has the lock. Consider breaking it. */ | 696 | /* Someone else has the lock. Consider breaking it. */ |
| 692 | Lisp_Object attack; | 697 | Lisp_Object attack; |
| @@ -717,9 +722,9 @@ unlock_file (Lisp_Object fn) | |||
| 717 | lfname = SSDATA (ENCODE_FILE (lock_filename)); | 722 | lfname = SSDATA (ENCODE_FILE (lock_filename)); |
| 718 | 723 | ||
| 719 | int err = current_lock_owner (0, lfname); | 724 | int err = current_lock_owner (0, lfname); |
| 720 | if (err == -2 && unlink (lfname) != 0 && errno != ENOENT) | 725 | if (! (err == 0 || err == ANOTHER_OWNS_IT |
| 721 | err = errno; | 726 | || (err == I_OWN_IT |
| 722 | if (0 < err) | 727 | && (unlink (lfname) == 0 || (err = errno) == ENOENT)))) |
| 723 | report_file_errno ("Unlocking file", fn, err); | 728 | report_file_errno ("Unlocking file", fn, err); |
| 724 | 729 | ||
| 725 | return Qnil; | 730 | return Qnil; |
| @@ -865,8 +870,10 @@ t if it is locked by you, else a string saying which user has locked it. */) | |||
| 865 | owner = current_lock_owner (&locker, lfname); | 870 | owner = current_lock_owner (&locker, lfname); |
| 866 | switch (owner) | 871 | switch (owner) |
| 867 | { | 872 | { |
| 868 | case -2: ret = Qt; break; | 873 | case I_OWN_IT: ret = Qt; break; |
| 869 | case -1: ret = make_string (locker.user, locker.at - locker.user); break; | 874 | case ANOTHER_OWNS_IT: |
| 875 | ret = make_string (locker.user, locker.at - locker.user); | ||
| 876 | break; | ||
| 870 | case 0: ret = Qnil; break; | 877 | case 0: ret = Qnil; break; |
| 871 | default: report_file_errno ("Testing file lock", filename, owner); | 878 | default: report_file_errno ("Testing file lock", filename, owner); |
| 872 | } | 879 | } |