arch/um/drivers/mconsole_user.c

Source file repositories/reference/linux-study-clean/arch/um/drivers/mconsole_user.c

File Facts

System
Linux kernel
Corpus path
arch/um/drivers/mconsole_user.c
Extension
.c
Size
5376 bytes
Lines
222
Domain
Architecture Layer
Bucket
arch/um
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

strlen(cmd->command))) {
			return cmd;
		}
	}
	return NULL;
}

#ifndef MIN
#define MIN(a,b) ((a)<(b) ? (a):(b))
#endif

#define STRINGX(x) #x
#define STRING(x) STRINGX(x)

int mconsole_get_request(int fd, struct mc_request *req)
{
	int len;

	req->originlen = sizeof(req->origin);
	req->len = recvfrom(fd, &req->request, sizeof(req->request), 0,
			    (struct sockaddr *) req->origin, &req->originlen);
	if (req->len < 0)
		return 0;

	req->originating_fd = fd;

	if (req->request.magic != MCONSOLE_MAGIC) {
		/* Unversioned request */
		len = MIN(sizeof(req->request.data) - 1,
			  strlen((char *) &req->request));
		memmove(req->request.data, &req->request, len);
		req->request.data[len] = '\0';

		req->request.magic = MCONSOLE_MAGIC;
		req->request.version = 0;
		req->request.len = len;

		mconsole_reply_v0(req, "ERR Version 0 mconsole clients are "
				  "not supported by this driver");
		return 0;
	}

	if (req->request.len >= MCONSOLE_MAX_DATA) {
		mconsole_reply(req, "Request too large", 1, 0);
		return 0;
	}
	if (req->request.version != MCONSOLE_VERSION) {
		mconsole_reply(req, "This driver only supports version "
			       STRING(MCONSOLE_VERSION) " clients", 1, 0);
	}

	req->request.data[req->request.len] = '\0';
	req->cmd = mconsole_parse(req);
	if (req->cmd == NULL) {
		mconsole_reply(req, "Unknown command", 1, 0);
		return 0;
	}

	return 1;
}

int mconsole_reply_len(struct mc_request *req, const char *str, int total,
		       int err, int more)
{
	/*
	 * XXX This is a stack consumption problem.  It'd be nice to
	 * make it global and serialize access to it, but there are a
	 * ton of callers to this function.
	 */
	struct mconsole_reply reply;
	int len, n;

	do {
		reply.err = err;

		/* err can only be true on the first packet */
		err = 0;

		len = MIN(total, MCONSOLE_MAX_DATA - 1);

		if (len == total) reply.more = more;
		else reply.more = 1;

		memcpy(reply.data, str, len);
		reply.data[len] = '\0';
		total -= len;
		str += len;
		reply.len = len + 1;

		len = sizeof(reply) + reply.len - sizeof(reply.data);

Annotation

Implementation Notes