⛏️ index : haiku.git

/*
 * Copyright 2022-2023, Haiku Inc. All rights reserved.
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *		Copyright 2022, JΓ©rΓ΄me Duval, jerome.duval@gmail.com
 */


#include <fcntl.h>

#include "strace.h"
#include "Syscall.h"
#include "TypeHandler.h"


#define FLAG_INFO_ENTRY(name) \
	{ name, #name }

static const FlagsTypeHandler::FlagInfo kOpenFlagInfos[] = {
	FLAG_INFO_ENTRY(O_WRONLY),
	FLAG_INFO_ENTRY(O_RDWR),

	FLAG_INFO_ENTRY(O_EXCL),
	FLAG_INFO_ENTRY(O_CREAT),
	FLAG_INFO_ENTRY(O_TRUNC),
	FLAG_INFO_ENTRY(O_NOCTTY),
	FLAG_INFO_ENTRY(O_NOTRAVERSE),

	FLAG_INFO_ENTRY(O_CLOEXEC),
	FLAG_INFO_ENTRY(O_NONBLOCK),
	FLAG_INFO_ENTRY(O_APPEND),
	FLAG_INFO_ENTRY(O_SYNC),
	FLAG_INFO_ENTRY(O_RSYNC),
	FLAG_INFO_ENTRY(O_DSYNC),
	FLAG_INFO_ENTRY(O_NOFOLLOW),
	FLAG_INFO_ENTRY(O_DIRECT),

	FLAG_INFO_ENTRY(O_DIRECTORY),

	FLAG_INFO_ENTRY(O_CLOFORK),

	{ 0, NULL }
};


static const FlagsTypeHandler::FlagInfo kCloseRangeFlagInfos[] = {
	FLAG_INFO_ENTRY(CLOSE_RANGE_CLOEXEC),

	{ 0, NULL }
};


struct fcntl_info {
	unsigned int index;
	const char *name;
	TypeHandler *handler;
};

#define FCNTL_INFO_ENTRY(name) \
	{ name, #name, NULL }

#define FCNTL_INFO_ENTRY_TYPE(name, type) \
	{ name, #name, TypeHandlerFactory<type>::Create() }

static const fcntl_info kFcntls[] = {
	FCNTL_INFO_ENTRY_TYPE(F_DUPFD, int),
	FCNTL_INFO_ENTRY(F_GETFD),
	FCNTL_INFO_ENTRY_TYPE(F_SETFD, int),
	FCNTL_INFO_ENTRY(F_GETFL),
	FCNTL_INFO_ENTRY(F_SETFL),
	FCNTL_INFO_ENTRY_TYPE(F_GETLK, struct flock*),
	FCNTL_INFO_ENTRY_TYPE(F_SETLK, struct flock*),
	FCNTL_INFO_ENTRY_TYPE(F_SETLKW, struct flock*),
	{ 0, NULL, NULL }
};

static FlagsTypeHandler::FlagsList kOpenFlags;
static FlagsTypeHandler::FlagsList kCloseRangeFlags;
static EnumTypeHandler::EnumMap kFcntlNames;
static TypeHandlerSelector::SelectMap kFcntlTypeHandlers;

void
patch_fcntl()
{
	for (int i = 0; kOpenFlagInfos[i].name != NULL; i++) {
		kOpenFlags.push_back(kOpenFlagInfos[i]);
	}

	for (int i = 0; kCloseRangeFlagInfos[i].name != NULL; i++) {
		kCloseRangeFlags.push_back(kCloseRangeFlagInfos[i]);
	}

	for (int i = 0; kFcntls[i].name != NULL; i++) {
		kFcntlNames[kFcntls[i].index] = kFcntls[i].name;
		if (kFcntls[i].handler != NULL)
			kFcntlTypeHandlers[kFcntls[i].index] = kFcntls[i].handler;
	}

	kFcntlTypeHandlers[F_SETFL] = new FlagsTypeHandler(kOpenFlags);

	Syscall *open = get_syscall("_kern_open");
	open->GetParameter("openMode")->SetHandler(new FlagsTypeHandler(kOpenFlags));

	Syscall *closeRange = get_syscall("_kern_close_range");
	closeRange->GetParameter("flags")->SetHandler(new FlagsTypeHandler(kCloseRangeFlags));

	Syscall *fcntl = get_syscall("_kern_fcntl");
	fcntl->GetParameter("op")->SetHandler(new EnumTypeHandler(kFcntlNames));
	fcntl->GetParameter("argument")->SetHandler(
		new TypeHandlerSelector(kFcntlTypeHandlers,
				1, TypeHandlerFactory<void *>::Create()));

	Syscall *createPipe = get_syscall("_kern_create_pipe");
	createPipe->ParameterAt(0)->SetOut(true);
	createPipe->ParameterAt(0)->SetCount(2);
	createPipe->GetParameter("flags")->SetHandler(new FlagsTypeHandler(kOpenFlags));

	Syscall *dup2 = get_syscall("_kern_dup2");
	dup2->GetParameter("flags")->SetHandler(new FlagsTypeHandler(kOpenFlags));

}