DosSetFileLocks

From EDM2
Jump to: navigation, search

Locks and unlocks a range of an open file.

Syntax

DosSetFileLocks(hFile, pflUnlock, pflLock, timeout, flags)

Parameters

hFile (HFILE) - input 
File handle.
pflUnlock (PFILELOCK) - input 
Address of the structure containing the offset and length of a range to be unlocked.
pflLock (PFILELOCK) - input 
Address of the structure containing the offset and length of a range to be locked.
timeout (ULONG) - input 
The maximum time, in milliseconds, that the process is to wait for the requested locks.
flags (ULONG) - input 
Flags that describe the action to be taken.
This parameter has the following bit fields:
Bit Description
31-2 Reserved flags
1
Atomic
This bit defines a request for atomic locking. If this bit is set to 1 and the lock range is equal to the unlock range, an atomic lock occurs. If this bit is set to 1 and the lock range is not equal to the unlock range, an error is returned.
If this bit is set to 0, then the lock may or may not occur atomically with the unlock.
0
Share
This bit defines the type of access that other processes may have to the file range that is being locked.
If this bit is set to 0 (the default), other processes have no access to the locked file range. The current process has exclusive access to the locked file range, which must not overlap any other locked file range.
If this bit is set to 1, the current process and other processes have shared read-only access to the locked file range. A file range with shared access may overlap any other file range with shared access, but must not overlap any other file range with exclusive access.

Return Code

ulrc (APIRET) - returns

DosSetFileLocks returns one of the following values:

  • 0 NO_ERROR
  • 1 ERROR_INVALID_FUNCTION
  • 6 ERROR_INVALID_HANDLE
  • 33 ERROR_LOCK_VIOLATION
  • 36 ERROR_SHARING_BUFFER_EXCEEDED
  • 87 ERROR_INVALID_PARAMETER
  • 95 ERROR_INTERRUPT
  • 174 ERROR_ATOMIC_LOCK_NOT_SUPPORTED
  • 175 ERROR_READ_LOCKS_NOT_SUPPORTED

Remarks

DosSetFileLocks allows a process to lock and unlock a range in a file. The time during which a file range is locked should be short.

If the lock and unlock ranges are both zero, ERROR_LOCK_VIOLATION is returned to the caller.

If you only want to lock a file range, set the unlock file offset and the unlock range length to zero.

If you only want to unlock a file range, set the lock file offset and the lock range length to zero.

When the Atomic bit of flags is set to 0, and DosSetFileLocks specifies a lock operation and an unlock operation, the unlock operation occurs first, and then the lock operation is performed. If an error occurs during the unlock operation, an error code is returned and the lock operation is not performed. If an error occurs during the lock operation, an error code is returned and the unlock remains in effect if it was successful.

The lock operation is atomic when all of these conditions are met:

  • The Atomic bit is set to 1 in flags
  • The unlock range is the same as the lock range
  • The process has shared access to the file range, and has requested exclusive access to it; or the process has exclusive access to the file range, and has requested shared access to it.

Some file system drivers (FSDs) may not support atomic lock operations. Versions of the operating system prior to OS/2 Version 2.00 do not support atomic lock operations. If the application receives the error code ERROR_ATOMIC_LOCK_NOT_SUPPORTED, the application should unlock the file range and then lock it using a non-atomic operation (with the atomic bit set to 0 in flags). The application should also refresh its internal buffers before making any changes to the file.

If you issue DosClose to close a file with locks still in effect, the locks are released in no defined sequence.

If you end a process with a file open, and you have locks in effect in that file, the file is closed and the locks are released in no defined sequence.

The locked range can be anywhere in the logical file. Locking beyond the end of the file is not an error. A file range to be locked exclusively must first be cleared of any locked file subranges or overlapping locked file ranges.

If you repeat DosSetFileLocks for the same file handle and file range, then you duplicate access to the file range. Access to locked file ranges is not duplicated across DosExecPgm. The proper method of using locks is to attempt to lock the file range, and to examine the return value.

The following table shows the level of access granted when the accessed file range is locked with an exclusive lock or a shared lock. "Owner" refers to a process that owns the lock. "Non-owner" refers to a process that does not own the lock.

Action Exclusive Lock Shared Lock
Owner read Success Success
Non-owner read Wait for unlock. Return error code after time-out. Success
Owner write Success Wait for unlock. Return error code after time-out.
Non-owner write Wait for unlock. Return error code after time-out. Wait for unlock. Return error code after time-out.

If only locking is specified, DosSetFileLocks locks the specified file range using pflLock. If the lock operation cannot be accomplished, an error is returned, and the file range is not locked.

After the lock request is processed, a file range can be unlocked using the pflUnlock parameter of another DosSetFileLocks request. If unlocking cannot be accomplished, an error is returned.

Instead of denying read/write access to an entire file by specifying access and sharing modes with DosOpen requests, a process attempts to lock only the range needed for read/write access and examines the error code returned.

Once a specified file range is locked exclusively, read and write access by another process is denied until the file range is unlocked. If both unlocking and locking are specified by DosSetFileLocks, the unlocking operation is performed first, then locking is done.

Example Code

This example opens or creates and opens a file named "FLOCK.DAT," and updates it using file locks.

#define INCL_DOSFILEMGR       /* File Manager values */
#define INCL_DOSERRORS        /* DOS Error values    */
#include <os2.h>
#include <stdio.h>
#include <string.h>

int main(VOID) {

HFILE     FileHandle   = NULLHANDLE;  /* File handle */
ULONG     Action       = 0,           /* Action taken by DosOpen */
          Wrote        = 0,           /* Number of bytes written by DosWrite */
          i            = 0;           /* Loop index */
CHAR      FileData[40] = "Forty bytes of demonstration text data\r\n";
APIRET    rc           = NO_ERROR;    /* Return code */
FILELOCK  LockArea     = {0},         /* Area of file to lock */
          UnlockArea   = {0};         /* Area of file to unlock */

rc = DosOpen("flock.dat",                   /* File to open */
             &FileHandle,                   /* File handle */
             &Action,                       /* Action taken */
             4000L,                         /* File primary allocation */
             FILE_ARCHIVED,                 /* File attributes */
             FILE_OPEN | FILE_CREATE,       /* Open function type */
             OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE,
             0L);                           /* No extended attributes */
if (rc != NO_ERROR) {                       /* If open failed */
   printf("DosOpen error: return code = %u\n", rc);
   return 1;
}
LockArea.lOffset = 0L;              /* Start locking at beginning of file */
LockArea.lRange =  40L;             /* Use a lock range of 40 bytes       */

         /* Write 8000 bytes to the file, 40 bytes at a time */
for (i=0; i<200; ++i) {
  rc = DosSetFileLocks(FileHandle,        /* File handle   */
                       &UnlockArea,       /* Unlock previous record (if any) */
                       &LockArea,         /* Lock current record */
                       2000L,             /* Lock time-out value of 2 seconds */
                       0L);               /* Exclusive lock, not atomic */
  if (rc != NO_ERROR) {
     printf("DosSetFileLocks error: return code = %u\n", rc);
     return 1;
  }

  rc = DosWrite(FileHandle, FileData, sizeof(FileData), &Wrote);
  if (rc != NO_ERROR) {
     printf("DosWrite error: return code = %u\n", rc);
     return 1;
  }

   UnlockArea = LockArea;      /* Will unlock this record on next iteration */
   LockArea.lOffset += 40L;    /* Prepare to lock next record               */

} /* endfor - 8000 bytes written */
rc = DosClose(FileHandle);    /* Close file, this releases outstanding locks */
/* Should check if (rc != NO_ERROR) here ... */
return NO_ERROR;
}

Related Functions