diff options
Diffstat (limited to 'libtreefs/treefs-hooks.h')
-rw-r--r-- | libtreefs/treefs-hooks.h | 401 |
1 files changed, 401 insertions, 0 deletions
diff --git a/libtreefs/treefs-hooks.h b/libtreefs/treefs-hooks.h new file mode 100644 index 00000000..3af4a546 --- /dev/null +++ b/libtreefs/treefs-hooks.h @@ -0,0 +1,401 @@ +/* Hooks in libtreefs (also see "treefs-s-hooks.h") + + Copyright (C) 1995 Free Software Foundation, Inc. + + Written by Miles Bader <miles@gnu.ai.mit.edu> + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef __TREEFS_HOOKS_H__ +#define __TREEFS_HOOKS_H__ + +#include "treefs.h" + +/* ---------------------------------------------------------------- */ + +/* Hook indices */ +enum +{ + /* file rpcs */ + TREEFS_HOOK_S_FILE_EXEC, TREEFS_HOOK_S_FILE_CHOWN, + TREEFS_HOOK_S_FILE_CHAUTHOR, TREEFS_HOOK_S_FILE_CHMOD, + TREEFS_HOOK_S_FILE_CHFLAGS, TREEFS_HOOK_S_FILE_UTIMES, + TREEFS_HOOK_S_FILE_SET_SIZE, TREEFS_HOOK_S_FILE_LOCK, + TREEFS_HOOK_S_FILE_LOCK_STAT, TREEFS_HOOK_S_FILE_ACCESS, + TREEFS_HOOK_S_FILE_NOTICE, TREEFS_HOOK_S_FILE_SYNC, + TREEFS_HOOK_S_FILE_GET_LINK_NODE, + + /* io rpcs */ + TREEFS_HOOK_S_IO_WRITE, TREEFS_HOOK_S_IO_READ, TREEFS_HOOK_S_IO_SEEK, + TREEFS_HOOK_S_IO_READABLE, TREEFS_HOOK_S_IO_SET_ALL_OPENMODES, + TREEFS_HOOK_S_IO_GET_OPENMODES, TREEFS_HOOK_S_IO_SET_SOME_OPENMODES, + TREEFS_HOOK_S_IO_CLEAR_SOME_OPENMODES, TREEFS_HOOK_S_IO_ASYNC, + TREEFS_HOOK_S_IO_MOD_OWNER, TREEFS_HOOK_S_IO_GET_OWNER, + TREEFS_HOOK_S_IO_GET_ICKY_ASYNC_ID, TREEFS_HOOK_S_IO_SELECT, + TREEFS_HOOK_S_IO_STAT, TREEFS_HOOK_S_IO_REAUTHENTICATE, + TREEFS_HOOK_S_IO_RESTRICT_AUTH, TREEFS_HOOK_S_IO_DUPLICATE, + TREEFS_HOOK_S_IO_SERVER_VERSION, TREEFS_HOOK_S_IO_MAP, + TREEFS_HOOK_S_IO_MAP_CNTL, TREEFS_HOOK_S_IO_RELEASE_CONCH, + TREEFS_HOOK_S_IO_EOFNOTIFY, TREEFS_HOOK_S_IO_PRENOTIFY, + TREEFS_HOOK_S_IO_POSTNOTIFY, TREEFS_HOOK_S_IO_READNOTIFY, + TREEFS_HOOK_S_IO_READSLEEP, TREEFS_HOOK_S_IO_SIGIO, + + /* directory rpcs */ + TREEFS_HOOK_S_DIR_LOOKUP, TREEFS_HOOK_S_DIR_READDIR, TREEFS_HOOK_S_DIR_MKDIR, + TREEFS_HOOK_S_DIR_RMDIR, TREEFS_HOOK_S_DIR_UNLINK, TREEFS_HOOK_S_DIR_LINK, + TREEFS_HOOK_S_DIR_RENAME, TREEFS_HOOK_S_DIR_MKFILE, + TREEFS_HOOK_S_DIR_NOTICE_CHANGES, + + /* filesystem rpcs */ + TREEFS_HOOK_S_FSYS_GETROOT, TREEFS_HOOK_S_FSYS_SET_OPTIONS, + TREEFS_HOOK_S_FSYS_SYNCFS, TREEFS_HOOK_S_FSYS_GETFILE, TREEFS_S_FSYS_GOAWAY, + + /* Non-rpc fsys hooks */ + TREEFS_HOOK_FSYS_CREATE_NODE, TREEFS_HOOK_FSYS_DESTROY_NODE, + TREEFS_HOOK_FSYS_GET_ROOT, + + /* Node hooks */ + TREEFS_HOOK_NODE_TYPE, + TREEFS_HOOK_NODE_UNLINKED, TREEFS_HOOK_NODE_MOD_LINK_COUNT, + TREEFS_HOOK_DIR_LOOKUP, TREEFS_HOOK_DIR_NOENT, + TREEFS_HOOK_DIR_CREATE_CHILD, TREEFS_HOOK_DIR_LINK, TREEFS_HOOK_DIR_UNLINK, + TREEFS_HOOK_NODE_OWNED, TREEFS_HOOK_NODE_ACCESS, + TREEFS_HOOK_NODE_GET_SYMLINK, TREEFS_HOOK_NODE_GET_PASSIVE_TRANS, + TREEFS_HOOK_NODE_START_TRANSLATOR, TREEFS_HOOK_NODE_GET_TRANS_AUTH, + TREEFS_HOOK_NODE_DROP, TREEFS_HOOK_NODE_INIT, TREEFS_HOOK_DIR_INIT, + TREEFS_HOOK_NODE_INIT_PEROPEN, TREEFS_HOOK_NODE_INIT_HANDLE, + TREEFS_HOOK_NODE_FINALIZE, TREEFS_HOOK_DIR_FINALIZE, + TREEFS_HOOK_NODE_FINALIZE_PEROPEN, TREEFS_HOOK_NODE_FINALIZE_HANDLE, + + /* Reference counting support */ + TREEFS_HOOK_NODE_NEW_REFS, TREEFS_HOOK_NODE_LOST_REFS, + TREEFS_HOOK_NODE_TRY_DROPPING_WEAK_REFS, + + TREEFS_NUM_HOOKS +}; + +/* ---------------------------------------------------------------- */ +/* Hook calling/defining macros */ + +/* Call the hook number HOOK in the hook vector HOOKS, whose function is of + type TYPE, with the args ARGS (my this is a useful comment). */ +#define TREEFS_CALL_HOOK(hooks, hook, type, args...) \ + ((type *)(hooks)[hook])(args) +#define TREEFS_CALL_HANDLE_HOOK(h, hook, type, args...) \ + ({struct treefs_handle *_tfs_cn_h = (h); \ + TREEFS_CALL_HOOK(_tfs_cn_h->po->node->hooks,hook,type, \ + _tfs_cn_h , ##args);}) +#define TREEFS_CALL_NODE_HOOK(node, hook, type, args...) \ + ({struct treefs_node *_tfs_cn_node = (node); \ + TREEFS_CALL_HOOK(_tfs_cn_node->hooks,hook,type, _tfs_cn_node , ##args);}) +#define TREEFS_CALL_FSYS_HOOK(fsys, hook, type, args...) \ + ({struct treefs_fsys *_tfs_cn_fsys = (fsys); \ + TREEFS_CALL_HOOK(_tfs_cn_fsys->hooks,hook,type, _tfs_cn_fsys , ##args);}) + +/* Shorthand form of TREEFS_CALL_*_HOOK (only used here). */ +#define _TREEFS_CHH(h, hook_id, type_id, args...) \ + TREEFS_CALL_HANDLE_HOOK(h, TREEFS_HOOK_##hook_id, treefs_##type_id##_t , ##args) +#define _TREEFS_CNH(node, hook_id, type_id, args...) \ + TREEFS_CALL_NODE_HOOK(node, TREEFS_HOOK_##hook_id, treefs_##type_id##_t , ##args) +#define _TREEFS_CFH(fsys, hook_id, type_id, args...) \ + TREEFS_CALL_FSYS_HOOK(fsys, TREEFS_HOOK_##hook_id, treefs_##type_id##_t , ##args) + +/* Forward declare some structures used before definition. */ +struct treefs_node; +struct treefs_fsys; +struct treefs_auth; +struct treefs_handle; +struct treefs_peropen; + +/* Shorthand for declaring the various hook types (each hook has an + associated type so that a user can type-check his hook routine). */ +#define DNH(name_sym, ret_type, argtypes...) \ + typedef ret_type treefs_##name_sym##_t (struct treefs_node * , ##argtypes); +#define DFH(name_sym, ret_type, argtypes...) \ + typedef ret_type treefs_##name_sym##_t (struct treefs_fsys * , ##argtypes); + +/* ---------------------------------------------------------------- */ +/* Non RPC hooks */ + +/* Called to get the root node of the a filesystem, with a reference, + returning it in ROOT, or return an error if it can't be had. The default + hook just returns FSYS->root or an error if it's NULL. Note that despite + the similar name, this is very different from fsys_s_getroot! FSYS must + not be locked. */ +DFH(fsys_get_root, error_t, struct treefs_node **root) +#define treefs_fsys_get_root(fsys, args...) \ + _TREEFS_CFH(fsys, FSYS_GET_ROOT, fsys_get_root , ##args) + +/* Called on a filesystem to create a new node in that filesystem, returning + it, with one reference, in NODE. DIR, if non-NULL, is the nominal parent + directory, and MODE and AUTH are the desired mode and user info + respectively. This hook should also call node_init_stat & node_init to + initialize the various user bits. */ +DFH(fsys_create_node, error_t, + struct treefs_node *dir, mode_t mode, struct treefs_auth *auth, + struct treefs_node **node) +#define treefs_fsys_create_node(fsys, args...) \ + _TREEFS_CFH(fsys, FSYS_CREATE_NODE, fsys_create_node , ##args) + +/* Called on a filesystem to destroy a node in that filesystem. This call + should *really* destroy it -- i.e., it's only called once all references + are gone. */ +DFH(fsys_destroy_node, void, struct treefs_node *node) +#define treefs_fsys_destroy_node(fsys, node) \ + _TREEFS_CFH(fsys, FSYS_DESTROY_NODE, fsys_destroy_node , ##args) + +/* Returns the type of NODE, as an S_IFMT value (e.g., S_IFDIR). The + default routine just looks at NODE's stat mode. */ +DNH(node_type, int); +#define treefs_node_type(node, args...) \ + _TREEFS_CNH(node, NODE_TYPE, node_type , ##args) + +#define treefs_node_isdir(node) (treefs_node_type(node) == S_IFDIR) +#define treefs_node_isreg(node) (treefs_node_type(node) == S_IFREG) + +/* Return TRUE if NODE is `unlinked' -- that is, can be deleted when all + (in-memory) references go away. */ +DNH(node_unlinked, int); +#define treefs_node_unlinked(node, args...) \ + _TREEFS_CNH(node, NODE_UNLINKED, node_unlinked , ##args) + +/* Changes the link count of NODE by CHANGE; if any error is returned, the + operation trying to change the link count will fail, so filesystems that + don't support real links can restrict it to 1 or 0. This is mostly used + by the in-core directory code when it makes a link. The default hook uses + the link field of NODE's stat entry. */ +DNH(node_mod_link_count, error_t, int change); +#define treefs_node_mod_link_count(node, args...) \ + _TREEFS_CNH(node, NODE_MOD_LINK_COUNT, node_mod_link_count , ##args) + +/* Lookup NAME in NODE, returning the result in CHILD; AUTH should be used to + do authentication. If FLAGS contains O_CREAT, and NAME is not found, then + an entry should be created with a mode of CREATE_MODE (which includes the + S_IFMT bits, e.g., S_IFREG means a normal file), unless O_EXCL is also + set, in which case EEXIST should be returned. Possible special errors + returned include: EAGAIN -- result would be the parent of our filesystem + root. Note that is a single-level lookup, unlike treefs_s_dir_lookup. */ +DNH(dir_lookup, error_t, + char *name, struct treefs_auth *auth, int flags, int create_mode, + struct treefs_node **child) +#define treefs_dir_lookup(dir, args...) \ + _TREEFS_CNH(dir, DIR_LOOKUP, dir_lookup , ##args) + +/* Called by the default implementation of treefs_dir_lookup (and possibly + user-versions as well) when a directory lookup returns ENOENT, before a + new node is created. This hook may return the desire node in CHILD and + return 0, or return an error code. Note that a returned node need not + actually be in the directory DIR, and indeed may be anonymous. */ +DNH(dir_noent, error_t, + char *name, struct treefs_auth *auth, int flags, int create_mode, + struct treefs_node **child); +#define treefs_dir_noent(dir, args...) \ + _TREEFS_CNH(dir, DIR_NOENT, dir_noent , ##args) + +/* Return in CHILD a new node with one reference, presumably a possible child + of DIR, with a mode MODE. All attempts to create a new node go through + this hook, so it may be overridden to easily control creation (e.g., + replacing it with a hook that always returns EPERM). Note that this + routine doesn't actually enter the child into the directory, or give the + node a non-zero link count, that should be done by the caller. */ +DNH(dir_create_child, error_t, + mode_t mode, struct treefs_auth *auth, struct treefs_node **child); +#define treefs_dir_create_child(dir, args...) \ + _TREEFS_CNH(dir, DIR_CREATE_CHILD, dir_create_child , ##args) + +/* Link the node CHILD into DIR as NAME, using AUTH to check authentication. + DIR should be locked and CHILD shouldn't be. The default hook puts it + into DIR's in-core directory, and uses a reference to CHILD (this way, a + node can be linked to both in-core and out-of-core directories and the + permanent link-count will be right). */ +DNH(dir_link, error_t, + char *name, struct treefs_node *child, struct treefs_auth *auth) +#define treefs_dir_link(dir, args...) \ + _TREEFS_CNH(dir, DIR_LINK, dir_link , ##args) + +/* Remove the entry NAME from DIR, using AUTH to check authentication. DIR + should be locked. The default hook removes NAME from DIR's in-core + directory. */ +DNH(dir_unlink, error_t, char *name, struct treefs_auth *auth) +#define treefs_dir_unlink(dir, args...) \ + _TREEFS_CNH(dir, DIR_UNLINK, dir_unlink , ##args) + +/* Check to see if the user identified by AUTH is permitted to do owner-only + operations on node NP; if so, return 0; if not, return EPERM. */ +DNH(node_owned, error_t, struct treefs_auth *auth) +#define treefs_node_owned(node, args...) \ + _TREEFS_CNH(node, NODE_OWNED, node_owned , ##args) + +/* Check to see is the user identified by AUTH is permitted to do + operation OP on node NP. Op is one of S_IREAD, S_IWRITE, or S_IEXEC. + Return 0 if the operation is permitted and EACCES if not. */ +DNH(node_access, error_t, int opt, struct treefs_auth *auth) +#define treefs_node_access(node, args...) \ + _TREEFS_CNH(node, NODE_ACCESS, node_access , ##args) + +/* NODE now has no more references; clean all state. The + _treefs_node_refcnt_lock must be held, and will be released upon return. + NODE must be locked. */ +DNH(node_drop, error_t); +#define treefs_node_drop(node, args...) \ + _TREEFS_CNH(node, NODE_DROP, node_drop , ##args) + +/* Called when a new directory is created, after trees_node_init. If this + routine returns an error, the new node will be destroyed and the create + will fail. */ +DNH(dir_init, error_t) +#define treefs_dir_init(dir, args...) \ + _TREEFS_CNH(dir, DIR_INIT, dir_init , ##args) + +/* If NODE is a symlink, copies the contents into BUF, which should have at + least *LEN bytes available, and returns 0; if the symlink is too big, + E2BIG is returned. Either way, the actual length of the symlink is + returned in *LEN (so if it's too big, you can allocate an appropiately + sized buffer and try again). If NODE is not a symlink, EINVAL is + returned. */ +DNH(node_get_symlink, error_t, char *buf, int *len) +#define treefs_node_get_symlink(node, args...) \ + _TREEFS_CNH(node, NODE_GET_SYMLINK, node_get_symlink , ##args) + +/* If NODE has a passive translator, copies the contents into BUF, which + should have at least *LEN bytes available, and returns 0; if the string is + too big, E2BIG is returned. Either way, the actual length of the + translator string is returned in *LEN (so if it's too big, you can + allocate an appropiately sized buffer and try again). If NODE has no + passive translator, EINVAL is returned. */ +DNH(node_get_passive_trans, error_t, char *buf, int *len) +#define treefs_node_get_passive_trans(node, args...) \ + _TREEFS_CNH(node, NODE_GET_PASSIVE_TRANS, node_get_passive_trans , ##args) + +/* Returns the user and group that a newly started translator should be + authenticated as. The default just returns the owner/group of NODE. */ +DNH(node_get_trans_auth, error_t, uid_t *uid, gid_t *gid) +#define treefs_node_get_trans_auth(node, args...) \ + _TREEFS_CNH(node, NODE_GET_TRANS_AUTH, node_get_trans_auth , ##args) + +/* Start the translator TRANS (of length TRANS_LEN) on NODE, which should be + locked, and will be unlocked during the execution of this function. + PARENT_PORT should be a send right to use as the parent port passed to the + translator. */ +DNH(node_start_translator, error_t, + char *trans, unsigned trans_len, file_t parent_port) +#define treefs_node_start_translator(node, args...) \ + _TREEFS_CNH(node, NODE_START_TRANSLATOR, node_start_translator , ##args) + +/* Called to initialize a new node's stat entry, after all default fields are + filled in (but before node_init is called). */ +DNH(node_init_stat, error_t, + struct treefs_node *dir, mode_t mode, struct treefs_auth *auth) +#define treefs_node_init_stat(node, args...) \ + _TREEFS_CNH(node, NODE_INIT_STAT, node_init_stat , ##args) + +/* Called to initialize a new node, after all default fields are filled in. + If this routine returns an error, the new node will be destroyed and the + create will fail. */ +DNH(node_init, error_t, + struct treefs_node *dir, mode_t mode, struct treefs_auth *auth) +#define treefs_node_init(node, args...) \ + _TREEFS_CNH(node, NODE_INIT, node_init , ##args) + +/* Called to cleanup node-specific info in a node about to be destroyed. */ +DNH(node_finalize, void) +#define treefs_node_finalize(node, args...) \ + _TREEFS_CNH(node, NODE_FINALIZE, node_finalize , ##args) + +/* Called to cleanup node-specific directory info in a node about to be + destroyed. Called before node_finalize. */ +DNH(dir_finalize, void) +#define treefs_dir_finalize(dir, args...) \ + _TREEFS_CNH(dir, DIR_FINALIZE, dir_finalize , ##args) + +/* Called when the new peropen structure PO is made for NODE, with the + authorization in AUTH, opened with the flags FLAGS (note that this a copy + of PO->flags, which the hook may modify). If an error is returned, the + open will fail with that error. The default hook does explicit checks + against AUTH using treefs_node_access, and otherwise does nothing. */ +DNH(node_init_peropen, error_t, + struct treefs_peropen *po, int flags, struct treefs_auth *auth) +#define treefs_node_init_peropen(node, args...) \ + _TREEFS_CNH(node, NODE_INIT_PEROPEN, node_init_peropen , ##args) + +/* Called the peropen structure PO for NODE is being destroyed. */ +DNH(node_finalize_peropen, void, struct treefs_peropen *po) +#define treefs_node_finalize_peropen(node, args...) \ + _TREEFS_CNH(node, NODE_FINALIZE_PEROPEN, node_finalize_peropen , ##args) + +/* Called when a new handle structure is made for a node. The default does + nothing. */ +DNH(node_init_handle, void, struct treefs_handle *handle) +#define treefs_node_init_handle(node, args...) \ + _TREEFS_CNH(node, NODE_INIT_HANDLE, node_init_handle , ##args) + +/* Called when the handle HANDLE for NODE is being destroyed. */ +DNH(node_finalize_handle, void, struct treefs_handle *handle) +#define treefs_node_finalize_handle(node, args...) \ + _TREEFS_CNH(node, NODE_FINALIZE_HANDLE, node_finalize_handle , ##args) + +/* ---------------------------------------------------------------- */ +/* Ref counting stuff */ + +/* NODE has just acquired a hard reference where it had none previously. It + is thus now OK again to have weak references without real users. NODE is + locked. */ +DNH(node_new_refs, void); +#define treefs_node_new_refs(node, args...) \ + _TREEFS_CNH(node, NODE_NEW_REFS, node_new_refs , ##args) + +/* NODE has some weak references but has just lost its last hard reference. + NP is locked. */ +DNH(node_lost_refs, void); +#define treefs_node_lost_refs(node, args...) \ + _TREEFS_CNH(node, NODE_LOST_REFS, node_lost_refs , ##args) + +/* NODE has some weak references, but has just lost its last hard references. + Take steps so that if any weak references can be freed, they are. NP is + locked as is the pager refcount lock. This function will be called after + treefs_node_lost_refs. */ +DNH(node_try_dropping_weak_refs, void); +#define treefs_node_try_dropping_weak_refs(node, args...) \ + _TREEFS_CNH(node, NODE_TRY_DROPPING_WEAK_REFS, node_try_dropping_weak_refs , ##args) + +/* Turn off our shorthand notation. */ +#undef DNH +#undef DFH + +/* ---------------------------------------------------------------- */ +/* Default routines for some hooks (each is the default value for the hook + with the same name minus the leading underscore). When you add something + here, you should also add it to the initialize code in defhooks.c. */ + +treefs_fsys_create_node_t _treefs_fsys_create_node; +treefs_fsys_destroy_node_t _treefs_fsys_destroy_node; +treefs_fsys_get_root_t _treefs_fsys_get_root; +treefs_node_type_t _treefs_node_type; +treefs_node_unlinked_t _treefs_node_unlinked; +treefs_node_mod_link_count_t _treefs_node_mod_link_count; +treefs_node_mod_link_count_t _treefs_mod_link_count; +treefs_dir_lookup_t _treefs_dir_lookup; +treefs_dir_noent_t _treefs_dir_noent; +treefs_dir_create_child_t _treefs_dir_create_child; +treefs_dir_link_t _treefs_dir_link; +treefs_dir_unlink_t _treefs_dir_unlink; +treefs_node_owned_t _treefs_node_owned; +treefs_node_access_t _treefs_node_access; +treefs_node_start_translator_t _treefs_node_start_translator; +treefs_node_get_trans_auth_t _treefs_node_get_trans_auth; + +#endif /* __TREEFS_HOOKS_H__ */ |