⛏️ index : haiku.git

/*
 * Copyright 2005, Axel DΓΆrfler, axeld@pinc-software.de.
 * Distributed under the terms of the MIT License.
 */


#include <OS.h>

#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>


bool gDone = false;


static int32
try_to_lock(void *_fd)
{
	intptr_t fd = (intptr_t)_fd;

	struct flock flock = {
		F_RDLCK,	// shared lock
		SEEK_SET,
		200,
		0,			// until the end of the file
		0
	};

	if (fcntl(fd, F_SETLK, &flock) == 0) {
		fprintf(stderr, "a. Could lock file!\n");
		return -1;
	} else
		puts("test a passed.");

	gDone = true;

	// wait for lock to become free

	if (fcntl(fd, F_SETLKW, &flock) == -1) {
		fprintf(stderr, "b. Could not lock file: %s\n", strerror(errno));
		return -1;
	} else
		puts("test b passed.");

	flock.l_type = F_UNLCK;

	if (fcntl(fd, F_SETLK, &flock) == -1) {
		fprintf(stderr, "c. Could not unlock file: %s\n", strerror(errno));
		return -1;
	} else
		puts("test c passed.");

	return 0;
}


int 
main(int argc, char **argv)
{
	intptr_t fd = open("/etc/passwd", O_RDONLY);
	if (fd < 0) {
		fprintf(stderr, "could not open file: %s\n", strerror(errno));
		return -1;
	}

	struct flock flock = {
		F_WRLCK,	// exclusive lock
		SEEK_SET,	// lock whole file
		0,
		0,
		0
	};

	if (fcntl(fd, F_SETLK, &flock) == 0) {
		fprintf(stderr, "0. Could lock file exclusively without write access!\n");
		return -1;
	} else
		puts("test 0 passed.");

	flock.l_type = F_RDLCK;
		// shared locks should be allowed

	if (fcntl(fd, F_SETLK, &flock) == -1) {
		fprintf(stderr, "1. Could not lock file: %s\n", strerror(errno));
		return -1;
	} else
		puts("test 1 passed.");

	close(fd);

	fd = open("/etc/passwd", O_RDWR);
	if (fd < 0) {
		fprintf(stderr, "could not open file: %s\n", strerror(errno));
		return -1;
	}

	flock.l_type = F_WRLCK;
	flock.l_start = 100;
	flock.l_len = 42;

	if (fcntl(fd, F_SETLK, &flock) == -1) {
		fprintf(stderr, "2. Could not lock file: %s\n", strerror(errno));
		return -1;
	} else
		puts("test 2 passed.");

	flock.l_start = 200;

	if (fcntl(fd, F_SETLK, &flock) == -1) {
		fprintf(stderr, "3. Could not lock file: %s\n", strerror(errno));
		return -1;
	} else
		puts("test 3 passed.");

	flock.l_start = 80;

	if (fcntl(fd, F_SETLK, &flock) == 0) {
		fprintf(stderr, "4. Could lock file exclusively on locked region!\n");
		return -1;
	} else
		puts("test 4 passed.");

	flock.l_type = F_UNLCK;
	flock.l_start = 100;

	if (fcntl(fd, F_SETLK, &flock) == -1) {
		fprintf(stderr, "5. Could not unlock file: %s\n", strerror(errno));
		return -1;
	} else
		puts("test 5 passed.");

	flock.l_type = F_WRLCK;
	flock.l_start = 80;

	if (fcntl(fd, F_SETLK, &flock) == -1) {
		fprintf(stderr, "6. Could not lock file: %s\n", strerror(errno));
		return -1;
	} else
		puts("test 6 passed.");

	thread_id thread = spawn_thread(try_to_lock, "try", B_NORMAL_PRIORITY, (void *)fd);
	if (thread < B_OK) {
		fprintf(stderr, "Could not spawn thread: %s\n", strerror(thread));
		return -1;
	}
	resume_thread(thread);

	while (!gDone) {
		snooze(100000); // 0.1s
	}

	flock.l_type = F_UNLCK;
	flock.l_start = 200;

	if (fcntl(fd, F_SETLK, &flock) == -1) {
		fprintf(stderr, "7. Could not unlock file: %s\n", strerror(errno));
		return -1;
	} else
		puts("test 7 passed.");

	status_t returnCode;
	wait_for_thread(thread, &returnCode);

	close(fd);
	return 0;
}