aboutsummaryrefslogtreecommitdiffstats
path: root/src/filelock.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/filelock.c')
-rw-r--r--src/filelock.c86
1 files changed, 44 insertions, 42 deletions
diff --git a/src/filelock.c b/src/filelock.c
index 46349a63e4a..ff25d6475de 100644
--- a/src/filelock.c
+++ b/src/filelock.c
@@ -504,9 +504,9 @@ read_lock_data (char *lfname, char lfinfo[MAX_LFINFO + 1])
504} 504}
505 505
506/* Return 0 if nobody owns the lock file LFNAME or the lock is obsolete, 506/* Return 0 if nobody owns the lock file LFNAME or the lock is obsolete,
507 1 if another process owns it (and set OWNER (if non-null) to info), 507 -1 if another process owns it (and set OWNER (if non-null) to info),
508 2 if the current process owns it, 508 -2 if the current process owns it,
509 or -1 if something is wrong with the locking mechanism. */ 509 or an errno value if something is wrong with the locking mechanism. */
510 510
511static int 511static int
512current_lock_owner (lock_info_type *owner, char *lfname) 512current_lock_owner (lock_info_type *owner, char *lfname)
@@ -525,23 +525,23 @@ current_lock_owner (lock_info_type *owner, char *lfname)
525 /* If nonexistent lock file, all is well; otherwise, got strange error. */ 525 /* If nonexistent lock file, all is well; otherwise, got strange error. */
526 lfinfolen = read_lock_data (lfname, owner->user); 526 lfinfolen = read_lock_data (lfname, owner->user);
527 if (lfinfolen < 0) 527 if (lfinfolen < 0)
528 return errno == ENOENT ? 0 : -1; 528 return errno == ENOENT ? 0 : errno;
529 if (MAX_LFINFO < lfinfolen) 529 if (MAX_LFINFO < lfinfolen)
530 return -1; 530 return ENAMETOOLONG;
531 owner->user[lfinfolen] = 0; 531 owner->user[lfinfolen] = 0;
532 532
533 /* Parse USER@HOST.PID:BOOT_TIME. If can't parse, return -1. */ 533 /* Parse USER@HOST.PID:BOOT_TIME. If can't parse, return EINVAL. */
534 /* The USER is everything before the last @. */ 534 /* The USER is everything before the last @. */
535 owner->at = at = memrchr (owner->user, '@', lfinfolen); 535 owner->at = at = memrchr (owner->user, '@', lfinfolen);
536 if (!at) 536 if (!at)
537 return -1; 537 return EINVAL;
538 owner->dot = dot = strrchr (at, '.'); 538 owner->dot = dot = strrchr (at, '.');
539 if (!dot) 539 if (!dot)
540 return -1; 540 return EINVAL;
541 541
542 /* The PID is everything from the last '.' to the ':' or equivalent. */ 542 /* The PID is everything from the last '.' to the ':' or equivalent. */
543 if (! c_isdigit (dot[1])) 543 if (! c_isdigit (dot[1]))
544 return -1; 544 return EINVAL;
545 errno = 0; 545 errno = 0;
546 pid = strtoimax (dot + 1, &owner->colon, 10); 546 pid = strtoimax (dot + 1, &owner->colon, 10);
547 if (errno == ERANGE) 547 if (errno == ERANGE)
@@ -562,20 +562,20 @@ current_lock_owner (lock_info_type *owner, char *lfname)
562 mistakenly transliterate ':' to U+F022 in symlink contents. 562 mistakenly transliterate ':' to U+F022 in symlink contents.
563 See <https://bugzilla.redhat.com/show_bug.cgi?id=1384153>. */ 563 See <https://bugzilla.redhat.com/show_bug.cgi?id=1384153>. */
564 if (! (boot[0] == '\200' && boot[1] == '\242')) 564 if (! (boot[0] == '\200' && boot[1] == '\242'))
565 return -1; 565 return EINVAL;
566 boot += 2; 566 boot += 2;
567 FALLTHROUGH; 567 FALLTHROUGH;
568 case ':': 568 case ':':
569 if (! c_isdigit (boot[0])) 569 if (! c_isdigit (boot[0]))
570 return -1; 570 return EINVAL;
571 boot_time = strtoimax (boot, &lfinfo_end, 10); 571 boot_time = strtoimax (boot, &lfinfo_end, 10);
572 break; 572 break;
573 573
574 default: 574 default:
575 return -1; 575 return EINVAL;
576 } 576 }
577 if (lfinfo_end != owner->user + lfinfolen) 577 if (lfinfo_end != owner->user + lfinfolen)
578 return -1; 578 return EINVAL;
579 579
580 /* On current host? */ 580 /* On current host? */
581 Lisp_Object system_name = Fsystem_name (); 581 Lisp_Object system_name = Fsystem_name ();
@@ -584,22 +584,22 @@ current_lock_owner (lock_info_type *owner, char *lfname)
584 && memcmp (at + 1, SSDATA (system_name), SBYTES (system_name)) == 0) 584 && memcmp (at + 1, SSDATA (system_name), SBYTES (system_name)) == 0)
585 { 585 {
586 if (pid == getpid ()) 586 if (pid == getpid ())
587 ret = 2; /* We own it. */ 587 ret = -2; /* We own it. */
588 else if (0 < pid && pid <= TYPE_MAXIMUM (pid_t) 588 else if (0 < pid && pid <= TYPE_MAXIMUM (pid_t)
589 && (kill (pid, 0) >= 0 || errno == EPERM) 589 && (kill (pid, 0) >= 0 || errno == EPERM)
590 && (boot_time == 0 590 && (boot_time == 0
591 || (boot_time <= TYPE_MAXIMUM (time_t) 591 || (boot_time <= TYPE_MAXIMUM (time_t)
592 && within_one_second (boot_time, get_boot_time ())))) 592 && within_one_second (boot_time, get_boot_time ()))))
593 ret = 1; /* An existing process on this machine owns it. */ 593 ret = -1; /* An existing process on this machine owns it. */
594 /* The owner process is dead or has a strange pid, so try to 594 /* The owner process is dead or has a strange pid, so try to
595 zap the lockfile. */ 595 zap the lockfile. */
596 else 596 else
597 return unlink (lfname); 597 return unlink (lfname) < 0 ? errno : 0;
598 } 598 }
599 else 599 else
600 { /* If we wanted to support the check for stale locks on remote machines, 600 { /* If we wanted to support the check for stale locks on remote machines,
601 here's where we'd do it. */ 601 here's where we'd do it. */
602 ret = 1; 602 ret = -1;
603 } 603 }
604 604
605 return ret; 605 return ret;
@@ -608,9 +608,9 @@ current_lock_owner (lock_info_type *owner, char *lfname)
608 608
609/* Lock the lock named LFNAME if possible. 609/* Lock the lock named LFNAME if possible.
610 Return 0 in that case. 610 Return 0 in that case.
611 Return positive if some other process owns the lock, and info about 611 Return negative if some other process owns the lock, and info about
612 that process in CLASHER. 612 that process in CLASHER.
613 Return -1 if cannot lock for any other reason. */ 613 Return positive errno value if cannot lock for any other reason. */
614 614
615static int 615static int
616lock_if_free (lock_info_type *clasher, char *lfname) 616lock_if_free (lock_info_type *clasher, char *lfname)
@@ -618,20 +618,18 @@ lock_if_free (lock_info_type *clasher, char *lfname)
618 int err; 618 int err;
619 while ((err = lock_file_1 (lfname, 0)) == EEXIST) 619 while ((err = lock_file_1 (lfname, 0)) == EEXIST)
620 { 620 {
621 switch (current_lock_owner (clasher, lfname)) 621 err = current_lock_owner (clasher, lfname);
622 if (err != 0)
622 { 623 {
623 case 2: 624 if (err < 0)
624 return 0; /* We ourselves locked it. */ 625 return -2 - err; /* We locked it, or someone else has it. */
625 case 1: 626 break; /* current_lock_owner returned strange error. */
626 return 1; /* Someone else has it. */
627 case -1:
628 return -1; /* current_lock_owner returned strange error. */
629 } 627 }
630 628
631 /* We deleted a stale lock; try again to lock the file. */ 629 /* We deleted a stale lock; try again to lock the file. */
632 } 630 }
633 631
634 return err ? -1 : 0; 632 return err;
635} 633}
636 634
637/* lock_file locks file FN, 635/* lock_file locks file FN,
@@ -697,8 +695,9 @@ lock_file (Lisp_Object fn)
697 /* Create the name of the lock-file for file fn */ 695 /* Create the name of the lock-file for file fn */
698 MAKE_LOCK_NAME (lfname, encoded_fn); 696 MAKE_LOCK_NAME (lfname, encoded_fn);
699 697
700 /* Try to lock the lock. */ 698 /* Try to lock the lock. FIXME: This ignores errors when
701 if (0 < lock_if_free (&lock_info, lfname)) 699 lock_if_free returns a positive errno value. */
700 if (lock_if_free (&lock_info, lfname) < 0)
702 { 701 {
703 /* Someone else has the lock. Consider breaking it. */ 702 /* Someone else has the lock. Consider breaking it. */
704 Lisp_Object attack; 703 Lisp_Object attack;
@@ -725,13 +724,16 @@ unlock_file (Lisp_Object fn)
725 char *lfname; 724 char *lfname;
726 USE_SAFE_ALLOCA; 725 USE_SAFE_ALLOCA;
727 726
728 fn = Fexpand_file_name (fn, Qnil); 727 Lisp_Object filename = Fexpand_file_name (fn, Qnil);
729 fn = ENCODE_FILE (fn); 728 fn = ENCODE_FILE (filename);
730 729
731 MAKE_LOCK_NAME (lfname, fn); 730 MAKE_LOCK_NAME (lfname, fn);
732 731
733 if (current_lock_owner (0, lfname) == 2) 732 int err = current_lock_owner (0, lfname);
734 unlink (lfname); 733 if (err == -2 && unlink (lfname) != 0 && errno != ENOENT)
734 err = errno;
735 if (0 < err)
736 report_file_errno ("Unlocking file", filename, err);
735 737
736 SAFE_FREE (); 738 SAFE_FREE ();
737} 739}
@@ -822,17 +824,17 @@ t if it is locked by you, else a string saying which user has locked it. */)
822 USE_SAFE_ALLOCA; 824 USE_SAFE_ALLOCA;
823 825
824 filename = Fexpand_file_name (filename, Qnil); 826 filename = Fexpand_file_name (filename, Qnil);
825 filename = ENCODE_FILE (filename); 827 Lisp_Object encoded_filename = ENCODE_FILE (filename);
826 828 MAKE_LOCK_NAME (lfname, encoded_filename);
827 MAKE_LOCK_NAME (lfname, filename);
828 829
829 owner = current_lock_owner (&locker, lfname); 830 owner = current_lock_owner (&locker, lfname);
830 if (owner <= 0) 831 switch (owner)
831 ret = Qnil; 832 {
832 else if (owner == 2) 833 case -2: ret = Qt; break;
833 ret = Qt; 834 case -1: ret = make_string (locker.user, locker.at - locker.user); break;
834 else 835 case 0: ret = Qnil; break;
835 ret = make_string (locker.user, locker.at - locker.user); 836 default: report_file_errno ("Testing file lock", filename, owner);
837 }
836 838
837 SAFE_FREE (); 839 SAFE_FREE ();
838 return ret; 840 return ret;