diff options
Diffstat (limited to 'lib9p/include/lib9p/9p.h')
-rw-r--r-- | lib9p/include/lib9p/9p.h | 206 |
1 files changed, 0 insertions, 206 deletions
diff --git a/lib9p/include/lib9p/9p.h b/lib9p/include/lib9p/9p.h deleted file mode 100644 index 42381cf..0000000 --- a/lib9p/include/lib9p/9p.h +++ /dev/null @@ -1,206 +0,0 @@ -/* lib9p/9p.h - Base 9P protocol definitions for both clients and servers - * - * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -#ifndef _LIB9P_9P_H_ -#define _LIB9P_9P_H_ - -#include <stdbool.h> -#include <sys/types.h> /* for ssize_t */ - -#include <libmisc/assert.h> - -#include <lib9p/linux-errno.h> -#include <lib9p/9p.generated.h> - -#ifndef CONFIG_9P_MAX_ERR_SIZE - #error config.h must define CONFIG_9P_MAX_ERR_SIZE -#endif -static_assert(CONFIG_9P_MAX_ERR_SIZE <= UINT16_MAX); - -/* constants ******************************************************************/ - -enum { - LIB9P_DEFAULT_PORT_9FS = 564, - LIB9P_DEFAULT_PORT_STYX = 6666, -}; - -/* strings ********************************************************************/ - -const char *lib9p_version_str(enum lib9p_version); -const char *lib9p_msgtype_str(enum lib9p_version, enum lib9p_msg_type); - -struct lib9p_s lib9p_str(char *s); -struct lib9p_s lib9p_strn(char *s, size_t maxlen); -struct lib9p_s lib9p_str_slice(struct lib9p_s s, uint16_t beg, uint16_t end); -#define lib9p_str_sliceleft(s, beg) lib9p_str_slice(s, beg, (s).len) -bool lib9p_str_eq(struct lib9p_s a, struct lib9p_s b); - -/* ctx ************************************************************************/ - -struct lib9p_ctx { - /* negotiated */ - enum lib9p_version version; - uint32_t max_msg_size; - - /* state */ -#ifdef CONFIG_9P_ENABLE_9P2000_u - lib9p_errno_t err_num; -#endif - [[gnu::nonstring]] char err_msg[CONFIG_9P_MAX_ERR_SIZE]; -}; - -void lib9p_ctx_clear_error(struct lib9p_ctx *ctx); - -bool lib9p_ctx_has_error(struct lib9p_ctx *ctx); - -/** Write an static error into ctx, return -1. */ -int lib9p_error(struct lib9p_ctx *ctx, lib9p_errno_t linux_errno, char const *msg); -/** Write a printf-style error into ctx, return -1. */ -int lib9p_errorf(struct lib9p_ctx *ctx, lib9p_errno_t linux_errno, char const *fmt, ...) [[gnu::format(printf, 3, 4)]]; - -/* misc utilities *************************************************************/ - -uint32_t lib9p_version_min_msg_size(enum lib9p_version); - -lo_interface fmt_formatter lo_box_lib9p_msg_as_fmt_formatter(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body); - -/* main T-message functions ***************************************************/ - -/** - * Validate a message's structure; its size, string encodings, enums, - * and bitfields. - * - * Return how much space the message will take when unmarshaled. This - * number may be larger than net_bytes due to (1) struct padding, (2) - * array pointers. - * - * Emits an error (return -1, set ctx->err_num and ctx->err_msg) if - * either the message type is unknown, or if net_bytes is too short - * for that message type, or if an invalid string (invalid UTF-8, - * contains a nul-byte) is encountered. - * - * @param net_bytes : the complete request, starting with the "size[4]" - * - * @return required size, or -1 on error - * - * @errno LINUX_EOPNOTSUPP: message is an R-message - * @errno LINUX_EOPNOTSUPP: message has unknown type - * @errno LINUX_EBADMSG: message is wrong size for content - * @errno LINUX_EBADMSG: message contains invalid UTF-8 - * @errno LINUX_EBADMSG: message contains a bitfield with unknown bits - * @errno LINUX_EMSGSIZE: would-be return value overflows SSIZE_MAX - */ -ssize_t lib9p_Tmsg_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes); - -/** - * Unmarshal the 9P message `net_bytes` into the C struct `ret_body`. - * - * lib9p_Tmsg_unmarshal does no validation; you must run - * lib9p_Tmsg_validate() first. - * - * @param ctx : negotiated protocol parameters - * @param net_bytes : the complete message, starting with the "size[4]" - * - * @return ret_typ : the mesage type - * @return ret_body : the message body, must be at least lib9p_Tmsg_validate() bytes - */ -void lib9p_Tmsg_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes, - enum lib9p_msg_type *ret_typ, void *ret_body); - -/** - * Marshal a `struct lib9p_msg_{typ}` structure into a byte-array. - * - * lib9p_Tmsg_marshal does no validation; it trusts that the - * programmer won't give it garbage input. However, just as it - * doesn't marshal struct fields that aren't in ctx->version, it won't - * marshal bitfield bits that aren't in ctx->version; it applies a - * version-specific mask to bitfields. - * - * @param ctx : negotiated protocol parameters, where to record errors - * @param typ : the message type - * @param msg : the message to encode - * - * @return ret_bytes : the buffer to encode to, must be at be at least ctx->max_msg_size bytes - * @return whether there was an error (false=success, true=error) - * - * @errno LINUX_ERANGE: reply does not fit in ctx->max_msg_size - */ -bool lib9p_Tmsg_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body, - struct lib9p_Tmsg_send_buf *ret); - -/* main R-message functions ***************************************************/ - -/** Same as above, but for R-messages instead of T-messages. */ - -ssize_t lib9p_Rmsg_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes); -void lib9p_Rmsg_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes, - enum lib9p_msg_type *ret_typ, void *ret_body); -bool lib9p_Rmsg_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body, - struct lib9p_Rmsg_send_buf *ret); - - -/* `struct lib9p_stat` helpers ************************************************/ - -/** Assert that a `struct lib9p_stat` object looks valid. */ -static inline void lib9p_stat_assert(struct lib9p_stat stat) { - assert( ((bool)(stat.file_mode & LIB9P_DM_DIR )) == ((bool)(stat.file_qid.type & LIB9P_QT_DIR )) ); - assert( ((bool)(stat.file_mode & LIB9P_DM_APPEND)) == ((bool)(stat.file_qid.type & LIB9P_QT_APPEND)) ); - assert( ((bool)(stat.file_mode & LIB9P_DM_EXCL )) == ((bool)(stat.file_qid.type & LIB9P_QT_EXCL )) ); - assert( ((bool)(stat.file_mode & LIB9P_DM_AUTH )) == ((bool)(stat.file_qid.type & LIB9P_QT_AUTH )) ); - assert( ((bool)(stat.file_mode & LIB9P_DM_TMP )) == ((bool)(stat.file_qid.type & LIB9P_QT_TMP )) ); - assert( (stat.file_size == 0) || !(stat.file_mode & LIB9P_DM_DIR) ); -} - -/** - * Validate a message's `stat` structure. - * - * @param ctx : negotiated protocol parameters, where to record errors - * @param net_bytes : network-encoded stat structure - * @param net_size : the number of net_bytes that may be read - * - * @return ret_net_size : number of bytes consumed; <=net_size - * @return ret_host_size : number of bytes that lib9p_stat_unmarshal would take - * @return whether there was an error - */ -bool lib9p_stat_validate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, - uint32_t *ret_net_size, size_t *ret_host_size); - -/** - * Unmarshal the 9P `net_bytes` into the C struct `ret_obj`. - * - * lib9p_stat_unmarshal does no validation; you must run - * lib9p_stat_validate() first. - * - * @param ctx : negotiated protocol parameters - * @param net_bytes : network-encoded stat structure - * - * @return ret : the stat object, must be at least lib9p_stat_validate()->ret_net_size bytes - */ -void lib9p_stat_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes, - struct lib9p_stat *ret); - -/** - * Marhsal a `struct lib9p_stat` structure into a byte-array. - * - * lib9p_Tmsg_marshal does no validation; it trusts that the - * programmer won't give it garbage input. However, just as it - * doesn't marshal struct fields that aren't in ctx->version, it won't - * marshal bitfield bits that aren't in ctx->version; it applies a - * version-specific mask to bitfields. - * - * @param ctx : negotiated protocol parameters, where to record errors - * @param max_net_size : the maximum network-encoded size to allow - * @param obj : the message to encode - * - * @return ret_bytes: the buffer to encode into - * @return the number of bytes written, or 0 if the stat object does not fit in max_net_size - * - * @errno LINUX_ERANGE: reply does not fit in max_net_size - */ -uint32_t lib9p_stat_marshal(struct lib9p_ctx *ctx, uint32_t max_net_size, struct lib9p_stat *obj, - uint8_t *ret_bytes); - -#endif /* _LIB9P_9P_H_ */ |