summaryrefslogtreecommitdiffstats
path: root/tests/fcntl_lock.c
blob: 242b9f7adfb6fe707b704faf8e88b6a68af699d6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/* test whether fcntl locking works on this system */

#if defined(HAVE_UNISTD_H)
#include <unistd.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>

#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif

#ifdef HAVE_SYS_FCNTL_H
#include <sys/fcntl.h>
#endif

#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif

#include <errno.h>

static int sys_waitpid(pid_t pid,int *status,int options)
{
#ifdef HAVE_WAITPID
  return waitpid(pid,status,options);
#else /* USE_WAITPID */
  return wait4(pid, status, options, NULL);
#endif /* USE_WAITPID */
}

#define DATA "conftest.fcntl"

#ifndef SEEK_SET
#define SEEK_SET 0
#endif

/* lock a byte range in a open file */
int main(int argc, char *argv[])
{
	struct flock lock;
	int fd, ret, status=1;
	pid_t pid;
	char *testdir = NULL;

	testdir = getenv("TESTDIR");
	if (testdir) chdir(testdir);

	alarm(10);

	if (!(pid=fork())) {
		sleep(2);
		fd = open(DATA, O_RDONLY);

		if (fd == -1) {
			fprintf(stderr,"ERROR: failed to open %s (errno=%d)\n", 
				DATA, (int)errno);
			exit(1);
		}

		lock.l_type = F_WRLCK;
		lock.l_whence = SEEK_SET;
		lock.l_start = 0x100000000LL;
		lock.l_len = 4;
		lock.l_pid = getpid();
		
		lock.l_type = F_WRLCK;
		
		/* check if a lock applies */
		ret = fcntl(fd,F_GETLK,&lock);

		if ((ret == -1) ||
		    (lock.l_type == F_UNLCK)) {
			fprintf(stderr,"ERROR: lock test failed (ret=%d errno=%d)\n", ret, (int)errno);
			exit(1);
		} else {
			exit(0);
		}
	}

	unlink(DATA);
	fd = open(DATA, O_RDWR|O_CREAT|O_EXCL, 0600);

	if (fd == -1) {
		fprintf(stderr,"ERROR: failed to open %s (errno=%d)\n", 
			DATA, (int)errno);
		exit(1);
	}

	lock.l_type = F_WRLCK;
	lock.l_whence = SEEK_SET;
	lock.l_start = 0;
	lock.l_len = 0x100000004LL;
	lock.l_pid = getpid();

	/* set a 100000004 byte write lock, should conflict with the above */
	ret = fcntl(fd,F_SETLK,&lock);

	sys_waitpid(pid, &status, 0);

	unlink(DATA);

	if (ret != 0) {
		fprintf(stderr,"ERROR: failed to lock %s (errno=%d)\n", 
			DATA, (int)errno);
		exit(1);
	}

	if (lock.l_len < 0x100000004LL) {
		fprintf(stderr,"ERROR: setting lock overflowed\n");
		exit(1);
	}

#if defined(WIFEXITED) && defined(WEXITSTATUS)
    if(WIFEXITED(status)) {
        status = WEXITSTATUS(status);
    } else {
        status = 1;
    }
#else /* defined(WIFEXITED) && defined(WEXITSTATUS) */
	status = (status == 0) ? 0 : 1;
#endif /* defined(WIFEXITED) && defined(WEXITSTATUS) */

	if (status) {
		fprintf(stderr,"ERROR: lock test failed with status=%d\n", 
			status);
	}

	exit(status);
}