Flow-IPC 1.0.0
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/**
66 * Simple specifier of desired access permissions, usually but not necessarily translated into
67 * a `Permissions` value (though even then different value in different contexts). May be used to map, say,
68 * from a Permissions_level to a #Permissions value in an
69 * `array<Permissions, size_t(Permissions_level::S_END_SENTINEL)>`.
70 *
71 * While, unlike #Permissions, this `enum` intends not be overtly based on a POSIX RWXRWXRWC model, it does
72 * still assume the 3 user groupings are "user themselves," "user's group," and "everyone." The 1st and 3rd
73 * are likely universal, but the 2nd may not apply to all OS -- through probably all POSIX/Unix ones --
74 * and even for something like Linux there could be different groupings such as ones based on OS ACL.
75 * As of this writing it's fine, as this is a POSIX-targeted library at least (in fact, Linux, as of this writing,
76 * but that could change to include, say, MacOS/BSD).
77 *
78 * @internal
79 * ### Maintenance ###
80 * Do *not* change the order of these constants unless absolutely necessary. In general any change here
81 * means updating any `array<>`s (etc.) that map implicitly from a `size_t` representing
82 * Permissions_level. By convention they are named `*_PERMISSIONS_LVL_MAP` as of this writing.
83 *
84 * The `array<>` mapping scheme is for max performance; if one uses an `unordered_map` or similar, then there is no
85 * similar issue.
86 */
87enum class Permissions_level : size_t
88{
89 /// Forbids all access, even by the creator's user. Most likely this would be useful for testing or debugging.
91
92 /// Allows access by resource-owning user (in POSIX/Unix identified by UID) and no one else.
94
95 /**
96 * Allows access by resource-owning user's containing group(s) (in POSIX/Unix identified by GID) and no one else.
97 * This implies, as well, at least as much access as `S_USER_ACCESS`.
98 */
100
101 /// Allows access by all. Implies, as well, at least as much access as `S_GROUP_ACCESS` and thus `S_USER_ACCESS`.
103
104 /// Sentinel: not a valid value. May be used to, e.g., size an `array<>` mapping from Permissions_level.
106}; // enum class Permissions_level
107
108/// Short-hand for Flow's `String_view`.
110/// Short-hand for Flow's `Fine_duration`.
112/// Short-hand for Flow's `Fine_time_pt`.
114
115/// Short-hand for polymorphic function (a-la `std::function<>`) that takes no arguments and returns nothing.
117
118/**
119 * Short-hand for an immutable blob somewhere in memory, stored as exactly a `void const *` and a `size_t`.
120 *
121 * ### How to use ###
122 * We provide this alias as a stylistic short-hand, as it better suits various interfaces especially in
123 * ipc::transport. Nevertheless it's not meant to more than that; it's an attempt to abstract it away.
124 *
125 * That is to say, to work with these (create them, access them, etc.), do use the highly convenient
126 * boost.asio buffer APIs which are well documented in boost.asio's docs.
127 */
128using Blob_const = boost::asio::const_buffer;
129
130/**
131 * Short-hand for an mutable blob somewhere in memory, stored as exactly a `void*` and a `size_t`.
132 * @see ipc::util::Blob_const; usability notes in that doc header apply similarly here.
133 */
134using Blob_mutable = boost::asio::mutable_buffer;
135
136/// Syntactic-sugary type for POSIX process ID (integer).
137using process_id_t = ::pid_t;
138
139/// Syntactic-sugary type for POSIX user ID (integer).
140using user_id_t = ::uid_t;
141
142/// Syntactic-sugary type for POSIX group ID (integer).
143using group_id_t = ::gid_t;
144
145/// Tag type indicating an atomic open-if-exists-else-create operation. @see #OPEN_OR_CREATE.
146using Open_or_create = bipc::open_or_create_t;
147
148/// Tag type indicating an ideally-atomic open-if-exists-else-fail operation. @see #OPEN_ONLY.
149using Open_only = bipc::open_only_t;
150
151/// Tag type indicating a create-unless-exists-else-fail operation. @see #CREATE_ONLY.
152using Create_only = bipc::create_only_t;
153
154/// Short-hand for Unix (POSIX) permissions class.
155using Permissions = bipc::permissions;
156
157// Constants.
158
159/// Tag value indicating an open-if-exists-else-create operation.
160extern const Open_or_create OPEN_OR_CREATE;
161
162/// Tag value indicating an atomic open-if-exists-else-fail operation.
163extern const Open_only OPEN_ONLY;
164
165/// Tag value indicating an atomic create-unless-exists-else-fail operation.
166extern const Create_only CREATE_ONLY;
167
168/// A (default-cted) string. May be useful for functions returning `const std::string&`.
169extern const std::string EMPTY_STRING;
170
171// Free functions.
172
173/**
174 * Maps general Permissions_level specifier to low-level #Permissions value, when the underlying resource
175 * is in the file-system and is either accessible (read-write in terms of file system) or inaccessible.
176 * Examples of such resources are SHM pools (e.g., shm::classic::Pool_arena), bipc MQs (transport::Bipc_mq_handle),
177 * POSIX MQs (transport::Posix_mq_handle).
178 *
179 * Please do not confuse this setting with the read-only/read-write dichotomy potentially specified each time such
180 * a resource is opened for access (as is the case for SHM pools): the present mapping applies to a persistent
181 * protection in the file system, not at runtime at the code writer's discretion. The present permissions check
182 * is performed at opening time; the runtime writability check each time a datum is written into the resource.
183 *
184 * @param permissions_lvl
185 * The value to translate.
186 * @return The result.
187 */
189
190/**
191 * Utility that sets the permissions of the given resource (at the supplied file system path) to specified
192 * POSIX value. If the resource cannot be accessed (not found, permissions...) that system Error_code shall be
193 * emitted.
194 *
195 * ### Rationale ###
196 * It may seem unnecessary, particularly given that it sometimes (in our internal code, but I mention it
197 * publicly for exposition purposes) placed right after the
198 * creation of the resource (file, SHM pool, POSIX MQ, shared mutex, etc.) -- where the same `perms` is supplied
199 * to the creation-API, whichever is applicable. The reason is that those APIs tend to make the corresponding OS
200 * call (e.g., `open()`) which is bound by the "process umask" in POSIX/Linux; so for example if it's set to
201 * the typical 022 (octal), then it's impossible to make the resource group- or all-writable, regardless of
202 * `perms`. set_resource_permissions() uses a technique that bypasses the umask thing. Note that it does not make
203 * any calls to change the umask to accomplish this.
204 *
205 * Note 1: Sometimes there is not even the creation-API argument for `perms`; in which case the rationale is even
206 * more straightforward.
207 *
208 * Note 2: Sometimes there *is* that API... and (namely in boost.ipc at least) they actually took care to do this
209 * (what we do here) themselves (via `fchmod()` and such)... so we don't need to; in fact I (ygoldfel) treated
210 * it as valuable confirmation of the correctness of this maneuver.
211 *
212 * @param logger_ptr
213 * Logger to use for logging (WARNING, on error only). Caller can themselves log further info if desired.
214 * @param path
215 * Path to resource. Symlinks are followed, and the target is the resource in question (not the symlink).
216 * @param perms
217 * See other overload.
218 * @param err_code
219 * See `flow::Error_code` docs for error reporting semantics. #Error_code generated:
220 * see other overload; note that in addition file-not-found and the like are possible errors (in fact
221 * arguably the likeliest).
222 */
223void set_resource_permissions(flow::log::Logger* logger_ptr, const fs::path& path,
224 const Permissions& perms, Error_code* err_code = 0);
225
226/**
227 * Identical to the other set_resource_permissions() overload but operates on a pre-opened Native_handle
228 * (a/k/a handle, socket, file descriptor) to the resource in question.
229 *
230 * @param logger_ptr
231 * See other overload.
232 * @param handle
233 * See above. `handle.null() == true` causes undefined behavior (assertion may trip).
234 * Closed/invalid/etc. handle will yield civilized Error_code emission.
235 * @param perms
236 * See other overload.
237 * @param err_code
238 * See `flow::Error_code` docs for error reporting semantics. #Error_code generated:
239 * system error codes if permissions cannot be set (invalid descriptor, un-opened descriptor, etc.).
240 */
241void set_resource_permissions(flow::log::Logger* logger_ptr, Native_handle handle,
242 const Permissions& perms, Error_code* err_code = 0);
243
244/**
245 * Returns `true` if and only if the given process (by PID) is reported as running by the OS.
246 * Caution: It may be running, but it may be a zombie; and/or it may be running now but dead shortly after
247 * this function returns. Use defensively.
248 *
249 * Implementation: It invokes POSIX `kill()` with the fake zero signal; this indicates the process *can*
250 * be signaled and therefore exists.
251 *
252 * @param process_id
253 * The process ID of the process in question.
254 * @return See above.
255 */
256bool process_running(process_id_t process_id);
257
258/**
259 * Syntactic-sugary helper that returns pointer to first byte in an immutable buffer, as `const uint8_t*`.
260 *
261 * @param blob
262 * The buffer.
263 * @return See above.
264 */
265const uint8_t* blob_data(const Blob_const& blob);
266
267/**
268 * Syntactic-sugary helper that returns pointer to first byte in a mutable buffer, as `uint8_t*`.
269 *
270 * @param blob
271 * The buffer.
272 * @return See above.
273 */
274uint8_t* blob_data(const Blob_mutable& blob);
275
276} // 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:137
bipc::permissions Permissions
Short-hand for Unix (POSIX) permissions class.
Definition: util_fwd.hpp:155
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:156
Permissions_level
Simple specifier of desired access permissions, usually but not necessarily translated into a Permiss...
Definition: util_fwd.hpp:88
@ 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:116
bipc::open_only_t Open_only
Tag type indicating an ideally-atomic open-if-exists-else-fail operation.
Definition: util_fwd.hpp:149
::gid_t group_id_t
Syntactic-sugary type for POSIX group ID (integer).
Definition: util_fwd.hpp:143
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:140
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:134
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:146
bipc::create_only_t Create_only
Tag type indicating a create-unless-exists-else-fail operation.
Definition: util_fwd.hpp:152
flow::Fine_time_pt Fine_time_pt
Short-hand for Flow's Fine_time_pt.
Definition: util_fwd.hpp:113
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:111
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:128
flow::util::String_view String_view
Short-hand for Flow's String_view.
Definition: util_fwd.hpp:109
@ 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:297
A monolayer-thin wrapper around a native handle, a/k/a descriptor a/k/a FD.