fat.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. #include <algorithm>
  2. #include <assert.h>
  3. #include <ctype.h>
  4. #include <stdint.h>
  5. #include <stdio.h>
  6. #include <types/allocator.hpp>
  7. #include <types/status.h>
  8. #include <fs/fat.hpp>
  9. #include <kernel/mem.h>
  10. #include <kernel/mm.hpp>
  11. #include <kernel/module.hpp>
  12. #include <kernel/vfs.hpp>
  13. #define VFAT_FILENAME_LOWERCASE (0x08)
  14. #define VFAT_EXTENSION_LOWERCASE (0x10)
  15. namespace fs::fat {
  16. // buf MUST be larger than 512 bytes
  17. void fat32::_raw_read_sector(void* buf, uint32_t sector_no)
  18. {
  19. auto nread = _read_sector_range(
  20. buf, SECTOR_SIZE,
  21. sector_no, 1
  22. );
  23. assert((size_t)nread == SECTOR_SIZE);
  24. }
  25. // buf MUST be larger than 4096 bytes
  26. void fat32::_raw_read_cluster(void* buf, cluster_t no)
  27. {
  28. // data cluster start from cluster #2
  29. no -= 2;
  30. auto nread = _read_sector_range(
  31. buf, sectors_per_cluster * SECTOR_SIZE,
  32. data_region_offset + no * sectors_per_cluster,
  33. sectors_per_cluster);
  34. assert((size_t)nread == SECTOR_SIZE * sectors_per_cluster);
  35. }
  36. ssize_t fat32::_read_sector_range(void* _buf, size_t buf_size, uint32_t sector_offset, size_t sector_cnt)
  37. {
  38. buf_size &= ~(SECTOR_SIZE - 1);
  39. sector_cnt = std::min(sector_cnt, buf_size / SECTOR_SIZE);
  40. auto* buf = (char*)_buf;
  41. auto n = fs::block_device_read(device,
  42. buf, buf_size,
  43. sector_offset * SECTOR_SIZE,
  44. sector_cnt * SECTOR_SIZE
  45. );
  46. return n;
  47. }
  48. char* fat32::read_cluster(cluster_t no)
  49. {
  50. auto iter = buf.find(no);
  51. if (iter) {
  52. auto& [ idx, buf ] = *iter;
  53. ++buf.ref;
  54. return buf.data;
  55. }
  56. auto* data = new char[sectors_per_cluster * SECTOR_SIZE];
  57. _raw_read_cluster(data, no);
  58. buf.emplace(no,
  59. buf_object {
  60. data,
  61. 1,
  62. // false,
  63. });
  64. return data;
  65. }
  66. void fat32::release_cluster(cluster_t no)
  67. {
  68. auto iter = buf.find(no);
  69. if (iter)
  70. --iter->second.ref;
  71. }
  72. int fat32::readdir(fs::inode* dir, size_t offset, const fs::vfs::filldir_func& filldir)
  73. {
  74. cluster_t next = cl(dir);
  75. for (size_t i = 0; i < (offset / (sectors_per_cluster * SECTOR_SIZE)); ++i) {
  76. if (next >= EOC)
  77. return 0;
  78. next = fat[next];
  79. }
  80. size_t nread = 0;
  81. do {
  82. char* buf = read_cluster(next);
  83. auto* d = reinterpret_cast<directory_entry*>(buf) + (offset % (sectors_per_cluster * SECTOR_SIZE)) / sizeof(directory_entry);
  84. offset = 0;
  85. auto* end = d + (sectors_per_cluster * SECTOR_SIZE / sizeof(directory_entry));
  86. for (; d < end && d->filename[0]; ++d) {
  87. if (d->attributes.volume_label) {
  88. nread += sizeof(directory_entry);
  89. continue;
  90. }
  91. ino_t ino = _rearrange(d);
  92. auto* ind = get_inode(ino);
  93. if (!ind) {
  94. mode_t mode = 0777;
  95. if (d->attributes.subdir)
  96. mode |= S_IFDIR;
  97. else
  98. mode |= S_IFREG;
  99. ind = cache_inode(d->size, ino, mode, 0, 0);
  100. ind->nlink = d->attributes.subdir ? 2 : 1;
  101. }
  102. types::string<> fname;
  103. for (int i = 0; i < 8; ++i) {
  104. if (d->filename[i] == ' ')
  105. break;
  106. if (d->_reserved & VFAT_FILENAME_LOWERCASE)
  107. fname += tolower(d->filename[i]);
  108. else
  109. fname += toupper(d->filename[i]);
  110. }
  111. if (d->extension[0] != ' ')
  112. fname += '.';
  113. for (int i = 1; i < 3; ++i) {
  114. if (d->extension[i] == ' ')
  115. break;
  116. if (d->_reserved & VFAT_EXTENSION_LOWERCASE)
  117. fname += tolower(d->extension[i]);
  118. else
  119. fname += toupper(d->extension[i]);
  120. }
  121. auto ret = filldir(fname.c_str(), 0, ind, ind->mode & S_IFMT);
  122. if (ret != GB_OK) {
  123. release_cluster(next);
  124. return nread;
  125. }
  126. nread += sizeof(directory_entry);
  127. }
  128. release_cluster(next);
  129. next = fat[next];
  130. } while (next < EOC);
  131. return nread;
  132. }
  133. fat32::fat32(dev_t _device)
  134. : device { _device }
  135. , label { }
  136. {
  137. auto* buf = new char[SECTOR_SIZE];
  138. _raw_read_sector(buf, 0);
  139. auto* info = reinterpret_cast<ext_boot_sector*>(buf);
  140. sector_cnt = info->sectors_cnt;
  141. sectors_per_fat = info->sectors_per_fat;
  142. sectors_per_cluster = info->old.sectors_per_cluster;
  143. serial_number = info->serial_number;
  144. root_dir = info->root_directory;
  145. reserved_sectors = info->old.reserved_sectors;
  146. fat_copies = info->old.fat_copies;
  147. data_region_offset = reserved_sectors + fat_copies * sectors_per_fat;
  148. // read file allocation table
  149. fat.resize(SECTOR_SIZE * sectors_per_fat / sizeof(cluster_t));
  150. _read_sector_range(
  151. fat.data(), SECTOR_SIZE * sectors_per_fat,
  152. reserved_sectors, sectors_per_fat);
  153. int i = 0;
  154. while (i < 11 && info->label[i] != 0x20) {
  155. label[i] = info->label[i];
  156. ++i;
  157. }
  158. label[i] = 0x00;
  159. _raw_read_sector(buf, info->fs_info_sector);
  160. auto* fsinfo = reinterpret_cast<fs_info_sector*>(buf);
  161. free_clusters = fsinfo->free_clusters;
  162. next_free_cluster_hint = fsinfo->next_free_cluster;
  163. delete[] buf;
  164. size_t _root_dir_clusters = 1;
  165. cluster_t next = root_dir;
  166. while ((next = fat[next]) < EOC)
  167. ++_root_dir_clusters;
  168. auto* n = cache_inode(
  169. _root_dir_clusters * sectors_per_cluster * SECTOR_SIZE,
  170. root_dir, S_IFDIR | 0777, 0, 0);
  171. n->nlink = 2;
  172. register_root_node(n);
  173. }
  174. size_t fat32::read(inode* file, char* buf, size_t buf_size, size_t offset, size_t n)
  175. {
  176. cluster_t next = cl(file);
  177. uint32_t cluster_size = SECTOR_SIZE * sectors_per_cluster;
  178. size_t orig_n = n;
  179. do {
  180. if (offset == 0) {
  181. if (n > cluster_size) {
  182. auto* data = read_cluster(next);
  183. memcpy(buf, data, cluster_size);
  184. release_cluster(next);
  185. buf_size -= cluster_size;
  186. buf += cluster_size;
  187. n -= cluster_size;
  188. } else {
  189. auto* data = read_cluster(next);
  190. auto read = _write_buf_n(buf, buf_size, data, n);
  191. release_cluster(next);
  192. return orig_n - n + read;
  193. }
  194. } else {
  195. if (offset > cluster_size) {
  196. offset -= cluster_size;
  197. } else {
  198. auto* data = read_cluster(next);
  199. auto to_read = cluster_size - offset;
  200. if (to_read > n)
  201. to_read = n;
  202. auto read = _write_buf_n(buf, buf_size, data + offset, to_read);
  203. buf += read;
  204. n -= read;
  205. release_cluster(next);
  206. if (read != to_read) {
  207. return orig_n - n;
  208. }
  209. offset = 0;
  210. }
  211. }
  212. next = fat[next];
  213. } while (n && next < EOC);
  214. return orig_n - n;
  215. }
  216. int fat32::inode_statx(dentry* ent, statx* st, unsigned int mask)
  217. {
  218. st->stx_mask = 0;
  219. if (mask & STATX_SIZE) {
  220. st->stx_size = ent->ind->size;
  221. st->stx_mask |= STATX_SIZE;
  222. }
  223. if (mask & STATX_BLOCKS) {
  224. st->stx_blocks = align_up<12>(ent->ind->size) / 512;
  225. st->stx_blksize = 4096;
  226. st->stx_mask |= STATX_BLOCKS;
  227. }
  228. if (mask & STATX_NLINK) {
  229. st->stx_nlink = ent->ind->nlink;
  230. st->stx_mask |= STATX_NLINK;
  231. }
  232. st->stx_mode = 0;
  233. if (mask & STATX_MODE) {
  234. st->stx_mode |= ent->ind->mode & ~S_IFMT;
  235. st->stx_mask |= STATX_MODE;
  236. }
  237. if (mask & STATX_TYPE) {
  238. st->stx_mode |= ent->ind->mode & S_IFMT;
  239. st->stx_mask |= STATX_TYPE;
  240. }
  241. if (mask & STATX_INO) {
  242. st->stx_ino = ent->ind->ino;
  243. st->stx_mask |= STATX_INO;
  244. }
  245. if (mask & STATX_UID) {
  246. st->stx_uid = ent->ind->uid;
  247. st->stx_mask |= STATX_UID;
  248. }
  249. if (mask & STATX_GID) {
  250. st->stx_gid = ent->ind->gid;
  251. st->stx_mask |= STATX_GID;
  252. }
  253. return GB_OK;
  254. }
  255. int fat32::inode_stat(dentry* dent, struct stat* st)
  256. {
  257. auto* ind = dent->ind;
  258. memset(st, 0x00, sizeof(struct stat));
  259. st->st_mode = ind->mode;
  260. st->st_dev = device;
  261. st->st_nlink = S_ISDIR(ind->mode) ? 2 : 1;
  262. st->st_size = ind->size;
  263. st->st_blksize = 4096;
  264. st->st_blocks = (ind->size + 511) / 512;
  265. st->st_ino = ind->ino;
  266. return GB_OK;
  267. }
  268. static fat32* create_fat32(dev_t device)
  269. {
  270. return new fat32(device);
  271. }
  272. class fat32_module : public virtual kernel::module::module {
  273. public:
  274. fat32_module() : module("fat32") { }
  275. ~fat32_module()
  276. {
  277. // TODO: unregister filesystem
  278. }
  279. virtual int init() override
  280. {
  281. int ret = fs::register_fs("fat32", create_fat32);
  282. if (ret != 0)
  283. return kernel::module::MODULE_FAILED;
  284. return kernel::module::MODULE_SUCCESS;
  285. }
  286. };
  287. } // namespace fs::fat
  288. static kernel::module::module* fat32_module_init()
  289. { return new fs::fat::fat32_module; }
  290. INTERNAL_MODULE(fat32_module_loader, fat32_module_init);