Index
#include <x/fd.H> x::fd file(x::fd::base::open("/etc/passwd", O_RDONLY)); x::fdptr fileptr;
x::fdObj
is a reference-counted object that represents
an open file descriptor.
This object provides a somewhat lower-level access to file
descriptor than STL's input/output library.
An x::fdObj
wouldn't be usually instantiated directly,
but by using constructors defined in the base class of the
x::fd
and
x::fdptr
typedefs for x::fdObj
.
The x::fd
typedef is a
x::ref to an open file descriptor
object, while x::fdptr
is a typedef for a reference
x::ptr
. Use
null
() to check if a
x::fdptr
points to a file
descriptor object, or not.
When the last reference or pointer to the file descriptor object goes out
of scope, and the object gets destroyed, the underlying file descriptor
gets closed automatically.
x::fdObj
's methods, generally, throw an exception
when an error occurs, instead of returning an error code. However, when
x::fdObj
's destructor closes the underlying
file descriptor, no exceptions gets thrown if the system
close
() returns an error (as it can, for certain
kinds of file descriptors and situations).
x::fd file; // ... file->close();
An explicit call to close
() closes the underlying
file descriptor, and throws an exception if an error occured.
x::fdObj
still exists after close
() returns, but calling
its methods will throw exceptions. Use an explicit
close
() when it's desirable to verify that the
file descriptor gets closed without any errors.
The base class of
x::fd
and
x::fdptr
defines several constructors that open new file descriptors.
All of the following constructors are equally accessed via either
x::fd::base
or
x::fdptr::base
, for convenience. They are
documented with one or the other for clarity only.
Unless otherwise noted, all of these constructors create file descriptors that have their close-on-exec bit set by default:
x::fd regular_file(x::fd::base::open("filename.dat", O_CREAT|O_TRUNC|O_RDWR, 0777); x::fd create_file_on_close(x::fd::create("filename", 0777)); x::fd duped_filedesc(x::fd::base::dup(0)); std::pair<x::fd, x::fd> pipe(x::fd::base::pipe()); std::pair<x::fd, x::fd> spipe(x::fd::base::socketpair()); x::fd temporary_file(x::fd::base::tmpfile()); x::fd temporary_file(x::fd::base::tmpfile("/var/tmp")); x::fd sock(x::fd::base::socket(PF_UNIX, SOCK_STREAM)); std::string dirname=x::fd::base::mktempdir(0700); std::pair<x::fd, std::string> sock(x::fd::base::tmpunixfilesock(dirname + "/sysmon.")); x::fdptr lock_file(x::fdptr::base::lockf("/var/tmp/sysmon.lock", F_TLOCK, 0777);
open
() constructs a file descriptor object referring
to an open file, using the traditional
open(2)
parameters.
create
() is a version of open
()
that always uses O_CREAT|O_TRUNC|O_RDWR
, additionally
the file gets actually created as
“filename
.tmp”, then renamed to
filename
when the file gets closed, either
automatically when the last pointer or reference to the object goes out of
scope and it gets destroyed, or by an explicit close
().
dup
() dup-es the specified raw file descriptor, and
constructs a new file descriptor object, that owns the dup-ed file
descriptor. An existing x::fd
or
x::fdptr
may be given instead of a raw
file descriptor, referring to another open file descriptor. This
essentially clones an existing file descriptor object.
pipe
() and spipe
() create a
regular pipe, and a socketpair pipe, respectively.
tmpfile
() creates a temporary file in the default, or
an explicitly specified directory (which carries only an academic purpose,
since, as is the tradition with temporary files, it gets immediately
unlinked from the directory, immediately upon creation.
socket
() creates a new socket.
mktempdir
() initializes a temporary subdirectory in
/tmp
with the specific permissions.
mktempdir
() tries to use
“libcxx.app.dir.userid
.groupid
.permissions
”,
first, creating it if necessary. If this subdirectory already exists,
the process's effective user and group id must match the existing
subdirectory's actual ownership. Otherwise,
mktempdir
()
creates a random subdirectory in /tmp
.
tmpunixfilesock
() creates and binds a filesystem
domain socket. The socket's name gets created randomly, with the prefix
that's specified as the mandatory parameter. Note that "/" must be
appended to the return value from mktempdir, so that
tmpunixfilesock
() gets a pathname into that
directory, since tmpunixfilesock
() treats its
parameter as a simple prefix (it's also recommended to
also prepend the application's name, too).
tmpunixfilesock
() returns the opened socket,
and its filename. The socket's filesystem permissions are set to
0777
Combined together,
mktempdir
() and
tmpunixfilesock
() provide the means for
securely installing filesystem domain sockets in /tmp
using filesystem permissions to keep out interlopers, and keeping the
pollution in /tmp
at a minimum. In a multiuser
environment, admins should keep an eye out on impersonators in
/tmp
. Because mktempdir
()
verifies any existing subdirectory's permissions, it'll then use
a random subdirectory as a fallback plan, meanwhile the pretender's
actual userid will identify the culprit.
The first time, though, any application creates the right subdirectory
with mktempdir
(), it should not remove the
subdirectory itself, but rather do any housekeeping inside it.
The subdirectory's persistance will keep the troublemakers away,
automatically.
See
x::fdObj
for more information on x::fdObj
's available
methods, once that object gets constructed.
x::fd::base
and
x::fdptr::base
also define several
miscellaneous file-related functions:
std::string dir=x::fd::base::cwd();
cwd
() returns the process's current working
directory.
std::string s=x::fd::base::realpath("."); std::string s=x::fd::base::combinepath("subdir1", "subdir2");
realpath
() expands all symbolic links,
references to “.”, “..”, etc, and
translates its parameter to an absolute pathname.
combinepath
() combines two paths together.
The paths may or may not exist.
combinepath
>() operates on its parameters only.
combinepath("/home", "me")
returns
“/home/me”,
combinepath("/home/user/bin", "..")
returns
“/home/user”, and so on.