162306a36Sopenharmony_ci// SPDX-License-Identifier: LGPL-2.1
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * trace/beauty/fcntl.c
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *  Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include "trace/beauty/beauty.h"
962306a36Sopenharmony_ci#include <linux/kernel.h>
1062306a36Sopenharmony_ci#include <uapi/linux/fcntl.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_cistatic size_t fcntl__scnprintf_getfd(unsigned long val, char *bf, size_t size, bool show_prefix)
1362306a36Sopenharmony_ci{
1462306a36Sopenharmony_ci	return val ? scnprintf(bf, size, "%s", "0") :
1562306a36Sopenharmony_ci		     scnprintf(bf, size, "%s%s", show_prefix ? "FD_" : "", "CLOEXEC");
1662306a36Sopenharmony_ci}
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_cistatic size_t syscall_arg__scnprintf_fcntl_getfd(char *bf, size_t size, struct syscall_arg *arg)
1962306a36Sopenharmony_ci{
2062306a36Sopenharmony_ci	return fcntl__scnprintf_getfd(arg->val, bf, size, arg->show_string_prefix);
2162306a36Sopenharmony_ci}
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_cistatic size_t fcntl__scnprintf_getlease(unsigned long val, char *bf, size_t size, bool show_prefix)
2462306a36Sopenharmony_ci{
2562306a36Sopenharmony_ci	static const char *fcntl_setlease[] = { "RDLCK", "WRLCK", "UNLCK", };
2662306a36Sopenharmony_ci	static DEFINE_STRARRAY(fcntl_setlease, "F_");
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	return strarray__scnprintf(&strarray__fcntl_setlease, bf, size, "%x", show_prefix, val);
2962306a36Sopenharmony_ci}
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_cistatic size_t syscall_arg__scnprintf_fcntl_getlease(char *bf, size_t size, struct syscall_arg *arg)
3262306a36Sopenharmony_ci{
3362306a36Sopenharmony_ci	return fcntl__scnprintf_getlease(arg->val, bf, size, arg->show_string_prefix);
3462306a36Sopenharmony_ci}
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_cisize_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_arg *arg)
3762306a36Sopenharmony_ci{
3862306a36Sopenharmony_ci	if (arg->val == F_GETFL) {
3962306a36Sopenharmony_ci		syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_open_flags);
4062306a36Sopenharmony_ci		goto mask_arg;
4162306a36Sopenharmony_ci	}
4262306a36Sopenharmony_ci	if (arg->val == F_GETFD) {
4362306a36Sopenharmony_ci		syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_fcntl_getfd);
4462306a36Sopenharmony_ci		goto mask_arg;
4562306a36Sopenharmony_ci	}
4662306a36Sopenharmony_ci	if (arg->val == F_DUPFD_CLOEXEC || arg->val == F_DUPFD) {
4762306a36Sopenharmony_ci		syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_fd);
4862306a36Sopenharmony_ci		goto out;
4962306a36Sopenharmony_ci	}
5062306a36Sopenharmony_ci	if (arg->val == F_GETOWN) {
5162306a36Sopenharmony_ci		syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_pid);
5262306a36Sopenharmony_ci		goto mask_arg;
5362306a36Sopenharmony_ci	}
5462306a36Sopenharmony_ci	if (arg->val == F_GETLEASE) {
5562306a36Sopenharmony_ci		syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_fcntl_getlease);
5662306a36Sopenharmony_ci		goto mask_arg;
5762306a36Sopenharmony_ci	}
5862306a36Sopenharmony_ci	/*
5962306a36Sopenharmony_ci	 * Some commands ignore the third fcntl argument, "arg", so mask it
6062306a36Sopenharmony_ci	 */
6162306a36Sopenharmony_ci	if (arg->val == F_GET_SEALS ||
6262306a36Sopenharmony_ci	    arg->val == F_GETSIG) {
6362306a36Sopenharmony_cimask_arg:
6462306a36Sopenharmony_ci		arg->mask |= (1 << 2);
6562306a36Sopenharmony_ci	}
6662306a36Sopenharmony_ciout:
6762306a36Sopenharmony_ci	return syscall_arg__scnprintf_strarrays(bf, size, arg);
6862306a36Sopenharmony_ci}
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_cisize_t syscall_arg__scnprintf_fcntl_arg(char *bf, size_t size, struct syscall_arg *arg)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	bool show_prefix = arg->show_string_prefix;
7362306a36Sopenharmony_ci	int cmd = syscall_arg__val(arg, 1);
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	if (cmd == F_DUPFD)
7662306a36Sopenharmony_ci		return syscall_arg__scnprintf_fd(bf, size, arg);
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	if (cmd == F_SETFD)
7962306a36Sopenharmony_ci		return fcntl__scnprintf_getfd(arg->val, bf, size, show_prefix);
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	if (cmd == F_SETFL)
8262306a36Sopenharmony_ci		return open__scnprintf_flags(arg->val, bf, size, show_prefix);
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	if (cmd == F_SETOWN)
8562306a36Sopenharmony_ci		return syscall_arg__scnprintf_pid(bf, size, arg);
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	if (cmd == F_SETLEASE)
8862306a36Sopenharmony_ci		return fcntl__scnprintf_getlease(arg->val, bf, size, show_prefix);
8962306a36Sopenharmony_ci	/*
9062306a36Sopenharmony_ci	 * We still don't grab the contents of pointers on entry or exit,
9162306a36Sopenharmony_ci	 * so just print them as hex numbers
9262306a36Sopenharmony_ci	 */
9362306a36Sopenharmony_ci	if (cmd == F_SETLK || cmd == F_SETLKW || cmd == F_GETLK ||
9462306a36Sopenharmony_ci	    cmd == F_OFD_SETLK || cmd == F_OFD_SETLKW || cmd == F_OFD_GETLK ||
9562306a36Sopenharmony_ci	    cmd == F_GETOWN_EX || cmd == F_SETOWN_EX ||
9662306a36Sopenharmony_ci	    cmd == F_GET_RW_HINT || cmd == F_SET_RW_HINT ||
9762306a36Sopenharmony_ci	    cmd == F_GET_FILE_RW_HINT || cmd == F_SET_FILE_RW_HINT)
9862306a36Sopenharmony_ci		return syscall_arg__scnprintf_hex(bf, size, arg);
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	return syscall_arg__scnprintf_long(bf, size, arg);
10162306a36Sopenharmony_ci}
102