@@ -65,6 +65,27 @@ BSLS_IDENT("$Id: $")
6565// each message. This trailing newline is stripped from the message before
6666// the message is passed to the control callback.
6767//
68+ // /Pipe Permissions
69+ // /----------------
70+ // This component creates its underlying named pipe with a permission bit
71+ // mask that defaults to `k_DEFAULT_PERMISSIONS` (`0666`, i.e., read and write
72+ // for owner, group, and others). A different permission bit mask may be
73+ // supplied at construction time via the constructor overload taking an
74+ // `int permissions` argument, or may be changed after construction (but before
75+ // `start`) by calling `setPermissions`. The bit-mask semantics follow the
76+ // conventional Unix mode-bit layout enumerated by `bdls::FilePermissions`;
77+ // callers may express the desired permissions either as an octal literal
78+ // (e.g., `0640`) or by OR-ing together `bdls::FilePermissions` enumerators
79+ // (e.g., `bdls::FilePermissions::k_OWNER_READ | ...`). Only the nine
80+ // owner/group/others read/write/execute bits are accepted (see
81+ // `bdls::FilePermissions::isValidBaseBits`); `k_SET_UID`, `k_SET_GID`, and
82+ // `k_STICKY_BIT` are not meaningful for a control pipe and result in
83+ // undefined behavior.
84+ //
85+ // On operating systems that do not support Unix-style permission bits
86+ // (notably Windows) the requested permission bit mask is silently ignored
87+ // and the pipe is created with the operating-system default permissions.
88+ //
6889// /Platform-Specific Pipe Name Encoding Caveats
6990// /--------------------------------------------
7091// Pipe-name encodings have the following caveats for the following operating
@@ -209,6 +230,8 @@ BSLS_IDENT("$Id: $")
209230
210231#include < balscm_version.h>
211232
233+ #include < bdls_filepermissions.h>
234+
212235#include < bslmt_threadattributes.h>
213236#include < bslmt_threadutil.h>
214237
@@ -247,6 +270,17 @@ class PipeControlChannel {
247270 typedef bsl::function<void (const bslstl::StringRef& message)>
248271 ControlCallback;
249272
273+ // CONSTANTS
274+
275+ // / The default permission bit mask for the underlying named pipe
276+ // / (read/write for owner, group, and others).
277+ static const int k_DEFAULT_PERMISSIONS =
278+ bdls::FilePermissions::k_OWNER_READ |
279+ bdls::FilePermissions::k_OWNER_WRITE |
280+ bdls::FilePermissions::k_GROUP_READ |
281+ bdls::FilePermissions::k_GROUP_WRITE |
282+ bdls::FilePermissions::k_OTHERS_READ |
283+ bdls::FilePermissions::k_OTHERS_WRITE;
250284 private:
251285 // TYPES
252286 enum BackgroundThreadState {
@@ -261,6 +295,10 @@ class PipeControlChannel {
261295 bsl::vector<char > d_buffer; // message buffer
262296 bslmt::ThreadUtil::Handle d_thread; // background processing thread
263297 bsls::AtomicInt d_backgroundState; // the background thread state
298+ int d_permissions; // permission bit mask for the
299+ // created named pipe (see
300+ // `bdls_filepermissions`);
301+ // ignored on Windows
264302 bool d_isPipeOpen; // true if the pipe is still open
265303
266304 union {
@@ -320,19 +358,50 @@ class PipeControlChannel {
320358
321359 // / Create a pipe control mechanism that dispatches messages to the
322360 // / specified `callback`. Optionally specify `basicAllocator` to supply
323- // / memory. If `basicAllocator` is zero, the currently installed
324- // / default allocator is used.
361+ // / memory. If `basicAllocator` is zero, the currently installed default
362+ // / allocator is used. The permission bit mask of the underlying named
363+ // / pipe defaults to `k_DEFAULT_PERMISSIONS` (0666, i.e., read/write for
364+ // / everyone) and may be changed by calling `setPermissions` before
365+ // / `start`.
325366 explicit
326367 PipeControlChannel (const ControlCallback& callback,
327368 bslma::Allocator *basicAllocator = 0 );
328369
370+ // / Create a pipe control mechanism that dispatches messages to the
371+ // / specified `callback` and creates its underlying named pipe with the
372+ // / specified `permissions` bit mask. Optionally specify
373+ // / `basicAllocator` to supply memory. If `basicAllocator` is zero, the
374+ // / currently installed default allocator is used. The behavior is
375+ // / undefined unless `bdls::FilePermissions::isValidBaseBits(permissions)`
376+ // / (i.e., unless `permissions` is a combination of the nine
377+ // / owner/group/others read/write/execute bits defined by
378+ // / `bdls::FilePermissions`; note that `k_SET_UID`, `k_SET_GID`, and
379+ // / `k_STICKY_BIT` are not accepted). On operating systems that do not
380+ // / support Unix-style permission bits (notably Windows) the value is
381+ // / ignored and falls back to the operating-system default (see the
382+ // / component-level documentation for details).
383+ PipeControlChannel (const ControlCallback& callback,
384+ int permissions,
385+ bslma::Allocator *basicAllocator = 0 );
386+
329387 // / Destroy this object. Shut down the processing thread if it is still
330388 // / running and block until it terminates. Close the named pipe and
331389 // / clean up any associated system resources.
332390 ~PipeControlChannel ();
333391
334392 // MANIPULATORS
335393
394+ // / Set the permission bit mask for the underlying named pipe to the
395+ // / specified `permissions` value. The behavior is undefined unless
396+ // / `bdls::FilePermissions::isValidBaseBits(permissions)`. This setting
397+ // / only takes effect on the next call to `start`; calling this method
398+ // / has no effect on a pipe that has already been opened. See the
399+ // / class-level documentation for a description of the cross-platform
400+ // / semantics. The behavior is undefined if this method is called while
401+ // / the background thread is running (i.e., after `start` and before
402+ // / `shutdown`), or if the `permissions` value is not valid.
403+ void setPermissions (int permissions);
404+
336405 // / Open a named pipe having the specified `pipeName`, and start a
337406 // / thread to read messages and dispatch them to the callback specified
338407 // / at construction. Optionally specify `attributes` of the background
@@ -363,6 +432,10 @@ class PipeControlChannel {
363432
364433 // ACCESSORS
365434
435+ // / Return the permission bit mask that will be applied to the named
436+ // / pipe on the next call to `start`.
437+ int permissions () const ;
438+
366439 // / Return the fully qualified system name of the pipe.
367440 const bsl::string& pipeName () const ;
368441
@@ -458,6 +531,12 @@ int PipeControlChannel::start(const STRING_TYPE& pipeName,
458531}
459532
460533// ACCESSORS
534+ inline
535+ int PipeControlChannel::permissions () const
536+ {
537+ return d_permissions;
538+ }
539+
461540inline
462541const bsl::string& PipeControlChannel::pipeName () const
463542{
0 commit comments