home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR41 / CBASE11.ZIP / LOCKB.C < prev    next >
C/C++ Source or Header  |  1993-01-01  |  8KB  |  340 lines

  1. /*
  2.  *    Copyright (c) 1989-1992 Citadel Software, Inc.
  3.  *    All Rights Reserved
  4.  */
  5.  
  6. /* #ident    "@(#)lockb.c    1.7 - 93/01/01" */
  7.  
  8. #include <port.h>
  9.  
  10. /* standard headers */
  11. #include <errno.h>
  12. #ifdef AC_STDDEF
  13. #include <stddef.h>
  14. #endif
  15.  
  16. /* local headers */
  17. #include "blkio_.h"
  18.  
  19. /* system headers */
  20. #if OPSYS == OS_AMIGA        /* Amiga DOS =================================*/
  21.  
  22. #elif OPSYS == OS_MAC        /* Macintosh =================================*/
  23.  
  24. #elif OPSYS == OS_DOS        /* DOS =======================================*/
  25. #include <limits.h>        /* LONG_MAX definition */
  26. #if CCOM == CC_BC        /* Borland C++ -------------------------------*/
  27. #include <io.h>
  28. #define _LK_UNLCK    (0)    /* unlock */
  29. #define _LK_LOCK    (1)    /* lock */
  30. #define _LK_NBLCK    (2)    /* non-blocking lock */
  31. #define _LK_RLCK    (3)    /* read lock */
  32. #define _LK_NBRLCK    (4)    /* non-blocking read lock */
  33. #elif CCOM == CC_MSC || CCOM == CC_MSQC    /* Microsoft C or Quick C ------------*/
  34. #include <sys\locking.h>
  35. #include <io.h>
  36. #endif
  37. #elif OPSYS == OS_UNIX        /* UNIX ======================================*/
  38. #include <fcntl.h>
  39. #ifdef AC_PROTO
  40. int fcntl(int fd, int cmd, ...);
  41. #else
  42. int fcntl();
  43. #endif
  44. #elif OPSYS == OS_VMS        /* VMS =======================================*/
  45.  
  46. #endif
  47.  
  48. /*man---------------------------------------------------------------------------
  49. NAME
  50.      lockb - block file record locking
  51.  
  52. SYNOPSIS
  53.      #include <blkio.h>
  54.  
  55.      int lockb(bp, ltype, start, len)
  56.      BLKFILE *bp;
  57.      int ltype;
  58.      bpos_t start;
  59.      bpos_t len;
  60.  
  61. DESCRIPTION
  62.      The lockb function will allow segments of a block file to be
  63.      locked.  bp is the BLKFILE pointer for the file to be locked.
  64.  
  65.      ltype indicates the target status of the lock.  The lock types
  66.      available are:
  67.  
  68.        B_UNLCK unlock block file segment
  69.        B_RDLCK lock block file segment for reading
  70.        B_WRLCK lock block file segment for reading and writing
  71.        B_RDLKW lock block file segment for reading (wait)
  72.        B_WRLKW lock block file segment for reading and writing (wait)
  73.  
  74.      For the lock types which wait, lockb will not return until the
  75.      lock is available.  For the lock types which do not wait, if the
  76.      lock is unavailable because of a lock held by another process  a
  77.      value of -1 is returned and errno set to EAGAIN.
  78.  
  79.      start is the first block to lock.  len is the number of
  80.      contiguous blocks including and following block start to be
  81.      locked or unlocked.  A lock may be set to extend to the end of
  82.      the file by setting len to zero.
  83.  
  84.      The buffers are flushed before unlocking.
  85.  
  86.      lockb will fail if one or more of the following is true:
  87.  
  88.      [EAGAIN]       ltype is B_RDLCK and the file segment to be locked
  89.                     is already write locked by another process, or
  90.                     ltype is B_WRLCK and the file segment to be locked
  91.                     is already read or write locked by another
  92.                     process.
  93.      [EINVAL]       bp is is not a valid BLKFILE pointer.
  94.      [EINVAL]       ltype is not one of the valid lock types.
  95.      [BENOPEN]      bp is not open.
  96.      [BENOPEN]      ltype is B_RDLCK or B_RDLKW and bp is not opened
  97.                     for reading or ltype is B_WRLCK or B_WRLKW and bp
  98.                     is not open for writing.
  99.  
  100. DIAGNOSTICS
  101.      Upon successful completion, a value of 0 is returned.  Otherwise,
  102.      a value of -1 is returned, and errno set to indicate the error.
  103.  
  104. ------------------------------------------------------------------------------*/
  105. #ifdef AC_PROTO
  106. int lockb(BLKFILE *bp, int ltype, bpos_t start, bpos_t len)
  107. #else
  108. int lockb(bp, ltype, start, len)
  109. BLKFILE *bp;
  110. int ltype;
  111. bpos_t start;
  112. bpos_t len;
  113. #endif
  114. {
  115. #if OPSYS == AMIGA
  116.  
  117. #elif OPSYS == OS_DOS
  118.     long    length    = 0;    /* length in bytes of segment to lock */
  119.     int    mode    = 0;    /* file locking mode */
  120.     long    offset    = 0;    /* offset from start of file */
  121. #elif OPSYS == OS_MAC
  122.  
  123. #elif OPSYS == OS_UNIX
  124.     int    cmd    = 0;    /* lock command */
  125.     struct flock lck;    /* lock structure */
  126. #elif OPSYS == OS_VMS
  127.  
  128. #endif
  129.     /* validate arguments */
  130.     if (!b_valid(bp)) {
  131.         errno = EINVAL;
  132.         return -1;
  133.     }
  134.  
  135.     /* check if not open */
  136.     if (!(bp->flags & BIOOPEN)) {
  137.         errno = BENOPEN;
  138.         return -1;
  139.     }
  140.  
  141.     /* set lock flags */
  142.     switch (ltype) {
  143.     case B_RDLCK:
  144.         if (!(bp->flags & BIOREAD)) {
  145.             errno = BENOPEN;
  146.             return -1;
  147.         }
  148. #if OPSYS == AMIGA
  149.  
  150. #elif OPSYS == OS_DOS
  151.         mode = _LK_NBRLCK;
  152. #elif OPSYS == OS_MAC
  153.  
  154. #elif OPSYS == OS_UNIX
  155.         cmd = F_SETLK;
  156.         lck.l_type = F_RDLCK;
  157. #elif OPSYS == OS_VMS
  158.  
  159. #endif
  160.         break;
  161.     case B_RDLKW:
  162.         if (!(bp->flags & BIOREAD)) {
  163.             errno = BENOPEN;
  164.             return -1;
  165.         }
  166. #if OPSYS == AMIGA
  167.  
  168. #elif OPSYS == OS_DOS
  169.         mode = _LK_RLCK;
  170. #elif OPSYS == OS_MAC
  171.  
  172. #elif OPSYS == OS_UNIX
  173.         cmd = F_SETLKW;
  174.         lck.l_type = F_RDLCK;
  175. #elif OPSYS == OS_VMS
  176.  
  177. #endif
  178.         break;
  179.     case B_WRLCK:
  180.         if (!(bp->flags & BIOWRITE)) {
  181.             errno = BENOPEN;
  182.             return -1;
  183.         }
  184. #if OPSYS == AMIGA
  185.  
  186. #elif OPSYS == OS_DOS
  187.         mode = _LK_NBLCK;
  188. #elif OPSYS == OS_MAC
  189.  
  190. #elif OPSYS == OS_UNIX
  191.         cmd = F_SETLK;
  192.         lck.l_type = F_WRLCK;
  193. #elif OPSYS == OS_VMS
  194.  
  195. #endif
  196.         break;
  197.     case B_WRLKW:
  198.         if (!(bp->flags & BIOWRITE)) {
  199.             errno = BENOPEN;
  200.             return -1;
  201.         }
  202. #if OPSYS == AMIGA
  203.  
  204. #elif OPSYS == OS_DOS
  205.         mode = _LK_LOCK;
  206. #elif OPSYS == OS_MAC
  207.  
  208. #elif OPSYS == OS_UNIX
  209.         cmd = F_SETLKW;
  210.         lck.l_type = F_WRLCK;
  211. #elif OPSYS == OS_VMS
  212.  
  213. #endif
  214.         break;
  215.     case B_UNLCK:
  216.         /* flush buffers */
  217.         if (bflush(bp) == -1) {
  218.             BERRLOG;
  219.             return -1;
  220.         }
  221. #if OPSYS == AMIGA
  222.  
  223. #elif OPSYS == OS_DOS
  224.         mode = _LK_UNLCK;
  225. #elif OPSYS == OS_MAC
  226.  
  227. #elif OPSYS == OS_UNIX
  228.         cmd = F_SETLK;
  229.         lck.l_type = F_UNLCK;
  230. #elif OPSYS == OS_VMS
  231.  
  232. #endif
  233.         break;
  234.     default:
  235.         errno = EINVAL;
  236.         return -1;
  237.         break;
  238.     }
  239.  
  240.     /* lock */
  241. #ifndef SINGLE_USER
  242. #if OPSYS == AMIGA
  243.  
  244. #elif OPSYS == OS_DOS
  245.     if (start == 0) {
  246.         offset = 0;
  247.         if (len == 0) {
  248.             length = LONG_MAX;
  249.         } else {
  250.             length = bp->hdrsize + (len - 1) * bp->blksize;
  251.         }
  252.     } else {
  253.         offset = bp->hdrsize + (start - 1) * bp->blksize;
  254.         if (len == 0) {
  255.             length = LONG_MAX - offset;
  256.         } else {
  257.             length = len * bp->blksize;
  258.         }
  259.     }
  260. #if CCOM == CC_BC
  261.     switch (mode) {
  262.     case _LK_UNLCK:    /* unlock */
  263.         if (unlock(bp->fd.i, offset, length) == -1) {
  264.             /* ignore 'segment not locked' error */
  265.             if (errno == EACCES) return 0;
  266.             return -1;
  267.         }
  268.         break;
  269.     default:    /* lock */
  270.         if (lock(bp->fd.i, offset, length) == -1) {
  271.             if (errno == EACCES) errno = EAGAIN;
  272. #ifdef DEBUG
  273.             if (errno != EAGAIN) BERRLOG;
  274. #endif
  275.             return -1;
  276.         }
  277.         break;
  278.     }
  279. #elif CCOM == CC_MSC || CCOM == CC_MSQC
  280.     if (lseek(bp->fd.i, offset, SEEK_SET) == -1) {
  281.         BERRLOG;
  282.         return -1;
  283.     }
  284.     if (_locking(bp->fd.i, mode, length) == -1) {
  285.         /* ignore 'segment not locked' error */
  286.         if (mode == _LK_UNLCK) {
  287.             if (errno == EACCES) return 0;
  288.         }
  289.         if (errno == EACCES) errno = EAGAIN;
  290. #ifdef DEBUG
  291.         if (errno != EAGAIN) BERRLOG;
  292. #endif
  293.         return -1;
  294.     }
  295. #endif
  296. #elif OPSYS == OS_MAC
  297.  
  298. #elif OPSYS == OS_UNIX
  299.     if (start == 0) {
  300.         lck.l_whence = 0;
  301.         if (len == 0) {
  302.             lck.l_len = 0;
  303.         } else {
  304.             lck.l_len = bp->hdrsize + (len - 1) * bp->blksize;
  305.         }
  306.     } else {
  307.         lck.l_whence = bp->hdrsize + (start - 1) * bp->blksize;
  308.         if (len == 0) {
  309.             lck.l_len = 0;
  310.         } else {
  311.             lck.l_len = len * bp->blksize;
  312.         }
  313.     }
  314.     lck.l_start = 0;
  315. /*    lck.l_sysid = 0; l_sysid not defined by BSD UNIX */
  316.     lck.l_pid = 0;
  317.     if (fcntl(bp->fd.i, cmd, &lck) == -1) {
  318.         /* new versions of fcntl will use EAGAIN */
  319.         if (errno == EACCES) errno = EAGAIN;
  320. #ifdef DEBUG
  321.         if (errno != EAGAIN) BERRLOG;
  322. #endif
  323.         return -1;
  324.     }
  325. #elif OPSYS == OS_VMS
  326.  
  327. #endif
  328. #endif    /* #ifndef SINGLE_USER */
  329.  
  330.     /* if locking, load endblk */
  331.     if (ltype != B_UNLCK) {
  332.         if (b_uendblk(bp, &bp->endblk) == -1) {
  333.             BERRLOG;
  334.             return -1;
  335.         }
  336.     }
  337.  
  338.     return 0;
  339. }
  340.