Annotation of GNUtools/emacs/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 free software; you can redistribute it and/or modify
                      6: it under the terms of the GNU General Public License as published by
                      7: the Free Software Foundation; either version 1, or (at your option)
                      8: any later version.
                      9: 
                     10: GNU Emacs is distributed in the hope that it will be useful,
                     11: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     12: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     13: GNU General Public License for more details.
                     14: 
                     15: You should have received a copy of the GNU General Public License
                     16: along with GNU Emacs; see the file COPYING.  If not, write to
                     17: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     18: 
                     19: 
                     20: #include <sys/types.h>
                     21: #include <sys/stat.h>
                     22: #include "config.h"
                     23: #ifdef hpux
                     24: /* needed by <pwd.h> */
                     25: #include <stdio.h>
                     26: #undef NULL
                     27: #endif
                     28: #include "lisp.h"
                     29: #include "paths.h"
                     30: #include "buffer.h"
                     31: 
                     32: #ifdef VMS
                     33: #include "vms-pwd.h"
                     34: #else
                     35: #include <pwd.h>
                     36: #endif
                     37: 
                     38: #include <errno.h>
                     39: #include <sys/file.h>
                     40: #ifdef USG
                     41: #include <fcntl.h>
                     42: #endif /* USG */
                     43: 
                     44: #include "filetypes.h"
                     45: 
                     46: extern int errno;
                     47: 
                     48: #ifdef VMS
                     49: /* Prevent the file from being totally empty.  */
                     50: static dummy () {}
                     51: #endif
                     52: 
                     53: #ifdef CLASH_DETECTION
                     54:   
                     55: /* If system does not have symbolic links, it does not have lstat.
                     56:    In that case, use ordinary stat instead.  */
                     57: 
                     58: #ifndef S_IFLNK
                     59: #define lstat stat
                     60: #endif
                     61: 
                     62: static Lisp_Object
                     63: lock_file_owner_name (lfname)
                     64:      char *lfname;
                     65: {
                     66:   struct stat s;
                     67:   struct passwd *the_pw;
                     68:   extern struct passwd *getpwuid ();
                     69: 
                     70:   if (lstat (lfname, &s) == 0)
                     71:     the_pw = getpwuid (s.st_uid);
                     72:   return (the_pw == 0 ? Qnil : build_string (the_pw->pw_name));
                     73: }
                     74: 
                     75: 
                     76: /* lock_file locks file fn,
                     77:    meaning it serves notice on the world that you intend to edit that file.
                     78:    This should be done only when about to modify a file-visiting
                     79:    buffer previously unmodified.
                     80:    Do not (normally) call lock_buffer for a buffer already modified,
                     81:    as either the file is already locked, or the user has already
                     82:    decided to go ahead without locking.
                     83: 
                     84:    When lock_buffer returns, either the lock is locked for us,
                     85:    or the user has said to go ahead without locking.
                     86: 
                     87:    If the file is locked by someone else, lock_buffer calls
                     88:    ask-user-about-lock (a Lisp function) with two arguments,
                     89:    the file name and the name of the user who did the locking.
                     90:    This function can signal an error, or return t meaning
                     91:    take away the lock, or return nil meaning ignore the lock.  */
                     92: 
                     93: /* The lock file name is the file name with "/" replaced by "!"
                     94:    and put in the Emacs lock directory.  */
                     95: /* (ie., /ka/king/junk.tex -> /!/!ka!king!junk.tex). */
                     96: 
                     97: /* If SHORT_FILE_NAMES is defined, the lock file name is the hex
                     98:    representation of a 14-bytes CRC generated from the file name
                     99:    and put in the Emacs lock directory (not very nice, but it works).
                    100:    (ie., /ka/king/junk.tex -> /!/ec92d3ed24a8f0). */
                    101: 
                    102: #ifdef SHORT_FILE_NAMES
                    103: 
                    104: # define CREATE_LOCK_FILE_NAME(lfname, fn) \
                    105:   { lfname = (char *) alloca (14 + strlen (PATH_LOCK) + 1); \
                    106:   fill_in_lock_short_file_name (lfname, fn); }
                    107: 
                    108: #else
                    109: 
                    110: # define CREATE_LOCK_FILE_NAME(lfname, fn) \
                    111:   { lfname = (char *) alloca (XSTRING (fn)->size + strlen (PATH_LOCK) + 1); \
                    112:   fill_in_lock_file_name (lfname, fn); }
                    113: 
                    114: #endif
                    115: 
                    116: 
                    117: 
                    118: void
                    119: lock_file (fn)
                    120:      register Lisp_Object fn;
                    121: {
                    122:   register Lisp_Object attack;
                    123:   register char *lfname;
                    124: 
                    125:   /* Create the name of the lock-file for file fn */
                    126:   CREATE_LOCK_FILE_NAME (lfname, fn);
                    127: 
                    128:   /* See if this file is visited and has changed on disk since it was visited.  */
                    129:   {
                    130:     register Lisp_Object subject_buf = Fget_file_buffer (fn);
                    131:     if (!NULL (subject_buf)
                    132:        && NULL (Fverify_visited_file_modtime (subject_buf))
                    133:        && !NULL (Ffile_exists_p (fn)))
                    134:       call1 (intern ("ask-user-about-supersession-threat"), fn);
                    135:   }
                    136: 
                    137:   /* Try to lock the lock. */
                    138:   if (lock_if_free (lfname) <= 0)
                    139:     /* Return now if we have locked it, or if lock dir does not exist */
                    140:     return;
                    141: 
                    142:   /* Else consider breaking the lock */
                    143:   attack = call2 (intern ("ask-user-about-lock"), fn,
                    144:                  lock_file_owner_name (lfname));
                    145:   if (!NULL (attack))
                    146:     /* User says take the lock */
                    147:     {
                    148:       lock_superlock (lfname);
                    149:       lock_file_1 (lfname, O_WRONLY) ;
                    150:       unlink (PATH_SUPERLOCK);
                    151:       return;
                    152:     }
                    153:   /* User says ignore the lock */
                    154: }
                    155: 
                    156: fill_in_lock_file_name (lockfile, fn)
                    157:      register char *lockfile;
                    158:      register Lisp_Object fn;
                    159: {
                    160:   register char *p;
                    161: 
                    162:   strcpy (lockfile, PATH_LOCK);
                    163: 
                    164:   p = lockfile + strlen (lockfile);
                    165: 
                    166:   strcpy (p, XSTRING (fn)->data);
                    167: 
                    168:   for (; *p; p++)
                    169:     {
                    170:       if (*p == '/')
                    171:        *p = '!';
                    172:     }
                    173: }
                    174: 
                    175: #ifdef SHORT_FILE_NAMES
                    176: fill_in_lock_short_file_name (lockfile, fn)
                    177:      register char *lockfile;
                    178:      register Lisp_Object fn;
                    179: {
                    180:   register union
                    181:     {
                    182:       unsigned int  word [2];
                    183:       unsigned char byte [8];
                    184:     } crc;
                    185:   register unsigned char *p, new;
                    186:   
                    187:   /* 7-bytes cyclic code for burst correction on byte-by-byte basis.
                    188:      the used polynomial is D^7 + D^6 + D^3 +1. [email protected] */
                    189: 
                    190:   crc.word[0] = crc.word[1] = 0;
                    191: 
                    192:   for (p = XSTRING (fn)->data; new = *p++; )
                    193:     {
                    194:       new += crc.byte[7];
                    195:       crc.byte[7] = crc.byte[6];
                    196:       crc.byte[6] = crc.byte[5] + new;
                    197:       crc.byte[5] = crc.byte[4];
                    198:       crc.byte[4] = crc.byte[3];
                    199:       crc.byte[3] = crc.byte[2] + new;
                    200:       crc.byte[2] = crc.byte[1];
                    201:       crc.byte[1] = crc.byte[0];
                    202:       crc.byte[0] = new;
                    203:     }
                    204:   sprintf (lockfile, "%s%.2x%.2x%.2x%.2x%.2x%.2x%.2x", PATH_LOCK,
                    205:           crc.byte[0], crc.byte[1], crc.byte[2], crc.byte[3],
                    206:           crc.byte[4], crc.byte[5], crc.byte[6]);
                    207: }
                    208: #endif /* SHORT_FILE_NAMES */
                    209: 
                    210: /* Lock the lock file named LFNAME.
                    211:    If MODE is O_WRONLY, we do so even if it is already locked.
                    212:    If MODE is O_WRONLY | O_EXCL | O_CREAT, we do so only if it is free.
                    213:    Return 1 if successful, 0 if not.  */
                    214: 
                    215: int
                    216: lock_file_1 (lfname, mode)
                    217:      int mode; char *lfname; 
                    218: {
                    219:   register int fd;
                    220:   char buf[20];
                    221: 
                    222:   if ((fd = open (lfname, mode, 0666)) >= 0)
                    223:     {
                    224: #ifdef NO_FCHMOD
                    225:       chmod (lfname, 0666);
                    226: #else
                    227:       fchmod (fd, 0666);
                    228: #endif
                    229:       sprintf (buf, "%d ", getpid ());
                    230:       write (fd, buf, strlen (buf));
                    231:       close (fd);
                    232:       return 1;
                    233:     }
                    234:   else
                    235:     return 0;
                    236: }
                    237: 
                    238: /* Lock the lock named LFNAME if possible.
                    239:    Return 0 in that case.
                    240:    Return positive if lock is really locked by someone else.
                    241:    Return -1 if cannot lock for any other reason.  */
                    242: 
                    243: int
                    244: lock_if_free (lfname)
                    245:      register char *lfname; 
                    246: {
                    247:   register int clasher;
                    248: 
                    249:   while (lock_file_1 (lfname, O_WRONLY | O_EXCL | O_CREAT) == 0)
                    250:     {
                    251:       if (errno != EEXIST)
                    252:        return -1;
                    253:       clasher = current_lock_owner (lfname);
                    254:       if (clasher != 0)
                    255:        if (clasher != getpid ())
                    256:          return (clasher);
                    257:        else return (0);
                    258:       /* Try again to lock it */
                    259:     }
                    260:   return 0;
                    261: }
                    262: 
                    263: /* Return the pid of the process that claims to own the lock file LFNAME,
                    264:    or 0 if nobody does or the lock is obsolete,
                    265:    or -1 if something is wrong with the locking mechanism.  */
                    266: 
                    267: int
                    268: current_lock_owner (lfname)
                    269:      char *lfname;
                    270: {
                    271:   int owner = current_lock_owner_1 (lfname);
                    272:   if (owner == 0 && errno == ENOENT)
                    273:     return (0);
                    274:   /* Is it locked by a process that exists?  */
                    275:   if (owner != 0 && (kill (owner, 0) >= 0 || errno == EPERM))
                    276:     return (owner);
                    277:   if (unlink (lfname) < 0)
                    278:     return (-1);
                    279:   return (0);
                    280: }
                    281: 
                    282: int
                    283: current_lock_owner_1 (lfname)
                    284:      char *lfname;
                    285: {
                    286:   register int fd;
                    287:   char buf[20];
                    288:   int tem;
                    289: 
                    290:   fd = open (lfname, O_RDONLY, 0666);
                    291:   if (fd < 0)
                    292:     return 0;
                    293:   tem = read (fd, buf, sizeof buf);
                    294:   close (fd);
                    295:   return (tem <= 0 ? 0 : atoi (buf));
                    296: }
                    297: 
                    298: 
                    299: void
                    300: unlock_file (fn)
                    301:      register Lisp_Object fn;
                    302: {
                    303:   register char *lfname;
                    304: 
                    305:   CREATE_LOCK_FILE_NAME (lfname, fn);
                    306: 
                    307:   lock_superlock (lfname);
                    308: 
                    309:   if (current_lock_owner_1 (lfname) == getpid ())
                    310:     unlink (lfname);
                    311: 
                    312:   unlink (PATH_SUPERLOCK);
                    313: }
                    314: 
                    315: lock_superlock (lfname)
                    316:      char *lfname;
                    317: {
                    318:   register int i, fd;
                    319: 
                    320:   for (i = -20; i < 0 && (fd = open (PATH_SUPERLOCK,
                    321:                                     O_WRONLY | O_EXCL | O_CREAT, 0666)) < 0;
                    322:        i++)
                    323:     {
                    324:       if (errno != EEXIST)
                    325:        return;
                    326:       sleep (1);
                    327:     }
                    328:   if (fd >= 0)
                    329:     {
                    330: #ifdef NO_FCHMOD
                    331:       chmod (PATH_SUPERLOCK, 0666);
                    332: #else
                    333:       fchmod (fd, 0666);
                    334: #endif
                    335:       write (fd, lfname, strlen (lfname));
                    336:       close (fd);
                    337:     }
                    338: }
                    339: 
                    340: void
                    341: unlock_all_files ()
                    342: {
                    343:   register Lisp_Object tail;
                    344:   register struct buffer *b;
                    345: 
                    346:   for (tail = Vbuffer_alist; XGCTYPE (tail) == Lisp_Cons;
                    347:        tail = XCONS (tail)->cdr)
                    348:     {
                    349:       b = XBUFFER (XCONS (XCONS (tail)->car)->cdr);
                    350:       if (XTYPE (b->filename) == Lisp_String &&
                    351:          b->save_modified < BUF_MODIFF (b))
                    352:        unlock_file (b->filename);
                    353:     }
                    354: }
                    355: 
                    356: 
                    357: DEFUN ("lock-buffer", Flock_buffer, Slock_buffer,
                    358:   0, 1, 0,
                    359:   "Locks FILE, if current buffer is modified.\n\
                    360: FILE defaults to current buffer's visited file,\n\
                    361: or else nothing is done if current buffer isn't visiting a file.")
                    362:   (fn)
                    363:      Lisp_Object fn;
                    364: {
                    365:   if (NULL (fn))
                    366:     fn = current_buffer->filename;
                    367:   else
                    368:     CHECK_STRING (fn, 0);
                    369:   if (current_buffer->save_modified < MODIFF
                    370:       && !NULL (fn))
                    371:     lock_file (fn);
                    372:   return Qnil;    
                    373: }
                    374: 
                    375: DEFUN ("unlock-buffer", Funlock_buffer, Sunlock_buffer,
                    376:   0, 0, 0,
                    377:  "Unlocks the file visited in the current buffer,\n\
                    378: if it should normally be locked.")
                    379:   ()
                    380: {
                    381:   if (current_buffer->save_modified < MODIFF &&
                    382:       XTYPE (current_buffer->filename) == Lisp_String)
                    383:     unlock_file (current_buffer->filename);
                    384:   return Qnil;
                    385: }
                    386: 
                    387: 
                    388: /* Unlock the file visited in buffer BUFFER.  */
                    389: 
                    390: unlock_buffer (buffer)
                    391:      struct buffer *buffer;
                    392: {
                    393:   if (buffer->save_modified < BUF_MODIFF (buffer)
                    394:       && XTYPE (buffer->filename) == Lisp_String)
                    395:     unlock_file (buffer->filename);
                    396: }
                    397: 
                    398: DEFUN ("file-locked-p", Ffile_locked_p, Sfile_locked_p, 0, 1, 0,
                    399:   "Returns nil if the FILENAME is not locked,\n\
                    400: t if it is locked by you, else a string of the name of the locker.")
                    401:   (fn)
                    402:   Lisp_Object fn;
                    403: {
                    404:   register char *lfname;
                    405:   int owner;
                    406: 
                    407:   fn = Fexpand_file_name (fn, Qnil);
                    408: 
                    409:   /* Create the name of the lock-file for file filename */
                    410:   CREATE_LOCK_FILE_NAME (lfname, fn);
                    411: 
                    412:   owner = current_lock_owner (lfname);
                    413:   if (owner <= 0)
                    414:     return (Qnil);
                    415:   else if (owner == getpid ())
                    416:     return (Qt);
                    417:   
                    418:   return (lock_file_owner_name (lfname));
                    419: }
                    420: 
                    421: syms_of_filelock ()
                    422: {
                    423:   defsubr (&Sunlock_buffer);
                    424:   defsubr (&Slock_buffer);
                    425:   defsubr (&Sfile_locked_p);
                    426: }
                    427: 
                    428: #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.