groff 1.23.0 added .MR to its -man macro package. The NEWS file states
that the inclusion of the macro "was prompted by its introduction to
Plan 9 from User Space's troff in August 2020." From d32deab it seems
that the name for Plan 9 from User Space's implementation was suggested
by groff maintainer G. Brandon Robinson.
Not sure if the intention was to make these definitions compatible, but
it would be nice if they were.
Currently, Plan 9 from User Space's .MR expects its second argument to
be parenthesized. groff's .MR does not. This results in extra
parentheses appearing in manual references when viewing Plan 9 from User
Space's manual pages on a system using groff.
224 lines
4.3 KiB
Groff
224 lines
4.3 KiB
Groff
.TH 9P-FILE 3
|
|
.SH NAME
|
|
Tree, alloctree, freetree,
|
|
File, createfile, closefile, removefile, walkfile,
|
|
opendirfile, readdirfile, closedirfile, hasperm \- in-memory file hierarchy
|
|
.SH SYNOPSIS
|
|
.ft L
|
|
.nf
|
|
#include <u.h>
|
|
#include <libc.h>
|
|
#include <fcall.h>
|
|
#include <thread.h>
|
|
#include <9p.h>
|
|
.fi
|
|
.PP
|
|
.ft L
|
|
.nf
|
|
.ta \w'\fLFile 'u
|
|
typedef struct File
|
|
{
|
|
Ref;
|
|
Dir;
|
|
void *aux;
|
|
\fI...\fP
|
|
} File;
|
|
.fi
|
|
.PP
|
|
.ft L
|
|
.nf
|
|
.ta \w'\fLTree 'u
|
|
typedef struct Tree
|
|
{
|
|
File *root;
|
|
\fI...\fP
|
|
} Tree;
|
|
.fi
|
|
.PP
|
|
.ft L
|
|
.nf
|
|
.ta \w'\fLReaddir* 'u +4n +4n
|
|
Tree* alloctree(char *uid, char *gid, ulong mode,
|
|
void (*destroy)(File*))
|
|
void freetree(Tree *tree)
|
|
File* createfile(File *dir, char *name, char *uid,
|
|
ulong mode, void *aux)
|
|
int removefile(File *file)
|
|
void closefile(File *file)
|
|
File* walkfile(File *dir, char *path)
|
|
Readdir* opendirfile(File *dir)
|
|
long readdirfile(Readdir *rdir, char *buf, long n)
|
|
void closedirfile(Readdir *rdir)
|
|
int hasperm(File *file, char *uid, int p)
|
|
.fi
|
|
.SH DESCRIPTION
|
|
.BR File s
|
|
and
|
|
.BR Tree s
|
|
provide an in-memory file hierarchy
|
|
intended for use in 9P file servers.
|
|
.PP
|
|
.I Alloctree
|
|
creates a new tree of files, and
|
|
.I freetree
|
|
destroys it.
|
|
The root of the tree
|
|
(also the
|
|
.B root
|
|
element in the structure)
|
|
will have mode
|
|
.I mode
|
|
and be owned by user
|
|
.I uid
|
|
and group
|
|
.IR gid .
|
|
.I Destroy
|
|
is used when freeing
|
|
.B File
|
|
structures and is described later.
|
|
.PP
|
|
.BR File s
|
|
(including directories)
|
|
other than the root are created using
|
|
.IR createfile ,
|
|
which attempts to create a file named
|
|
.I name
|
|
in the directory
|
|
.IR dir .
|
|
If created, the file will have owner
|
|
.I uid
|
|
and have a group inherited from
|
|
the directory.
|
|
.I Mode
|
|
and the permissions of
|
|
.I dir
|
|
are used to calculate the permission bits for
|
|
the file as described in
|
|
.IR open (9p).
|
|
It is permissible for
|
|
.I name
|
|
to be a slash-separated path rather than a single element.
|
|
.PP
|
|
.I Removefile
|
|
removes a file from the file tree.
|
|
The file will not be freed until the last
|
|
reference to it has been removed.
|
|
Directories may only be removed when empty.
|
|
.I Removefile
|
|
returns zero on success, \-1 on error.
|
|
It is correct to consider
|
|
.I removefile
|
|
to be
|
|
.I closefile
|
|
with the side effect of removing the file
|
|
when possible.
|
|
.PP
|
|
.I Walkfile
|
|
evaluates
|
|
.I path
|
|
relative to the directory
|
|
.IR dir ,
|
|
returning the resulting file,
|
|
or zero if the named file or any intermediate element
|
|
does not exist.
|
|
.PP
|
|
The
|
|
.B File
|
|
structure's
|
|
.B aux
|
|
pointer may be used by the client
|
|
for
|
|
.RB per- File
|
|
storage.
|
|
.BR File s
|
|
are reference-counted: if not zero,
|
|
.I destroy
|
|
(specified in the call to
|
|
.IR alloctree )
|
|
will be called for each file when its
|
|
last reference is removed or when the tree is freed.
|
|
.I Destroy
|
|
should take care of any necessary cleanup related to
|
|
.BR aux .
|
|
When creating new file references by copying pointers,
|
|
call
|
|
.I incref
|
|
(see
|
|
.MR lock 3 )
|
|
to update the reference count.
|
|
To note the removal of a reference to a file, call
|
|
.IR closefile .
|
|
.I Createfile
|
|
and
|
|
.I walkfile
|
|
return new references.
|
|
.IR Removefile ,
|
|
.IR closefile ,
|
|
and
|
|
.I walkfile
|
|
(but not
|
|
.IR createfile )
|
|
consume the passed reference.
|
|
.PP
|
|
Directories may be read, yielding a directory entry structure
|
|
(see
|
|
.IR stat (9p))
|
|
for each file in the directory.
|
|
In order to allow concurrent reading of directories,
|
|
clients must obtain a
|
|
.B Readdir
|
|
structure by calling
|
|
.I opendirfile
|
|
on a directory.
|
|
Subsequent calls to
|
|
.I readdirfile
|
|
will each yield an integral number of machine-independent
|
|
stat buffers, until end of directory.
|
|
When finished, call
|
|
.I closedirfile
|
|
to free the
|
|
.BR Readdir .
|
|
.PP
|
|
.I Hasperm
|
|
does simplistic permission checking; it assumes only
|
|
one-user groups named by uid and returns non-zero if
|
|
.I uid
|
|
has permission
|
|
.I p
|
|
(a bitwise-or of
|
|
.BR AREAD ,
|
|
.BR AWRITE
|
|
and
|
|
.BR AEXEC )
|
|
according to
|
|
.IB file ->mode \fR.
|
|
9P servers written using
|
|
.B File
|
|
trees will do standard permission checks automatically;
|
|
.I hasperm
|
|
may be called explicitly to do additional checks.
|
|
A 9P server may link against a different
|
|
.I hasperm
|
|
implementation to provide more complex groups.
|
|
.SH EXAMPLE
|
|
The following code correctly handles references
|
|
when elementwise walking a path and creating a file.
|
|
.IP
|
|
.EX
|
|
f = tree->root;
|
|
incref(f);
|
|
for(i=0; i<n && f!=nil; i++)
|
|
f = walkfile(f, elem[i]);
|
|
if(f == nil)
|
|
return nil;
|
|
nf = createfile(f, "foo", "nls", 0666, nil);
|
|
closefile(f);
|
|
return nf;
|
|
.EE
|
|
.SH SOURCE
|
|
.B \*9/src/lib9p/file.c
|
|
.SH SEE ALSO
|
|
.MR 9p 3
|
|
.SH BUGS
|
|
The reference counting is cumbersome.
|