vfs.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. #include <kernel/mem.h>
  2. #include <kernel/stdio.h>
  3. #include <kernel/tty.h>
  4. #include <kernel/vfs.h>
  5. #include <types/allocator.hpp>
  6. #include <types/list.hpp>
  7. #include <types/vector.hpp>
  8. using types::allocator_traits;
  9. using types::kernel_allocator;
  10. using types::list;
  11. using types::vector;
  12. struct tmpfs_file_entry {
  13. size_t ino;
  14. char filename[128];
  15. };
  16. class tmpfs {
  17. private:
  18. using inode_list_type = list<struct inode, kernel_allocator>;
  19. private:
  20. size_t m_limit;
  21. // TODO: hashtable etc.
  22. inode_list_type m_inodes;
  23. struct fs_info m_fs;
  24. size_t m_last_inode_no;
  25. protected:
  26. inline vector<struct tmpfs_file_entry>* mk_fe_vector(void)
  27. {
  28. return allocator_traits<kernel_allocator<vector<struct tmpfs_file_entry>>>::allocate_and_construct();
  29. }
  30. inline vector<char>* mk_data_vector(void)
  31. {
  32. return allocator_traits<kernel_allocator<vector<char>>>::allocate_and_construct();
  33. }
  34. inline struct inode mk_inode(unsigned int dir, unsigned int file, unsigned int mnt, void* data)
  35. {
  36. struct inode i { };
  37. i.flags.directory = dir;
  38. i.flags.file = file;
  39. i.flags.mount_point = mnt;
  40. i.fs = &m_fs;
  41. i.impl = data;
  42. i.ino = m_last_inode_no++;
  43. i.perm = 0777;
  44. return i;
  45. }
  46. public:
  47. explicit tmpfs(size_t limit);
  48. void mklink(struct inode* dir, struct inode* inode, const char* filename);
  49. void mkfile(struct inode* dir, const char* filename);
  50. void mkdir(struct inode* dir, const char* dirname);
  51. size_t read(struct inode* file, char* buf, size_t buf_size, size_t offset, size_t n);
  52. size_t write(struct inode* file, const char* buf, size_t offset, size_t n);
  53. int readdir(struct inode* dir, struct dirent* entry, size_t i);
  54. struct inode* root_inode(void)
  55. {
  56. return &*m_inodes.begin();
  57. }
  58. };
  59. size_t tmpfs_read(struct inode* file, char* buf, size_t buf_size, size_t offset, size_t n)
  60. {
  61. auto* fs = static_cast<tmpfs*>(file->fs->impl);
  62. return fs->read(file, buf, buf_size, offset, n);
  63. }
  64. size_t tmpfs_write(struct inode* file, const char* buf, size_t offset, size_t n)
  65. {
  66. auto* fs = static_cast<tmpfs*>(file->fs->impl);
  67. return fs->write(file, buf, offset, n);
  68. }
  69. int tmpfs_readdir(struct inode* dir, struct dirent* entry, size_t i)
  70. {
  71. auto* fs = static_cast<tmpfs*>(dir->fs->impl);
  72. return fs->readdir(dir, entry, i);
  73. }
  74. // int tmpfs_finddir(struct inode* dir, struct dirent* entry, const char* filename)
  75. // {
  76. // auto* fs = static_cast<tmpfs*>(dir->fs->impl);
  77. // return fs->finddir(dir, entry, filename);
  78. // }
  79. int tmpfs_mkfile(struct inode* dir, const char* filename)
  80. {
  81. auto* fs = static_cast<tmpfs*>(dir->fs->impl);
  82. fs->mkfile(dir, filename);
  83. return GB_OK;
  84. }
  85. // int tmpfs_rmfile(struct inode* dir, const char* filename)
  86. // {
  87. // auto* fs = static_cast<tmpfs*>(dir->fs->impl);
  88. // fs->rmfile(dir, filename);
  89. // return GB_OK;
  90. // }
  91. int tmpfs_mkdir(struct inode* dir, const char* dirname)
  92. {
  93. auto* fs = static_cast<tmpfs*>(dir->fs->impl);
  94. fs->mkfile(dir, dirname);
  95. return GB_OK;
  96. }
  97. static const struct inode_ops tmpfs_inode_ops = {
  98. .read = tmpfs_read,
  99. .write = tmpfs_write,
  100. .readdir = tmpfs_readdir,
  101. .finddir = 0,
  102. .mkfile = tmpfs_mkfile,
  103. .rmfile = 0,
  104. .mkdir = tmpfs_mkdir,
  105. };
  106. tmpfs::tmpfs(size_t limit)
  107. : m_limit(limit)
  108. , m_fs { .ops = &tmpfs_inode_ops, .impl = this }
  109. , m_last_inode_no(0)
  110. {
  111. struct inode in = mk_inode(1, 0, 1, mk_fe_vector());
  112. mklink(&in, &in, ".");
  113. mklink(&in, &in, "..");
  114. m_inodes.push_back(in);
  115. }
  116. void tmpfs::mklink(struct inode* dir, struct inode* inode, const char* filename)
  117. {
  118. auto* fes = static_cast<vector<struct tmpfs_file_entry>*>(dir->impl);
  119. struct tmpfs_file_entry ent = {
  120. .ino = inode->ino,
  121. .filename = { 0 },
  122. };
  123. snprintf(ent.filename, sizeof(ent.filename), filename);
  124. fes->push_back(ent);
  125. }
  126. void tmpfs::mkfile(struct inode* dir, const char* filename)
  127. {
  128. struct inode file = mk_inode(0, 1, 0, mk_data_vector());
  129. m_inodes.push_back(file);
  130. mklink(dir, &file, filename);
  131. }
  132. void tmpfs::mkdir(struct inode* dir, const char* dirname)
  133. {
  134. struct inode new_dir = mk_inode(1, 0, 0, mk_fe_vector());
  135. m_inodes.push_back(new_dir);
  136. mklink(&new_dir, &new_dir, ".");
  137. mklink(dir, &new_dir, dirname);
  138. mklink(&new_dir, dir, "..");
  139. }
  140. size_t tmpfs::read(struct inode* file, char* buf, size_t buf_size, size_t offset, size_t n)
  141. {
  142. if (file->flags.file != 1)
  143. return 0;
  144. auto* data = static_cast<vector<char>*>(file->impl);
  145. size_t fsize = data->size();
  146. if (offset + n > fsize)
  147. n = fsize - offset;
  148. if (buf_size < n) {
  149. n = buf_size;
  150. }
  151. memcpy(buf, data->data() + offset, n);
  152. return n;
  153. }
  154. size_t tmpfs::write(struct inode* file, const char* buf, size_t offset, size_t n)
  155. {
  156. if (file->flags.file != 1)
  157. return 0;
  158. auto* data = static_cast<vector<char>*>(file->impl);
  159. data->at(offset + n - 1) = 0x00;
  160. memcpy(data->data() + offset, buf, n);
  161. return n;
  162. }
  163. int tmpfs::readdir(struct inode* dir, struct dirent* entry, size_t i)
  164. {
  165. if (dir->flags.directory != 1)
  166. return GB_FAILED;
  167. auto* fes = static_cast<vector<struct tmpfs_file_entry>*>(dir->impl);
  168. if (i >= fes->size())
  169. return GB_FAILED;
  170. entry->ino = fes->at(i).ino;
  171. snprintf(entry->name, sizeof(entry->name), fes->at(i).filename);
  172. return GB_OK;
  173. }
  174. // typedef int (*inode_finddir)(struct inode* dir, struct dirent* entry, const char* filename);
  175. // typedef int (*inode_rmfile)(struct inode* dir, const char* filename);
  176. size_t vfs_read(struct inode* file, char* buf, size_t buf_size, size_t offset, size_t n)
  177. {
  178. if (file->fs->ops->read) {
  179. return file->fs->ops->read(file, buf, buf_size, offset, n);
  180. } else {
  181. return 0;
  182. }
  183. }
  184. size_t vfs_write(struct inode* file, const char* buf, size_t offset, size_t n)
  185. {
  186. if (file->fs->ops->write) {
  187. return file->fs->ops->write(file, buf, offset, n);
  188. } else {
  189. return 0;
  190. }
  191. }
  192. int vfs_readdir(struct inode* dir, struct dirent* entry, size_t i)
  193. {
  194. if (dir->fs->ops->readdir) {
  195. return dir->fs->ops->readdir(dir, entry, i);
  196. } else {
  197. return 0;
  198. }
  199. }
  200. int vfs_finddir(struct inode* dir, struct dirent* entry, const char* filename)
  201. {
  202. if (dir->fs->ops->finddir) {
  203. return dir->fs->ops->finddir(dir, entry, filename);
  204. } else {
  205. return 0;
  206. }
  207. }
  208. int vfs_mkfile(struct inode* dir, const char* filename)
  209. {
  210. if (dir->fs->ops->mkfile) {
  211. return dir->fs->ops->mkfile(dir, filename);
  212. } else {
  213. return 0;
  214. }
  215. }
  216. int vfs_rmfile(struct inode* dir, const char* filename)
  217. {
  218. if (dir->fs->ops->rmfile) {
  219. return dir->fs->ops->rmfile(dir, filename);
  220. } else {
  221. return 0;
  222. }
  223. }
  224. int vfs_mkdir(struct inode* dir, const char* dirname)
  225. {
  226. if (dir->fs->ops->mkdir) {
  227. return dir->fs->ops->mkdir(dir, dirname);
  228. } else {
  229. return 0;
  230. }
  231. }
  232. struct inode* fs_root;
  233. static tmpfs* rootfs;
  234. void init_vfs(void)
  235. {
  236. rootfs = allocator_traits<kernel_allocator<tmpfs>>::allocate_and_construct(4096 * 1024);
  237. fs_root = rootfs->root_inode();
  238. vfs_mkdir(fs_root, "dev");
  239. vfs_mkdir(fs_root, "root");
  240. vfs_mkfile(fs_root, "init");
  241. struct dirent ent { };
  242. int i = 0;
  243. char buf[256];
  244. while (vfs_readdir(fs_root, &ent, i) == GB_OK) {
  245. snprintf(buf, 256, "%s: inode(%d)\n", ent.name, ent.ino);
  246. tty_print(console, buf);
  247. ++i;
  248. }
  249. }