1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2024, Ideas on Board Oy
*
* Anonymous file creation
*/
#include <libcamera/base/memfd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <libcamera/base/log.h>
/**
* \file base/memfd.h
* \brief Anonymous file creation
*/
#ifndef __DOXYGEN__
namespace {
/* uClibc doesn't provide the file sealing API. */
#if not HAVE_FILE_SEALS
#define F_ADD_SEALS 1033
#define F_SEAL_SHRINK 0x0002
#define F_SEAL_GROW 0x0004
#endif
#if not HAVE_MEMFD_CREATE
int memfd_create(const char *name, unsigned int flags)
{
return syscall(SYS_memfd_create, name, flags);
}
#endif
} /* namespace */
#endif /* __DOXYGEN__ */
namespace libcamera {
LOG_DECLARE_CATEGORY(File)
/**
* \class MemFd
* \brief Helper class to create anonymous files
*
* Anonymous files behave like regular files, and can be modified, truncated,
* memory-mapped and so on. Unlike regular files, they however live in RAM and
* don't have permanent backing storage.
*/
/**
* \enum MemFd::Seal
* \brief Seals for the MemFd::create() function
* \var MemFd::Seal::None
* \brief No seals (used as default value)
* \var MemFd::Seal::Shrink
* \brief Prevent the memfd from shrinking
* \var MemFd::Seal::Grow
* \brief Prevent the memfd from growing
*/
/**
* \typedef MemFd::Seals
* \brief A bitwise combination of MemFd::Seal values
*/
/**
* \brief Create an anonymous file
* \param[in] name The file name (displayed in symbolic links in /proc/self/fd/)
* \param[in] size The file size
* \param[in] seals The file seals
*
* This function is a helper that wraps anonymous file (memfd) creation and
* sets the file size and optional seals.
*
* \return The descriptor of the anonymous file if creation succeeded, or an
* invalid UniqueFD otherwise
*/
UniqueFD MemFd::create(const char *name, std::size_t size, Seals seals)
{
int ret = memfd_create(name, MFD_ALLOW_SEALING | MFD_CLOEXEC);
if (ret < 0) {
ret = errno;
LOG(File, Error)
<< "Failed to allocate memfd storage for " << name
<< ": " << strerror(ret);
return {};
}
UniqueFD memfd(ret);
ret = ftruncate(memfd.get(), size);
if (ret < 0) {
ret = errno;
LOG(File, Error)
<< "Failed to set memfd size for " << name
<< ": " << strerror(ret);
return {};
}
if (seals) {
int fileSeals = (seals & Seal::Shrink ? F_SEAL_SHRINK : 0)
| (seals & Seal::Grow ? F_SEAL_GROW : 0);
ret = fcntl(memfd.get(), F_ADD_SEALS, fileSeals);
if (ret < 0) {
ret = errno;
LOG(File, Error)
<< "Failed to seal the memfd for " << name
<< ": " << strerror(ret);
return {};
}
}
return memfd;
}
} /* namespace libcamera */
|