vfs.cpp 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084
  1. #include <cstddef>
  2. #include <map>
  3. #include <sys/types.h>
  4. #include <vector>
  5. #include <bit>
  6. #include <utility>
  7. #include <bits/alltypes.h>
  8. #include <assert.h>
  9. #include <errno.h>
  10. #include <stdint.h>
  11. #include <stdio.h>
  12. #include <kernel/log.hpp>
  13. #include <kernel/mem.h>
  14. #include <kernel/process.hpp>
  15. #include <kernel/tty.hpp>
  16. #include <kernel/vfs.hpp>
  17. #include <types/allocator.hpp>
  18. #include <types/status.h>
  19. #include <types/path.hpp>
  20. #include <types/string.hpp>
  21. struct tmpfs_file_entry {
  22. size_t ino;
  23. char filename[128];
  24. };
  25. fs::vfs::dentry::dentry(dentry* _parent, inode* _ind, name_type _name)
  26. : parent(_parent) , ind(_ind) , flags { } , name(_name)
  27. {
  28. // the dentry is filesystem root or _ind MUST be non null
  29. assert(_ind || !_parent);
  30. if (!ind || S_ISDIR(ind->mode)) {
  31. flags.dir = 1;
  32. children = new std::list<dentry>;
  33. idx_children = new types::hash_map<name_type, dentry*>;
  34. }
  35. }
  36. fs::vfs::dentry* fs::vfs::dentry::append(inode* ind, name_type name)
  37. {
  38. auto& ent = children->emplace_back(this, ind, name);
  39. idx_children->emplace(ent.name, &ent);
  40. return &ent;
  41. }
  42. fs::vfs::dentry* fs::vfs::dentry::find(const name_type& name)
  43. {
  44. if (!flags.dir)
  45. return nullptr;
  46. if (name[0] == '.') {
  47. if (!name[1])
  48. return this;
  49. if (name[1] == '.' && !name[2])
  50. return parent ? parent : this;
  51. }
  52. if (!flags.present)
  53. ind->fs->load_dentry(this);
  54. auto iter = idx_children->find(name);
  55. if (!iter) {
  56. errno = ENOENT;
  57. return nullptr;
  58. }
  59. return iter->second;
  60. }
  61. fs::vfs::dentry* fs::vfs::dentry::replace(dentry* val)
  62. {
  63. // TODO: prevent the dirent to be swapped out of memory
  64. parent->idx_children->find(this->name)->second = val;
  65. return this;
  66. }
  67. void fs::vfs::dentry::remove(const name_type& name)
  68. {
  69. for (auto iter = children->begin(); iter != children->end(); ++iter) {
  70. if (iter->name != name)
  71. continue;
  72. children->erase(iter);
  73. break;
  74. }
  75. idx_children->remove(name);
  76. }
  77. fs::vfs::vfs()
  78. : _root { nullptr, nullptr, "" }
  79. {
  80. }
  81. void fs::vfs::dentry::path(
  82. const dentry& root, types::path &out_dst) const
  83. {
  84. const dentry* dents[32];
  85. int cnt = 0;
  86. const dentry* cur = this;
  87. while (cur != &root) {
  88. assert(cnt < 32);
  89. dents[cnt++] = cur;
  90. cur = cur->parent;
  91. }
  92. out_dst.append("/");
  93. for (int i = cnt - 1; i >= 0; --i)
  94. out_dst.append(dents[i]->name.c_str());
  95. }
  96. fs::inode* fs::vfs::cache_inode(size_t size, ino_t ino,
  97. mode_t mode, uid_t uid, gid_t gid)
  98. {
  99. auto [ iter, inserted ] =
  100. _inodes.try_emplace(ino, inode { ino, this, size, 0, mode, uid, gid });
  101. return &iter->second;
  102. }
  103. void fs::vfs::free_inode(ino_t ino)
  104. {
  105. assert(_inodes.erase(ino) == 1);
  106. }
  107. fs::inode* fs::vfs::get_inode(ino_t ino)
  108. {
  109. auto iter = _inodes.find(ino);
  110. // TODO: load inode from disk if not found
  111. if (iter)
  112. return &iter->second;
  113. else
  114. return nullptr;
  115. }
  116. void fs::vfs::register_root_node(inode* root)
  117. {
  118. if (!_root.ind)
  119. _root.ind = root;
  120. }
  121. int fs::vfs::load_dentry(dentry* ent)
  122. {
  123. auto* ind = ent->ind;
  124. if (!ent->flags.dir || !S_ISDIR(ind->mode)) {
  125. errno = ENOTDIR;
  126. return GB_FAILED;
  127. }
  128. size_t offset = 0;
  129. for (int ret = 1; ret > 0; offset += ret) {
  130. ret = this->inode_readdir(ind, offset,
  131. [ent, this](const char* name, size_t len, ino_t ino, uint8_t) -> int {
  132. if (!len)
  133. ent->append(get_inode(ino), name);
  134. else
  135. ent->append(get_inode(ino), dentry::name_type(name, len));
  136. return GB_OK;
  137. });
  138. }
  139. ent->flags.present = 1;
  140. return GB_OK;
  141. }
  142. int fs::vfs::mount(dentry* mnt, vfs* new_fs)
  143. {
  144. if (!mnt->flags.dir) {
  145. errno = ENOTDIR;
  146. return GB_FAILED;
  147. }
  148. auto* new_ent = new_fs->root();
  149. new_ent->parent = mnt->parent;
  150. new_ent->name = mnt->name;
  151. auto* orig_ent = mnt->replace(new_ent);
  152. _mount_recover_list.emplace(new_ent, orig_ent);
  153. return GB_OK;
  154. }
  155. size_t fs::vfs::inode_read(inode*, char*, size_t, size_t, size_t)
  156. { return -EINVAL; }
  157. size_t fs::vfs::inode_write(inode*, const char*, size_t, size_t)
  158. { return -EINVAL; }
  159. int fs::vfs::inode_mkfile(dentry*, const char*, mode_t)
  160. { return -EINVAL; }
  161. int fs::vfs::inode_mknode(dentry*, const char*, mode_t, dev_t)
  162. { return -EINVAL; }
  163. int fs::vfs::inode_rmfile(dentry*, const char*)
  164. { return -EINVAL; }
  165. int fs::vfs::inode_mkdir(dentry*, const char*, mode_t)
  166. { return -EINVAL; }
  167. int fs::vfs::inode_statx(dentry*, statx*, unsigned int)
  168. { return -EINVAL; }
  169. int fs::vfs::inode_stat(dentry*, struct stat*)
  170. { return -EINVAL; }
  171. int fs::vfs::inode_devid(fs::inode*, dev_t&)
  172. { return -EINVAL; }
  173. int fs::vfs::truncate(inode*, size_t)
  174. { return -EINVAL; }
  175. class tmpfs : public virtual fs::vfs {
  176. private:
  177. using fe_t = tmpfs_file_entry;
  178. using vfe_t = std::vector<fe_t>;
  179. using fdata_t = std::vector<char>;
  180. private:
  181. std::map<ino_t, void*> inode_data;
  182. ino_t _next_ino;
  183. private:
  184. ino_t _assign_ino(void)
  185. {
  186. return _next_ino++;
  187. }
  188. static constexpr vfe_t* as_vfe(void* data)
  189. {
  190. return static_cast<vfe_t*>(data);
  191. }
  192. static constexpr fdata_t* as_fdata(void* data)
  193. {
  194. return static_cast<fdata_t*>(data);
  195. }
  196. static constexpr ptr_t as_val(void* data)
  197. {
  198. return std::bit_cast<ptr_t>(data);
  199. }
  200. inline void* _getdata(ino_t ino) const
  201. {
  202. return inode_data.find(ino)->second;
  203. }
  204. inline ino_t _savedata(void* data)
  205. {
  206. ino_t ino = _assign_ino();
  207. inode_data.insert(std::make_pair(ino, data));
  208. return ino;
  209. }
  210. inline ino_t _savedata(ptr_t data)
  211. {
  212. return _savedata((void*)data);
  213. }
  214. protected:
  215. inline vfe_t* mk_fe_vector() { return new vfe_t{}; }
  216. inline fdata_t* mk_data_vector() { return new fdata_t{}; }
  217. void mklink(fs::inode* dir, fs::inode* inode, const char* filename)
  218. {
  219. auto* fes = as_vfe(_getdata(dir->ino));
  220. fes->emplace_back(fe_t {
  221. .ino = inode->ino,
  222. .filename = {} });
  223. dir->size += sizeof(fe_t);
  224. auto& emplaced = fes->back();
  225. strncpy(emplaced.filename, filename, sizeof(emplaced.filename));
  226. emplaced.filename[sizeof(emplaced.filename) - 1] = 0;
  227. ++inode->nlink;
  228. }
  229. virtual int inode_readdir(fs::inode* dir, size_t offset, const fs::vfs::filldir_func& filldir) override
  230. {
  231. if (!S_ISDIR(dir->mode)) {
  232. return -1;
  233. }
  234. auto& entries = *as_vfe(_getdata(dir->ino));
  235. size_t off = offset / sizeof(fe_t);
  236. size_t nread = 0;
  237. for (; (off + 1) <= entries.size(); ++off, nread += sizeof(fe_t)) {
  238. const auto& entry = entries[off];
  239. auto* ind = get_inode(entry.ino);
  240. // inode mode filetype is compatible with user dentry filetype
  241. auto ret = filldir(entry.filename, 0, entry.ino, ind->mode & S_IFMT);
  242. if (ret != GB_OK)
  243. break;
  244. }
  245. return nread;
  246. }
  247. public:
  248. explicit tmpfs(void)
  249. : _next_ino(1)
  250. {
  251. auto& in = *cache_inode(0, _savedata(mk_fe_vector()), S_IFDIR | 0777, 0, 0);
  252. mklink(&in, &in, ".");
  253. mklink(&in, &in, "..");
  254. register_root_node(&in);
  255. }
  256. virtual int inode_mkfile(dentry* dir, const char* filename, mode_t mode) override
  257. {
  258. if (!dir->flags.dir)
  259. return -ENOTDIR;
  260. auto& file = *cache_inode(0, _savedata(mk_data_vector()), S_IFREG | mode, 0, 0);
  261. mklink(dir->ind, &file, filename);
  262. if (dir->flags.present)
  263. dir->append(get_inode(file.ino), filename);
  264. return GB_OK;
  265. }
  266. virtual int inode_mknode(dentry* dir, const char* filename, mode_t mode, dev_t dev) override
  267. {
  268. if (!dir->flags.dir)
  269. return -ENOTDIR;
  270. if (!S_ISBLK(mode) && !S_ISCHR(mode))
  271. return -EINVAL;
  272. auto& node = *cache_inode(0, _savedata(dev), mode, 0, 0);
  273. mklink(dir->ind, &node, filename);
  274. if (dir->flags.present)
  275. dir->append(get_inode(node.ino), filename);
  276. return GB_OK;
  277. }
  278. virtual int inode_mkdir(dentry* dir, const char* dirname, mode_t mode) override
  279. {
  280. if (!dir->flags.dir)
  281. return -ENOTDIR;
  282. auto new_dir = cache_inode(0, _savedata(mk_fe_vector()), S_IFDIR | (mode & 0777), 0, 0);
  283. mklink(new_dir, new_dir, ".");
  284. mklink(dir->ind, new_dir, dirname);
  285. mklink(new_dir, dir->ind, "..");
  286. if (dir->flags.present)
  287. dir->append(new_dir, dirname);
  288. return GB_OK;
  289. }
  290. virtual size_t inode_read(fs::inode* file, char* buf, size_t buf_size, size_t offset, size_t n) override
  291. {
  292. if (!S_ISREG(file->mode))
  293. return 0;
  294. auto* data = as_fdata(_getdata(file->ino));
  295. size_t fsize = data->size();
  296. if (offset + n > fsize)
  297. n = fsize - offset;
  298. if (buf_size < n) {
  299. n = buf_size;
  300. }
  301. memcpy(buf, data->data() + offset, n);
  302. return n;
  303. }
  304. virtual size_t inode_write(fs::inode* file, const char* buf, size_t offset, size_t n) override
  305. {
  306. if (!S_ISREG(file->mode))
  307. return 0;
  308. auto* data = as_fdata(_getdata(file->ino));
  309. if (data->size() < offset + n)
  310. data->resize(offset+n);
  311. memcpy(data->data() + offset, buf, n);
  312. file->size = data->size();
  313. return n;
  314. }
  315. virtual int inode_statx(dentry* dent, statx* st, unsigned int mask) override
  316. {
  317. auto* ind = dent->ind;
  318. const mode_t mode = ind->mode;
  319. st->stx_mask = 0;
  320. if (mask & STATX_NLINK) {
  321. st->stx_nlink = ind->nlink;
  322. st->stx_mask |= STATX_NLINK;
  323. }
  324. // TODO: set modification time
  325. if (mask & STATX_MTIME) {
  326. st->stx_mtime = {};
  327. st->stx_mask |= STATX_MTIME;
  328. }
  329. if (mask & STATX_SIZE) {
  330. st->stx_size = ind->size;
  331. st->stx_mask |= STATX_SIZE;
  332. }
  333. st->stx_mode = 0;
  334. if (mask & STATX_MODE) {
  335. st->stx_mode |= ind->mode & ~S_IFMT;
  336. st->stx_mask |= STATX_MODE;
  337. }
  338. if (mask & STATX_TYPE) {
  339. st->stx_mode |= ind->mode & S_IFMT;
  340. if (S_ISBLK(mode) || S_ISCHR(mode)) {
  341. auto nd = (dev_t)as_val(_getdata(ind->ino));
  342. st->stx_rdev_major = NODE_MAJOR(nd);
  343. st->stx_rdev_minor = NODE_MINOR(nd);
  344. }
  345. st->stx_mask |= STATX_TYPE;
  346. }
  347. if (mask & STATX_INO) {
  348. st->stx_ino = ind->ino;
  349. st->stx_mask |= STATX_INO;
  350. }
  351. if (mask & STATX_BLOCKS) {
  352. st->stx_blocks = align_up<9>(ind->size) / 512;
  353. st->stx_blksize = 4096;
  354. st->stx_mask |= STATX_BLOCKS;
  355. }
  356. if (mask & STATX_UID) {
  357. st->stx_uid = ind->uid;
  358. st->stx_mask |= STATX_UID;
  359. }
  360. if (mask & STATX_GID) {
  361. st->stx_gid = ind->gid;
  362. st->stx_mask |= STATX_GID;
  363. }
  364. return GB_OK;
  365. }
  366. virtual int inode_rmfile(dentry* dir, const char* filename) override
  367. {
  368. if (!dir->flags.dir)
  369. return -ENOTDIR;
  370. auto* vfe = as_vfe(_getdata(dir->ind->ino));
  371. assert(vfe);
  372. auto* dent = dir->find(filename);
  373. if (!dent)
  374. return -ENOENT;
  375. for (auto iter = vfe->begin(); iter != vfe->end(); ) {
  376. if (iter->ino != dent->ind->ino) {
  377. ++iter;
  378. continue;
  379. }
  380. if (S_ISREG(dent->ind->mode)) {
  381. // since we do not allow hard links in tmpfs, there is no need
  382. // to check references, we remove the file data directly
  383. auto* filedata = as_fdata(_getdata(iter->ino));
  384. assert(filedata);
  385. delete filedata;
  386. }
  387. free_inode(iter->ino);
  388. dir->remove(filename);
  389. vfe->erase(iter);
  390. return 0;
  391. }
  392. kmsg("[tmpfs] warning: file entry not found in vfe\n");
  393. return -EIO;
  394. }
  395. virtual int inode_devid(fs::inode* file, dev_t& out_dev) override
  396. {
  397. out_dev = as_val(_getdata(file->ino));
  398. return 0;
  399. }
  400. virtual int truncate(fs::inode* file, size_t size) override
  401. {
  402. if (!S_ISREG(file->mode))
  403. return -EINVAL;
  404. auto* data = as_fdata(_getdata(file->ino));
  405. data->resize(size);
  406. file->size = size;
  407. return GB_OK;
  408. }
  409. };
  410. fs::regular_file::regular_file(vfs::dentry* parent,
  411. file_flags flags, size_t cursor, inode* ind)
  412. : file(ind->mode, parent, flags), cursor(cursor), ind(ind) { }
  413. ssize_t fs::regular_file::read(char* __user buf, size_t n)
  414. {
  415. if (!flags.read)
  416. return -EBADF;
  417. if (S_ISDIR(ind->mode))
  418. return -EISDIR;
  419. // TODO: copy to user function !IMPORTANT
  420. ssize_t n_wrote = fs::vfs_read(ind, buf, n, cursor, n);
  421. if (n_wrote >= 0)
  422. cursor += n_wrote;
  423. return n_wrote;
  424. }
  425. ssize_t fs::regular_file::do_write(const char* __user buf, size_t n)
  426. {
  427. if (S_ISDIR(mode))
  428. return -EISDIR;
  429. // TODO: check privilege of user ptr
  430. ssize_t n_wrote = fs::vfs_write(ind, buf, cursor, n);
  431. if (n_wrote >= 0)
  432. cursor += n_wrote;
  433. return n_wrote;
  434. }
  435. ssize_t fs::regular_file::seek(off_t n, int whence)
  436. {
  437. if (!S_ISREG(mode))
  438. return -ESPIPE;
  439. size_t pos;
  440. switch (whence) {
  441. case SEEK_SET:
  442. pos = n;
  443. break;
  444. case SEEK_CUR:
  445. pos = cursor + n;
  446. break;
  447. case SEEK_END:
  448. pos = ind->size + n;
  449. break;
  450. }
  451. if (pos > ind->size)
  452. return -EINVAL;
  453. cursor = pos;
  454. return cursor;
  455. }
  456. int fs::regular_file::getdents(char* __user buf, size_t cnt)
  457. {
  458. if (!S_ISDIR(ind->mode))
  459. return -ENOTDIR;
  460. size_t orig_cnt = cnt;
  461. int nread = ind->fs->inode_readdir(ind, cursor,
  462. [&buf, &cnt](const char* fn, size_t len, ino_t ino, uint8_t type) {
  463. if (!len)
  464. len = strlen(fn);
  465. size_t reclen = sizeof(fs::user_dirent) + 1 + len;
  466. if (cnt < reclen)
  467. return GB_FAILED;
  468. auto* dirp = (fs::user_dirent*)buf;
  469. dirp->d_ino = ino;
  470. dirp->d_reclen = reclen;
  471. // TODO: show offset
  472. // dirp->d_off = 0;
  473. // TODO: use copy_to_user
  474. memcpy(dirp->d_name, fn, len);
  475. buf[reclen - 2] = 0;
  476. buf[reclen - 1] = type;
  477. buf += reclen;
  478. cnt -= reclen;
  479. return GB_OK;
  480. });
  481. if (nread > 0)
  482. cursor += nread;
  483. return orig_cnt - cnt;
  484. }
  485. int fs::regular_file::getdents64(char* __user buf, size_t cnt)
  486. {
  487. if (!S_ISDIR(ind->mode))
  488. return -ENOTDIR;
  489. size_t orig_cnt = cnt;
  490. int nread = ind->fs->inode_readdir(ind, cursor,
  491. [&buf, &cnt](const char* fn, size_t len, ino_t ino, uint8_t type) {
  492. if (!len)
  493. len = strlen(fn);
  494. size_t reclen = sizeof(fs::user_dirent64) + len;
  495. if (cnt < reclen)
  496. return GB_FAILED;
  497. auto* dirp = (fs::user_dirent64*)buf;
  498. dirp->d_ino = ino;
  499. dirp->d_off = 114514;
  500. dirp->d_reclen = reclen;
  501. dirp->d_type = type;
  502. // TODO: use copy_to_user
  503. memcpy(dirp->d_name, fn, len);
  504. buf[reclen - 1] = 0;
  505. buf += reclen;
  506. cnt -= reclen;
  507. return GB_OK;
  508. });
  509. if (nread > 0)
  510. cursor += nread;
  511. return orig_cnt - cnt;
  512. }
  513. fs::fifo_file::fifo_file(vfs::dentry* parent, file_flags flags,
  514. std::shared_ptr<fs::pipe> ppipe)
  515. : file(S_IFIFO, parent, flags), ppipe(ppipe) { }
  516. ssize_t fs::fifo_file::read(char* __user buf, size_t n)
  517. {
  518. if (!flags.read)
  519. return -EBADF;
  520. return ppipe->read(buf, n);
  521. }
  522. ssize_t fs::fifo_file::do_write(const char* __user buf, size_t n)
  523. {
  524. return ppipe->write(buf, n);
  525. }
  526. fs::fifo_file::~fifo_file()
  527. {
  528. assert(flags.read ^ flags.write);
  529. if (flags.read)
  530. ppipe->close_read();
  531. else
  532. ppipe->close_write();
  533. }
  534. static std::map<dev_t, fs::blkdev_ops> blkdevs;
  535. static std::map<dev_t, fs::chrdev_ops> chrdevs;
  536. size_t fs::vfs_read(fs::inode* file, char* buf, size_t buf_size, size_t offset, size_t n)
  537. {
  538. if (S_ISDIR(file->mode)) {
  539. errno = EISDIR;
  540. return -1U;
  541. }
  542. if (S_ISREG(file->mode))
  543. return file->fs->inode_read(file, buf, buf_size, offset, n);
  544. if (S_ISBLK(file->mode) || S_ISCHR(file->mode)) {
  545. dev_t dev;
  546. if (file->fs->inode_devid(file, dev) != 0) {
  547. errno = EINVAL;
  548. return -1U;
  549. }
  550. ssize_t ret;
  551. if (S_ISBLK(file->mode))
  552. ret = block_device_read(dev, buf, buf_size, offset, n);
  553. else
  554. ret = char_device_read(dev, buf, buf_size, n);
  555. if (ret < 0) {
  556. errno = -ret;
  557. return -1U;
  558. }
  559. return ret;
  560. }
  561. errno = EINVAL;
  562. return -1U;
  563. }
  564. size_t fs::vfs_write(fs::inode* file, const char* buf, size_t offset, size_t n)
  565. {
  566. if (S_ISDIR(file->mode)) {
  567. errno = EISDIR;
  568. return -1U;
  569. }
  570. if (S_ISREG(file->mode))
  571. return file->fs->inode_write(file, buf, offset, n);
  572. if (S_ISBLK(file->mode) || S_ISCHR(file->mode)) {
  573. dev_t dev;
  574. if (file->fs->inode_devid(file, dev) != 0) {
  575. errno = EINVAL;
  576. return -1U;
  577. }
  578. ssize_t ret;
  579. if (S_ISBLK(file->mode))
  580. ret = block_device_write(dev, buf, offset, n);
  581. else
  582. ret = char_device_write(dev, buf, n);
  583. if (ret < 0) {
  584. errno = -ret;
  585. return -1U;
  586. }
  587. return ret;
  588. }
  589. errno = EINVAL;
  590. return -1U;
  591. }
  592. int fs::vfs_mkfile(fs::vfs::dentry* dir, const char* filename, mode_t mode)
  593. {
  594. return dir->ind->fs->inode_mkfile(dir, filename, mode);
  595. }
  596. int fs::vfs_mknode(fs::vfs::dentry* dir, const char* filename, mode_t mode, dev_t dev)
  597. {
  598. return dir->ind->fs->inode_mknode(dir, filename, mode, dev);
  599. }
  600. int fs::vfs_rmfile(fs::vfs::dentry* dir, const char* filename)
  601. {
  602. return dir->ind->fs->inode_rmfile(dir, filename);
  603. }
  604. int fs::vfs_mkdir(fs::vfs::dentry* dir, const char* dirname, mode_t mode)
  605. {
  606. return dir->ind->fs->inode_mkdir(dir, dirname, mode);
  607. }
  608. fs::vfs::dentry* fs::vfs_open(fs::vfs::dentry& root, const types::path& path)
  609. {
  610. fs::vfs::dentry* cur = &root;
  611. for (const auto& item : path) {
  612. if (item.empty())
  613. continue;
  614. cur = cur->find(item);
  615. if (!cur)
  616. return nullptr;
  617. }
  618. return cur;
  619. }
  620. int fs::vfs_stat(fs::vfs::dentry* ent, statx* stat, unsigned int mask)
  621. {
  622. return ent->ind->fs->inode_statx(ent, stat, mask);
  623. }
  624. int fs::vfs_truncate(inode *file, size_t size)
  625. {
  626. return file->fs->truncate(file, size);
  627. }
  628. static std::list<fs::vfs*, types::memory::ident_allocator<fs::vfs*>> fs_es;
  629. int fs::register_block_device(dev_t node, fs::blkdev_ops ops)
  630. {
  631. auto iter = blkdevs.find(node);
  632. if (iter)
  633. return -EEXIST;
  634. std::tie(iter, std::ignore) = blkdevs.emplace(node, std::move(ops));
  635. return 0;
  636. }
  637. int fs::register_char_device(dev_t node, fs::chrdev_ops ops)
  638. {
  639. auto iter = chrdevs.find(node);
  640. if (iter)
  641. return -EEXIST;
  642. std::tie(iter, std::ignore) = chrdevs.emplace(node, std::move(ops));
  643. return 0;
  644. }
  645. // MBR partition table, used by partprobe()
  646. struct PACKED mbr_part_entry {
  647. uint8_t attr;
  648. uint8_t chs_start[3];
  649. uint8_t type;
  650. uint8_t chs_end[3];
  651. uint32_t lba_start;
  652. uint32_t cnt;
  653. };
  654. struct PACKED mbr {
  655. uint8_t code[440];
  656. uint32_t signature;
  657. uint16_t reserved;
  658. mbr_part_entry parts[4];
  659. uint16_t magic;
  660. };
  661. static inline void mbr_part_probe(dev_t node, char ch)
  662. {
  663. mbr buf_mbr;
  664. // TODO: devtmpfs
  665. auto* dev = fs::vfs_open(*fs::fs_root, "/dev");
  666. if (!dev)
  667. return;
  668. char label[] = "sda1";
  669. label[2] = ch;
  670. auto ret = fs::block_device_read(node, (char*)&buf_mbr, sizeof(mbr), 0, 512);
  671. if (ret < 0) {
  672. kmsg("[kernel] cannot read device for part probing.\n");
  673. return;
  674. }
  675. int n = 1;
  676. for (const auto& part : buf_mbr.parts) {
  677. if (n >= 8)
  678. break;
  679. if (!part.type)
  680. continue;
  681. std::size_t part_offset = part.lba_start * 512;
  682. // TODO: add partition offset limit
  683. fs::register_block_device(node + n, {
  684. [=](char* buf, size_t buf_size, size_t offset, size_t n) -> ssize_t {
  685. offset += part_offset;
  686. return fs::block_device_read(node, buf, buf_size, offset, n);
  687. },
  688. [=](const char* buf, size_t offset, size_t n) -> ssize_t {
  689. offset += part_offset;
  690. return fs::block_device_write(node, buf, offset, n);
  691. }
  692. });
  693. ret = fs::vfs_mknode(dev, label, 0660 | S_IFBLK, node + n);
  694. ++n, ++label[3];
  695. }
  696. }
  697. void fs::partprobe()
  698. {
  699. auto* dev = fs::vfs_open(*fs::fs_root, "/dev");
  700. if (!dev)
  701. return;
  702. char ch = 'a';
  703. char name[] = "sd*";
  704. types::string<> path = "/dev/sd*";
  705. for (const auto& device : blkdevs) {
  706. // only the devices whose minor number is a multiple of 8
  707. // are considered as a disk instead of partitions
  708. if (NODE_MINOR(device.first) % 8 != 0)
  709. continue;
  710. path.pop();
  711. path += ch;
  712. name[2] = ch;
  713. auto* blkfile = fs::vfs_open(*fs::fs_root, path.c_str());
  714. if (!blkfile)
  715. vfs_mknode(dev, name, 0660 | S_IFBLK, device.first);
  716. mbr_part_probe(device.first, ch);
  717. ++ch;
  718. }
  719. }
  720. ssize_t fs::block_device_read(dev_t node, char* buf, size_t buf_size, size_t offset, size_t n)
  721. {
  722. auto iter = blkdevs.find(node);
  723. if (!iter || !iter->second.read)
  724. return -EINVAL;
  725. return iter->second.read(buf, buf_size, offset, n);
  726. }
  727. ssize_t fs::block_device_write(dev_t node, const char* buf, size_t offset, size_t n)
  728. {
  729. auto iter = blkdevs.find(node);
  730. if (!iter || !iter->second.write)
  731. return -EINVAL;
  732. return iter->second.write(buf, offset, n);
  733. }
  734. ssize_t fs::char_device_read(dev_t node, char* buf, size_t buf_size, size_t n)
  735. {
  736. auto iter = chrdevs.find(node);
  737. if (!iter || !iter->second.read)
  738. return -EINVAL;
  739. return iter->second.read(buf, buf_size, n);
  740. }
  741. ssize_t fs::char_device_write(dev_t node, const char* buf, size_t n)
  742. {
  743. auto iter = chrdevs.find(node);
  744. if (!iter || !iter->second.read)
  745. return -EINVAL;
  746. return iter->second.write(buf, n);
  747. }
  748. fs::vfs* fs::register_fs(vfs* fs)
  749. {
  750. fs_es.push_back(fs);
  751. return fs;
  752. }
  753. ssize_t b_null_read(char* buf, size_t buf_size, size_t n)
  754. {
  755. if (n >= buf_size)
  756. n = buf_size;
  757. memset(buf, 0x00, n);
  758. return n;
  759. }
  760. ssize_t b_null_write(const char*, size_t n)
  761. {
  762. return n;
  763. }
  764. static ssize_t console_read(char* buf, size_t buf_size, size_t n)
  765. {
  766. return console->read(buf, buf_size, n);
  767. }
  768. static ssize_t console_write(const char* buf, size_t n)
  769. {
  770. size_t orig_n = n;
  771. while (n--)
  772. console->putchar(*(buf++));
  773. return orig_n;
  774. }
  775. fs::pipe::pipe(void)
  776. : buf { PIPE_SIZE }
  777. , flags { READABLE | WRITABLE }
  778. {
  779. }
  780. void fs::pipe::close_read(void)
  781. {
  782. {
  783. types::lock_guard lck(m_cv.mtx());
  784. flags &= (~READABLE);
  785. }
  786. m_cv.notify_all();
  787. }
  788. void fs::pipe::close_write(void)
  789. {
  790. {
  791. types::lock_guard lck(m_cv.mtx());
  792. flags &= (~WRITABLE);
  793. }
  794. m_cv.notify_all();
  795. }
  796. int fs::pipe::write(const char* buf, size_t n)
  797. {
  798. // TODO: check privilege
  799. // TODO: check EPIPE
  800. {
  801. auto& mtx = m_cv.mtx();
  802. types::lock_guard lck(mtx);
  803. if (!is_readable()) {
  804. current_thread->send_signal(SIGPIPE);
  805. return -EPIPE;
  806. }
  807. while (this->buf.avail() < n) {
  808. if (!m_cv.wait(mtx))
  809. return -EINTR;
  810. if (!is_readable()) {
  811. current_thread->send_signal(SIGPIPE);
  812. return -EPIPE;
  813. }
  814. }
  815. for (size_t i = 0; i < n; ++i)
  816. this->buf.put(*(buf++));
  817. }
  818. m_cv.notify();
  819. return n;
  820. }
  821. int fs::pipe::read(char* buf, size_t n)
  822. {
  823. // TODO: check privilege
  824. {
  825. auto& mtx = m_cv.mtx();
  826. types::lock_guard lck(mtx);
  827. if (!is_writeable()) {
  828. size_t orig_n = n;
  829. while (!this->buf.empty() && n--)
  830. *(buf++) = this->buf.get();
  831. return orig_n - n;
  832. }
  833. while (this->buf.size() < n) {
  834. if (!m_cv.wait(mtx))
  835. return -EINTR;
  836. if (!is_writeable()) {
  837. size_t orig_n = n;
  838. while (!this->buf.empty() && n--)
  839. *(buf++) = this->buf.get();
  840. return orig_n - n;
  841. }
  842. }
  843. for (size_t i = 0; i < n; ++i)
  844. *(buf++) = this->buf.get();
  845. }
  846. m_cv.notify();
  847. return n;
  848. }
  849. SECTION(".text.kinit")
  850. void init_vfs(void)
  851. {
  852. using namespace fs;
  853. // null
  854. register_char_device(make_device(1, 0), { b_null_read, b_null_write });
  855. // console (supports serial console only for now)
  856. // TODO: add interface to bind console device to other devices
  857. register_char_device(make_device(2, 0), { console_read, console_write });
  858. auto* rootfs = new tmpfs;
  859. fs_es.push_back(rootfs);
  860. fs_root = rootfs->root();
  861. vfs_mkdir(fs_root, "dev", 0755);
  862. vfs_mkdir(fs_root, "mnt", 0755);
  863. vfs_mkfile(fs_root, "init", 0755);
  864. auto* init = vfs_open(*fs_root, "/init");
  865. assert(init);
  866. const char* str = "#!/mnt/busybox sh\n"
  867. "cd /\n"
  868. "busybox mkdir etc\n"
  869. "busybox mkdir root\n"
  870. "busybox cat > /etc/passwd <<EOF\n"
  871. "root:x:0:0:root:/root:/mnt/busybox_ sh\n"
  872. "EOF\n"
  873. "busybox cat > /etc/group <<EOF\n"
  874. "root:x:0:root\n"
  875. "EOF\n"
  876. "exec /mnt/init /mnt/busybox_ sh < /dev/console"
  877. " >> /dev/console 2>>/dev/console\n";
  878. vfs_write(init->ind, str, 0, strlen(str));
  879. auto* dev = vfs_open(*fs_root, "/dev");
  880. assert(dev);
  881. vfs_mknode(dev, "null", 0666 | S_IFCHR, make_device(1, 0));
  882. vfs_mknode(dev, "console", 0666 | S_IFCHR, make_device(2, 0));
  883. }