/[emacs]/emacs/src/filelock.c
ViewVC logotype

Diff of /emacs/src/filelock.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.96 by rms, Wed Feb 6 15:44:28 2002 UTC revision 1.96.4.1 by miles, Fri Apr 4 06:20:58 2003 UTC
# Line 80  Lisp_Object Vtemporary_file_directory; Line 80  Lisp_Object Vtemporary_file_directory;
80  #ifndef WTMP_FILE  #ifndef WTMP_FILE
81  #define WTMP_FILE "/var/log/wtmp"  #define WTMP_FILE "/var/log/wtmp"
82  #endif  #endif
83      
84  /* The strategy: to lock a file FN, create a symlink .#FN in FN's  /* The strategy: to lock a file FN, create a symlink .#FN in FN's
85     directory, with link data `user@host.pid'.  This avoids a single     directory, with link data `user@host.pid'.  This avoids a single
86     mount (== failure) point for lock files.     mount (== failure) point for lock files.
87    
88     When the host in the lock data is the current host, we can check if     When the host in the lock data is the current host, we can check if
89     the pid is valid with kill.     the pid is valid with kill.
90      
91     Otherwise, we could look at a separate file that maps hostnames to     Otherwise, we could look at a separate file that maps hostnames to
92     reboot times to see if the remote pid can possibly be valid, since we     reboot times to see if the remote pid can possibly be valid, since we
93     don't want Emacs to have to communicate via pipes or sockets or     don't want Emacs to have to communicate via pipes or sockets or
# Line 105  Lisp_Object Vtemporary_file_directory; Line 105  Lisp_Object Vtemporary_file_directory;
105     files to be useful on old systems lacking symlinks, nowadays     files to be useful on old systems lacking symlinks, nowadays
106     virtually all such systems are probably single-user anyway, so it     virtually all such systems are probably single-user anyway, so it
107     didn't seem worth the complication.     didn't seem worth the complication.
108      
109     Similarly, we don't worry about a possible 14-character limit on     Similarly, we don't worry about a possible 14-character limit on
110     file names, because those are all the same systems that don't have     file names, because those are all the same systems that don't have
111     symlinks.     symlinks.
112      
113     This is compatible with the locking scheme used by Interleaf (which     This is compatible with the locking scheme used by Interleaf (which
114     has contributed this implementation for Emacs), and was designed by     has contributed this implementation for Emacs), and was designed by
115     Ethan Jacobson, Kimbo Mundy, and others.     Ethan Jacobson, Kimbo Mundy, and others.
116      
117     --karl@cs.umb.edu/karl@hq.ileaf.com.  */     --karl@cs.umb.edu/karl@hq.ileaf.com.  */
118    
119    
# Line 222  get_boot_time () Line 222  get_boot_time ()
222                args[3] = Qnil;                args[3] = Qnil;
223                args[4] = build_string ("-c");                args[4] = build_string ("-c");
224                sprintf (cmd_string, "gunzip < %s.%d.gz > %s",                sprintf (cmd_string, "gunzip < %s.%d.gz > %s",
225                         WTMP_FILE, counter, XSTRING (tempname)->data);                         WTMP_FILE, counter, SDATA (tempname));
226                args[5] = build_string (cmd_string);                args[5] = build_string (cmd_string);
227                Fcall_process (6, args);                Fcall_process (6, args);
228                filename = tempname;                filename = tempname;
# Line 232  get_boot_time () Line 232  get_boot_time ()
232    
233        if (! NILP (filename))        if (! NILP (filename))
234          {          {
235            get_boot_time_1 (XSTRING (filename)->data, 1);            get_boot_time_1 (SDATA (filename), 1);
236            if (delete_flag)            if (delete_flag)
237              unlink (XSTRING (filename)->data);              unlink (SDATA (filename));
238          }          }
239      }      }
240    
# Line 325  typedef struct Line 325  typedef struct
325     trailing period plus one for the digit after it plus one for the     trailing period plus one for the digit after it plus one for the
326     null.  */     null.  */
327  #define MAKE_LOCK_NAME(lock, file) \  #define MAKE_LOCK_NAME(lock, file) \
328    (lock = (char *) alloca (STRING_BYTES (XSTRING (file)) + 2 + 1 + 1 + 1), \    (lock = (char *) alloca (SBYTES (file) + 2 + 1 + 1 + 1), \
329     fill_in_lock_file_name (lock, (file)))     fill_in_lock_file_name (lock, (file)))
330    
331  static void  static void
# Line 337  fill_in_lock_file_name (lockfile, fn) Line 337  fill_in_lock_file_name (lockfile, fn)
337    struct stat st;    struct stat st;
338    int count = 0;    int count = 0;
339    
340    strcpy (lockfile, XSTRING (fn)->data);    strcpy (lockfile, SDATA (fn));
341    
342    /* Shift the nondirectory part of the file name (including the null)    /* Shift the nondirectory part of the file name (including the null)
343       right two characters.  Here is one of the places where we'd have to       right two characters.  Here is one of the places where we'd have to
344       do something to support 14-character-max file names.  */       do something to support 14-character-max file names.  */
345    for (p = lockfile + strlen (lockfile); p != lockfile && *p != '/'; p--)    for (p = lockfile + strlen (lockfile); p != lockfile && *p != '/'; p--)
346      p[2] = *p;      p[2] = *p;
347      
348    /* Insert the `.#'.  */    /* Insert the `.#'.  */
349    p[1] = '.';    p[1] = '.';
350    p[2] = '#';    p[2] = '#';
# Line 368  fill_in_lock_file_name (lockfile, fn) Line 368  fill_in_lock_file_name (lockfile, fn)
368    
369  static int  static int
370  lock_file_1 (lfname, force)  lock_file_1 (lfname, force)
371       char *lfname;       char *lfname;
372       int force;       int force;
373  {  {
374    register int err;    register int err;
# Line 378  lock_file_1 (lfname, force) Line 378  lock_file_1 (lfname, force)
378    char *lock_info_str;    char *lock_info_str;
379    
380    if (STRINGP (Fuser_login_name (Qnil)))    if (STRINGP (Fuser_login_name (Qnil)))
381      user_name = (char *)XSTRING (Fuser_login_name (Qnil))->data;      user_name = (char *)SDATA (Fuser_login_name (Qnil));
382    else    else
383      user_name = "";      user_name = "";
384    if (STRINGP (Fsystem_name ()))    if (STRINGP (Fsystem_name ()))
385      host_name = (char *)XSTRING (Fsystem_name ())->data;      host_name = (char *)SDATA (Fsystem_name ());
386    else    else
387      host_name = "";      host_name = "";
388    lock_info_str = (char *)alloca (strlen (user_name) + strlen (host_name)    lock_info_str = (char *)alloca (strlen (user_name) + strlen (host_name)
# Line 394  lock_file_1 (lfname, force) Line 394  lock_file_1 (lfname, force)
394               (unsigned long) getpid (), (unsigned long) boot_time);               (unsigned long) getpid (), (unsigned long) boot_time);
395    else    else
396      sprintf (lock_info_str, "%s@%s.%lu", user_name, host_name,      sprintf (lock_info_str, "%s@%s.%lu", user_name, host_name,
397               (unsigned long) getpid ());                   (unsigned long) getpid ());
398    
399    err = symlink (lock_info_str, lfname);    err = symlink (lock_info_str, lfname);
400    if (errno == EEXIST && force)    if (errno == EEXIST && force)
# Line 448  current_lock_owner (owner, lfname) Line 448  current_lock_owner (owner, lfname)
448  #endif  #endif
449      }      }
450    while (len >= bufsize);    while (len >= bufsize);
451      
452    /* If nonexistent lock file, all is well; otherwise, got strange error. */    /* If nonexistent lock file, all is well; otherwise, got strange error. */
453    if (len == -1)    if (len == -1)
454      {      {
# Line 458  current_lock_owner (owner, lfname) Line 458  current_lock_owner (owner, lfname)
458    
459    /* Link info exists, so `len' is its length.  Null terminate.  */    /* Link info exists, so `len' is its length.  Null terminate.  */
460    lfinfo[len] = 0;    lfinfo[len] = 0;
461      
462    /* Even if the caller doesn't want the owner info, we still have to    /* Even if the caller doesn't want the owner info, we still have to
463       read it to determine return value, so allocate it.  */       read it to determine return value, so allocate it.  */
464    if (!owner)    if (!owner)
# Line 466  current_lock_owner (owner, lfname) Line 466  current_lock_owner (owner, lfname)
466        owner = (lock_info_type *) alloca (sizeof (lock_info_type));        owner = (lock_info_type *) alloca (sizeof (lock_info_type));
467        local_owner = 1;        local_owner = 1;
468      }      }
469      
470    /* Parse USER@HOST.PID:BOOT_TIME.  If can't parse, return -1.  */    /* Parse USER@HOST.PID:BOOT_TIME.  If can't parse, return -1.  */
471    /* The USER is everything before the first @.  */    /* The USER is everything before the first @.  */
472    at = index (lfinfo, '@');    at = index (lfinfo, '@');
# Line 480  current_lock_owner (owner, lfname) Line 480  current_lock_owner (owner, lfname)
480    owner->user = (char *) xmalloc (len + 1);    owner->user = (char *) xmalloc (len + 1);
481    strncpy (owner->user, lfinfo, len);    strncpy (owner->user, lfinfo, len);
482    owner->user[len] = 0;    owner->user[len] = 0;
483      
484    /* The PID is everything from the last `.' to the `:'.  */    /* The PID is everything from the last `.' to the `:'.  */
485    owner->pid = atoi (dot + 1);    owner->pid = atoi (dot + 1);
486    colon = dot;    colon = dot;
# Line 500  current_lock_owner (owner, lfname) Line 500  current_lock_owner (owner, lfname)
500    
501    /* We're done looking at the link info.  */    /* We're done looking at the link info.  */
502    xfree (lfinfo);    xfree (lfinfo);
503      
504    /* On current host?  */    /* On current host?  */
505    if (STRINGP (Fsystem_name ())    if (STRINGP (Fsystem_name ())
506        && strcmp (owner->host, XSTRING (Fsystem_name ())->data) == 0)        && strcmp (owner->host, SDATA (Fsystem_name ())) == 0)
507      {      {
508        if (owner->pid == getpid ())        if (owner->pid == getpid ())
509          ret = 2; /* We own it.  */          ret = 2; /* We own it.  */
# Line 524  current_lock_owner (owner, lfname) Line 524  current_lock_owner (owner, lfname)
524           here's where we'd do it.  */           here's where we'd do it.  */
525        ret = 1;        ret = 1;
526      }      }
527      
528    /* Avoid garbage.  */    /* Avoid garbage.  */
529    if (local_owner || ret <= 0)    if (local_owner || ret <= 0)
530      {      {
# Line 543  current_lock_owner (owner, lfname) Line 543  current_lock_owner (owner, lfname)
543  static int  static int
544  lock_if_free (clasher, lfname)  lock_if_free (clasher, lfname)
545       lock_info_type *clasher;       lock_info_type *clasher;
546       register char *lfname;       register char *lfname;
547  {  {
548    while (lock_file_1 (lfname, 0) == 0)    while (lock_file_1 (lfname, 0) == 0)
549      {      {
# Line 551  lock_if_free (clasher, lfname) Line 551  lock_if_free (clasher, lfname)
551    
552        if (errno != EEXIST)        if (errno != EEXIST)
553          return -1;          return -1;
554          
555        locker = current_lock_owner (clasher, lfname);        locker = current_lock_owner (clasher, lfname);
556        if (locker == 2)        if (locker == 2)
557          {          {
# Line 634  lock_file (fn) Line 634  lock_file (fn)
634    sprintf (locker, "%s@%s (pid %lu)", lock_info.user, lock_info.host,    sprintf (locker, "%s@%s (pid %lu)", lock_info.user, lock_info.host,
635             lock_info.pid);             lock_info.pid);
636    FREE_LOCK_INFO (lock_info);    FREE_LOCK_INFO (lock_info);
637      
638    attack = call2 (intern ("ask-user-about-lock"), fn, build_string (locker));    attack = call2 (intern ("ask-user-about-lock"), fn, build_string (locker));
639    if (!NILP (attack))    if (!NILP (attack))
640      /* User says take the lock */      /* User says take the lock */
# Line 691  or else nothing is done if current buffe Line 691  or else nothing is done if current buffe
691    if (SAVE_MODIFF < MODIFF    if (SAVE_MODIFF < MODIFF
692        && !NILP (file))        && !NILP (file))
693      lock_file (file);      lock_file (file);
694    return Qnil;        return Qnil;
695  }  }
696    
697  DEFUN ("unlock-buffer", Funlock_buffer, Sunlock_buffer,  DEFUN ("unlock-buffer", Funlock_buffer, Sunlock_buffer,

Legend:
Removed from v.1.96  
changed lines
  Added in v.1.96.4.1

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26