Exemple #1
0
char *parse_lock(char *line, struct response *req)
{
	char *more;

	more = get_fpos(line, &req->r_fpos, REQUIRES_MORE);

	if (more == NULL)
		return more;

	more = get_lock_type(more, &req->r_lock_type);

	if (more == NULL)
		return more;

	if (req->r_lock_type != F_RDLCK && req->r_lock_type != F_WRLCK) {
		errno = EINVAL;
		strcpy(errdetail, "Invalid lock type");
		sprintf(badtoken, "%s", str_lock_type(req->r_lock_type));
	}

	more =
	    get_longlong(more, &req->r_start, REQUIRES_MORE,
			 "Invalid lock start");

	if (more == NULL)
		return more;

	return get_longlong(more, &req->r_length, REQUIRES_NO_MORE,
			    "Invalid lock len");
}
Exemple #2
0
void do_lock(struct response *resp)
{
	int rc;
	struct flock lock;
	int cmd;

	if (resp->r_cmd == CMD_LOCKW)
		cmd = F_SETLKW;
	else
		cmd = F_SETLK;

	if (resp->r_fpos != 0 && fno[resp->r_fpos] == 0) {
		strcpy(errdetail, "Invalid file number");
		sprintf(badtoken, "%ld", resp->r_fpos);
		resp->r_status = STATUS_ERRNO;
		resp->r_errno = EBADF;
		return;
	}

	lock.l_whence = SEEK_SET;
	lock.l_type = resp->r_lock_type;
	lock.l_start = resp->r_start;
	lock.l_len = resp->r_length;

	if (cmd == F_SETLKW && alarmtag == 0) {
		/* Don't let a blocking lock block hang us
		 * Test case can set an alarm before LOCKW to specify
		 * a different time
		 */
		resp->r_secs = 30;
		do_alarm(resp);
	}

	rc = fcntl(fno[resp->r_fpos], cmd, &lock);

	if (rc == -1) {
		if (errno == EAGAIN) {
			resp->r_status = STATUS_DENIED;
		} else if (errno == EINTR) {
			resp->r_status = STATUS_CANCELED;
		} else if (errno == EDEADLK) {
			resp->r_status = STATUS_DEADLOCK;
		} else {
			strcpy(errdetail, "Lock failed");
			sprintf(badtoken, "%s %lld %lld",
				str_lock_type(lock.l_type), resp->r_start,
				resp->r_length);
			resp->r_status = STATUS_ERRNO;
			resp->r_errno = errno;
		}
	} else
		resp->r_status = STATUS_GRANTED;

	if (cmd == F_SETLKW && alarmtag == resp->r_tag) {
		/* cancel the alarm we set */
		alarm(0);
		alarmtag = 0;
	}
}
Exemple #3
0
void do_test(struct response *resp)
{
	int rc;
	struct flock lock;
	int cmd = F_GETLK;

	if (resp->r_fpos != 0 && fno[resp->r_fpos] == 0) {
		strcpy(errdetail, "Invalid file number");
		sprintf(badtoken, "%ld", resp->r_fpos);
		resp->r_status = STATUS_ERRNO;
		resp->r_errno = EBADF;
		return;
	}

	lock.l_whence = SEEK_SET;
	lock.l_type = resp->r_lock_type;
	lock.l_start = resp->r_start;
	lock.l_len = resp->r_length;

	fprintf(stdout, "TEST lock type %s\n", str_lock_type(lock.l_type));

	rc = fcntl(fno[resp->r_fpos], cmd, &lock);

	if (rc == -1) {
		strcpy(errdetail, "Test failed");
		sprintf(badtoken, "%s %lld %lld", str_lock_type(lock.l_type),
			resp->r_start, resp->r_length);
		resp->r_status = STATUS_ERRNO;
		return;
	}

	if (lock.l_type == F_UNLCK) {
		fprintf(stdout, "GRANTED TEST lock type %s\n",
			str_lock_type(lock.l_type));
		resp->r_status = STATUS_GRANTED;
	} else {
		resp->r_lock_type = lock.l_type;
		resp->r_pid = lock.l_pid;
		resp->r_start = lock.l_start;
		resp->r_length = lock.l_len;
		resp->r_status = STATUS_CONFLICT;
	}
}
Exemple #4
0
void do_unhop(struct response *resp)
{
	int rc;
	int pos;
	struct flock lock;
	int cmd;

	cmd = F_SETLK;

	if (resp->r_fpos != 0 && fno[resp->r_fpos] == 0) {
		strcpy(errdetail, "Invalid file number");
		sprintf(badtoken, "%ld", resp->r_fpos);
		resp->r_status = STATUS_ERRNO;
		resp->r_errno = EBADF;
		return;
	}

	for (pos = resp->r_start; pos < resp->r_start + resp->r_length; pos++) {
		if ((pos == 0) || (pos == (resp->r_start + resp->r_length - 1)))
			lock.l_start = pos;
		else if ((pos & 1) == 0)
			lock.l_start = pos - 1;
		else
			lock.l_start = pos + 1;

		lock.l_whence = SEEK_SET;
		lock.l_type = resp->r_lock_type;
		lock.l_len = 1;

		rc = fcntl(fno[resp->r_fpos], cmd, &lock);

		if (rc == -1) {
			strcpy(errdetail, "Unhop failed");
			sprintf(badtoken, "%s %ld",
				str_lock_type(resp->r_lock_type), lock.l_start);
			resp->r_status = STATUS_ERRNO;
			break;
		} else
			resp->r_status = STATUS_GRANTED;
	}

	if (resp->r_status != STATUS_GRANTED) {
		lock.l_whence = SEEK_SET;
		lock.l_type = F_UNLCK;
		lock.l_start = resp->r_start;
		lock.l_len = resp->r_length;
		rc = fcntl(fno[resp->r_fpos], cmd, &lock);
		if (rc == -1) {
			strcpy(errdetail, "Unhop Unlock failed");
			sprintf(badtoken, "%lld %lld", resp->r_start,
				resp->r_length);
			resp->r_status = STATUS_ERRNO;
		}
	}
}
Exemple #5
0
int list_locks(long long int start, long long int end, struct response *resp)
{
	long long int conf_end;
	struct flock lock;
	int rc;

	lock.l_whence = SEEK_SET;
	lock.l_type = F_WRLCK;
	lock.l_start = start;

	if (end == INT64_MAX)
		lock.l_len = 0;
	else
		lock.l_len = end - start;

	rc = fcntl(fno[resp->r_fpos], F_GETLK, &lock);

	if (rc == -1) {
		strcpy(errdetail, "Test failed");
		sprintf(badtoken, "%s %lld %lld", str_lock_type(lock.l_type),
			resp->r_start, resp->r_length);
		resp->r_errno = errno;
		resp->r_status = STATUS_ERRNO;
		respond(resp);
		return false;
	}

	/* Our test succeeded */
	if (lock.l_type == F_UNLCK)
		return false;

	resp->r_status = STATUS_CONFLICT;
	resp->r_lock_type = lock.l_type;
	resp->r_pid = lock.l_pid;
	resp->r_start = lock.l_start;
	resp->r_length = lock.l_len;

	respond(resp);

	conf_end = lock_end(lock.l_start, lock.l_len);

	if (lock.l_start > start)
		make_test_item(start, lock.l_start);

	if (conf_end < end)
		make_test_item(conf_end, end);

	return true;
}
Exemple #6
0
void sprintf_resp(char *line, const char *lead, struct response *resp)
{
	char *rest = line;

	if (lead != NULL) {
		const char *name = "<NULL>";

		if (resp->r_client != NULL)
			name = resp->r_client->c_name;

		rest = rest + sprintf(line, "%s %s ", lead, name);
	}

	rest =
	    rest + sprintf(rest, "%ld %s %s", resp->r_tag,
			   commands[resp->r_cmd].cmd_name,
			   str_status(resp->r_status));

	switch (resp->r_status) {
	case STATUS_OK:
		switch (resp->r_cmd) {
		case CMD_COMMENT:
		case CMD_HELLO:
			sprintf(rest, " \"%s\"\n", resp->r_data);
			break;

		case CMD_LOCKW:
		case CMD_LOCK:
		case CMD_UNLOCK:
		case CMD_TEST:
		case CMD_LIST:
		case CMD_HOP:
		case CMD_UNHOP:
		case NUM_COMMANDS:
			sprintf(rest, " Unexpected Status\n");
			break;

		case CMD_ALARM:
			sprintf(rest, " %ld\n", resp->r_secs);
			break;

		case CMD_QUIT:
			sprintf(rest, "\n");
			break;

		case CMD_OPEN:
			sprintf(rest, " %ld %ld\n", resp->r_fpos, resp->r_fno);
			break;

		case CMD_CLOSE:
		case CMD_SEEK:
			sprintf(rest, " %ld\n", resp->r_fpos);
			break;

		case CMD_WRITE:
			sprintf(rest, " %ld %lld\n", resp->r_fpos,
				resp->r_length);
			break;

		case CMD_READ:
			sprintf(rest, " %ld %lld \"%s\"\n", resp->r_fpos,
				resp->r_length, resp->r_data);
			break;
		}
		break;

	case STATUS_AVAILABLE:
	case STATUS_GRANTED:
	case STATUS_DENIED:
	case STATUS_DEADLOCK:
		if (resp->r_cmd == CMD_LIST)
			sprintf(rest, " %ld %lld %lld\n", resp->r_fpos,
				resp->r_start, resp->r_length);
		else
			sprintf(rest, " %ld %s %lld %lld\n", resp->r_fpos,
				str_lock_type(resp->r_lock_type), resp->r_start,
				resp->r_length);
		break;

	case STATUS_CONFLICT:
		sprintf(rest, " %ld %ld %s %lld %lld\n", resp->r_fpos,
			resp->r_pid, str_lock_type(resp->r_lock_type),
			resp->r_start, resp->r_length);
		break;

	case STATUS_CANCELED:
		if (resp->r_cmd == CMD_LOCKW) {
			sprintf(rest, " %ld %s %lld %lld\n", resp->r_fpos,
				str_lock_type(resp->r_lock_type), resp->r_start,
				resp->r_length);
		} else if (resp->r_cmd == CMD_ALARM) {
			sprintf(rest, " %ld\n", resp->r_secs);
		} else {
		}
		break;

	case STATUS_COMPLETED:
		sprintf(rest, "\n");
		break;

	case STATUS_ERRNO:
		if (errno == 0)
			sprintf(rest, " %ld \"%s\"\n", resp->r_errno,
				errdetail);
		else
			sprintf(rest, " %ld \"%s\" \"%s\" bad token \"%s\"\n",
				resp->r_errno, strerror(resp->r_errno),
				errdetail, badtoken);
		break;

	case STATUS_PARSE_ERROR:
		break;

	case STATUS_ERROR:
		break;
	}
}
Exemple #7
0
void sprintf_req(char *line, const char *lead, struct response *req)
{
	char *rest = line;

	if (lead != NULL) {
		const char *name = "<NULL>";

		if (req->r_client != NULL)
			name = req->r_client->c_name;

		rest = rest + sprintf(line, "%s %s ", lead, name);
	}

	rest =
	    rest + sprintf(rest, "%ld %s", req->r_tag,
			   commands[req->r_cmd].cmd_name);

	switch (req->r_cmd) {
	case CMD_COMMENT:
	case CMD_HELLO:
		sprintf(rest, " \"%s\"\n", req->r_data);
		break;

	case CMD_LOCKW:
	case CMD_LOCK:
	case CMD_TEST:
	case CMD_HOP:
		sprintf(rest, " %ld %s %lld %lld\n", req->r_fpos,
			str_lock_type(req->r_lock_type), req->r_start,
			req->r_length);
		break;

	case CMD_UNLOCK:
	case CMD_LIST:
	case CMD_UNHOP:
		sprintf(rest, " %ld %lld %lld\n", req->r_fpos, req->r_start,
			req->r_length);
		break;

	case NUM_COMMANDS:
		sprintf(rest, " Unexpected Command\n");
		break;

	case CMD_ALARM:
		sprintf(rest, " %ld\n", req->r_secs);
		break;

	case CMD_QUIT:
		sprintf(rest, "\n");
		break;

	case CMD_OPEN:
		rest +=
		    sprintf(rest, " %ld %s", req->r_fpos,
			    str_read_write_flags(req->r_flags));
		rest += sprintf_open_flags(rest, req->r_flags);
		rest += sprintf(rest, " \"%s\"\n", req->r_data);
		break;

	case CMD_CLOSE:
		sprintf(rest, " %ld\n", req->r_fpos);
		break;

	case CMD_SEEK:
		sprintf(rest, " %ld %lld\n", req->r_fpos, req->r_start);
		break;

	case CMD_WRITE:
		sprintf(rest, " %ld %s\n", req->r_fpos, req->r_data);
		break;

	case CMD_READ:
		sprintf(rest, " %ld %lld\n", req->r_fpos, req->r_length);
		break;
	}
}