home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pp / pp-6.0 / Lib / util / lock.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-18  |  3.4 KB  |  188 lines

  1. /* lock.c: file locking subroutines  */
  2.  
  3. # ifndef lint
  4. static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/lock.c,v 6.0 1991/12/18 20:25:18 jpo Rel $";
  5. # endif
  6.  
  7. /*
  8.  * $Header: /xtel/pp/pp-beta/Lib/util/RCS/lock.c,v 6.0 1991/12/18 20:25:18 jpo Rel $
  9.  *
  10.  * $Log: lock.c,v $
  11.  * Revision 6.0  1991/12/18  20:25:18  jpo
  12.  * Release 6.0
  13.  *
  14.  */
  15.  
  16.  
  17.  
  18. #include "util.h"
  19. #include "sys.file.h"
  20. #ifdef SUNOS4 
  21. #include <fcntl.h>
  22. #endif
  23. #if defined(sun) || defined(SYS5)
  24. #include <unistd.h>
  25. #endif
  26. #include <sys/stat.h>
  27.  
  28.  
  29. static int lk_file ();
  30. static int lk_unlck ();
  31.  
  32. static struct {
  33.     char *name;
  34.     int mode;
  35. } locks [FD_SETSIZE];
  36.  
  37. extern char    *lockdir;
  38. extern int    lockstyle;
  39. extern int    lock_break_time;    /* 30 minutes grace ? */
  40. extern time_t time ();
  41.  
  42. FILE    *flckopen (name, mode)
  43. char    *name;
  44. char    *mode;
  45. {
  46.     FILE    *fp;
  47.  
  48.     if ((fp = fopen (name, mode)) == NULL)
  49.         return NULL;
  50.  
  51.     locks[fileno(fp)].mode = (*mode == 'r' ? O_RDONLY : O_WRONLY);
  52.     switch (lockstyle) {
  53.         case LOCK_FLOCK:
  54. #ifdef LOCK_EX
  55.         if (flock (fileno (fp), LOCK_EX | LOCK_NB) == NOTOK) {
  56.             (void) fclose (fp);
  57.             return NULL;
  58.         }
  59.         return fp;
  60. #else
  61.         break;
  62. #endif
  63.         
  64.         case LOCK_FCNTL:
  65. #ifdef F_RDLCK
  66.         {
  67.             struct flock l;
  68.  
  69.             l.l_len = 0;
  70.             l.l_start = 0;
  71.             l.l_whence = 0;
  72.  
  73.             if (*mode == 'r' && mode[1] != '+')
  74.                 l.l_type = F_RDLCK;
  75.             else
  76.                 l.l_type = F_WRLCK;
  77.                 
  78.             if (fcntl (fileno(fp), F_SETLK, &l) < 0) {
  79.                 (void) fclose (fp);
  80.                 return NULL;
  81.             }
  82.         }
  83.         return fp;
  84. #else
  85.         break;
  86. #endif
  87.         case LOCK_LOCKF:
  88. #ifdef F_TLOCK
  89.         if (lockf (fileno (fp), F_TLOCK, 0L) == NOTOK) {
  90.             (void) fclose (fp);
  91.             return NULL;
  92.         }
  93.         return fp;
  94. #else
  95.         break;
  96. #endif    
  97.         default:
  98.         case LOCK_FILE:
  99.         if (lk_file (name, fileno (fp)) == NOTOK) {
  100.             (void) fclose (fp);
  101.             return NULL;
  102.         }
  103.         break;
  104.     }
  105.     PP_OPER (NULLCP, ("Specified styple of locking (%d) not supported",
  106.               lockstyle));
  107.     return NULL;
  108. }
  109.  
  110. static int lk_file (name, n)
  111. char    *name;
  112. int    n;
  113. {
  114.     char    locktmp[MAXPATHLENGTH];
  115.     char    lockname[MAXPATHLENGTH];
  116.     struct stat st;
  117.     int    fd;
  118.     time_t    now;
  119.  
  120.     if (n < 0 || n >= FD_SETSIZE)
  121.         return NOTOK;
  122.  
  123.     if (fstat (n, &st) == NOTOK) {
  124.         PP_SLOG (LLOG_EXCEPTIONS, name, ("Can't fstat %d file", n));
  125.         return NOTOK;
  126.     }
  127.  
  128.     (void) sprintf (locktmp, "%s/LCK%05.5o+%o.t", lockdir,
  129.             st.st_dev, st.st_ino);
  130.     (void) sprintf (lockname, "%s/LCK%05.5o+%o",
  131.             lockdir, st.st_dev, st.st_ino);
  132.  
  133.     if ((fd = open (locktmp, O_RDWR|O_CREAT, 0)) < 0) {
  134.         PP_SLOG (LLOG_EXCEPTIONS, locktmp,
  135.              ("Can't create lock temp file"));
  136.         return NOTOK;
  137.     }
  138.     (void) close (fd);
  139.  
  140.     if (stat (lockname, &st) != NOTOK) {
  141.         (void) time (&now);
  142.         if (st.st_mtime + lock_break_time < now) {
  143.             PP_NOTICE (("Forcing lock for %s", lockname));
  144.             (void) unlink (lockname);
  145.         }
  146.     }
  147.     if (link (locktmp, lockname) == NOTOK) {
  148.         PP_SLOG (LLOG_EXCEPTIONS, lockname,
  149.              ("Can't lock by linking %s to ", locktmp));
  150.         (void) unlink (locktmp);
  151.         return NOTOK;
  152.     }
  153.     (void) unlink (locktmp);
  154.     locks[fd].name = strdup (lockname);
  155.     return OK;
  156. }
  157.  
  158. int    flckclose (fp)
  159. FILE    *fp;
  160. {
  161.     switch (lockstyle) {
  162.         case LOCK_FCNTL:
  163.         case LOCK_FLOCK:
  164.         if (locks[fileno(fp)].mode == O_WRONLY)
  165.             return check_close (fp);
  166.         else return fclose(fp);
  167.  
  168.         default:
  169.         case LOCK_FILE:
  170.         return lk_unlck (fp);
  171.     }
  172. }
  173.  
  174. static int lk_unlck (fp)
  175. FILE    *fp;
  176. {
  177.     int    n = fileno (fp);
  178.  
  179.     if (n >= 0 && n < FD_SETSIZE && locks[n].name) {
  180.         (void) unlink (locks[n].name);
  181.         free (locks[n].name);
  182.         locks[n].name = NULLCP;
  183.         return check_close (fp);
  184.     }
  185.     (void) fclose (fp);
  186.     return NOTOK;
  187. }
  188.