Annotation of 43BSDReno/contrib/emacs-18.55/src/filelock.c, revision 1.1.1.1

1.1       root        1: /* Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
                      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 <sys/types.h>
                     22: #include <sys/stat.h>
                     23: #include "config.h"
                     24: #include "lisp.h"
                     25: #include "paths.h"
                     26: #include "buffer.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: extern int errno;
                     35: 
                     36: #ifdef CLASH_DETECTION
                     37:   
                     38: /* If system does not have symbolic links, it does not have lstat.
                     39:    In that case, use ordinary stat instead.  */
                     40: 
                     41: #ifndef S_IFLNK
                     42: #define lstat stat
                     43: #endif
                     44: 
                     45: static Lisp_Object
                     46: lock_file_owner_name (lfname)
                     47: {
                     48:   struct stat s;
                     49:   struct passwd *the_pw;
                     50:   extern struct passwd *getpwuid ();
                     51: 
                     52:   if (lstat (lfname, &s) == 0)
                     53:     the_pw = getpwuid (s.st_uid);
                     54:   return (the_pw == 0 ? Qnil : build_string (the_pw->pw_name));
                     55: }
                     56: 
                     57: 
                     58: /* lock_file locks file fn,
                     59:    meaning it serves notice on the world that you intend to edit that file.
                     60:    This should be done only when about to modify a file-visiting
                     61:    buffer previously unmodified.
                     62:    Do not (normally) call lock_buffer for a buffer already modified,
                     63:    as either the file is already locked, or the user has already
                     64:    decided to go ahead without locking.
                     65: 
                     66:    When lock_buffer returns, either the lock is locked for us,
                     67:    or the user has said to go ahead without locking.
                     68: 
                     69:    If the file is locked by someone else, lock_buffer calls
                     70:    ask-user-about-lock (a Lisp function) with two arguments,
                     71:    the file name and the name of the user who did the locking.
                     72:    This function can signal an error, or return t meaning
                     73:    take away the lock, or return nil meaning ignore the lock.  */
                     74: 
                     75: /* The lock file name is the file name with "/" replaced by "!"
                     76:    and put in the Emacs lock directory.  */
                     77: /* (ie., /ka/king/junk.tex -> /!/!ka!king!junk.tex). */
                     78: 
                     79: void
                     80: lock_file (fn)
                     81:      register Lisp_Object fn;
                     82: {
                     83:   register Lisp_Object attack;
                     84:   register char *lfname;
                     85: 
                     86:   /* Create the name of the lock-file for file fn */
                     87:   lfname = (char *) alloca (XSTRING (fn)->size + strlen (PATH_LOCK) + 1);
                     88:   fill_in_lock_file_name (lfname, fn);
                     89: 
                     90:   /* See if this file is visited and has changed on disk since it was visited.  */
                     91:   {
                     92:     register Lisp_Object subject_buf = Fget_file_buffer (fn);
                     93:     if (!NULL (subject_buf)
                     94:        && NULL (Fverify_visited_file_modtime (subject_buf))
                     95:        && !NULL (Ffile_exists_p (fn)))
                     96:       call1 (intern ("ask-user-about-supersession-threat"), fn);
                     97:   }
                     98: 
                     99:   /* Try to lock the lock. */
                    100:   if (lock_if_free (lfname) <= 0)
                    101:     /* Return now if we have locked it, or if lock dir does not exist */
                    102:     return;
                    103: 
                    104:   /* Else consider breaking the lock */
                    105:   attack = call2 (intern ("ask-user-about-lock"), fn,
                    106:                  lock_file_owner_name (lfname));
                    107:   if (!NULL (attack))
                    108:     /* User says take the lock */
                    109:     {
                    110:       lock_superlock (lfname);
                    111:       lock_file_1 (lfname, O_WRONLY) ;
                    112:       unlink (PATH_SUPERLOCK);
                    113:       return;
                    114:     }
                    115:   /* User says ignore the lock */
                    116: }
                    117: 
                    118: fill_in_lock_file_name (lockfile, fn)
                    119:      register char *lockfile;
                    120:      register Lisp_Object fn;
                    121: {
                    122:   register char *p;
                    123: 
                    124:   strcpy (lockfile, PATH_LOCK);
                    125: 
                    126:   p = lockfile + strlen (lockfile);
                    127: 
                    128:   strcpy (p, XSTRING (fn)->data);
                    129: 
                    130:   for (; *p; p++)
                    131:     {
                    132:       if (*p == '/')
                    133:        *p = '!';
                    134:     }
                    135: }
                    136: 
                    137: /* Lock the lock file named LFNAME.
                    138:    If MODE is O_WRONLY, we do so even if it is already locked.
                    139:    If MODE is O_WRONLY | O_EXCL | O_CREAT, we do so only if it is free.
                    140:    Return 1 if successful, 0 if not.  */
                    141: 
                    142: int
                    143: lock_file_1 (lfname, mode)
                    144:      int mode; char *lfname; 
                    145: {
                    146:   register int fd;
                    147:   char buf[20];
                    148: 
                    149:   if ((fd = open (lfname, mode, 0666)) >= 0)
                    150:     {
                    151:       fchmod (fd, 0666);
                    152:       sprintf (buf, "%d ", getpid ());
                    153:       write (fd, buf, strlen (buf));
                    154:       close (fd);
                    155:       return 1;
                    156:     }
                    157:   else
                    158:     return 0;
                    159: }
                    160: 
                    161: /* Lock the lock named LFNAME if possible.
                    162:    Return 0 in that case.
                    163:    Return positive if lock is really locked by someone else.
                    164:    Return -1 if cannot lock for any other reason.  */
                    165: 
                    166: int
                    167: lock_if_free (lfname)
                    168:      register char *lfname; 
                    169: {
                    170:   register int clasher;
                    171: 
                    172:   while (lock_file_1 (lfname, O_WRONLY | O_EXCL | O_CREAT) == 0)
                    173:     {
                    174:       if (errno != EEXIST)
                    175:        return -1;
                    176:       clasher = current_lock_owner (lfname);
                    177:       if (clasher != 0)
                    178:        if (clasher != getpid ())
                    179:          return (clasher);
                    180:        else return (0);
                    181:       /* Try again to lock it */
                    182:     }
                    183:   return 0;
                    184: }
                    185: 
                    186: /* Return the pid of the process that claims to own the lock file LFNAME,
                    187:    or 0 if nobody does or the lock is obsolete,
                    188:    or -1 if something is wrong with the locking mechanism.  */
                    189: 
                    190: int
                    191: current_lock_owner (lfname)
                    192:      char *lfname;
                    193: {
                    194:   int owner = current_lock_owner_1 (lfname);
                    195:   if (owner == 0 && errno == ENOENT)
                    196:     return (0);
                    197:   /* Is it locked by a process that exists?  */
                    198:   if (owner != 0 && (kill (owner, 0) >= 0 || errno == EPERM))
                    199:     return (owner);
                    200:   if (unlink (lfname) < 0)
                    201:     return (-1);
                    202:   return (0);
                    203: }
                    204: 
                    205: int
                    206: current_lock_owner_1 (lfname)
                    207:      char *lfname;
                    208: {
                    209:   register int fd;
                    210:   char buf[20];
                    211:   int tem;
                    212: 
                    213:   fd = open (lfname, O_RDONLY, 0666);
                    214:   if (fd < 0)
                    215:     return 0;
                    216:   tem = read (fd, buf, sizeof buf);
                    217:   close (fd);
                    218:   return (tem <= 0 ? 0 : atoi (buf));
                    219: }
                    220: 
                    221: 
                    222: void
                    223: unlock_file (fn)
                    224:      register Lisp_Object fn;
                    225: {
                    226:   register char *lfname;
                    227: 
                    228:   lfname = (char *) alloca (XSTRING (fn)->size + strlen (PATH_LOCK) + 1);
                    229:   fill_in_lock_file_name (lfname, fn);
                    230: 
                    231:   lock_superlock (lfname);
                    232: 
                    233:   if (current_lock_owner_1 (lfname) == getpid ())
                    234:     unlink (lfname);
                    235: 
                    236:   unlink (PATH_SUPERLOCK);
                    237: }
                    238: 
                    239: lock_superlock (lfname)
                    240:      char *lfname;
                    241: {
                    242:   register int i, fd;
                    243: 
                    244:   for (i = -20; i < 0 && (fd = open (PATH_SUPERLOCK,
                    245:                                     O_WRONLY | O_EXCL | O_CREAT, 0666)) < 0;
                    246:        i++)
                    247:     {
                    248:       if (errno != EEXIST)
                    249:        return;
                    250:       sleep (1);
                    251:     }
                    252:   if (fd >= 0)
                    253:     {
                    254:       fchmod (fd, 0666);
                    255:       write (fd, lfname, strlen (lfname));
                    256:       close (fd);
                    257:     }
                    258: }
                    259: 
                    260: void
                    261: unlock_all_files ()
                    262: {
                    263:   register Lisp_Object tail;
                    264:   register struct buffer *b;
                    265: 
                    266:   for (tail = Vbuffer_alist; XGCTYPE (tail) == Lisp_Cons;
                    267:        tail = XCONS (tail)->cdr)
                    268:     {
                    269:       b = XBUFFER (XCONS (XCONS (tail)->car)->cdr);
                    270:       if (XTYPE (b->filename) == Lisp_String &&
                    271:          b->save_modified < b->text.modified)
                    272:        unlock_file (b->filename);
                    273:     }
                    274: }
                    275: 
                    276: 
                    277: DEFUN ("lock-buffer", Flock_buffer, Slock_buffer,
                    278:   0, 1, 0,
                    279:   "Locks FILE, if current buffer is modified.\n\
                    280: FILE defaults to current buffer's visited file,\n\
                    281: or else nothing is done if current buffer isn't visiting a file.")
                    282:   (fn)
                    283:      Lisp_Object fn;
                    284: {
                    285:   if (NULL (fn))
                    286:     fn = bf_cur->filename;
                    287:   else
                    288:     CHECK_STRING (fn, 0);
                    289:   if (bf_cur->save_modified < bf_modified
                    290:       && !NULL (fn))
                    291:     lock_file (fn);
                    292:   return Qnil;    
                    293: }
                    294: 
                    295: DEFUN ("unlock-buffer", Funlock_buffer, Sunlock_buffer,
                    296:   0, 0, 0,
                    297:  "Unlocks the file visited in the current buffer,\n\
                    298: if it should normally be locked.")
                    299:   ()
                    300: {
                    301:   if (bf_cur->save_modified < bf_modified &&
                    302:       XTYPE (bf_cur->filename) == Lisp_String)
                    303:     unlock_file (bf_cur->filename);
                    304:   return Qnil;
                    305: }
                    306: 
                    307: 
                    308: /* Unlock the file visited in buffer BUFFER.  */
                    309: 
                    310: unlock_buffer (buffer)
                    311:      struct buffer *buffer;
                    312: {
                    313:   bf_cur->text.modified = bf_modified;
                    314:   if (buffer->save_modified < buffer->text.modified &&
                    315:       XTYPE (buffer->filename) == Lisp_String)
                    316:     unlock_file (buffer->filename);
                    317: }
                    318: 
                    319: DEFUN ("file-locked-p", Ffile_locked_p, Sfile_locked_p, 0, 1, 0,
                    320:   "Returns nil if the FILENAME is not locked,\n\
                    321: t if it is locked by you, else a string of the name of the locker.")
                    322:   (fn)
                    323:   Lisp_Object fn;
                    324: {
                    325:   register char *lfname;
                    326:   int owner;
                    327: 
                    328:   fn = Fexpand_file_name (fn, Qnil);
                    329: 
                    330:   /* Create the name of the lock-file for file filename */
                    331:   lfname = (char *) alloca (XSTRING (fn)->size + strlen (PATH_LOCK) + 1);
                    332:   fill_in_lock_file_name (lfname, fn);
                    333: 
                    334:   owner = current_lock_owner (lfname);
                    335:   if (owner <= 0)
                    336:     return (Qnil);
                    337:   else if (owner == getpid ())
                    338:     return (Qt);
                    339:   
                    340:   return (lock_file_owner_name (lfname));
                    341: }
                    342: 
                    343: syms_of_filelock ()
                    344: {
                    345:   defsubr (&Sunlock_buffer);
                    346:   defsubr (&Slock_buffer);
                    347:   defsubr (&Sfile_locked_p);
                    348: }
                    349: 
                    350: #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.