summaryrefslogtreecommitdiff
path: root/libtreefs/treefs-hooks.h
diff options
context:
space:
mode:
Diffstat (limited to 'libtreefs/treefs-hooks.h')
-rw-r--r--libtreefs/treefs-hooks.h401
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__ */