Hurd Reference Manual: 5. Files
<<
Up
>>
Top
Contents
Index
5. Files
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
5.1 Translators
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:
Disk-based filesystem formats, such as
ext2fs
ufs
, and
iso9660fs
(see section
Stored Filesystems
).
Network filesystems, such as
nfs
and
ftpfs
(see section
Distributed Filesystems
).
Single files with dynamic content, such as FIXME: we need a good
example.
Hurd servers which translate rendezvous filesystem nodes in standard
locations, so that other programs can easily find them and use
server-specific interfaces. For example,
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
5.1.1 Invoking
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:
`-a'
`--active'
Set
node
's active translator.
Active translators
are
started immediately and are not persistent: if the system is rebooted
then they are lost.
`-c'
`--create'
Create
node
as a zero-length file if it doesn't already exist.
`-L'
`--dereference'
If
node
is already translated, stack the new translator on top of
it (rather than replacing the existing translator).
`--help'
Display a brief usage message, then exit.
`-p'
`--passive'
Set
node
's passive translator.
Passive translators
are only
activated by the underlying filesystem when clients try to use the
node
, and they shut down automatically after they are no longer
active in order to conserve system resources.
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:
`-g'
`--goaway'
Tell the active translator to go away. In this case, the following
additional options apply:
`-f'
`--force'
If the active translator doesn't go away, then force it.
`-S'
`--nosync'
Don't flush its contents to disk before terminating.
`-R'
`--recursive'
Shut down all of the active translator's children, too.
`-k'
`--keep-active'
Leave the existing active translator running. The new translator will
not be started unless the active translator has stopped.
`-P'
`--pause'
When starting an active translator, prompt and wait for a newline on
standard input before completing the startup handshake. This is useful
when debugging a translator, as it gives you time to start the debugger.
`-t
sec
`--timeout=
sec
If the translator does not start up in
sec
seconds (the default is
60), then return an error; if
sec
is 0, then never timeout.
`--version'
Output program version information and exit.
`-x'
`--exclusive'
Only set the translator if there is none already.
<<
Up
>>
Top
Contents
Index
5.1.2 Invoking
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
Always display
filename
: before translators.
-P
--no-prefix
Never display
filename
: before translators.
-s
--silent
No output; useful when checking error status.
-t
--translated
Only display files that have translators.
<<
Up
>>
Top
Contents
Index
5.1.3 Invoking
mount
<<
Up
>>
Top
Contents
Index
5.1.4 Invoking
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
If
filesys
is a symbolic link, follow it.
-R
--recursive
Pass these options to any child translators.
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.
The options passed as
fs_option
s are meant to augment or change those
which are already set, they're not meant to completely replace the existing
command line options. For example, passing
--readonly
to a file system
server will change the server from writable to read-only, but will not touch
the used backing store. Passing
--address=new_IP
to
`/servers/socket/2'
will change the local IP address to
new_IP
, but
will not touch the interface, netmask and gateway settings.
<<
Up
>>
Top
Contents
Index
5.2 Trivfs Library
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
, 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
5.2.1 Trivfs Startup
In order to use the trivfs library, you will need to define the
appropriate callbacks (see section
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
(libc)Argp
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:
Variable:
extern struct argp *
trivfs_runtime_argp
If this is defined or set to an argp structure, it will be used by the
default
trivfs_set_options
to handle runtime options parsing.
Redefining this is the normal way to add option parsing to a trivfs
program.
Function:
error_t
trivfs_set_options
(struct trivfs_control *
fsys
, char *
argz
, size_t
argz_len
Set runtime options for
fsys
to
argz
and
argz_len
The default definition for this routine simply uses
trivfs_runtime_argp
(supplying
fsys
as the argp input
field).
Function:
error_t
trivfs_append_args
(struct trivfs_control *
fsys
, char **
argz
, size_t *
argz_len
Append to the malloced string
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
Function:
error_t
trivfs_startup
(mach_port_t
bootstrap
, int
flags
, struct port_class *
control_class
, struct port_bucket *
control_bucket
, struct port_class *
protid_class
, struct port_bucket *
protid_bucket
, struct trivfs_control **
control
Function:
error_t
trivfs_create_control
(mach_port_t
bootstrap
, struct port_class *
control_class
, struct port_bucket *
control_bucket
, struct port_class *
protid_class
, struct port_bucket *
protid_bucket
, struct trivfs_control **
control
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
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.
Function:
int
trivfs_demuxer
(mach_msg_header_t *
inp
, mach_msg_header_t *
outp
Demultiplex incoming
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
Function:
struct trivfs_control *
trivfs_begin_using_control
(mach_port_t
port
Function:
struct trivfs_protid *
trivfs_begin_using_protid
(mach_port_t
port
These functions can be used as
intran
functions for a MiG port
type to have the stubs called with either the control or protid pointer.
Function:
void
trivfs_end_using_control
(struct trivfs_control *
port
Function:
void
trivfs_end_using_protid
(struct trivfs_protid *
port
These can be used as `destructor' functions for a MiG port type, to have
the stubs called with the control or protid pointer.
Function:
error_t
trivfs_open
(struct trivfs_control *
fsys
, struct iouser *
user
, unsigned
flags
, mach_port_t
realnode
, struct trivfs_protid **
cred
Return a new protid (that is, a port representing an open of this node)
pointing to a new peropen in
cred
, with
realnode
as the
underlying node reference, with the given identity, and open flags in
flags
cntl
is the trivfs control object.
Function:
error_t
trivfs_protid_dup
(struct trivfs_protid *
cred
, struct trivfs_protid **
dup
Return a duplicate of
cred
in
dup
, sharing the same peropen
and hook. A non-null protid
hook
indicates that
trivfs_peropen_create_hook
created this protid (see section
Trivfs Options
).
Function:
error_t
trivfs_set_atime
(struct trivfs_control *
cntl
Function:
error_t
trivfs_set_mtime
(struct trivfs_control *
cntl
Call these to set atime or mtime for the node to the current time.
<<
Up
>>
Top
Contents
Index
5.2.2 Trivfs Callbacks
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:
Variable:
extern int
trivfs_fstype
Variable:
extern int
trivfs_fsid
These variables are returned in the
st_fstype
and
st_fsid
fields of
struct stat
trivfs_fstype
should be chosen
from the
FSTYPE_*
constants found in
Variable:
extern int
trivfs_allow_open
Set this to some bitwise OR combination of
O_READ
O_WRITE
, and
O_EXEC
; trivfs will only allow opens of the
specified modes.
Variable:
extern int
trivfs_support_read
Variable:
extern int
trivfs_support_write
Variable:
extern int
trivfs_support_exec
Set these to nonzero if trivfs should allow read, write, or execute of
the file. These variables are necessary because
trivfs_allow_open
is used only to validate opens, not actual operations.
Function:
void
trivfs_modify_stat
(struct trivfs_protid *
cred
, struct stat *
stbuf
This should modify a
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.
Function:
error_t
trivfs_goaway
(struct trivfs_control *
cntl
, int
flags
This function is called when someone wants the filesystem
cntl
to
go away.
flags
are from the set
FSYS_GOAWAY_*
found in
<<
Up
>>
Top
Contents
Index
5.2.3 Trivfs Options
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.
Variable:
extern struct port_class *
trivfs_protid_portclasses
[]
Variable:
extern int
trivfs_protid_nportclasses
Variable:
extern struct port_class *
trivfs_cntl_portclasses
[]
Variable:
extern int
trivfs_cntl_nportclasses
If you define these, they should be vectors (and the associated sizes)
of port classes that will be translated into control and protid pointers
for passing to RPCs, in addition to those passed to or created by
trivfs_create_control
(or
trivfs_startup
), which will
automatically be recognized.
Variable:
error_t
(*trivfs_check_open_hook)
(struct trivfs_control *
cntl
, struct iouser *
user
, int
flags
If this variable is non-zero, it will be called every time an open happens.
user
and
flags
are from the open;
cntl
identifies the
node being opened. This call need not check permissions on the
underlying node. This call can block as necessary, unless
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.
Variable:
error_t
(*trivfs_protid_create_hook)
(struct trivfs_protid *
prot
Variable:
error_t
(*trivfs_peropen_create_hook)
(struct trivfs_peropen *
perop
If these variables are non-zero, they will be called every time a new protid or
peropen structure is created and initialized.
Variable:
void
(*trivfs_protid_destroy_hook)
(struct trivfs_protid *
prot
Variable:
void
(*trivfs_peropen_destroy_hook)
(struct trivfs_peropen *
perop
If these variables is non-zero, they will be called every time a protid or
peropen structure is about to be destroyed.
Variable:
error_t
(*trivfs_getroot_hook)
(struct trivfs_control *
cntl
, mach_port_t
reply_port
, mach_msg_type_name_t
reply_port_type
, mach_port_t
dotdot
, uid_t *
uids
, u_int
nuids
, uid_t *
gids
, u_int
ngids
, int
flags
, retry_type *
do_retry
, char *
retry_name
, mach_port_t *
node
, mach_msg_type_name_t *
node_type
If this variable is set, it will be called by
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
5.2.4 Trivfs Ports
If you choose to allocate your own trivfs port classes and buckets, the
following functions may come in handy:
Function:
error_t
trivfs_add_port_bucket
(struct port_bucket **
bucket
Add the port bucket
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
Function:
void
trivfs_remove_port_bucket
(struct port_bucket *
bucket
Remove the previously added dynamic port bucket
bucket
, freeing it
if it was allocated by
trivfs_add_port_bucket
Function:
error_t
trivfs_add_control_port_class
(struct port_class **
class
Function:
error_t
trivfs_add_protid_port_class
(struct port_class **
class
Add the port class
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
Function:
void
trivfs_remove_control_port_class
(struct port_class *
class
Function:
void
trivfs_remove_protid_port_class
(struct port_class *
class
Remove the previously added dynamic control or protid port class
class
, freeing it if it was allocated by
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:
Function:
void
trivfs_clean_cntl
(void *
port
Function:
void
trivfs_clean_protid
(void *
port
These functions should be installed as
libports
cleanroutines for
control port classes and protid port classes, respectively.
<<
Up
>>
Top
Contents
Index
5.3 Fshelp Library
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
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
5.3.1 Passive Translator Linkage
These routines are self-contained and start passive translators,
returning the control port. They do not require multithreading or the
ports library.
Typedef:
typedef
error_t
(*fshelp_open_fn_t) (int
flags
, file_t *
node
, mach_msg_type_name_t *
node_type
A callback used by the translator starting functions.
Given some open flags, opens the appropriate file, and
returns the node port.
Function:
error_t
fshelp_start_translator_long
(fshelp_open_fn_t
underlying_open_fn
, char *
name
, char *
argz
, int
argz_len
, mach_port_t *
fds
, mach_msg_type_name_t
fds_type
, int
fds_len
, mach_port_t *
ports
, mach_msg_type_name_t
ports_type
, int
ports_len
, int *
ints
, int
ints_len
, int
timeout
, fsys_t *
control
Start a passive translator
name
with arguments
argz
(length
argz_len
). Initialize the initports to
ports
(length
ports_len
), the initints to
ints
(length
ints_len
),
and the file descriptor table to
fds
(length
fds_len
).
Return the control port in
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
Function:
error_t
fshelp_start_translator
(fshelp_open_fn_t
underlying_open_fn
, char *
name
, char *
argz
, int
argz_len
, int
timeout
, fsys_t *
control
Same as
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
Active Translator Linkage
).
<<
Up
>>
Top
Contents
Index
5.3.2 Active Translator Linkage
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.
Function:
void
fshelp_transbox_init
(struct transbox *
transbox
, struct mutex *
lock
, void *
Initialize a transbox, which contains state information for active
translators.
Typedef:
typedef
error_t
(*fshelp_fetch_root_callback1_t) (void *
cookie1
, void *
cookie2
, uid_t *
uid
, gid_t *
gid
, char **
argz
, size_t *
argz_len
This routine is called by
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
Typedef:
typedef
error_t
(*fshelp_fetch_root_callback2_t) (void *
cookie1
, void *
cookie2
, int
flags
, mach_port_t *
underlying
, mach_msg_type_name_t *
underlying_type
This routine is called by
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
Function:
error_t
fshelp_fetch_root
(struct transbox *
transbox
, void *
, file_t
dotdot
, struct iouser *
user
, int
flags
, fshelp_fetch_root_callback1_t
callback1
, fshelp_fetch_root_callback2_t
callback2
, retry_type *
retry
, char *
retryname
, mach_port_t *
root
Fetch the root from
transbox
dotdot
is an unauthenticated
port for the directory in which we are looking;
user
specifies the
ids of the user responsible for the call.
flags
are as for
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.
Function:
int
fshelp_translated
(struct transbox *
box
Return true if and only if there is an active translator on this box.
Function:
error_t
fshelp_set_active
(struct transbox *
box
, fsys_t
newactive
, int
excl
Atomically replace the existing active translator port for this box with
newactive
. If
excl
is non-zero then don't modify an
existing active transbox; return
EBUSY
instead.
Function:
error_t
fshelp_fetch_control
(struct transbox *
box
, mach_port_t *
control
Fetch the control port to make a request on it. It's a bad idea to use
fsys_getroot
with the result; use
fshelp_fetch_root
instead.
Function:
void
fshelp_drop_transbox
(struct transbox *
box
Clean transbox state so that deallocation or reuse is possible.
<<
Up
>>
Top
Contents
Index
5.3.3 Fshelp Locking
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
5.3.4 Fshelp Permissions
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.
Function:
error_t
fshelp_isowner
(struct stat *
st
, struct iouser *
user
Check to see whether
user
should be considered the owner of the
file identified by
st
. If so, return zero; otherwise return an
appropriate error code.
Function:
error_t
fshelp_access
(struct stat *
st
, int
op
, struct iouser *
user
Check to see whether the user
user
can operate on the file
identified by
st
op
is one of
S_IREAD
S_IWRITE
, and
S_IEXEC
. If the access is permitted, return
zero; otherwise return an appropriate error code.
Function:
error_t
fshelp_checkdirmod
(struct stat *
dir
, struct stat *
st
, struct iouser *
user
Check to see whether
user
is allowed to modify
dir
with respect to
existing file
st
. If there is no existing file, then
st
should be set to zero. If the access is permissible, return zero;
otherwise return an appropriate error code.
<<
Up
>>
Top
Contents
Index
5.3.5 Fshelp Misc
The following functions are completely standalone:
Function:
error_t
fshelp_delegate_translation
(char *
server_name
, mach_port_t
requestor
, char **
argv
Try to hand off responsibility from a translator to the server located
on the node
server_name
requestor
is the translator's
bootstrap port, and
argv
is the command line. If
server_name
is null, then a name is concocted by prepending
_servers
to
argv[0]
Function:
error_t
fshelp_exec_reauth
(int
suid
, uid_t
uid
, int
sgid
, gid_t
gid
, auth_t
auth
, error_t (*
get_file_ids
) (struct idvec *
uids
, struct idvec *
gids
), mach_port_t *
ports
, mach_msg_type_number_t
num_ports
, mach_port_t *
fds
, mach_msg_type_number_t
num_fds
, int *
secure
If
suid
or
sgid
is true, adds
uid
and/or
gid
respectively to the authentication in
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.
Function:
error_t
fshelp_get_identity
(struct port_bucket *
bucket
, ino_t
fileno
, mach_port_t *
pt
Return an identity port in
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.
Function:
error_t
fshelp_return_malloced_buffer
(char *
buf
, size_t
len
, char **
rbuf
, mach_msg_type_number_t *
rlen
Put data from the malloced buffer
buf
len
bytes long, into
rbuf
(which is
rlen
bytes long), suitable for returning from
an RPC. If
len
is greater than zero,
buf
is freed,
regardless of whether an error is returned or not.
Function:
error_t
fshelp_set_options
(struct argp *
argp
, int
flags
, char *
argz
, size_t
argz_len
, void *
input
Invoke
argp_parse
in the standard way, with data from
argz
and
argz_len
Function:
void
fshelp_touch
(struct stat *
st
, unsigned
what
, volatile struct mapped_time_value *
maptime
Change the stat times of
node
as indicated by
what
to
the current time.
what
is a bitmask of one or more of
the
TOUCH_ATIME
TOUCH_MTIME
, and
TOUCH_CTIME
constants.
<<
Up
>>
Top
Contents
Index
5.4 File Interface
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
5.4.1 File Overview
The file interface is a superset of the I/O interface (see section
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
Trivfs Library
.)
The interface definitions for the file interface are found in
Files have various pieces of status information which are returned by
io_stat
(see section
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
Diskfs Library
) implements these rules for stored filesystems.
These rules have also been implemented in the fshelp library
(see section
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
5.4.2 Changing Status
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
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
5.4.3 Program Execution
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
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
5.4.4 File Locking
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
5.4.5 File Frobbing
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
5.4.6 Opening Files
FIXME: Looking up files in directories
dir_lookup
dir_readdir
<<
Up
>>
Top
Contents
Index
5.4.7 Modifying Directories
Function:
kern_return_t
dir_mkfile
(file_t
directory
, int
flags
, mode_t
mode
, mach_port_t *
newnode
Create a new file in
directory
without linking it into the
filesystem. You still must have write permission on the specified
directory, even though it will not actually be written.
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.
Function:
kern_return_t
dir_mkdir
(file_t
directory
, char *
name
, mode_t
mode
Create a new directory named
name
in
directory
with
permission specified by
mode
Function:
kern_return_t
dir_rmdir
(file_t
directory
, char *
name
Remove the directory named
name
from
directory
Function:
kern_return_t
dir_unlink
(file_t
directory
, char *
name
Remove the non-directory node
name
from
directory
Function:
kern_return_t
dir_link
(file_t
directory
, file_t
file
, char *
name
, int
excl
Create a hard link in
directory
. If
excl
is set and
name
already exists in
directory
, then this function will
fail. If
excl
is not set and
name
already exists the old
file named
name
will be unlinked. If
directory
and
file
are not on the same filesystem, then
dir_link
might
fail with
EXDEV
Function:
kern_return_t
dir_rename
(file_t
olddirectory
, char *
oldname
, file_t
newdirectory
, char *
newname
, int
excl
Move the node
oldname
in
olddirectory
to the node
newname
in
newdirectory
. If
excl
is set and
newname
already exists in
newdirectory
, then this function
will fail. If
excl
is not set and
newname
already exists,
the old file named
newname
will be unlinked. If
olddirectory
and
newdirectory
are not on the same
filesystem, then
dir_rename
might fail with
EXDEV
<<
Up
>>
Top
Contents
Index
5.4.8 Notifications
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
5.4.9 File Translators
FIXME: How to set and get translators
file_set_translator
file_get_translator
file_get_translator_cntl
<<
Up
>>
Top
Contents
Index
5.5 Filesystem Interface
The filesystem interface (described in
) is
supported by translator control ports.
FIXME: finish
<<
>>
Top
Contents
Index
This document was generated by
Thomas Schwinge
on
November, 8 2007
using
texi2html 1.76
US