[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A file is traditionally thought of as a quantity of disk storage. In the Hurd, files are an extension of the I/O interface, but they do not necessarily correspond to disk storage.
Every file in the Hurd is represented by a port, which is connected to the server that manages the file. When a client wants to operate on a file, it makes RPC requests via a file port to its server process, which is commonly called a translator.
5.1 Translators | Extending the Hurd filesystem hierarchy. | |
5.2 Trivfs Library | Implementing single-file translators. | |
5.3 Fshelp Library | Miscellaneous generic filesystem routines. | |
5.4 File Interface | File ports implement the file interface. | |
5.5 Filesystem Interface | Translator control interface. |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The Hurd filesystem allows you to set translators on any file or directory that you own. A translator is any Hurd server which provides the basic filesystem interface. Translated nodes are somewhat like a cross between Unix symbolic links and mount points.
Whenever a program tries to access the contents of a translated node, the filesystem server redirects the request to the appropriate translator (starting it if necessary). Then, the new translator services the client's request. The GNU C library makes this behaviour seamless from the client's perspective, so that standard Unix programs behave correctly under the Hurd.
Translators run with the privileges of the translated node's owner, so they cannot be used to compromise the security of the system. This also means that any user can write their own translators, and provide other users with arbitrary filesystem-structured data, regardless of the data's actual source. Other chapters in this manual describe existing translators, and how you can modify them or write your own.
The standard Hurd filesystem servers are constantly evolving to provide innovative features that users want. Here are a few examples of existing translators:
ext2fs
, ufs
, and
iso9660fs
(see section 8. Stored Filesystems).
nfs
and ftpfs
(see section 10. Distributed Filesystems).
pflocal
implements the
filesystem interfaces, but it also provides a special Unix-domain socket
RPC interface (FIXME xref). Programs can fetch a port to this
translator simply by calling file_name_lookup
(FIXME xref) on
`/servers/socket/1'(6), then use Unix
socket-specific RPCs on that port, rather than adhering to the file
protocol.
This section focuses on the generic programs that you need to understand in order to use existing translators. Many other parts of this manual describe how you can write your own translators.
5.1.1 Invoking settrans | Declaring how a node should be translated. | |
5.1.2 Invoking showtrans | Displaying how nodes are translated. | |
5.1.3 Invoking mount | Unix-compatible active filesystem translators. | |
5.1.4 Invoking fsysopts | Modifying translation parameters at runtime. |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
settrans
The settrans
program allows you to set a translator on a file or
directory. By default, the passive translator is set (see the
`--passive' option).
The settrans
program has the following synopsis:
settrans [option]... node [translator arg...] |
where translator is the absolute filename of the new translator
program. Each arg is passed to translator when it starts.
If translator is not specified, then settrans
clears the
existing translator rather than setting a new one.
settrans
accepts the following options:
Passive translators are stored on the underlying filesystem media, and so they persist between system reboots. Not all filesystems support passive translators, due to limitations in their underlying media. Consult the filesystem-specific documentation to see if they are supported.
If you are setting the passive translator, and node already has an active translator, then the following options apply:
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
showtrans
The showtrans
program allows you to show the passive translator
setting on a file system node.
The showtrans
program has the following synopsis:
showtrans [option]... file... |
showtrans
accepts the following options:
-p
--prefix
-P
--no-prefix
-s
--silent
-t
--translated
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
mount
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
fsysopts
The fsysopts
program allows you to retrieve or set command line
options for running translator filesys.
The fsysopts
program has the following synopsis:
fsysopts [option...] filesys [fs_option...] |
fsysopts
accepts the following options:
-L
--dereference
-R
--recursive
The legal values for fs_option depends on filesys, but some common ones are:
--readonly
--writable
--remount
--sync[=interval]
--nosync
If no options are supplied, filesys' current options are printed.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Certain translators do not need to be very complex, because they
represent a single file rather than an entire directory hierarchy. The
trivfs library, which is declared in <hurd/trivfs.h>
, does most of
the work of implementing this kind of translator. This library requires
the iohelp and ports libraries.
5.2.1 Trivfs Startup | Writing a simple trivfs-based translator. | |
5.2.2 Trivfs Callbacks | Mandatory user-defined trivfs functions. | |
5.2.3 Trivfs Options | Optional user-defined trivfs functions. | |
5.2.4 Trivfs Ports | Managing control and protid ports. |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
In order to use the trivfs library, you will need to define the appropriate callbacks (see section 5.2.2 Trivfs Callbacks). As with all Hurd servers, your trivfs-based translator should first parse any command-line options, in case the user is just asking for help. Trivfs uses argp (see section `Argp' in The GNU C Library Reference Manual) for parsing command-line arguments.
Your translator should redefine the following functions and variables as
necessary, and then call argp_parse
with the relevant arguments:
trivfs_set_options
to handle runtime options parsing.
Redefining this is the normal way to add option parsing to a trivfs
program.
*argz
of length
*argz_len
a NUL-separated list of the arguments to this
translator.
After your translator parses its command-line arguments, it should fetch
its bootstrap port by using task_get_bootstrap_port
. If this
port is MACH_PORT_NULL
, then your program wasn't started as a
translator. Otherwise, you can use the bootstrap port to create a new
control structure (and advertise its port) with trivfs_startup
:
trivfs_startup
creates a new trivfs control port, advertises it
to the underlying node bootstrap with fsys_startup
,
returning the results of this call, and places its control structure in
*control
. trivfs_create_control
does the same
thing, except it doesn't advertise the control port to the underlying
node. control_class and control_bucket are passed to
libports
to create the control port, and protid_class and
protid_bucket are used when creating ports representing opens of
this node; any of these may be zero, in which case an appropriate port
class/bucket is created. If control is non-null, the trivfs
control port is returned in it. flags (a bitmask of the
appropriate O_*
constants) specifies how to open the underlying
node.
If you did not supply zeros as the class and bucket arguments to
trivfs_startup
, you will probably need to use the trivfs port
management functions (see section 5.2.4 Trivfs Ports).
Once you have successfully called trivfs_startup
, and have a
pointer to the control structure stored in, say, the fsys
variable, you are ready to call one of the
ports_manage_port_operations_*
functions using
fsys->pi.bucket
and trivfs_demuxer
. This will
handle any incoming filesystem requests, invoking your callbacks when
necessary.
libports
messages on trivfs ports.
The following functions are not usually necessary, but they allow you to
use the trivfs library even when it is not possible to turn
message-handling over to trivfs_demuxer
and libports
:
intran
functions for a MiG port
type to have the stubs called with either the control or protid pointer.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Like several other Hurd libraries, libtrivfs
requires that you
define a number of application-specific callback functions and
configuration variables. You must define the following variables
and functions:
struct stat
. trivfs_fstype should be chosen
from the FSTYPE_*
constants found in <hurd/hurd_types.h>
.
O_READ
,
O_WRITE
, and O_EXEC
; trivfs will only allow opens of the
specified modes.
struct stat
(as returned from the underlying
node) for presentation to callers of io_stat
. It is permissible
for this function to do nothing, but it must still be defined.
FSYS_GOAWAY_*
found in
<hurd/hurd_types.h>
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The functions and variables described in this subsection already have
default definitions in libtrivfs
, so you are not forced to define
them; rather, they may be redefined on a case-by-case basis.
trivfs_create_control
(or trivfs_startup
), which will
automatically be recognized.
O_NONBLOCK
is set in flags. Any desired error can be
returned, which will be reflected to the user and will prevent the open from
succeeding.
trivfs_S_fsys_getroot
before any other processing takes place. If the return value is
EAGAIN
, normal trivfs getroot processing continues, otherwise the
RPC returns with that return value.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
If you choose to allocate your own trivfs port classes and buckets, the following functions may come in handy:
*bucket
to the list of dynamically-
allocated port buckets; if *bucket
is zero, an attempt is
made to allocate a new port bucket, which is then stored in
*bucket
.
trivfs_add_port_bucket
.
*class
to the list of control or protid port
classes recognized by trivfs; if *class
is zero, an attempt is
made to allocate a new port class, which is stored in *class
.
trivfs_add_control_port_class
or
trivfs_add_protid_port_class
.
Even if you do not use the above allocation functions, you may still be able to use the default trivfs cleanroutines:
libports
cleanroutines for
control port classes and protid port classes, respectively.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The fshelp library implements various things that are useful to most
implementors of the file protocol. It presumes that you are using the
iohelp library as well. libfshelp
is divided into separate
facilities which may be used independently. These functions are
declared in <hurd/fshelp.h>
.
5.3.1 Passive Translator Linkage | Invoking passive translators. | |
5.3.2 Active Translator Linkage | Managing active translators. | |
5.3.3 Fshelp Locking | Implementing file locking. | |
5.3.4 Fshelp Permissions | Standard file access permission policies. | |
5.3.5 Fshelp Misc | Useful standalone routines. |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
These routines are self-contained and start passive translators, returning the control port. They do not require multithreading or the ports library.
*control
. If the translator doesn't
respond or die in timeout milliseconds (if timeout is
greater than zero), return an appropriate error. If the translator dies
before responding, return EDIED
.
fshelp_start_translator_long
, except the initports and
ints are copied from our own state, fd[2] is copied from our own
stderr, and the other fds are cleared. For full-service filesystems, it
is almost always wrong to use fshelp_start_translator
, because
the current working directory of the translator will not then be as
normally expected. (Current working directories of passive translators
should be the directory they were found in.) In fact, full-service
filesystems should usually start passive translators as a side-effect of
calling fshelp_fetch_root
(see section 5.3.2 Active Translator Linkage).
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
These routines implement the linkage to active translators needed by any filesystem which supports them. They require the threads library and use the passive translator routines above, but they don't require the ports library at all.
This interface is complex, because creating the ports and state
necessary for start_translator_long
is expensive. The caller to
fshelp_fetch_root
should not need to create them on every call,
since usually there will be an existing active translator.
fshelp_fetch_root
to fetch more
information. Return the owner and group of the underlying translated
file in *uid
and *gid
; point
*argz
at the entire passive translator specification for
the file (setting *argz_len
to the length). If there is no
passive translator, then return ENOENT
. cookie1 is the
cookie passed in fshelp_transbox_init
. cookie2 is the
cookie passed in the call to fshelp_fetch_root
.
fshelp_fetch_root
to fetch more
information. Return an unauthenticated node for the file itself in
*underlying
and *underlying_type
(opened with
flags). cookie1 is the cookie passed in
fshelp_transbox_init
. cookie2 is the cookie passed in the
call to fshelp_fetch_root
.
dir_lookup
(but O_CREAT
and O_EXCL
are not
meaningful and are ignored). The transbox lock (as set by
fshelp_transbox_init
) must be held before the call, and will be
held upon return, but may be released during the operation of the call.
EBUSY
instead.
fsys_getroot
with the result; use fshelp_fetch_root
instead.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The flock
call is in flux, as the current Hurd interface (as of
version 0.2) is not suitable for implementing the POSIX
record-locking semantics.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
These functions are designed to aid with user permission checking. It is a good idea to use these routines rather than to roll your own, so that Hurd users see consistent handling of file and directory permission bits.
S_IREAD
,
S_IWRITE
, and S_IEXEC
. If the access is permitted, return
zero; otherwise return an appropriate error code.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The following functions are completely standalone:
_servers
to argv[0]
.
ports[INIT_PORT_AUTH]
, and replaces it with the result.
All the other ports in ports and fds are then
reauthenticated, using any privileges available through auth. If
the auth port in ports[INIT_PORT_AUTH]
is bogus, and
get_file_ids is non-null, it is called to get a list
of uids and gids from the file to use as a replacement. If secure
is non-null and any added ids are new, then the variable it points to is
set to nonzero, otherwise zero. If either the uid or gid case fails,
then the other may still apply.
*pt
for the node numbered
fileno, suitable for returning from io_identity
; exactly
one send right must be created from the returned value. fileno
should be the same value returned as the fileno out-parameter in
io_identity
, and in the enclosing directory (except for mount
points), and in the st_ino
stat field. bucket should be a
libports
port bucket; fshelp requires the caller to make sure
port operations (for no-senders notifications) are used.
argp_parse
in the standard way, with data from argz
and argz_len.
TOUCH_ATIME
, TOUCH_MTIME
, and TOUCH_CTIME
constants.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This section documents the interface for operating on files.
5.4.1 File Overview | Basic concepts for the file interface. | |
5.4.2 Changing Status | Changing the owner (etc.) of a file. | |
5.4.3 Program Execution | Executing files. | |
5.4.4 File Locking | Implementing the flock call. | |
5.4.5 File Frobbing | Other active calls on files. | |
5.4.6 Opening Files | Looking up files in directories. | |
5.4.7 Modifying Directories | Creating and deleting nodes. | |
5.4.8 Notifications | File and directory change callbacks. | |
5.4.9 File Translators | How to set and get translators. |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The file interface is a superset of the I/O interface (see section 4.3 I/O Interface). Servers which provide the file interface are required to
support the I/O interface as well. All objects reachable in the
filesystem are expected to provide the file interface, even if they do
not contain data. (The trivfs
library makes it easy to do so for
ordinary sorts of cases. See section 5.2 Trivfs Library.)
The interface definitions for the file interface are found in
<hurd/fs.defs>
.
Files have various pieces of status information which are returned by
io_stat
(see section 4.3.5 Information Queries). Most of this status
information can be directly changed by various calls in the file
interface; some of it should vary implicitly as the contents of the file
change.
Many of these calls have general rules associated with them describing
how security and privilege should operate. The diskfs
library
(see section 8.5 Diskfs Library) implements these rules for stored filesystems.
These rules have also been implemented in the fshelp library
(see section 5.3 Fshelp Library). Trivfs-based servers generally have no need
to implement these rules at all.
In special cases, there may be a reason to implement a different security check from that specified here, or to implement a call to do something slightly different. But such cases must be carefully considered; make sure that you will not confuse innocent user programs through excessive cleverness.
If some operation cannot be implemented (for example, chauthor
over FTP), then the call should return EOPNOTSUPP
. If it is
merely difficult to implement a call, it is much better to figure out a
way to implement it as a series of operations rather than to return
errors to the user.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
There are several RPCs available for users to change much of the status
information associated with a file. (The information is returned by the
io_stat
RPC; see 4.3.5 Information Queries.)
All these operations are restricted to root and the owner of the file.
When attempted by another user, they should return EPERM
.
The file_chown
RPC changes the owner and group of the file. Only
root should be able to change the owner, and changing the group to a
group the caller is not in should also be prohibited. Violating either
of these conditions should return EPERM
.
The file_chauthor
RPC changes the author of the file. It should
be legitimate to change the author to any value without restriction.
The file_chmod
RPC changes the file permission mode bits.
The file_chflags
RPC changes the flags of the file. It should be
legitimate to change the flags to any value without restriction. No
standard meanings have been assigned to the flags yet, but we intend to
do so. Do not assume that the flags format we choose will map
identically to that of some existing filesystem format.
The file_utimes
RPC changes the atime and mtime of
the file. Making this call must cause the ctime to be updated as
well, even if no actual change to either the mtime or the
atime occurs.
The file_set_size
RPC is special; not only does it change the
status word specifying the size of the file, but it also changes the
actual contents of the file. If the file size is being reduced it
should release secondary storage associated with the previous contents
of the file. If the file is being extended, the new region added to the
file must be zero-filled. Unlike the other RPCs in this section,
file_set_size
should be permitted to any user who is allowed to
write the file.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Execution of programs on the Hurd is done through fileservers with the
file_exec
RPC. The fileserver is expected to verify that the
user is allowed to execute the file, make whatever modifications to the
ports are necessary for setuid execution, and then invoke the standard
execserver found on `/servers/exec'.
This section specifically addresses what fileservers are expected to do, with minimal attention to the other parts of the process. See section 13. Running Programs, for more general information.
The file must be opened for execution; if it is not, EBADF
should
be returned. In addition, at least one of the execute bits must be on. A
failure of this check should result in EACCES
---not
ENOEXEC
. It is not proper for the fileserver ever to respond to
the file_exec
RPC with ENOEXEC
.
If either the setuid or setgid bits are set, the server needs to
construct a new authentication handle with the additional new ID's.
Then all the ports passed to file_exec
need to be reauthenticated
with the new handle. If the fileserver is unable to make the new
authentication handle (for example, because it is not running as root)
it is not acceptable to return an error; in such a case the server
should simply silently fail to implement the setuid/setgid semantics.
If the setuid/setgid transformation adds a new uid or gid to the user's
authentication handle that was not previously present (as opposed to
merely reordering them), then the EXEC_SECURE
and
EXEC_NEWTASK
flags should both be added in the call to
exec_exec
.
The server then needs to open a new port onto the executed file which
will not share any file pointers with the port the user passed in,
opened with O_READ
. Finally, all the information (mutated
appropriately for setuid/setgid) should be sent to the execserver with
exec_exec
. Whatever error code exec_exec
returns should
returned to the caller of file_exec
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The flock
call is in flux, as the current Hurd interface (as of
version 0.2) is not suitable for implementing the POSIX
record-locking semantics.
You should ignore the file_lock
and file_lock_stat
calls
until the new record-locking interface is implemented.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
FIXME: Other active calls on files
file_sync
file_getfh
file_getlinknode
file_check_access
These manipulate meta-information:
file_reparent
file_statfs
file_syncfs
file_getcontrol
file_get_storage_info
file_get_fs_options
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
FIXME: Looking up files in directories
dir_lookup
dir_readdir
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The function returns a port to the new file in *newnode. Flags
are the same as for dir_lookup
, but O_CREAT
and
O_TRUNC
are assumed even if not specified.
dir_link
might
fail with EXDEV
.
dir_rename
might fail with EXDEV
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
FIXME: File and directory change callbacks
File change notifications are not yet implemented, but directory notifications are.
file_notice_changes
dir_notice_changes
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
FIXME: How to set and get translators
file_set_translator
file_get_translator
file_get_translator_cntl
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The filesystem interface (described in <hurd/fsys.defs>
) is
supported by translator control ports.
FIXME: finish
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |