I was trying to write a test program to test if file locking works correctly. But, one of the tests is getting failed. I am trying to acquire a read lock on a file, but the test failed. When I tried to print the error number, it printed 9
which indicated EBADF
i.e. bad file number (or file descriptor). I also tried to print file descriptor value, it printed 3
which seems to be a valid file descriptor. I am using Netbeans IDE and its Simple Test functionality.
The file to be read is in the same folder as the source code file.
Here's my code:
#include <stdlib.h>
#include <iostream>
#include <sys/file.h>
#include <sys/unistd.h>
using namespace std;
/*
* Simple C++ Test Suite
*/
int acquireRLock(int fd, struct flock &lock) {
lock.l_len = 0;
lock.l_start = 0;
lock.l_whence = SEEK_SET;
lock.l_type = F_RDLCK;
struct flock temp_lock = lock;
fcntl(fd, F_GETLK, &temp_lock);
if(temp_lock.l_type == F_WRLCK) {
return -1;
}
else {
int ret_val = fcntl(fd, F_SETLK, &lock);
if(ret_val == -1) cout << "Failed here errno = " << errno << " fd = " << fd << endl;
return ret_val;
}
}
int acquireWLock(int fd, struct flock &lock) {
lock.l_len = 0;
lock.l_start = 0;
lock.l_whence = SEEK_SET;
lock.l_type = F_WRLCK;
struct flock temp_lock = lock;
fcntl(fd, F_GETLK, &temp_lock);
if(temp_lock.l_type == F_RDLCK || temp_lock.l_type == F_WRLCK)
return -1;
else
return fcntl(fd, F_SETLK, &lock);
}
int FileOpenTest() {
int fd = open("test_file.txt", O_WRONLY);
if(fd == -1) {
cout << "%TEST_FAILED% time=0 testname=FileOPenTest (newsimpletest) message=file open failed" << endl;
}
return fd;
}
void FileReadLockTest(int fd) {
struct flock lock;
if(acquireRLock(fd, lock) < 0) {
cout << "%TEST_FAILED% time=0 testname=FileReadLockTest (newsimpletest) message=file read lock acquire failed" << endl;
}
}
void FileWriteLockTest(int fd) {
struct flock lock;
if(acquireWLock(fd, lock) < 0) {
cout << "%TEST_FAILED% time=0 testname=FileWriteLockTest (newsimpletest) message=file write lock acquire failed" << endl;
}
}
void FileWriteTest(int fd) {
if(write(fd, (void*) "I am a ball", 13) <= 0) {
cout << "%TEST_FAILED% time=0 testname=FileWriteTest (newsimpletest) message=file write failed" << endl;
}
}
void FileCloseTest(int fd) {
if(close(fd) < 0) {
cout << "%TEST_FAILED% time=0 testname=FileCloseTest (newsimpletest) message=file close failed" << endl;
}
}
int main(int argc, char** argv) {
std::cout << "%SUITE_STARTING% newsimpletest" << std::endl;
std::cout << "%SUITE_STARTED%" << std::endl;
std::cout << "%TEST_STARTED% FileOpenTest (newsimpletest)" << std::endl;
int fd = FileOpenTest();
std::cout << "%TEST_FINISHED% time=0 FileOpenTest (newsimpletest)" << std::endl;
std::cout << "%TEST_STARTED% FileReadLockTest (newsimpletest)\n" << std::endl;
FileReadLockTest(fd);
std::cout << "%TEST_FINISHED% time=0 FileReadLockTest (newsimpletest)" << std::endl;
// std::cout << "%TEST_STARTED% FileWriteLockTest (newsimpletest)\n" << std::endl;
// FileWriteLockTest(fd);
// std::cout << "%TEST_FINISHED% time=0 FileWriteLockTest (newsimpletest)" << std::endl;
//
// std::cout << "%TEST_STARTED% FileWriteTest (newsimpletest)\n" << std::endl;
// FileWriteTest(fd);
// std::cout << "%TEST_FINISHED% time=0 FileWriteTest (newsimpletest)" << std::endl;
std::cout << "%TEST_STARTED% FileCloseTest (newsimpletest)\n" << std::endl;
FileCloseTest(fd);
std::cout << "%TEST_FINISHED% time=0 FileCloseTest (newsimpletest)" << std::endl;
std::cout << "%SUITE_FINISHED% time=0" << std::endl;
return (EXIT_SUCCESS);
}
It shows following output:
On un-commenting the code to acquire write lock, write lock is acquired and file is written, and the read lock still fails as shown in the output below. But, the actual behavior should be success for read lock and failure for write lock:
Please help me in finding out why the test is failing.
On the man page for fcntl we can read
In order to place a read lock, fd must be open for reading. In order to place a write lock, fd must be open for writing. To place both types of lock, open a file read-write.
You are opening the file with
int fd = open("test_file.txt", O_WRONLY);
From man page for open
O_RDONLY Open for reading only.
O_WRONLY Open for writing only.
O_RDWR Open for reading and writing. The result is undefined if this flag is applied to a FIFO.
For placing read and write locks, open the file with
int fd = open("test_file.txt", O_RDWR);