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.

446 regels
13 KiB

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