1 /*
2  * Copyright (c) 2025 Antmicro <www.antmicro.com>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /*
8  * This header provides helper functions to pack FUSE client requests. Note the client is the
9  * side which initiates these requests, and that in a typical FUSE usage the client would be
10  * the Linux kernel. While in Zephyr's case this is to enable functionality like the embedded
11  * virtiofs client connecting to a virtiofsd daemon running in the host.
12  */
13 
14 #ifndef ZEPHYR_SUBSYS_FS_FUSE_CLIENT_H_
15 #define ZEPHYR_SUBSYS_FS_FUSE_CLIENT_H_
16 #include <stdint.h>
17 #include "fuse_abi.h"
18 
19 /*
20  * requests are put into structs to leverage the fact that they are contiguous in memory and can
21  * be passed to virtqueue as smaller amount of buffers, e.g. in_header + init_in can be sent as
22  * a single buffer containing both of them instead of two separate buffers
23  */
24 
25 struct fuse_init_req {
26 	struct fuse_in_header in_header;
27 	struct fuse_init_in init_in;
28 	struct fuse_out_header out_header;
29 	struct fuse_init_out init_out;
30 };
31 
32 struct fuse_open_req {
33 	struct fuse_in_header in_header;
34 	struct fuse_open_in open_in;
35 	struct fuse_out_header out_header;
36 	struct fuse_open_out open_out;
37 };
38 
39 struct fuse_create_req {
40 	struct fuse_in_header in_header;
41 	struct fuse_create_in create_in;
42 	struct fuse_out_header out_header;
43 	struct fuse_create_out create_out;
44 };
45 
46 struct fuse_write_req {
47 	struct fuse_in_header in_header;
48 	struct fuse_write_in write_in;
49 	struct fuse_out_header out_header;
50 	struct fuse_write_out write_out;
51 };
52 
53 struct fuse_lseek_req {
54 	struct fuse_in_header in_header;
55 	struct fuse_lseek_in lseek_in;
56 	struct fuse_out_header out_header;
57 	struct fuse_lseek_out lseek_out;
58 };
59 
60 struct fuse_mkdir_req {
61 	struct fuse_in_header in_header;
62 	struct fuse_mkdir_in mkdir_in;
63 	struct fuse_out_header out_header;
64 	struct fuse_entry_out entry_out;
65 };
66 
67 struct fuse_lookup_req {
68 	struct fuse_in_header in_header;
69 	struct fuse_out_header out_header;
70 	struct fuse_entry_out entry_out;
71 };
72 
73 struct fuse_read_req {
74 	struct fuse_in_header in_header;
75 	struct fuse_read_in read_in;
76 	struct fuse_out_header out_header;
77 };
78 
79 struct fuse_release_req {
80 	struct fuse_in_header in_header;
81 	struct fuse_release_in release_in;
82 	struct fuse_out_header out_header;
83 };
84 
85 struct fuse_destroy_req {
86 	struct fuse_in_header in_header;
87 	struct fuse_out_header out_header;
88 };
89 
90 struct fuse_setattr_req {
91 	struct fuse_in_header in_header;
92 	struct fuse_out_header out_header;
93 };
94 
95 struct fuse_fsync_req {
96 	struct fuse_in_header in_header;
97 	struct fuse_fsync_in fsync_in;
98 	struct fuse_out_header out_header;
99 };
100 
101 struct fuse_unlink_req {
102 	struct fuse_in_header in_header;
103 	struct fuse_out_header out_header;
104 };
105 
106 struct fuse_rename_req {
107 	struct fuse_in_header in_header;
108 	struct fuse_rename_in rename_in;
109 	struct fuse_out_header out_header;
110 };
111 
112 struct fuse_kstatfs_req {
113 	struct fuse_in_header in_header;
114 	struct fuse_out_header out_header;
115 	struct fuse_kstatfs kstatfs_out;
116 };
117 
118 struct fuse_forget_req {
119 	struct fuse_in_header in_header;
120 	struct fuse_forget_in forget_in;
121 };
122 
123 enum fuse_object_type {
124 	FUSE_FILE,
125 	FUSE_DIR
126 };
127 
128 void fuse_fill_header(struct fuse_in_header *hdr, uint32_t len, uint32_t opcode, uint64_t nodeid);
129 
130 void fuse_create_init_req(struct fuse_init_req *req);
131 void fuse_create_open_req(struct fuse_open_req *req, uint64_t inode, uint32_t flags,
132 	enum fuse_object_type type);
133 void fuse_create_lookup_req(struct fuse_lookup_req *req, uint64_t inode, uint32_t fname_len);
134 void fuse_create_read_req(
135 	struct fuse_read_req *req, uint64_t inode, uint64_t fh, uint64_t offset, uint32_t size,
136 	enum fuse_object_type type);
137 void fuse_create_release_req(struct fuse_release_req *req, uint64_t inode, uint64_t fh,
138 	enum fuse_object_type type);
139 void fuse_create_destroy_req(struct fuse_destroy_req *req);
140 void fuse_create_create_req(
141 	struct fuse_create_req *req, uint64_t inode, uint32_t fname_len, uint32_t flags,
142 	uint32_t mode);
143 void fuse_create_write_req(
144 	struct fuse_write_req *req, uint64_t inode, uint64_t fh,  uint64_t offset, uint32_t size);
145 void fuse_create_lseek_req(
146 	struct fuse_lseek_req *req, uint64_t inode, uint64_t fh, uint64_t offset, uint32_t whence);
147 void fuse_create_setattr_req(struct fuse_setattr_req *req, uint64_t inode);
148 void fuse_create_fsync_req(struct fuse_fsync_req *req, uint64_t inode, uint64_t fh);
149 void fuse_create_mkdir_req(
150 	struct fuse_mkdir_req *req, uint64_t inode, uint32_t dirname_len, uint32_t mode);
151 void fuse_create_unlink_req(
152 	struct fuse_unlink_req *req, uint32_t fname_len, enum fuse_object_type type);
153 void fuse_create_rename_req(
154 	struct fuse_rename_req *req, uint64_t old_dir_nodeid, uint32_t old_len,
155 	uint64_t new_dir_nodeid, uint32_t new_len);
156 
157 const char *fuse_opcode_to_string(uint32_t opcode);
158 
159 void fuse_dump_init_req_out(struct fuse_init_req *req);
160 void fuse_dump_entry_out(struct fuse_entry_out *eo);
161 void fuse_dump_open_req_out(struct fuse_open_req *req);
162 void fuse_dump_create_req_out(struct fuse_create_out *req);
163 void fuse_dump_write_out(struct fuse_write_out *wo);
164 void fuse_dump_lseek_out(struct fuse_lseek_out *lo);
165 void fuse_dump_attr_out(struct fuse_attr_out *ao);
166 void fuse_dump_kstafs(struct fuse_kstatfs *ks);
167 
168 #endif /* ZEPHYR_SUBSYS_FS_FUSE_CLIENT_H_ */
169