Annotation of 43BSD/contrib/emacs/src/filelock.c, revision 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.