1/*
2 * Copyright 2022-2023, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Copyright 2022, J��r��me Duval, jerome.duval@gmail.com
7 */
8
9
10#include <fcntl.h>
11
12#include "strace.h"
13#include "Syscall.h"
14#include "TypeHandler.h"
15
16
17#define FLAG_INFO_ENTRY(name) \
18	{ name, #name }
19
20static const FlagsTypeHandler::FlagInfo kOpenFlagInfos[] = {
21	FLAG_INFO_ENTRY(O_WRONLY),
22	FLAG_INFO_ENTRY(O_RDWR),
23
24	FLAG_INFO_ENTRY(O_EXCL),
25	FLAG_INFO_ENTRY(O_CREAT),
26	FLAG_INFO_ENTRY(O_TRUNC),
27	FLAG_INFO_ENTRY(O_NOCTTY),
28	FLAG_INFO_ENTRY(O_NOTRAVERSE),
29
30	FLAG_INFO_ENTRY(O_CLOEXEC),
31	FLAG_INFO_ENTRY(O_NONBLOCK),
32	FLAG_INFO_ENTRY(O_APPEND),
33	FLAG_INFO_ENTRY(O_SYNC),
34	FLAG_INFO_ENTRY(O_RSYNC),
35	FLAG_INFO_ENTRY(O_DSYNC),
36	FLAG_INFO_ENTRY(O_NOFOLLOW),
37	FLAG_INFO_ENTRY(O_DIRECT),
38
39	FLAG_INFO_ENTRY(O_DIRECTORY),
40
41	{ 0, NULL }
42};
43
44
45struct fcntl_info {
46	unsigned int index;
47	const char *name;
48	TypeHandler *handler;
49};
50
51#define FCNTL_INFO_ENTRY(name) \
52	{ name, #name, NULL }
53
54#define FCNTL_INFO_ENTRY_TYPE(name, type) \
55	{ name, #name, TypeHandlerFactory<type>::Create() }
56
57static const fcntl_info kFcntls[] = {
58	FCNTL_INFO_ENTRY_TYPE(F_DUPFD, int),
59	FCNTL_INFO_ENTRY(F_GETFD),
60	FCNTL_INFO_ENTRY_TYPE(F_SETFD, int),
61	FCNTL_INFO_ENTRY(F_GETFL),
62	FCNTL_INFO_ENTRY(F_SETFL),
63	FCNTL_INFO_ENTRY_TYPE(F_GETLK, struct flock*),
64	FCNTL_INFO_ENTRY_TYPE(F_SETLK, struct flock*),
65	FCNTL_INFO_ENTRY_TYPE(F_SETLKW, struct flock*),
66	{ 0, NULL, NULL }
67};
68
69static FlagsTypeHandler::FlagsList kOpenFlags;
70static EnumTypeHandler::EnumMap kFcntlNames;
71static TypeHandlerSelector::SelectMap kFcntlTypeHandlers;
72
73void
74patch_fcntl()
75{
76	for (int i = 0; kOpenFlagInfos[i].name != NULL; i++) {
77		kOpenFlags.push_back(kOpenFlagInfos[i]);
78	}
79
80	for (int i = 0; kFcntls[i].name != NULL; i++) {
81		kFcntlNames[kFcntls[i].index] = kFcntls[i].name;
82		if (kFcntls[i].handler != NULL)
83			kFcntlTypeHandlers[kFcntls[i].index] = kFcntls[i].handler;
84	}
85
86	kFcntlTypeHandlers[F_SETFL] = new FlagsTypeHandler(kOpenFlags);
87
88	Syscall *open = get_syscall("_kern_open");
89	open->GetParameter("openMode")->SetHandler(new FlagsTypeHandler(kOpenFlags));
90
91	Syscall *fcntl = get_syscall("_kern_fcntl");
92	fcntl->GetParameter("op")->SetHandler(new EnumTypeHandler(kFcntlNames));
93	fcntl->GetParameter("argument")->SetHandler(
94		new TypeHandlerSelector(kFcntlTypeHandlers,
95				1, TypeHandlerFactory<void *>::Create()));
96}
97
98