Annotation of 43BSD/contrib/emacs/src/filelock.c, revision 1.1.1.1

1.1       root        1: /* Copyright (C) 1985 Richard M. Stallman and Dick King
                      2: 
                      3: This file is part of GNU Emacs.
                      4: 
                      5: GNU Emacs is distributed in the hope that it will be useful,
                      6: but WITHOUT ANY WARRANTY.  No author or distributor
                      7: accepts responsibility to anyone for the consequences of using it
                      8: or for whether it serves any particular purpose or works at all,
                      9: unless he says so in writing.  Refer to the GNU Emacs General Public
                     10: License for full details.
                     11: 
                     12: Everyone is granted permission to copy, modify and redistribute
                     13: GNU Emacs, but only under the conditions described in the
                     14: GNU Emacs General Public License.   A copy of this license is
                     15: supposed to have been given to you along with GNU Emacs so you
                     16: can know your rights and responsibilities.  It should be in a
                     17: file named COPYING.  Among other things, the copyright notice
                     18: and this notice must be preserved on all copies.  */
                     19: 
                     20: 
                     21: #include "config.h"
                     22: #include "lisp.h"
                     23: #include "paths.h"
                     24: #include "buffer.h"
                     25: #include <sys/types.h>
                     26: #include <sys/stat.h>
                     27: #include <pwd.h>
                     28: #include <errno.h>
                     29: #include <sys/file.h>
                     30: #ifdef USG
                     31: #include <fcntl.h>
                     32: #endif /* USG */
                     33: 
                     34: #ifdef CLASH_DETECTION
                     35: 
                     36: /* lock_file locks file fn,
                     37:    meaning it serves notice on the world that you intend to edit that file.
                     38:    This should be done only when about to modify a file-visiting
                     39:    buffer previously unmodified.
                     40:    Do not (normally) call lock_buffer for a buffer already modified,
                     41:    as either the file is already locked, or the user has already
                     42:    decided to go ahead without locking.
                     43: 
                     44:    When lock_buffer returns, either the lock is locked for us,
                     45:    or the user has said to go ahead without locking.
                     46: 
                     47:    If the file is locked by someone else, lock_buffer calls
                     48:    ask-user-about-lock (a Lisp function) with two arguments,
                     49:    the file name and the name of the user who did the locking.
                     50:    This function can signal an error, or return t meaning
                     51:    take away the lock, or return nil meaning ignore the lock.  */
                     52: 
                     53: /* The lock file name is the file name with "/" replaced by "!"
                     54:    and put in the Emacs lock directory.  */
                     55: /* (ie., /ka/king/junk.tex -> /!/!ka!king!junk.tex). */
                     56: 
                     57: void
                     58: lock_file (fn)
                     59:      register Lisp_Object fn;
                     60: {
                     61:   register int fd;
                     62:   register Lisp_Object attack;
                     63:   register char *lfname;
                     64:   struct stat s;
                     65:   struct passwd *the_pw;
                     66:   extern struct passwd *getpwuid ();
                     67: 
                     68:   /* Create the name of the lock-file for file fn */
                     69:   lfname = (char *) alloca (XSTRING (fn)->size + strlen (PATH_LOCK) + 1);
                     70:   fill_in_lock_file_name (lfname, fn);
                     71: 
                     72:   /* Try to lock the lock. */
                     73:   if (lock_if_free (lfname) <= 0)
                     74:     /* Return now if we have locked it, or if lock dir does not exist */
                     75:     return;
                     76: 
                     77:   /* Else consider breaking the lock */
                     78:   the_pw = 0;
                     79:   if (lstat (lfname, &s) == 0)
                     80:     the_pw = getpwuid (s.st_uid);
                     81:   attack = call2 (intern ("ask-user-about-lock"), fn,
                     82:                  the_pw == 0 ? Qnil : build_string (the_pw->pw_name));
                     83:   if (!NULL (attack))
                     84:     /* User says take the lock */
                     85:     {
                     86:       lock_superlock (lfname);
                     87:       lock_file_1 (lfname, O_WRONLY) ;
                     88:       unlink (PATH_SUPERLOCK);
                     89:       return;
                     90:     }
                     91:   /* User says ignore the lock */
                     92: }
                     93: 
                     94: fill_in_lock_file_name (lockfile, fn)
                     95:      register char *lockfile;
                     96:      register Lisp_Object fn;
                     97: {
                     98:   register char *p;
                     99: 
                    100:   strcpy (lockfile, PATH_LOCK);
                    101: 
                    102:   p = lockfile + strlen (lockfile);
                    103: 
                    104:   strcpy (p, XSTRING (fn)->data);
                    105: 
                    106:   for (; *p; p++)
                    107:     {
                    108:       if (*p == '/')
                    109:        *p = '!';
                    110:     }
                    111: }
                    112: 
                    113: /* Lock the lock file named LFNAME.
                    114:    If MODE is O_WRONLY, we do so even if it is already locked.
                    115:    If MODE is O_WRONLY | O_EXCL | O_CREAT, we do so only if it is free.
                    116:    Return 1 if successful, 0 if not.  */
                    117: 
                    118: int
                    119: lock_file_1 (lfname, mode)
                    120:      int mode; char *lfname; 
                    121: {
                    122:   register int fd;
                    123:   char buf[20];
                    124: 
                    125:   if ((fd = open (lfname, mode, 0666)) >= 0)
                    126:     {
                    127:       fchmod (fd, 0666);
                    128:       sprintf (buf, "%d ", getpid ());
                    129:       write (fd, buf, strlen (buf));
                    130:       close (fd);
                    131:       return 1;
                    132:     }
                    133:   else
                    134:     return 0;
                    135: }
                    136: 
                    137: /* Lock the lock named LFNAME if possible.
                    138:    Return 0 in that case.
                    139:    Return 1 if lock is really locked by someone else.
                    140:    Return -1 if cannot lock for any other reason.  */
                    141: 
                    142: int
                    143: lock_if_free (lfname)
                    144:      register char *lfname; 
                    145: {
                    146:   register int clasher;
                    147:   extern int errno;
                    148: 
                    149:   while (lock_file_1 (lfname, O_WRONLY | O_EXCL | O_CREAT) == 0)
                    150:     {
                    151:       if (errno != EEXIST)
                    152:        return -1;
                    153:       clasher = current_lock_owner (lfname);
                    154:       if (clasher == 0 || (kill (clasher, 0) < 0 && errno == ESRCH))
                    155:        {
                    156:          if (unlink (lfname) < 0)
                    157:            return -1;
                    158:          /* If we delete the lock successfully, try again to lock.  */
                    159:        }
                    160:       else
                    161:        return (clasher != getpid ());
                    162:      }
                    163:   return 0;
                    164: }
                    165: 
                    166: int
                    167: current_lock_owner (lfname)
                    168:      char *lfname;
                    169: {
                    170:   register int fd;
                    171:   char buf[20];
                    172: 
                    173:   fd = open (lfname, O_RDONLY, 0666);
                    174:   if (fd < 0)
                    175:     return 0;
                    176: 
                    177:   if (read (fd, buf, sizeof buf) <= 0)
                    178:     return 0;
                    179:   close (fd);
                    180:   return atoi (buf);
                    181: }
                    182: 
                    183: void
                    184: unlock_file (fn)
                    185:      register Lisp_Object fn;
                    186: {
                    187:   register char *lfname;
                    188: 
                    189:   lfname = (char *) alloca (XSTRING (fn)->size + strlen (PATH_LOCK) + 1);
                    190:   fill_in_lock_file_name (lfname, fn);
                    191: 
                    192:   lock_superlock (lfname);
                    193: 
                    194:   if (current_lock_owner (lfname) == getpid ())
                    195:     unlink (lfname);
                    196: 
                    197:   unlink (PATH_SUPERLOCK);
                    198: }
                    199: 
                    200: lock_superlock (lfname)
                    201:      char *lfname;
                    202: {
                    203:   register int i, fd;
                    204:   extern int errno;
                    205: 
                    206:   for (i = -20; i < 0 && (fd = open (PATH_SUPERLOCK,
                    207:                                     O_WRONLY | O_EXCL | O_CREAT, 0666)) < 0;
                    208:        i++)
                    209:     {
                    210:       if (errno != EEXIST)
                    211:        return;
                    212:       sleep (1);
                    213:     }
                    214:   if (fd >= 0)
                    215:     {
                    216:       fchmod (fd, 0666);
                    217:       write (fd, lfname, strlen (lfname));
                    218:       close (fd);
                    219:     }
                    220: }
                    221: 
                    222: void
                    223: unlock_all_files ()
                    224: {
                    225:   register Lisp_Object tail;
                    226:   register struct buffer *b;
                    227: 
                    228:   for (tail = Vbuffer_alist; XGCTYPE (tail) == Lisp_Cons;
                    229:        tail = XCONS (tail)->cdr)
                    230:     {
                    231:       b = XBUFFER (XCONS (XCONS (tail)->car)->cdr);
                    232:       if (!NULL (b->filename)
                    233:          && b->save_modified < b->text.modified)
                    234:        unlock_file (b->filename);
                    235:     }
                    236: }
                    237: 
                    238: DEFUN ("lock-buffer", Flock_buffer, Slock_buffer,
                    239:   0, 1, 0,
                    240:   "Locks FILE, if current buffer is modified.\n\
                    241: FILE defaults to current buffer's visited file,\n\
                    242: or else nothing is done if current buffer isn't visiting a file.")
                    243:   (fn)
                    244:      Lisp_Object fn;
                    245: {
                    246:   if (NULL (fn))
                    247:     fn = bf_cur->filename;
                    248:   else
                    249:     CHECK_STRING (fn, 0);
                    250:   if (bf_cur->save_modified < bf_modified
                    251:       && !NULL (fn))
                    252:     lock_file (fn);
                    253:   return Qnil;    
                    254: }
                    255: 
                    256: DEFUN ("unlock-buffer", Funlock_buffer, Sunlock_buffer,
                    257:   0, 0, 0,
                    258:  "Unlocks the file visited in the current buffer,\n\
                    259: if it should normally be locked.")
                    260:   ()
                    261: {
                    262:   if (bf_cur->save_modified < bf_modified
                    263:       && !NULL (bf_cur->filename))
                    264:     unlock_file (bf_cur->filename);
                    265:   return Qnil;
                    266: }
                    267: 
                    268: syms_of_filelock ()
                    269: {
                    270:   defsubr (&Sunlock_buffer);
                    271:   defsubr (&Slock_buffer);
                    272: }
                    273: 
                    274: #endif /* CLASH_DETECTION */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.