libcosmos
Linux C++ System Programming Library
All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
cosmos::FileDescriptor Class Reference

Thin Wrapper around OS file descriptors. More...

#include <FileDescriptor.hxx>

+ Inheritance diagram for cosmos::FileDescriptor:

Classes

struct  Owner
 Information about file owner settings. More...
 

Public Types

enum class  DescFlag : int { NONE = 0 , CLOEXEC = FD_CLOEXEC }
 Configurable per file-descriptors flags. More...
 
enum class  SealFlag : unsigned int {
  SEAL = F_SEAL_SEAL , SHRINK = F_SEAL_SHRINK , GROW = F_SEAL_GROW , WRITE = F_SEAL_WRITE ,
  FUTURE_WRITE = F_SEAL_FUTURE_WRITE
}
 Flags used in addSeals(). More...
 
enum class  LeaseType : int { READ = F_RDLCK , WRITE = F_WRLCK , UNLOCK = F_UNLCK }
 Different request types for managing file leases. More...
 
using DescFlags = BitMask<DescFlag>
 Collection of OpenFlag used for opening files.
 
using SealFlags = BitMask<SealFlag>
 Collection flags for applying seals in addSeals().
 

Public Member Functions

constexpr FileDescriptor (FileNum fd)
 
bool valid () const
 Returns whether currently a valid file descriptor number is assigned.
 
bool invalid () const
 
void setFD (const FileNum fd)
 Assigns a new primitive file descriptor to the object.
 
void reset ()
 Invalidates the stored file descriptor.
 
void close ()
 Explicitly close the contained FD.
 
void duplicate (const FileDescriptor new_fd, const CloseOnExec cloexec=CloseOnExec{true}) const
 Get a duplicate file descriptor that will further be known as new_fd.
 
FileDescriptor duplicate (const FileNum lowest=FileNum{0}, const CloseOnExec cloexec=CloseOnExec{true}) const
 Get a duplicate file descriptor using the lowest available free file descriptor number.
 
DescFlags getFlags () const
 Retrieves the current file descriptor flags.
 
void setFlags (const DescFlags flags)
 Changes the current file descriptor flags.
 
void setCloseOnExec (bool on_off)
 convenience wrapper around setFlags to change CLOEXEC setting
 
std::tuple< OpenMode, OpenFlagsgetStatusFlags () const
 Retrieve the file's OpenMode and current OpenFlags.
 
void setStatusFlags (const OpenFlags flags)
 Change certain file descriptor status flags.
 
void sync ()
 Flush oustanding writes to disk.
 
void dataSync ()
 Flush outstanding writes to disk except metadata.
 
void addSeals (const SealFlags flags)
 Add a seal for memory file descriptors.
 
SealFlags getSeals () const
 Get the currently set SealFlags for the file descriptor.
 
int getPipeSize () const
 For pipe file descriptors return the size of the pipe buffer in the kernel.
 
int setPipeSize (const int new_size)
 For pipe file descriptors this sets a new size for the pipe buffer in the kernel.
 
FileNum raw () const
 Returns the primitive file descriptor contained in the object.
 
bool operator== (const FileDescriptor &other) const
 
bool operator!= (const FileDescriptor &other) const
 
bool getLock (FileLock &lock) const
 Check lock availability for traditional process-wide POSIX locks.
 
bool setLock (const FileLock &lock) const
 Release, or attempt to obtain, a traditional process-wide POSIX lock.
 
void setLockWait (const FileLock &lock) const
 Blocking version of setLock().
 
bool getOFDLock (FileLock &lock) const
 Just like getLock() but using open-file-description locks.
 
bool setOFDLock (const FileLock &lock) const
 Just like setLock() but using open-file-description locks.
 
void setOFDLockWait (const FileLock &lock) const
 Just like setLockWait() but using open-file-description locks.
 
void getOwner (Owner &owner) const
 Returns the current file descriptor owner settings.
 
void setOwner (const Owner owner)
 Change the current file descriptor owner settings.
 
std::optional< SignalgetSignal () const
 Returns the currently configured signal for asynchronous I/O.
 
void setSignal (std::optional< Signal > sig)
 Configure the signal to be used for asynchronous I/O.
 
LeaseType getLease () const
 Gets the lease type currently set, or required to resolve a lease break.
 
void setLease (const LeaseType lease)
 Sets a new lease type on the file descriptor.
 

Protected Member Functions

int fcntl (int cmd) const
 
template<typename T >
int fcntl (int cmd, T val) const
 

Protected Attributes

FileNum m_fd = FileNum::INVALID
 

Detailed Description

Thin Wrapper around OS file descriptors.

This type carries a primitive file descriptor and provides various operations to perform on it. This is mostly kept on a generic level without knowledge about the actual object represented by the file descriptor.

Instances of this type are not intended to be used on their own, they should only be used as building blocks to provide more abstract mechanisms. In particular this type does not automatically close the associated file descriptor during destruction. This has to be done explicitly instead.

Definition at line 35 of file FileDescriptor.hxx.

Member Typedef Documentation

◆ DescFlags

Collection of OpenFlag used for opening files.

Definition at line 45 of file FileDescriptor.hxx.

◆ SealFlags

Collection flags for applying seals in addSeals().

Definition at line 57 of file FileDescriptor.hxx.

Member Enumeration Documentation

◆ DescFlag

enum class cosmos::FileDescriptor::DescFlag : int
strong

Configurable per file-descriptors flags.

Definition at line 39 of file FileDescriptor.hxx.

39 : int {
40 NONE = 0,
41 CLOEXEC = FD_CLOEXEC
42 };
@ CLOEXEC
Instead of closing, mark all matching file descriptors as CLOEXEC.

◆ LeaseType

enum class cosmos::FileDescriptor::LeaseType : int
strong

Different request types for managing file leases.

The basic constants are the same as for FileLock::Type, but the underlying type is different. Semantically is also not quite the same, thus a distinct type is used here for file leases.

Definition at line 65 of file FileDescriptor.hxx.

65 : int {
66 READ = F_RDLCK,
67 WRITE = F_WRLCK,
68 UNLOCK = F_UNLCK
69 };
@ WRITE
Disallow changing the file contents (shrink/grow is still allowed).
@ UNLOCK
remove an existing lock (regardless of shared or exclusive)
@ READ
allow read access

◆ SealFlag

enum class cosmos::FileDescriptor::SealFlag : unsigned int
strong

Flags used in addSeals().

Enumerator
SEAL 

Locks the seal set itself, further changes will be disallowed.

SHRINK 

Disallow shrinking the file in any way.

GROW 

Disallow growing the file in any way.

WRITE 

Disallow changing the file contents (shrink/grow is still allowed).

FUTURE_WRITE 

Like WRITE but allow existing shared writable mappings to write.

Definition at line 48 of file FileDescriptor.hxx.

48 : unsigned int {
49 SEAL = F_SEAL_SEAL,
50 SHRINK = F_SEAL_SHRINK,
51 GROW = F_SEAL_GROW,
52 WRITE = F_SEAL_WRITE,
53 FUTURE_WRITE = F_SEAL_FUTURE_WRITE
54 };
@ FUTURE_WRITE
Like WRITE but allow existing shared writable mappings to write.
@ SEAL
Locks the seal set itself, further changes will be disallowed.
@ SHRINK
Disallow shrinking the file in any way.
@ GROW
Disallow growing the file in any way.

Constructor & Destructor Documentation

◆ FileDescriptor()

cosmos::FileDescriptor::FileDescriptor ( FileNum fd)
inlineexplicitconstexpr

Definition at line 191 of file FileDescriptor.hxx.

191 :
192 m_fd{fd} {}

Member Function Documentation

◆ addSeals()

void cosmos::FileDescriptor::addSeals ( const SealFlags flags)

Add a seal for memory file descriptors.

This is only supported for file descriptors referring to a "memfd" as it is created by MemFile. It allows to restrict what operations can be performed on the file in the future (this affects all open file descriptions referring to the file).

Definition at line 127 of file FileDescriptor.cxx.

127 {
128 const auto res = this->fcntl(F_ADD_SEALS, flags.raw());
129
130 if (res != 0) {
131 cosmos_throw (ApiError("fcntl(F_ADD_SEALS)"));
132 }
133}

◆ close()

void cosmos::FileDescriptor::close ( )

Explicitly close the contained FD.

This asks the operating system to close the associated file. The stored file descriptor will be reset().

On rare occasions closing a file can fail. The most prominent error is "invalid file descriptor" (EINVAL) but there can be other situations, like when during close() outstanding writes are performed.

This member function can thus throw an exception on these conditions. In this case the contained file descriptor will still be reset() to avoid identical follow-up errors.

Definition at line 17 of file FileDescriptor.cxx.

17 {
18 if(!valid())
19 return;
20 const auto fd = m_fd;
21 m_fd = FileNum::INVALID;
22 if (::close(to_integral(fd)) == 0) {
23 return;
24 }
25
26 cosmos_throw (ApiError("close()"));
27}
void close()
Explicitly close the contained FD.
bool valid() const
Returns whether currently a valid file descriptor number is assigned.

◆ dataSync()

void cosmos::FileDescriptor::dataSync ( )

Flush outstanding writes to disk except metadata.

This is an optimization of sync() that only writes out the actual file data, but not the metadata. This can make sense if e.g. the file size did not change but the data changed (e.g. for fixed size database files etc.).

Definition at line 123 of file FileDescriptor.cxx.

123 {
124 sync_helper(*this, fdatasync, "fdatasync()");
125}

◆ duplicate() [1/2]

void cosmos::FileDescriptor::duplicate ( const FileDescriptor new_fd,
const CloseOnExec cloexec = CloseOnExec{true} ) const

Get a duplicate file descriptor that will further be known as new_fd.

The currently stored file descriptor will be duplicated and the primitive file descriptor number set in new_fd will be used as the duplicate representation. If new_fd is already an open file object then it will first be silently closed, errors ignored.

Parameters
[in]cloexecDenotes whether the duplicate file descriptor will have the close-on-exec flag set.

Definition at line 38 of file FileDescriptor.cxx.

38 {
39 const auto res = ::dup3(to_integral(m_fd), to_integral(new_fd.raw()), cloexec ? O_CLOEXEC : 0);
40
41 if (res == -1) {
42 cosmos_throw (ApiError("dup3()"));
43 }
44}

◆ duplicate() [2/2]

FileDescriptor cosmos::FileDescriptor::duplicate ( const FileNum lowest = FileNum{0},
const CloseOnExec cloexec = CloseOnExec{true} ) const

Get a duplicate file descriptor using the lowest available free file descriptor number.

Be careful to close the returned file descriptor again when necessary. It is best to turn it into some object that manages file descriptor lifetime automatically.

Parameters
[in]lowestFrom which file descriptor to start looking for a free entry. By default zero, i.e. the lowest available free file descriptor number will be used.
[in]cloexecDenotes whether the duplicate file descriptor will have the close-on-exec flag set.

Definition at line 46 of file FileDescriptor.cxx.

46 {
47 const auto fd = this->fcntl(cloexec ? F_DUPFD_CLOEXEC : F_DUPFD, to_integral(lowest));
48
49 if (fd == -1) {
50 cosmos_throw (ApiError("fcntl(F_DUPFD)"));
51 }
52
53 return FileDescriptor{FileNum{fd}};
54}
FileNum
Primitive file descriptor.
Definition types.hxx:32

◆ fcntl() [1/2]

int cosmos::FileDescriptor::fcntl ( int cmd) const
protected

Definition at line 29 of file FileDescriptor.cxx.

29 {
30 return ::fcntl(to_integral(m_fd), cmd);
31}

◆ fcntl() [2/2]

template<typename T >
int cosmos::FileDescriptor::fcntl ( int cmd,
T val ) const
protected

Definition at line 34 of file FileDescriptor.cxx.

34 {
35 return ::fcntl(to_integral(m_fd), cmd, val);
36}

◆ getFlags()

FileDescriptor::DescFlags cosmos::FileDescriptor::getFlags ( ) const

Retrieves the current file descriptor flags.

Definition at line 56 of file FileDescriptor.cxx.

56 {
57 const auto flags = this->fcntl(F_GETFD);
58
59 if (flags == -1) {
60 cosmos_throw (ApiError("fcntl(F_GETFD)"));
61 }
62
63 return DescFlags{flags};
64}
BitMask< DescFlag > DescFlags
Collection of OpenFlag used for opening files.

◆ getLease()

FileDescriptor::LeaseType cosmos::FileDescriptor::getLease ( ) const

Gets the lease type currently set, or required to resolve a lease break.

For an overview of file leases, see setLease().

The semantics for getLease() are somewhat confusing. As long as there is no lease break in progress it returns the lease that is currently held on the file, or LeaseType::UNLOCK if no lease is currently present. As soon as a lease break happens and the lease holder is notified of it, getLease() returns the new target lease type that is necessary to resolve the lease break situation, which can be LeaseType::READ, if the lease breaker wants to open the file read-only and the lease can be downgraded, or LeaseType::UNLOCK if the lease breaker wants to open the file for writing and the lease has to be removed.

Definition at line 278 of file FileDescriptor.cxx.

278 {
279 const auto res = this->fcntl(F_GETLEASE);
280
281 if (res == -1) {
282 cosmos_throw (ApiError("fcntl(F_GETLEASE)"));
283 }
284
285 return LeaseType{res};
286}
LeaseType
Different request types for managing file leases.

◆ getLock()

bool cosmos::FileDescriptor::getLock ( FileLock & lock) const

Check lock availability for traditional process-wide POSIX locks.

On input the lock data structure describes a lock that the caller would like to place on the file. On output, if placing the lock would be possible, lock.type() will be FileLock::Type::UNLOCK. Otherwise lock will describe the conflicting lock that prevents placing the lock. More than one lock can be conflicting, but only the information for a single lock will be returned.

This check is subject to race conditions and cannot guarantee that a later call to setLock() will succeed. If true is returned, then placing the lock is currently possible (i.e. lock.type() == FileLock::Type::UNLOCK).

Definition at line 165 of file FileDescriptor.cxx.

165 {
166 const auto res = this->fcntl(F_GETLK, &lock);
167
168 if (res != 0) {
169 cosmos_throw (ApiError("fcntl(F_GETLK)"));
170 }
171
172 return lock.type() == FileLock::Type::UNLOCK;
173}

◆ getOFDLock()

bool cosmos::FileDescriptor::getOFDLock ( FileLock & lock) const

Just like getLock() but using open-file-description locks.

Definition at line 199 of file FileDescriptor.cxx.

199 {
200 const auto res = this->fcntl(F_OFD_GETLK, &lock);
201
202 if (res != 0) {
203 cosmos_throw (ApiError("fcntl(F_OFD_GETLK)"));
204 }
205
206 return lock.type() == FileLock::Type::UNLOCK;
207}

◆ getOwner()

void cosmos::FileDescriptor::getOwner ( Owner & owner) const

Returns the current file descriptor owner settings.

If no owner has been set previously, then the call will succeed but owner.valid() will return false. This is no fully specified in fcntl(2) but practical tests show that in this case Owner::Type::THREAD with a ThreadID of zero is returned by the kernel.

Definition at line 241 of file FileDescriptor.cxx.

241 {
242 const auto res = this->fcntl(F_GETOWN_EX, owner.raw());
243
244 if (res != 0) {
245 cosmos_throw (ApiError("fcntl(F_GETOWN_EX)"));
246 }
247}

◆ getPipeSize()

int cosmos::FileDescriptor::getPipeSize ( ) const

For pipe file descriptors return the size of the pipe buffer in the kernel.

Definition at line 145 of file FileDescriptor.cxx.

145 {
146 const auto res = this->fcntl(F_GETPIPE_SZ);
147
148 if (res != 0) {
149 cosmos_throw (ApiError("fcntl(F_GETPIP_SZ)"));
150 }
151
152 return res;
153}

◆ getSeals()

FileDescriptor::SealFlags cosmos::FileDescriptor::getSeals ( ) const

Get the currently set SealFlags for the file descriptor.

Definition at line 135 of file FileDescriptor.cxx.

135 {
136 const auto res = this->fcntl(F_GET_SEALS);
137
138 if (res != 0) {
139 cosmos_throw (ApiError("fcntl(F_GET_SEALS)"));
140 }
141
142 return SealFlags{static_cast<SealFlag>(res)};
143}
BitMask< SealFlag > SealFlags
Collection flags for applying seals in addSeals().
SealFlag
Flags used in addSeals().

◆ getSignal()

std::optional< Signal > cosmos::FileDescriptor::getSignal ( ) const

Returns the currently configured signal for asynchronous I/O.

If std::nullopt is returned, then the default SIGIO signal (cosmos::signal::IO_EVENT) is configured. Otherwise the returned signal will be delivered together with extra information if SA_SIGINFO handler is setup for it. This extra information allows to identify the file descriptor for which the event was sent.

There exists a corner case, though, if the file descriptor for which the event was configured is closed but a copy of the file descriptor is still around. Then the signal will report the original now closed file descriptor.

To keep track of multiple file descriptor events occurring in parallel it is recommended to use a realtime signal, which is queued in the kernel up to a certain limit.

Definition at line 257 of file FileDescriptor.cxx.

257 {
258 const auto res = this->fcntl(F_GETSIG);
259
260 if (res == -1) {
261 cosmos_throw (ApiError("fcntl(F_GETSIG)"));
262 }
263
264 if (res == 0)
265 return {};
266
267 return Signal{SignalNr{res}};
268}
SignalNr
A primitive signal number specification.
Definition types.hxx:50

◆ getStatusFlags()

std::tuple< OpenMode, OpenFlags > cosmos::FileDescriptor::getStatusFlags ( ) const

Retrieve the file's OpenMode and current OpenFlags.

Definition at line 74 of file FileDescriptor.cxx.

74 {
75 const auto flags = this->fcntl(F_GETFL);
76
77 if (flags == -1) {
78 cosmos_throw (ApiError("fcntl(F_GETFL)"));
79 }
80
81 OpenMode mode{flags & (O_RDONLY|O_WRONLY|O_RDWR)};
82 OpenFlags settings{flags & ~to_integral(mode)};
83
84 return {mode, settings};
85}
BitMask< OpenFlag > OpenFlags
Collection of OpenFlag used for opening files.
Definition types.hxx:96
OpenMode
Strong enum type wrapper for the basic open() mode flag.
Definition types.hxx:52

◆ invalid()

bool cosmos::FileDescriptor::invalid ( ) const
inline

Definition at line 196 of file FileDescriptor.hxx.

196{ return !valid(); }

◆ operator!=()

bool cosmos::FileDescriptor::operator!= ( const FileDescriptor & other) const
inline

Definition at line 347 of file FileDescriptor.hxx.

347 {
348 return !(*this == other);
349 }

◆ operator==()

bool cosmos::FileDescriptor::operator== ( const FileDescriptor & other) const
inline

Definition at line 343 of file FileDescriptor.hxx.

343 {
344 return m_fd == other.m_fd;
345 }

◆ raw()

FileNum cosmos::FileDescriptor::raw ( ) const
inline

Returns the primitive file descriptor contained in the object.

Definition at line 341 of file FileDescriptor.hxx.

341{ return m_fd; }

◆ reset()

void cosmos::FileDescriptor::reset ( )
inline

Invalidates the stored file descriptor.

This operation simply resets the stored file descriptor to FileNum::INVALID. No system call will be performed and if the file is not closed by other means a file descriptor leak will be the result.

Definition at line 212 of file FileDescriptor.hxx.

212{ m_fd = FileNum::INVALID; }

◆ setCloseOnExec()

void cosmos::FileDescriptor::setCloseOnExec ( bool on_off)
inline

convenience wrapper around setFlags to change CLOEXEC setting

Definition at line 266 of file FileDescriptor.hxx.

266 {
267 setFlags({on_off ? DescFlag::CLOEXEC : DescFlag::NONE});
268 }
void setFlags(const DescFlags flags)
Changes the current file descriptor flags.

◆ setFD()

void cosmos::FileDescriptor::setFD ( const FileNum fd)
inline

Assigns a new primitive file descriptor to the object.

A potentially already contained file descriptor will not be closed, the caller is responsible for preventing leaks.

Definition at line 203 of file FileDescriptor.hxx.

203{ m_fd = fd; }

◆ setFlags()

void cosmos::FileDescriptor::setFlags ( const DescFlags flags)

Changes the current file descriptor flags.

Definition at line 66 of file FileDescriptor.cxx.

66 {
67 const auto res = this->fcntl(F_SETFD, flags.raw());
68
69 if (res != 0) {
70 cosmos_throw (ApiError("fcntl(F_SETFD)"));
71 }
72}

◆ setLease()

void cosmos::FileDescriptor::setLease ( const LeaseType lease)

Sets a new lease type on the file descriptor.

A file lease is a mechanism that allows the lease holder to act on the file before another process (the lease breaker) accesses it. It has some similarity to a mandatory file lock in so far as the lease breaker will be blocked (in open() or truncate()) until the lease holder unlocks or downgrades the lease. The kernel puts a limit on the maximum block time in seconds until the lease holder has to resolve the situation, otherwise the lease will be forcibly removed. This time is configured in the sys.fs.lease-break-time sysctl.

The lease holder is informed of a lease break situation by a signal, which is configured via setSignal(). See also getSignal().

Leases are associated with the open file description and thus shared by copies of the file descriptor, can be inherited to child processes and will be automatically released once all copies of the file descriptor are closed.

File leases are only supported on regular files. A process may only acquire a lease for files it owns, or if the process has the CAP_LEASE capability, otherwise an ApiError with Errno::ACCESS is thrown.

This call is used to establish, remove or change an existing lease. To remove an existing lease pass LeaseType::UNLOCK to this function.

A lease of LeaseType::READ can only be placed on a file descriptor opened read-only. In this case the lease holder will be notified when the file is opened for writing or is truncated.

A lease of LeaseType::WRITE can only be placed if there are currently no other open file descriptors for the file (otherwise the lease would already be broken). The lease holder will be notified when the file is opened for reading, writing or is truncated. The file descriptor can be open for reading and writing.

A lease can be downgraded from LeaseType::WRITE to LeaseType::READ, which will allow lease breakers, that want to open the file for reading, to be unblocked. This only works if the file descriptor has been opened read-only, though.

If a conflicting lease is currently set on the file, or the file's OpenMode is not compatible with the requested lease, an ApiError with Errno::AGAIN is thrown.

Another process can open a file on which a lease is held in non-blocking mode, which will result in Errno::WOULD_BLOCK error. Even this attempt to open the file will trigger the lease breaker logic. The same is true if the lease breaker's system call is interrupted by a signal, or the lease breaker gets killed while blocking on the lease.

Definition at line 288 of file FileDescriptor.cxx.

288 {
289 const auto res = this->fcntl(F_SETLEASE, to_integral(lease));
290
291 if (res != 0) {
292 cosmos_throw (ApiError("fcntl(F_SETLEASE)"));
293 }
294}

◆ setLock()

bool cosmos::FileDescriptor::setLock ( const FileLock & lock) const

Release, or attempt to obtain, a traditional process-wide POSIX lock.

lock describes a lock to be released or to be placed on the file.

For unlocking set lock.type() to FileLock::Type::UNLOCK. Unlock operations always return true or throw an ApiError.

For unlocking this always returns true. For locking, if placing the lock succeeds, true is returned, false otherwise. This call will not block if the lock cannot be obtained. On error conditions an ApiError is thrown.

Definition at line 175 of file FileDescriptor.cxx.

175 {
176 const auto res = this->fcntl(F_SETLK, &lock);
177
178 if (res != 0) {
179 switch (get_errno()) {
180 case Errno::AGAIN:
181 case Errno::ACCESS:
182 return false;
183 default:
184 cosmos_throw (ApiError("fcntl(F_SETLK)"));
185 }
186 }
187
188 return true;
189}
Errno get_errno()
Wrapper that returns the Errno strongly typed representation of the current errno
Definition errno.hxx:111

◆ setLockWait()

void cosmos::FileDescriptor::setLockWait ( const FileLock & lock) const

Blocking version of setLock().

This call will block until the described lock is placed on the file. On error conditions an ApiError is thrown.

There is some basic deadlock detection for this operation which can result in an ApiError with Errno::DEADLOCK to be thrown.

Definition at line 191 of file FileDescriptor.cxx.

191 {
192 const auto res = this->fcntl(F_SETLKW, &lock);
193
194 if (res != 0) {
195 cosmos_throw (ApiError("fcntl(F_SETLKW)"));
196 }
197}

◆ setOFDLock()

bool cosmos::FileDescriptor::setOFDLock ( const FileLock & lock) const

Just like setLock() but using open-file-description locks.

Definition at line 209 of file FileDescriptor.cxx.

209 {
210 if (lock.pid() != ProcessID{0}) {
211 // provide better diagnostics, the kernel would just return EINVAL in this case
212 cosmos_throw (UsageError("attempt to set OFD lock with l_pid != 0"));
213 }
214 const auto res = this->fcntl(F_OFD_SETLK, &lock);
215
216 if (res != 0) {
217 switch (get_errno()) {
218 case Errno::AGAIN:
219 case Errno::ACCESS:
220 return false;
221 default:
222 cosmos_throw (ApiError("fcntl(F_OFD_SETLK)"));
223 }
224 }
225
226 return true;
227}

◆ setOFDLockWait()

void cosmos::FileDescriptor::setOFDLockWait ( const FileLock & lock) const

Just like setLockWait() but using open-file-description locks.

Definition at line 229 of file FileDescriptor.cxx.

229 {
230 if (lock.pid() != ProcessID{0}) {
231 // provide better diagnostics, the kernel would just return EINVAL in this case
232 cosmos_throw (UsageError("attempt to set OFD lock with l_pid != 0"));
233 }
234 const auto res = this->fcntl(F_OFD_SETLKW, &lock);
235
236 if (res != 0) {
237 cosmos_throw (ApiError("fcntl(F_OFD_SETLKW)"));
238 }
239}

◆ setOwner()

void cosmos::FileDescriptor::setOwner ( const Owner owner)

Change the current file descriptor owner settings.

The credentials at the time of this call will be associated with the file descriptor and will be used for permission checks when an asynchronous I/O signal needs to be delivered.

Definition at line 249 of file FileDescriptor.cxx.

249 {
250 const auto res = this->fcntl(F_SETOWN_EX, owner.raw());
251
252 if (res != 0) {
253 cosmos_throw (ApiError("fcntl(F_SETOWN_EX)"));
254 }
255}

◆ setPipeSize()

int cosmos::FileDescriptor::setPipeSize ( const int new_size)

For pipe file descriptors this sets a new size for the pipe buffer in the kernel.

The kernel can choose a larger size if it deems this necessary. /proc/sys/fs/pipe-max-size defines a maximum pipe buffer size for the system. The actually used size will be returned from this call.

Definition at line 155 of file FileDescriptor.cxx.

155 {
156 const auto res = this->fcntl(F_SETPIPE_SZ, new_size);
157
158 if (res != 0) {
159 cosmos_throw (ApiError("fcntl(F_SETPIP_SZ)"));
160 }
161
162 return res;
163}

◆ setSignal()

void cosmos::FileDescriptor::setSignal ( std::optional< Signal > sig)

Configure the signal to be used for asynchronous I/O.

If std::nullopt is passed then the default SIGIO signal will be configured and no extra information is provided to the signal handler. Otherwise the supplied signal is used and the extra information is supplied as described at getSignal().

This signal is also used to notify a process of file lease events, see setLease().

Definition at line 270 of file FileDescriptor.cxx.

270 {
271 const auto res = this->fcntl(F_SETSIG, sig ? to_integral(sig->raw()) : 0);
272
273 if (res != 0) {
274 cosmos_throw (ApiError("fcntl(F_SETSIG)"));
275 }
276}

◆ setStatusFlags()

void cosmos::FileDescriptor::setStatusFlags ( const OpenFlags flags)

Change certain file descriptor status flags.

The basic file OpenMode cannot be changed for an open file descriptor. From OpenFlags only the flags APPEND, ASYNC, DIRECT, NOATIME and NONBLOCK can be changed afterwards.

Definition at line 87 of file FileDescriptor.cxx.

87 {
88 const auto res = this->fcntl(F_SETFL, flags.raw());
89
90 if (res != 0) {
91 cosmos_throw (ApiError("fcntl(F_SETFL)"));
92 }
93}

◆ sync()

void cosmos::FileDescriptor::sync ( )

Flush oustanding writes to disk.

Kernel buffering may cause written data to stay in memory until it is deemed necessary to actually write to disk. Use this function to make sure that any writes that happened on the file descriptor will actually be transferred to the underlying disk device. This covers not only the actual file data but also the metadata (inode data).

This operation ensures that the data is on disk even if the system is hard reset, crashes or loses power. The call blocks until the underlying device reports that the transfer has completed.

Even after that it is not yet ensured that the directory containing the file has actually the directory entry written to disk. To ensure this as well perform sync() also on a file descriptor for the directory containing the file.

This call can cause an ApiError to be thrown e.g. if:

  • the file descriptor is invalid (Errno::BAD_FD)
  • a device level I/O error occurred (Errno::IO_ERROR)
  • space is exhausted on the file system (Errno::NO_SPACE)
  • the file descriptor does not support syncing, because it is a special file that does not support it (Errno::INVALID_ARG)

Definition at line 119 of file FileDescriptor.cxx.

119 {
120 sync_helper(*this, fsync, "fsync()");
121}

◆ valid()

bool cosmos::FileDescriptor::valid ( ) const
inline

Returns whether currently a valid file descriptor number is assigned.

Definition at line 195 of file FileDescriptor.hxx.

195{ return m_fd != FileNum::INVALID; }

Member Data Documentation

◆ m_fd

FileNum cosmos::FileDescriptor::m_fd = FileNum::INVALID
protected

Definition at line 535 of file FileDescriptor.hxx.


The documentation for this class was generated from the following files: