DosSetFileLocks

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:

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. 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. 
 * 1) define INCL_DOSFILEMGR      /* File Manager values */
 * 2) define INCL_DOSERRORS       /* DOS Error values    */
 * 3) include 
 * 4) include 
 * 5) include 

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

 * DosCancelLockRequest
 * DosDupHandle
 * DosExecPgm
 * DosOpen