Flow-IPC 1.0.2
Flow-IPC project: Full implementation reference.
util_fwd.hpp
Go to the documentation of this file.
1/* Flow-IPC: Core
2 * Copyright 2023 Akamai Technologies, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the
5 * "License"); you may not use this file except in
6 * compliance with the License. You may obtain a copy
7 * of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in
12 * writing, software distributed under the License is
13 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
14 * CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing
16 * permissions and limitations under the License. */
17
18/// @file
19#pragma once
20
22#include "ipc/common.hpp"
23#include <flow/log/log.hpp>
24#include <flow/async/util.hpp>
25#include <boost/asio.hpp>
26#include <boost/interprocess/permissions.hpp>
27#include <boost/interprocess/creation_tags.hpp>
28
29/**
30 * Flow-IPC module containing miscellaneous general-use facilities that ubiquitously used by ~all Flow-IPC modules
31 * and/or do not fit into any other Flow-IPC module.
32 *
33 * Each symbol therein is typically used by at least 1 other Flow-IPC module; but all public symbols (except ones
34 * under a detail/ subdirectory) are intended for use by Flow-IPC user as well. Some particulars to note:
35 *
36 * ipc::util::Shared_name is a universally used shared-resource name class, conceptually similar to
37 * `boost::filesystem::path`. It is used in ipc::transport APIs -- namely to name endpoints when establishing channels,
38 * and more -- but also in other Flow-IPC modules. For example `Shared_name` is used to name certain SHM entities
39 * in ipc::shm and in ipc::session when connecting to conversation partner process(es).
40 *
41 * ipc::util::Native_handle is a commonly used native-handle (FD in POSIX parlance) wrapper (so thin it doesn't add
42 * a single bit on top of the actul FD). These are ~always passed around by value (copied), as they are very small
43 * in practice.
44 *
45 * There are of course various other things; just check them out as they are referenced, or just look around.
46 * Note there are free functions providing various niceties; and more types including classes and scoped `enum`s.
47 */
48namespace ipc::util
49{
50
51// Types.
52
53// Find doc headers near the bodies of these compound types.
54
55template <typename T, typename Allocator = std::allocator<T>>
56class Default_init_allocator;
57
58class Use_counted_object;
59
60/* Normally we'd try to forward-declare the following only, but doing so means (1) having to specify `: size_t`
61 * in two places, here and the definition; and (2) ::S_END_SENTINEL cannot be used in _fwd.hpp to, say,
62 * set a compile-time array<> size. So just make an exception and define the enum fully here. It's not
63 * "really" an aggregate type (class), so it's all right. */
64
65#ifndef FLOW_OS_LINUX
66static_assert(false, "Design of Permissions_level assumes a POSIX-y security model with users and groups; "
67 "we have not yet considered whether it can apply to Windows in its current form. "
68 "Should work in non-Linux POSIX OS (like macOS) but must be checked/tested.");
69#endif
70
71/**
72 * Simple specifier of desired access permissions, usually but not necessarily translated into
73 * a `Permissions` value (though even then different value in different contexts). May be used to map, say,
74 * from a Permissions_level to a #Permissions value in an
75 * `array<Permissions, size_t(Permissions_level::S_END_SENTINEL)>`.
76 *
77 * While, unlike #Permissions, this `enum` intends not be overtly based on a POSIX RWXRWXRWX model, it does
78 * still assume the 3 user groupings are "user themselves," "user's group," and "everyone." The 1st and 3rd
79 * are likely universal, but the 2nd may not apply to all OS -- through probably all POSIX/Unix ones --
80 * and even for something like Linux there could be different groupings such as ones based on OS ACL.
81 * As of this writing it's fine, as this is a POSIX-targeted library at least (in fact, Linux, as of this writing,
82 * but that could change to include, say, macOS/similar).
83 *
84 * @internal
85 * ### Maintenance ###
86 * Do *not* change the order of these constants unless absolutely necessary. In general any change here
87 * means updating any `array<>`s (etc.) that map implicitly from a `size_t` representing
88 * Permissions_level. By convention they are named `*_PERMISSIONS_LVL_MAP` as of this writing.
89 *
90 * The `array<>` mapping scheme is for max performance; if one uses an `unordered_map` or similar, then there is no
91 * similar issue.
92 */
93enum class Permissions_level : size_t
94{
95 /// Forbids all access, even by the creator's user. Most likely this would be useful for testing or debugging.
97
98 /// Allows access by resource-owning user (in POSIX/Unix identified by UID) and no one else.
100
101 /**
102 * Allows access by resource-owning user's containing group(s) (in POSIX/Unix identified by GID) and no one else.
103 * This implies, as well, at least as much access as `S_USER_ACCESS`.
104 */
106
107 /// Allows access by all. Implies, as well, at least as much access as `S_GROUP_ACCESS` and thus `S_USER_ACCESS`.
109
110 /// Sentinel: not a valid value. May be used to, e.g., size an `array<>` mapping from Permissions_level.
112}; // enum class Permissions_level
113
114/// Short-hand for Flow's `String_view`.
116/// Short-hand for Flow's `Fine_duration`.
118/// Short-hand for Flow's `Fine_time_pt`.
120
121/// Short-hand for polymorphic function (a-la `std::function<>`) that takes no arguments and returns nothing.
123
124/**
125 * Short-hand for an immutable blob somewhere in memory, stored as exactly a `void const *` and a `size_t`.
126 *
127 * ### How to use ###
128 * We provide this alias as a stylistic short-hand, as it better suits various interfaces especially in
129 * ipc::transport. Nevertheless it's not meant to more than that; it's an attempt to abstract it away.
130 *
131 * That is to say, to work with these (create them, access them, etc.), do use the highly convenient
132 * boost.asio buffer APIs which are well documented in boost.asio's docs.
133 */
134using Blob_const = boost::asio::const_buffer;
135
136/**
137 * Short-hand for an mutable blob somewhere in memory, stored as exactly a `void*` and a `size_t`.
138 * @see ipc::util::Blob_const; usability notes in that doc header apply similarly here.
139 */
140using Blob_mutable = boost::asio::mutable_buffer;
141
142/// Syntactic-sugary type for POSIX process ID (integer).
143using process_id_t = ::pid_t;
144
145/// Syntactic-sugary type for POSIX user ID (integer).
146using user_id_t = ::uid_t;
147
148/// Syntactic-sugary type for POSIX group ID (integer).
149using group_id_t = ::gid_t;
150
151/// Tag type indicating an atomic open-if-exists-else-create operation. @see #OPEN_OR_CREATE.
152using Open_or_create = bipc::open_or_create_t;
153
154/// Tag type indicating an ideally-atomic open-if-exists-else-fail operation. @see #OPEN_ONLY.
155using Open_only = bipc::open_only_t;
156
157/// Tag type indicating a create-unless-exists-else-fail operation. @see #CREATE_ONLY.
158using Create_only = bipc::create_only_t;
159
160/// Short-hand for Unix (POSIX) permissions class.
161using Permissions = bipc::permissions;
162
163// Constants.
164
165/// Tag value indicating an open-if-exists-else-create operation.
166extern const Open_or_create OPEN_OR_CREATE;
167
168/// Tag value indicating an atomic open-if-exists-else-fail operation.
169extern const Open_only OPEN_ONLY;
170
171/// Tag value indicating an atomic create-unless-exists-else-fail operation.
172extern const Create_only CREATE_ONLY;
173
174/// A (default-cted) string. May be useful for functions returning `const std::string&`.
175extern const std::string EMPTY_STRING;
176
177// Free functions.
178
179/**
180 * Maps general Permissions_level specifier to low-level #Permissions value, when the underlying resource
181 * is in the file-system and is either accessible (read-write in terms of file system) or inaccessible.
182 * Examples of such resources are SHM pools (e.g., shm::classic::Pool_arena), bipc MQs (transport::Bipc_mq_handle),
183 * POSIX MQs (transport::Posix_mq_handle).
184 *
185 * Please do not confuse this setting with the read-only/read-write dichotomy potentially specified each time such
186 * a resource is opened for access (as is the case for SHM pools): the present mapping applies to a persistent
187 * protection in the file system, not at runtime at the code writer's discretion. The present permissions check
188 * is performed at opening time; the runtime writability check each time a datum is written into the resource.
189 *
190 * @param permissions_lvl
191 * The value to translate.
192 * @return The result.
193 */
195
196/**
197 * Utility that sets the permissions of the given resource (at the supplied file system path) to specified
198 * POSIX value. If the resource cannot be accessed (not found, permissions...) that system Error_code shall be
199 * emitted.
200 *
201 * ### Rationale ###
202 * It may seem unnecessary, particularly given that it sometimes (in our internal code, but I mention it
203 * publicly for exposition purposes) is placed right after the
204 * creation of the resource (file, SHM pool, POSIX MQ, shared mutex, etc.) -- where the same `perms` is supplied
205 * to the creation-API, whichever is applicable. The reason is that those APIs tend to make the corresponding OS
206 * call (e.g., `open()`) which is bound by the "process umask" in POSIX/Linux; so for example if it's set to
207 * the typical 022 (octal), then it's impossible to make the resource group- or all-writable, regardless of
208 * `perms`. set_resource_permissions() uses a technique that bypasses the umask thing. Note that it does not make
209 * any calls to change the umask to accomplish this.
210 *
211 * Note 1: Sometimes there is not even the creation-API argument for `perms`; in which case the rationale is even
212 * more straightforward.
213 *
214 * Note 2: Sometimes there *is* that API... and (namely in boost.ipc at least) they actually took care to do this
215 * (what we do here) themselves (via `fchmod()` and such)... so we don't need to; in fact I (ygoldfel) treated
216 * it as valuable confirmation of the correctness of this maneuver.
217 *
218 * @param logger_ptr
219 * Logger to use for logging (WARNING, on error only). Caller can themselves log further info if desired.
220 * @param path
221 * Path to resource. Symlinks are followed, and the target is the resource in question (not the symlink).
222 * @param perms
223 * See other overload.
224 * @param err_code
225 * See `flow::Error_code` docs for error reporting semantics. #Error_code generated:
226 * see other overload; note that in addition file-not-found and the like are possible errors (in fact
227 * arguably the likeliest).
228 */
229void set_resource_permissions(flow::log::Logger* logger_ptr, const fs::path& path,
230 const Permissions& perms, Error_code* err_code = 0);
231
232/**
233 * Identical to the other set_resource_permissions() overload but operates on a pre-opened Native_handle
234 * (a/k/a handle, socket, file descriptor) to the resource in question.
235 *
236 * @param logger_ptr
237 * See other overload.
238 * @param handle
239 * See above. `handle.null() == true` causes undefined behavior (assertion may trip).
240 * Closed/invalid/etc. handle will yield civilized Error_code emission.
241 * @param perms
242 * See other overload.
243 * @param err_code
244 * See `flow::Error_code` docs for error reporting semantics. #Error_code generated:
245 * system error codes if permissions cannot be set (invalid descriptor, un-opened descriptor, etc.).
246 */
247void set_resource_permissions(flow::log::Logger* logger_ptr, Native_handle handle,
248 const Permissions& perms, Error_code* err_code = 0);
249
250/**
251 * Returns `true` if and only if the given process (by PID) is reported as running by the OS.
252 * Caution: It may be running, but it may be a zombie; and/or it may be running now but dead shortly after
253 * this function returns. Use defensively.
254 *
255 * Implementation: It invokes POSIX `kill()` with the fake zero signal; this indicates the process *can*
256 * be signaled and therefore exists.
257 *
258 * @param process_id
259 * The process ID of the process in question.
260 * @return See above.
261 */
262bool process_running(process_id_t process_id);
263
264/**
265 * Syntactic-sugary helper that returns pointer to first byte in an immutable buffer, as `const uint8_t*`.
266 *
267 * @param blob
268 * The buffer.
269 * @return See above.
270 */
271const uint8_t* blob_data(const Blob_const& blob);
272
273/**
274 * Syntactic-sugary helper that returns pointer to first byte in a mutable buffer, as `uint8_t*`.
275 *
276 * @param blob
277 * The buffer.
278 * @return See above.
279 */
280uint8_t* blob_data(const Blob_mutable& blob);
281
282} // namespace ipc::util
Flow-IPC module containing miscellaneous general-use facilities that ubiquitously used by ~all Flow-I...
::pid_t process_id_t
Syntactic-sugary type for POSIX process ID (integer).
Definition: util_fwd.hpp:143
bipc::permissions Permissions
Short-hand for Unix (POSIX) permissions class.
Definition: util_fwd.hpp:161
const uint8_t * blob_data(const Blob_const &blob)
Syntactic-sugary helper that returns pointer to first byte in an immutable buffer,...
Definition: util.cpp:158
Permissions_level
Simple specifier of desired access permissions, usually but not necessarily translated into a Permiss...
Definition: util_fwd.hpp:94
@ S_UNRESTRICTED
Allows access by all. Implies, as well, at least as much access as S_GROUP_ACCESS and thus S_USER_ACC...
@ S_USER_ACCESS
Allows access by resource-owning user (in POSIX/Unix identified by UID) and no one else.
@ S_GROUP_ACCESS
Allows access by resource-owning user's containing group(s) (in POSIX/Unix identified by GID) and no ...
@ S_NO_ACCESS
Forbids all access, even by the creator's user. Most likely this would be useful for testing or debug...
flow::async::Task Task
Short-hand for polymorphic function (a-la std::function<>) that takes no arguments and returns nothin...
Definition: util_fwd.hpp:122
bipc::open_only_t Open_only
Tag type indicating an ideally-atomic open-if-exists-else-fail operation.
Definition: util_fwd.hpp:155
::gid_t group_id_t
Syntactic-sugary type for POSIX group ID (integer).
Definition: util_fwd.hpp:149
const Open_or_create OPEN_OR_CREATE
Tag value indicating an open-if-exists-else-create operation.
Definition: util.cpp:30
::uid_t user_id_t
Syntactic-sugary type for POSIX user ID (integer).
Definition: util_fwd.hpp:146
const Open_only OPEN_ONLY
Tag value indicating an atomic open-if-exists-else-fail operation.
Definition: util.cpp:31
boost::asio::mutable_buffer Blob_mutable
Short-hand for an mutable blob somewhere in memory, stored as exactly a void* and a size_t.
Definition: util_fwd.hpp:140
bool process_running(process_id_t process_id)
Returns true if and only if the given process (by PID) is reported as running by the OS.
Definition: util.cpp:134
bipc::open_or_create_t Open_or_create
Tag type indicating an atomic open-if-exists-else-create operation.
Definition: util_fwd.hpp:152
bipc::create_only_t Create_only
Tag type indicating a create-unless-exists-else-fail operation.
Definition: util_fwd.hpp:158
flow::Fine_time_pt Fine_time_pt
Short-hand for Flow's Fine_time_pt.
Definition: util_fwd.hpp:119
void set_resource_permissions(flow::log::Logger *logger_ptr, const fs::path &path, const Permissions &perms, Error_code *err_code)
Utility that sets the permissions of the given resource (at the supplied file system path) to specifi...
Definition: util.cpp:46
Permissions shared_resource_permissions(Permissions_level permissions_lvl)
Maps general Permissions_level specifier to low-level Permissions value, when the underlying resource...
Definition: util.cpp:37
flow::Fine_duration Fine_duration
Short-hand for Flow's Fine_duration.
Definition: util_fwd.hpp:117
const std::string EMPTY_STRING
A (default-cted) string. May be useful for functions returning const std::string&.
Definition: util.cpp:33
const Create_only CREATE_ONLY
Tag value indicating an atomic create-unless-exists-else-fail operation.
Definition: util.cpp:32
boost::asio::const_buffer Blob_const
Short-hand for an immutable blob somewhere in memory, stored as exactly a void const * and a size_t.
Definition: util_fwd.hpp:134
flow::util::String_view String_view
Short-hand for Flow's String_view.
Definition: util_fwd.hpp:115
@ S_END_SENTINEL
CAUTION – see ipc::Log_component doc header for directions to find actual members of this enum class.
flow::Error_code Error_code
Short-hand for flow::Error_code which is very common.
Definition: common.hpp:298
A monolayer-thin wrapper around a native handle, a/k/a descriptor a/k/a FD.