General Purpose library for Freestanding C++ and POSIX systems
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

445 lines
13 KiB

преди 4 години
  1. #pragma once
  2. #include "gp/array.hpp"
  3. #include <cstddef>
  4. #include <cstdint>
  5. // TODO: File locking and fsync/fdatasync
  6. /**
  7. * @brief this enum represents the types of operations available
  8. */
  9. enum class operation_type {
  10. version, ///< this operation queries properties of the filesystem
  11. flush, ///< flushes any buffer for writing on the filesystem
  12. attach, ///< adds a filesystem to the system
  13. detach, ///< remove a filesystem from the system
  14. walk, ///< change the current directory
  15. create, ///< creates a file
  16. open, ///< opens a file, yielding a fid
  17. read, ///< reads from a file
  18. write, ///< writes to a file
  19. clunk, ///< relinquishes a fid
  20. remove, ///< removes a file
  21. stat, ///< reads a file metadata
  22. wstat ///< writes a file metadata
  23. };
  24. /**
  25. * @brief this enum represent the type of file handled
  26. */
  27. enum class file_type {
  28. directory, ///< the file is a normal directory
  29. master_directory, ///< the file is the root directory of a non-root filesystem
  30. device_directory, ///< the file is a driver mapped to a directory
  31. root_directory, ///< the file is the root directory
  32. file, ///< the file is a normal file
  33. file_device, ///< the file is a driver mapped to a file
  34. message_pipe ///< the file is a channel to read and write messages to
  35. };
  36. /**
  37. * @brief represents file permissions
  38. */
  39. struct permission_list {
  40. bool
  41. read : 1,
  42. write : 1,
  43. execute : 1;
  44. };
  45. /**
  46. * @brief represents all levels of permissions in a file
  47. */
  48. struct file_permissions {
  49. permission_list
  50. user, ///< list of permissions for the owner
  51. group, ///< list of permissions for the owning group
  52. others; ///< list of permissions for other users
  53. };
  54. /**
  55. * @brief represent a value that should be unique for every entity of the system
  56. */
  57. using unique_node = uint64_t;
  58. /**
  59. * @brief represent a timestamp in seconds
  60. */
  61. using timestamp = uint64_t;
  62. /**
  63. * @brief represent a value that represent an offset into a file
  64. */
  65. using file_offset = uint64_t;
  66. /**
  67. * @brief the expected return type of a stat query, as well as its writing counterpart
  68. */
  69. struct f_stats {
  70. file_type type; ///< the type of file
  71. unique_node file_id; ///< the unique file id
  72. unique_node owner_user_id; ///< the user id of the owner of the file
  73. unique_node owner_group_id; ///< the group id of the file
  74. unique_node last_modifier_id; ///< the user id of the last user that wrote data to the file
  75. timestamp last_access; ///< the timestamp for the last time the file was opened or created. If the current user is not root, it is replaced by the system on wstat
  76. timestamp last_modification; ///< the last modification timestamp. If the current user is not root, it is replaced by the system on wstat
  77. file_offset file_size; ///< the filesize in bytes
  78. gp::array<char, 255> filename; ///< the filename, padded with null characters
  79. };
  80. /**
  81. * @brief Represent an IO operation as sent to the system, this is an abstract class.
  82. */
  83. struct io_operation {
  84. const operation_type type; ///< the discriminant for the operation type
  85. protected:
  86. io_operation(operation_type a) : type(a) {}
  87. };
  88. /**
  89. * @brief This operation obtains the version of the targeted filesystem
  90. */
  91. struct version_operation : public io_operation {
  92. const gp::buffer<char> destination; ///< the destination where the data is written
  93. const gp::buffer<char> root_path; ///< the path of the file system to query for version
  94. const gp::optional<gp_config::file_descriptor_t> fd; ///< the relative root to use
  95. /**
  96. * @brief Construct a new version operation object
  97. *
  98. * @param dest the destination where the data is written
  99. * @param path the path to the target filesystem
  100. * @param v_fd a relative root that is used
  101. */
  102. version_operation(
  103. gp::buffer<char> dest,
  104. gp::buffer<char> path,
  105. gp::optional<gp_config::file_descriptor_t> v_fd
  106. )
  107. : io_operation{operation_type::version}
  108. , destination(dest)
  109. , root_path(path)
  110. , fd(v_fd)
  111. {}
  112. };
  113. /**
  114. * @brief This operation flushes a filesystem, writing the data to the associated medium
  115. */
  116. struct flush_operation : public io_operation {
  117. const gp::buffer<char> root_path; ///< the path that is going to be flushed
  118. const gp::optional<gp_config::file_descriptor_t> fd; ///< the relative root to use
  119. /**
  120. * @brief Construct a new flush operation object
  121. *
  122. * @param path the path to a file or to a master directory that is to be flushed
  123. * @param v_fd a relative root that is used
  124. */
  125. flush_operation(
  126. gp::buffer<char> path,
  127. gp::optional<gp_config::file_descriptor_t> v_fd
  128. )
  129. : io_operation{operation_type::flush}
  130. , root_path(path)
  131. , fd(v_fd)
  132. {}
  133. };
  134. /**
  135. * @brief This operation mounts a filesystem given a format and a configuration data.
  136. *
  137. * It also mounts devices.
  138. */
  139. struct attach_operation : public io_operation {
  140. const gp::buffer<char> target_path; ///< location where the filesystem is going to be attached
  141. const gp::buffer<char> format; ///< format string of the filesystem
  142. const gp::buffer<char> configuration; ///< configuration data
  143. const gp::optional<gp_config::file_descriptor_t> fd; ///< the relative root to use
  144. /**
  145. * @brief Construct a new attach operation object
  146. *
  147. * @param path path where the filesystem will be attached, must be either not existing or an empty directory
  148. * @param v_format the format name that will be invoked with the config
  149. * @param config the configuration to send
  150. * @param v_fd a relative root that is used
  151. */
  152. attach_operation(
  153. gp::buffer<char> path,
  154. gp::buffer<char> v_format,
  155. gp::buffer<char> config,
  156. gp::optional<gp_config::file_descriptor_t> v_fd
  157. )
  158. : io_operation{operation_type::attach}
  159. , target_path(path)
  160. , format(v_format)
  161. , configuration(config)
  162. , fd(v_fd)
  163. {}
  164. };
  165. /**
  166. * @brief This operation removes the master status of a directory and dismounts the
  167. * filesystem attached to it after flushing it. Will fail if any file is still attached
  168. * in the filesystem.
  169. *
  170. * This applies to the devices too.
  171. */
  172. struct detach_operation : public io_operation {
  173. const gp::buffer<char> target_path; ///< the target master directory
  174. const gp::optional<gp_config::file_descriptor_t> fd; ///< the relative root to use
  175. /**
  176. * @brief Construct a new detach operation object
  177. *
  178. * @param path the item to be detached
  179. * @param v_fd a relative root that is used
  180. */
  181. detach_operation(
  182. gp::buffer<char> path,
  183. gp::optional<gp_config::file_descriptor_t> v_fd
  184. )
  185. : io_operation{operation_type::attach}
  186. , target_path(path)
  187. , fd(v_fd)
  188. {}
  189. };
  190. /**
  191. * @brief This operation will move the focus of the target directory relative to itself or absolutely
  192. */
  193. struct walk_operation : public io_operation {
  194. const gp::buffer<char> target_path; ///< the target to move to
  195. const gp_config::file_descriptor_t fd_to_alter; ///< the fd that will be modified
  196. /**
  197. * @brief Construct a new walk operation object
  198. *
  199. * @param path the target to move to
  200. * @param dir the original file descriptor
  201. */
  202. walk_operation(
  203. gp::buffer<char> path,
  204. gp_config::file_descriptor_t dir
  205. )
  206. : io_operation{operation_type::walk}
  207. , target_path(path)
  208. , fd_to_alter(dir)
  209. {}
  210. };
  211. /**
  212. * @brief selector for the type of file to be created in a given environment
  213. */
  214. enum class create_type {
  215. file, ///< normal file
  216. directory, ///< directory file
  217. temporary, ///< file which is to be remove upon all of his descriptors being closed
  218. pipe_read_side, ///< pipe, read side returned
  219. pipe_write_side ///< pipe, write side returned
  220. };
  221. /**
  222. * @brief This operation will attempt to create a file at the specified destination
  223. */
  224. struct create_operation : public io_operation {
  225. const gp::buffer<char> target_path;
  226. const create_type mode;
  227. const gp::optional<gp_config::file_descriptor_t> fd;
  228. /**
  229. * @brief Create a new create operation object
  230. *
  231. * @param path the new file that is created
  232. * @param v_mode the type of file to create
  233. * @param v_fd a relative root that is used
  234. */
  235. create_operation(
  236. gp::buffer<char> path,
  237. create_type v_mode,
  238. gp::optional<gp_config::file_descriptor_t> v_fd
  239. )
  240. : io_operation{operation_type::create}
  241. , target_path(path)
  242. , mode(v_mode)
  243. , fd(v_fd)
  244. {}
  245. };
  246. /**
  247. * @brief selector for the properties expected from an opened file descriptor
  248. */
  249. enum class open_mode {
  250. read_only, ///< the descriptor will be read only, will fail if no read permissions
  251. read_write, ///< the descriptor is read-write, will fail if no write permissions, but not if no read permissions
  252. read_write_create ///< the descriptor is read-write, and has the same proterties as the read-write. The file will be created if it does not exist.
  253. };
  254. /**
  255. * @brief This operation will attempt to open a file at the specified destination
  256. */
  257. struct open_operation : public io_operation {
  258. const gp::buffer<char> target_path; ///< the specified path
  259. open_mode mode; ///< the openning mode
  260. const gp::optional<gp_config::file_descriptor_t> fd; ///< the relative root to use
  261. /**
  262. * @brief Construct a new open operation object
  263. *
  264. * @param path the path where to open a file
  265. * @param v_mode the mode of opening
  266. * @param v_fd a relative root that is used
  267. */
  268. open_operation(
  269. gp::buffer<char> path,
  270. open_mode v_mode,
  271. gp::optional<gp_config::file_descriptor_t> v_fd
  272. )
  273. : io_operation{operation_type::create}
  274. , target_path(path)
  275. , mode(v_mode)
  276. , fd(v_fd)
  277. {}
  278. };
  279. /**
  280. * @brief This operation will attempt to read a file into the destination starting at the specified offset in the file
  281. */
  282. struct read_operation : public io_operation {
  283. const gp_config::file_descriptor_t fd; ///< the file to read
  284. const file_offset offset; ///< the offset to start reading at
  285. const gp::buffer<char> destination; ///< the destination where to write the data
  286. /**
  287. * @brief Construct a new read operation object
  288. *
  289. * @param v_fd the descriptor to read
  290. * @param off the offset to read
  291. * @param v_destination the location where the data will be written
  292. */
  293. read_operation(
  294. gp_config::file_descriptor_t v_fd,
  295. file_offset off,
  296. gp::buffer<char> v_destination
  297. )
  298. : io_operation{operation_type::read}
  299. , fd{v_fd}
  300. , offset(off)
  301. , destination(v_destination)
  302. {}
  303. };
  304. /**
  305. * @brief This operation will attempt to write in file from the source starting at the specified offset in the file
  306. */
  307. struct write_operation : public io_operation {
  308. const gp_config::file_descriptor_t fd; ///< the descriptor of the file where writing happens
  309. const file_offset offset; ///< the offset in the file where writing starts
  310. const gp::buffer<char> source; ///< the source data
  311. /**
  312. * @brief Construct a new write operation object
  313. *
  314. * @param v_fd the target file
  315. * @param off the target offset
  316. * @param v_source the data source buffer
  317. */
  318. write_operation(
  319. gp_config::file_descriptor_t v_fd,
  320. file_offset off,
  321. gp::buffer<char> v_source
  322. )
  323. : io_operation{operation_type::write}
  324. , fd{v_fd}
  325. , offset(off)
  326. , source(v_source)
  327. {}
  328. };
  329. /**
  330. * @brief This operation closes a file by relinquishing its file descriptor
  331. */
  332. struct clunk_operation : public io_operation {
  333. const gp_config::file_descriptor_t fd; ///< The descriptor that will be disposed of
  334. /**
  335. * @brief Construct a new clunk operation object
  336. *
  337. * @param v_fd the fd to close
  338. */
  339. clunk_operation(gp_config::file_descriptor_t v_fd)
  340. : io_operation{operation_type::clunk}
  341. , fd{v_fd}
  342. {}
  343. };
  344. /**
  345. * @brief This operation removes a fileas soon as all its file descriptors are given back
  346. */
  347. struct remove_operation : public io_operation {
  348. const gp::buffer<char*> target_path; ///< the target file
  349. const gp::optional<gp_config::file_descriptor_t> fd; ///< the relative root to use
  350. /**
  351. * @brief Construct a new remove operation object
  352. *
  353. * @param path the path to the file to remove
  354. * @param v_fd a relative root that is used
  355. */
  356. remove_operation(
  357. gp::buffer<char*> path,
  358. gp::optional<gp_config::file_descriptor_t> v_fd
  359. )
  360. : io_operation{operation_type::remove}
  361. , target_path(path)
  362. , fd(v_fd)
  363. {}
  364. };
  365. /**
  366. * @brief This operation fetches metadata about a file
  367. */
  368. struct stat_operation : public io_operation {
  369. const gp::buffer<char*> target_path; ///< the file to query metadata about
  370. const gp::optional<gp_config::file_descriptor_t> fd; ///< the relative root to use
  371. /**
  372. * @brief Construct a new stat operation object
  373. *
  374. * @param path the path to the file to query about
  375. * @param v_fd a relative root that is used
  376. */
  377. stat_operation(
  378. gp::buffer<char*> path,
  379. gp::optional<gp_config::file_descriptor_t> v_fd
  380. )
  381. : io_operation{operation_type::stat}
  382. , target_path(path)
  383. , fd(v_fd)
  384. {}
  385. };
  386. /**
  387. * @brief This operation writes metadata about a file
  388. */
  389. struct wstat_operation : public io_operation {
  390. const gp::buffer<char*> target_path; ///< the file to set metadata on
  391. const gp::optional<gp_config::file_descriptor_t> fd; ///< the relative root to use
  392. /**
  393. * @brief Construct a new wstat operation object
  394. *
  395. * @param path the path to the file to write about
  396. * @param v_fd a relative root that is used
  397. */
  398. wstat_operation(
  399. gp::buffer<char*> path,
  400. gp::optional<gp_config::file_descriptor_t> v_fd
  401. )
  402. : io_operation{operation_type::wstat}
  403. , target_path(path)
  404. , fd(v_fd)
  405. {}
  406. };