Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

893 Zeilen
32 KiB

  1. #ifndef LSFS_DISK_CONTROLLER_H
  2. #define LSFS_DISK_CONTROLLER_H
  3. #include <errno.h>
  4. #include <assert.h>
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <stdint.h>
  9. #include <stdbool.h>
  10. #include <time.h>
  11. #include <unistd.h>
  12. #include "lsfs_string.h"
  13. typedef struct Directory_Table Directory_Table;
  14. typedef struct struct_table_entry struct_table_entry;
  15. typedef struct struct_partition_control partition_control;
  16. typedef struct File_System_Control_Information FSCI;
  17. typedef struct meta_information_format mif;
  18. typedef struct tag_record tag_record;
  19. typedef struct lsfs_file lsfs_file;
  20. typedef uint64_t lsfs_sector_offset;
  21. typedef lsfs_sector_offset lsfs_file_id;
  22. typedef enum
  23. {
  24. // These are specific values since, is has to corrospond to the implementation in assembly
  25. ENTRY_EMPTY = 0,
  26. ENTRY_FILE = 1,
  27. ENTRY_DIRECTORY = 2,
  28. } Table_Entry_Kind;
  29. //typedef uint64_t sector_index;
  30. static FILE* disk = NULL;
  31. static partition_control p_control;
  32. static time_t timestamp_loading;
  33. int create_file_system(char* disk_name, char hdd_or_partition, uint64_t filesystem_size_in_MB);
  34. int lsfs_disk_create_entry(const char* path, Table_Entry_Kind entry_kind);
  35. Directory_Table* lsfs_find_directory(const char* path, bool drop_filename);
  36. int lsfs_disk_getattr(lsfs_file* find_file, const char *path);
  37. int lsfs_disk_delete_entry(lsfs_file *file);
  38. int get_free_sectors_table();
  39. int get_free_sectors(int num_sectors_needed, struct_table_entry* table_entry);
  40. int lsfs_disk_read_data_from_file(lsfs_file *file, int data_length, char *data, int64_t offset_to_next_entry);
  41. int lsfs_disk_write_data_to_file(lsfs_file* file, int data_length, char *data, int64_t offset_to_next_entry);
  42. int lsfs_disk_rename_file(const char* old_filename_, const char* new_filename);
  43. int lsfs_disk_load_disk(char* diskname);
  44. int write_data_to_disk(lsfs_sector_offset at_sector, uint32_t number_sectors, void* data_to_write);
  45. int write_data_to_disk_off(lsfs_sector_offset index, uint32_t number_sectors, void* data_to_write, int offset);
  46. int read_data_from_disk(lsfs_sector_offset index, uint32_t number_sectors, void* data_buffer);
  47. int read_data_from_disk_off(lsfs_sector_offset index, uint32_t number_sectors, void* data_to_write, int offset);
  48. int save_modified_file_information(lsfs_file* file);
  49. #define SPACE_MBR_RECORD 32 // 2048 // Sectors
  50. #define SPACE_VBR_RECORD 32 // 2048 // Sectors
  51. #define SIZE_FSCI_RECORD 1 // Sectors
  52. #define DEFAULT_ENTRY_SIZE 1 // Sectors
  53. #define SECTOR_SIZE 512 // BYTES
  54. #define NUMBER_OF_MBR_PARTITIONS 4
  55. #define DEFAULT_DATA_POINTER_SIZE 8 // This is in sectors
  56. #define DEFAULT_TABLE_SIZE 8 // 16
  57. #define NUM_DATA_POINTERS 27
  58. typedef struct Partition_Entry
  59. {
  60. uint8_t active_falg; // This has value 0x80 if it is a bootable partition / it is an active partition.
  61. uint8_t CHS_start_addr[3]; // [0] = H, [1] = S, [2] = C
  62. uint8_t partition_type; // This has a value such that one can idenfity which file system the partition is.
  63. uint8_t CHS_last_addr[3]; // [0] = H, [1] = S, [2] = C
  64. uint32_t LBA_abs_first_sector;
  65. uint32_t number_of_sectors;
  66. } __attribute__((packed)) Partition_Entry;
  67. typedef struct Master_Boot_record
  68. {
  69. uint8_t code[446]; // The code for the bootloader
  70. Partition_Entry partitions[4];
  71. uint16_t mbr_signature; // Signature
  72. } __attribute__((packed)) Master_Boot_record;
  73. typedef struct Volume_Boot_record
  74. {
  75. uint8_t code[446]; // The code for the bootloader
  76. uint64_t vbr_size_in_bytes; // Signature
  77. uint64_t vbr_LBA_address;
  78. uint64_t vbr_LBA_FSCI_position;
  79. uint64_t not_used[5];
  80. uint16_t vbr_signature; // Signature
  81. } __attribute__((packed)) Volume_Boot_record;
  82. typedef struct struct_table_entry
  83. {
  84. char filename[256];
  85. lsfs_file_id file_id;
  86. uint64_t file_size;
  87. mif* ext_file_data;
  88. uint32_t number_sectors; // This tells how many block there are allocated for the specific file. eg. we read this amount of bloks for the file.
  89. uint8_t entry_kind;
  90. uint8_t extra_control_bits1;
  91. uint8_t extra_control_bits2;
  92. uint8_t extra_control_bits3;
  93. lsfs_sector_offset table_entry_sector_index;
  94. lsfs_sector_offset data_pointer[NUM_DATA_POINTERS]; // if it is a directory, the first pointer will be to the next table.
  95. } __attribute__((packed)) Table_Entry;
  96. typedef struct Directory_Table
  97. {
  98. struct_table_entry entries[DEFAULT_TABLE_SIZE];
  99. } __attribute__((packed)) Directory_Table;
  100. typedef struct File_System_Control_Information
  101. {
  102. char filesystem_information[256];
  103. lsfs_sector_offset master_table_index;
  104. lsfs_sector_offset this_partition_offset_on_disk;
  105. lsfs_sector_offset next_free_sector;
  106. uint64_t next_uniqe_id; // both files and directories gets this.
  107. lsfs_sector_offset next_sector_reuse_pointer;
  108. lsfs_sector_offset last_sector_index_on_partition;
  109. lsfs_sector_offset maximum_sectors_on_disk;
  110. lsfs_sector_offset sector_size_on_disk;
  111. uint64_t not_used[24];
  112. } __attribute__((packed)) FSCI;
  113. typedef struct struct_partition_control
  114. {
  115. FSCI fsci;
  116. Directory_Table master_table;
  117. } __attribute__((packed)) partition_control;
  118. typedef struct meta_information_format {
  119. char filename[246]; // remeber that the 246 bytes has to be a /0 terminator..
  120. uint32_t owner_id;
  121. lsfs_file_id tags[32];
  122. uint64_t file_size;
  123. uint32_t control_bits;
  124. /* not pressent - Permission key table 64 bytes sha-265 pr. key*/
  125. uint64_t creation_date;
  126. uint64_t last_modification_data;
  127. uint64_t last_access_date;
  128. /*
  129. * 256 first pointers in direct mapping to data
  130. * 94 next pointers is a pointer
  131. * 94 next pointers to pointers to data
  132. */
  133. lsfs_sector_offset one_level_pointer_data[NUM_DATA_POINTERS];
  134. lsfs_sector_offset two_level_pointer_data[94];
  135. lsfs_sector_offset three_level_pointer_data[94];
  136. } __attribute__((packed)) mif;
  137. typedef struct tag_record {
  138. /* SIZE 16 bytes */
  139. lsfs_file_id mif_record;
  140. struct {
  141. uint64_t is_filename : 1;
  142. } control_bits;
  143. } __attribute__((packed)) tag_record;
  144. typedef struct lsfs_file {
  145. lsfs_file_id file_id;
  146. lsfs_sector_offset table_entry_pointer;
  147. struct_table_entry* table_backpointer;
  148. Table_Entry_Kind entry_kind;
  149. char* filename;
  150. uint32_t owner_id;
  151. uint64_t size;
  152. uint64_t creation_date;
  153. uint64_t access_time;
  154. uint64_t modification_time;
  155. uint32_t number_sectors;
  156. lsfs_sector_offset table_entry_sector_index;
  157. lsfs_sector_offset data_pointer[NUM_DATA_POINTERS];
  158. } lsfs_file;
  159. Directory_Table* lsfs_find_directory(const char *path, bool drop_filename)
  160. {
  161. Directory_Table *dir_table = calloc(1, sizeof(Directory_Table));
  162. // printf("Table index: %lu \n",p_control.fsci.master_table_index );
  163. read_data_from_disk(p_control.fsci.master_table_index, DEFAULT_TABLE_SIZE, dir_table);
  164. lsfs_string_array split_path = lsfs_string_split_c(path, '/', false);
  165. int number_of_traversal = split_path.length;
  166. if (drop_filename)
  167. {
  168. number_of_traversal -= 1;
  169. }
  170. // Start from the master table
  171. for (int i = 0; i < number_of_traversal; ++i)
  172. {
  173. for (int j = 0; j < DEFAULT_TABLE_SIZE; ++j)
  174. {
  175. if (strcmp(dir_table->entries[j].filename, split_path.strings[i].chars) == 0)
  176. {
  177. int index_sector = dir_table->entries[j].data_pointer[0];
  178. // printf("Table index: %lu \n",index_sector );
  179. read_data_from_disk(index_sector, DEFAULT_TABLE_SIZE, dir_table);
  180. break;
  181. }
  182. }
  183. }
  184. return dir_table;
  185. }
  186. int lsfs_disk_getattr(lsfs_file* find_file, const char* path) {
  187. lsfs_string_array split_path = lsfs_string_split_c(path, '/', false);
  188. lsfs_string filename = split_path.strings[split_path.length-1];
  189. // Start from the master table
  190. Directory_Table *dir_table = lsfs_find_directory(path, true);
  191. for (int i = 0; i < DEFAULT_TABLE_SIZE; ++i)
  192. {
  193. if(strcmp( filename.chars, dir_table->entries[i].filename ) == 0)
  194. {
  195. find_file->table_backpointer = &(dir_table->entries[i]);
  196. find_file->file_id = dir_table->entries[i].file_id;
  197. find_file->entry_kind = dir_table->entries[i].entry_kind;
  198. find_file->table_entry_pointer = i;
  199. find_file->filename = dir_table->entries[i].filename;
  200. find_file->table_entry_sector_index = dir_table->entries[i].table_entry_sector_index;
  201. find_file->owner_id = getuid();
  202. find_file->size = dir_table->entries[i].file_size; // dir_table->entries[i].data_pointer[0]; //;
  203. find_file->creation_date = (uint64_t) timestamp_loading;
  204. find_file->access_time = (uint64_t) timestamp_loading;
  205. find_file->modification_time = (uint64_t) timestamp_loading;
  206. memcpy(find_file->data_pointer, dir_table->entries[i].data_pointer, NUM_DATA_POINTERS * 8);
  207. find_file->number_sectors = 1; // TODO: should be loaded from disk.
  208. return 1;
  209. }
  210. }
  211. return 0;
  212. }
  213. int lsfs_disk_read_data_from_file(lsfs_file *file, int buffer_size, char *data, int64_t offset_to_next_entry)
  214. {
  215. int data_length = file->size - offset_to_next_entry;
  216. int amount_read = 0;
  217. int amount_to_read = 0;
  218. int remaining_offset = offset_to_next_entry;
  219. //printf("READ: buffer_size: %d\n", buffer_size);
  220. //printf("READ: Data length: %d\n", data_length);
  221. //printf("READ: Offset length: %d\n", offset_to_next_entry);
  222. int data_pointer_index = 0; // start at first data pointer.
  223. if (data_length > buffer_size)
  224. {
  225. data_length = buffer_size;
  226. }
  227. while(data_length > 0) // We have more to write
  228. {
  229. //printf("READ: Remaing Data length: %d\n", data_length);
  230. if (remaining_offset == 0)
  231. {
  232. char *tmp_buffer = calloc(DEFAULT_DATA_POINTER_SIZE, SECTOR_SIZE);
  233. assert(tmp_buffer);
  234. if (data_length < (DEFAULT_DATA_POINTER_SIZE * SECTOR_SIZE))
  235. {
  236. amount_to_read = data_length;
  237. }
  238. else
  239. {
  240. amount_to_read = (DEFAULT_DATA_POINTER_SIZE * SECTOR_SIZE);
  241. }
  242. //read_data_from_disk(lsfs_sector_offset index, uint32_t number_sectors, void* data_buffer)
  243. if (file->data_pointer[data_pointer_index] == 0)
  244. {
  245. break;
  246. }
  247. read_data_from_disk(file->data_pointer[data_pointer_index], DEFAULT_DATA_POINTER_SIZE, tmp_buffer);
  248. memcpy((data + amount_read), tmp_buffer, amount_to_read);
  249. data_length -= amount_to_read;
  250. amount_read += amount_to_read;
  251. data_pointer_index++;
  252. free(tmp_buffer);
  253. }
  254. else if (remaining_offset < (DEFAULT_DATA_POINTER_SIZE * SECTOR_SIZE))
  255. {
  256. char *tmp_buffer = calloc(1, (DEFAULT_DATA_POINTER_SIZE * SECTOR_SIZE));
  257. assert(tmp_buffer);
  258. if (data_length < ((DEFAULT_DATA_POINTER_SIZE * SECTOR_SIZE) - remaining_offset) )
  259. {
  260. amount_to_read = data_length;
  261. }
  262. else
  263. {
  264. amount_to_read = ((DEFAULT_DATA_POINTER_SIZE * SECTOR_SIZE) - remaining_offset);
  265. }
  266. read_data_from_disk(file->data_pointer[data_pointer_index], DEFAULT_DATA_POINTER_SIZE, tmp_buffer);
  267. memcpy(data, (tmp_buffer + remaining_offset), amount_to_read);
  268. data_length -= amount_to_read;
  269. amount_read += amount_to_read;
  270. remaining_offset -= amount_to_read;
  271. data_pointer_index++;
  272. free(tmp_buffer);
  273. }
  274. else
  275. {
  276. // We have to skip a whole data pointer:
  277. remaining_offset -= (DEFAULT_DATA_POINTER_SIZE * SECTOR_SIZE);
  278. data_pointer_index++;
  279. }
  280. }
  281. time_t current_time;
  282. time ( &current_time );
  283. file->access_time = current_time;
  284. return amount_read;
  285. }
  286. static inline time_t lsfs_disk_update_timestamps(lsfs_file *file) {
  287. return file->modification_time = file->access_time = time(NULL);
  288. }
  289. #define lsfs_num_sectors_for_size(x) (((x)+SECTOR_SIZE-1)&~(SECTOR_SIZE-1))
  290. int lsfs_disk_write_data_to_file(lsfs_file *file, int data_length, char *data, int64_t offset_to_next_entry)
  291. {
  292. int new_filesize = data_length + offset_to_next_entry;
  293. int amount_written = 0;
  294. int amount_to_write = 0;
  295. //printf("Data length: %d\n", data_length);
  296. //printf("Offset length: %d\n", offset_to_next_entry);
  297. int data_pointer_index = 0; // start at first data pointer.
  298. while(data_length > 0) // We have more to write
  299. {
  300. while (file->data_pointer[data_pointer_index] == 0)
  301. {
  302. // we have to assign a free sector
  303. if (get_free_sectors(1, file->table_backpointer))
  304. {
  305. // This is a fail case, we cannot assign a new sector:
  306. return amount_written;
  307. }
  308. }
  309. if (offset_to_next_entry == 0)
  310. {
  311. char *tmp_buffer = calloc(DEFAULT_DATA_POINTER_SIZE, SECTOR_SIZE);
  312. assert(tmp_buffer);
  313. if (data_length < (DEFAULT_DATA_POINTER_SIZE * SECTOR_SIZE))
  314. {
  315. amount_to_write = data_length;
  316. }
  317. else
  318. {
  319. amount_to_write = (DEFAULT_DATA_POINTER_SIZE * SECTOR_SIZE);
  320. }
  321. memcpy(tmp_buffer, (data + amount_written), amount_to_write);
  322. data_length -= amount_to_write;
  323. amount_written += amount_to_write;
  324. write_data_to_disk(file->data_pointer[data_pointer_index], DEFAULT_DATA_POINTER_SIZE, tmp_buffer);
  325. data_pointer_index++;
  326. free(tmp_buffer);
  327. }
  328. else if (offset_to_next_entry < (DEFAULT_DATA_POINTER_SIZE * SECTOR_SIZE))
  329. {
  330. char *tmp_buffer = calloc(1, (DEFAULT_DATA_POINTER_SIZE * SECTOR_SIZE));
  331. assert(tmp_buffer);
  332. read_data_from_disk(file->data_pointer[data_pointer_index], DEFAULT_DATA_POINTER_SIZE, tmp_buffer);
  333. if (data_length < ((DEFAULT_DATA_POINTER_SIZE * SECTOR_SIZE) - offset_to_next_entry) )
  334. {
  335. amount_to_write = data_length;
  336. }
  337. else
  338. {
  339. amount_to_write = ((DEFAULT_DATA_POINTER_SIZE * SECTOR_SIZE) - offset_to_next_entry);
  340. }
  341. memcpy(tmp_buffer + offset_to_next_entry, data, amount_to_write);
  342. data_length -= amount_to_write;
  343. amount_written += amount_to_write;
  344. offset_to_next_entry -= amount_to_write;
  345. write_data_to_disk(file->data_pointer[data_pointer_index], DEFAULT_DATA_POINTER_SIZE, tmp_buffer);
  346. data_pointer_index++;
  347. free(tmp_buffer);
  348. }
  349. else
  350. {
  351. // We have to skip a whole data pointer:
  352. offset_to_next_entry -= (DEFAULT_DATA_POINTER_SIZE * SECTOR_SIZE);
  353. //printf("Skip, offset is now: %d\n", offset_to_next_entry);
  354. data_pointer_index++;
  355. }
  356. }
  357. time_t current_time;
  358. time ( &current_time );
  359. //lsfs_disk_update_timestamps(&mif_record);
  360. file->size = new_filesize; // update file size
  361. file->access_time = current_time;
  362. file->modification_time = current_time;
  363. save_modified_file_information(file);
  364. //write_data_to_disk(file->file_id, 4, &p_control.master_table[file->file_id]);
  365. // Should return the total new file size
  366. //printf("We Think that we have written: %d \n", amount_written);
  367. return amount_written;
  368. }
  369. time_t lsfs_disk_truncate_file(lsfs_file *file, off_t offset) {
  370. //mif file_mif;
  371. //read_data_from_disk(file_id, &file_mif);
  372. time_t result = lsfs_disk_update_timestamps(file);
  373. file->size = (int) offset; // p_control.master_table.entries[i].data_pointer[0]; //;
  374. save_modified_file_information(file);
  375. //write_data_to_disk(file->file_id, 4, NULL);
  376. return result;
  377. }
  378. int lsfs_disk_rename_file(const char* old_filename, const char* new_filename) {
  379. lsfs_file *old_file = calloc(1, sizeof(lsfs_file));
  380. lsfs_file *new_file = calloc(1, sizeof(lsfs_file));
  381. lsfs_disk_getattr(old_file, old_filename);
  382. if (old_file->entry_kind == ENTRY_FILE)
  383. {
  384. lsfs_disk_create_entry(new_filename, ENTRY_FILE);
  385. }
  386. else
  387. {
  388. lsfs_disk_create_entry(new_filename, ENTRY_DIRECTORY);
  389. }
  390. lsfs_disk_getattr(new_file, new_filename);
  391. new_file->file_id = old_file->file_id;
  392. new_file->size = old_file->size;
  393. // TODO(Jørn) The data pointer assignt to the new file should be released.
  394. memcpy(new_file->data_pointer, old_file->data_pointer, NUM_DATA_POINTERS * 8);
  395. save_modified_file_information(new_file);
  396. lsfs_disk_delete_entry(old_file);
  397. return 0;
  398. }
  399. int lsfs_disk_delete_entry(lsfs_file *file) {
  400. //printf("file: %s - has been deleted \n", file->filename);
  401. Table_Entry *zero_buffer = calloc(1, (DEFAULT_ENTRY_SIZE * SECTOR_SIZE));
  402. //read_data_from_disk(file_id, 1, mif_record);
  403. write_data_to_disk(file->table_entry_sector_index, DEFAULT_ENTRY_SIZE, zero_buffer);
  404. free(zero_buffer);
  405. return 1;
  406. }
  407. int lsfs_disk_delete_directory(const char *path) {
  408. // Find the directory and check if this is empty for entries:
  409. Directory_Table *directory_table = calloc(1, (DEFAULT_ENTRY_SIZE * SECTOR_SIZE));
  410. directory_table = lsfs_find_directory(path, false);
  411. bool empty = true;
  412. for (int i = 0; i < DEFAULT_TABLE_SIZE; ++i)
  413. {
  414. if (directory_table->entries[i].entry_kind != 0)
  415. {
  416. empty = false;
  417. }
  418. }
  419. free(directory_table);
  420. if (!empty)
  421. {
  422. return 1;
  423. }
  424. lsfs_file *file = calloc(1, sizeof(lsfs_file));
  425. lsfs_disk_getattr(file, path);
  426. Table_Entry *zero_buffer = calloc(1, (DEFAULT_ENTRY_SIZE * SECTOR_SIZE));
  427. //read_data_from_disk(file_id, 1, mif_record);
  428. write_data_to_disk(file->table_entry_sector_index, DEFAULT_ENTRY_SIZE, zero_buffer);
  429. free(zero_buffer);
  430. return 0;
  431. }
  432. int get_free_sectors_table() {
  433. // We need DEFAULT_TABLE_SIZE sectors straight contigious for a table
  434. // Otherwise the file system cannot make a new table.
  435. // We return the offset where the table is starting.
  436. // If we cannot assing DEFAULT_TABLE_SIZE sectors, we report errror.
  437. int return_index = p_control.fsci.next_free_sector;
  438. if ((p_control.fsci.next_free_sector + DEFAULT_TABLE_SIZE) > p_control.fsci.last_sector_index_on_partition)
  439. {
  440. // We don't have space, report error
  441. return -EINVAL;
  442. }
  443. p_control.fsci.next_free_sector += DEFAULT_TABLE_SIZE;
  444. fseek ( disk , ((p_control.fsci.this_partition_offset_on_disk) * SECTOR_SIZE), SEEK_SET );
  445. fwrite(&p_control.fsci, 1, SECTOR_SIZE, disk);
  446. //printf("Table has got assigned Sector: %d\n", return_index);
  447. return return_index;
  448. }
  449. int get_free_sectors(int num_sectors_needed, struct_table_entry* table_entry) {
  450. if ((p_control.fsci.next_free_sector + num_sectors_needed) > p_control.fsci.last_sector_index_on_partition )
  451. {
  452. // We cannot assign what we want.
  453. return -EINVAL;
  454. }
  455. int i = 0;
  456. while (num_sectors_needed > 0)
  457. {
  458. if (i > NUM_DATA_POINTERS)
  459. {
  460. return -EINVAL; // We don't have any more data pointers.
  461. }
  462. if (table_entry->data_pointer[i] == 0)
  463. {
  464. // If free we can assign:
  465. table_entry->data_pointer[i] = p_control.fsci.next_free_sector;
  466. p_control.fsci.next_free_sector += DEFAULT_DATA_POINTER_SIZE;
  467. num_sectors_needed--;
  468. }
  469. i++;
  470. }
  471. fseek ( disk , (p_control.fsci.this_partition_offset_on_disk) * SECTOR_SIZE, SEEK_SET );
  472. fwrite(&p_control.fsci, 1, SECTOR_SIZE, disk);
  473. return 0;
  474. }
  475. int create_file_system(char* disk_name, char hdd_or_partition, uint64_t filesystem_size_in_MB) {
  476. //char* sector_to_write;
  477. // make default File System Control information (FSCI)
  478. // first integer says how many pointers we got
  479. // to master tag tables
  480. // Second and forward is the pointers to the master Tag Tables
  481. // we need the first number to allocate memory at one go.
  482. FSCI *fsci = calloc(1, sizeof(FSCI));
  483. // Create disk on host system:
  484. disk = fopen ( disk_name , "wb" );
  485. ftruncate(fileno(disk), (filesystem_size_in_MB * 2048 * 512));
  486. if (hdd_or_partition == '1')
  487. {
  488. // This is the create hdd case
  489. // This means that we setup the partition table.
  490. Master_Boot_record *mbr = calloc(1, sizeof(Master_Boot_record));
  491. mbr->partitions[0].partition_type = 0x18;
  492. mbr->partitions[0].LBA_abs_first_sector = SPACE_MBR_RECORD;
  493. mbr->partitions[0].number_of_sectors = filesystem_size_in_MB * 2048;
  494. mbr->mbr_signature = 0xaa55;
  495. write_data_to_disk(0, 1, mbr); // Write this to the first sector of the disk.
  496. }
  497. if ((hdd_or_partition == '1') || (hdd_or_partition == '2'))
  498. {
  499. // This is just a single partition
  500. // And then the file system is the only thing in the system.
  501. sprintf(fsci->filesystem_information, "LSFS v1.0.0-a4\r\n(LessSimpelFileSystem)(Generated by the disk_manager_utility.c)\r\nDeveloped to SingOS and QuasiOS\r\nby Jorn Guldberg\r\n");
  502. if (hdd_or_partition == '1')
  503. {
  504. fsci->this_partition_offset_on_disk = SPACE_MBR_RECORD + SPACE_VBR_RECORD;
  505. }
  506. else
  507. {
  508. fsci->this_partition_offset_on_disk = SPACE_VBR_RECORD;
  509. }
  510. fsci->master_table_index = fsci->this_partition_offset_on_disk + 1;
  511. fsci->next_free_sector = fsci->master_table_index + DEFAULT_TABLE_SIZE;
  512. fsci->next_uniqe_id = 1;
  513. fsci->next_sector_reuse_pointer = 0;
  514. fsci->last_sector_index_on_partition = filesystem_size_in_MB * 2048; // Todo, this is the ssectors pr MB, this should not be hardcoded.
  515. fsci->maximum_sectors_on_disk = filesystem_size_in_MB * 2048; //TODO(Jørn) Not in use yet
  516. fsci->sector_size_on_disk = SECTOR_SIZE;
  517. }
  518. else
  519. {
  520. // This is an error case, and we should not hit this case.
  521. assert(NULL);
  522. }
  523. write_data_to_disk(fsci->this_partition_offset_on_disk, 1, fsci);
  524. lsfs_disk_load_disk(NULL); // Reload disk
  525. return 0;
  526. }
  527. int lsfs_disk_install_bootloader(char *bootloader_name)
  528. {
  529. FILE *bootloader = fopen ( bootloader_name , "r+b" );
  530. Master_Boot_record *bootloader_mbr = calloc(1, sizeof(Master_Boot_record));
  531. fseek(bootloader, 0 * SECTOR_SIZE, SEEK_SET);
  532. fread(bootloader_mbr, 1, SECTOR_SIZE, bootloader);
  533. Master_Boot_record *mbr = calloc(1, sizeof(Master_Boot_record));
  534. fseek( disk , 0 * SECTOR_SIZE, SEEK_SET );
  535. fread(mbr, 1, SECTOR_SIZE, disk);
  536. memcpy(mbr->code, bootloader_mbr->code, 446);
  537. write_data_to_disk(0, 1, mbr); // Write this to the first sector of the disk.
  538. lsfs_disk_load_disk(NULL); // Reload disk
  539. return 0;
  540. }
  541. int lsfs_disk_install_vbr(char *vbr_path)
  542. {
  543. struct stat st;
  544. stat(vbr_path, &st);
  545. FILE *vbr = fopen ( vbr_path , "r+b" );
  546. Volume_Boot_record *vbr_first_sector = calloc(1, SECTOR_SIZE);
  547. void *vbr_buffer_rest = calloc(1, (SPACE_VBR_RECORD * SECTOR_SIZE - 1));
  548. // First load first sector
  549. fseek(vbr, 0, SEEK_SET);
  550. fread(vbr_first_sector, 1, SECTOR_SIZE, vbr);
  551. fseek(vbr, SECTOR_SIZE, SEEK_SET);
  552. fread(vbr_buffer_rest, 1, (st.st_size - SECTOR_SIZE), vbr);
  553. vbr_first_sector->vbr_size_in_bytes = st.st_size;
  554. vbr_first_sector->vbr_LBA_address = p_control.fsci.this_partition_offset_on_disk - SPACE_VBR_RECORD;
  555. vbr_first_sector->vbr_LBA_FSCI_position = p_control.fsci.this_partition_offset_on_disk;
  556. vbr_first_sector->vbr_signature = 0x1818;
  557. printf("VBR size: %lu\n", vbr_first_sector->vbr_size_in_bytes);
  558. printf("VBR lba address: %lu\n", vbr_first_sector->vbr_LBA_address);
  559. printf("VBR FSCI: %lu\n", vbr_first_sector->vbr_LBA_FSCI_position);
  560. write_data_to_disk((p_control.fsci.this_partition_offset_on_disk - SPACE_VBR_RECORD), 1, vbr_first_sector); // Write this to the first sector of the disk.
  561. write_data_to_disk((p_control.fsci.this_partition_offset_on_disk - SPACE_VBR_RECORD + 1), (SPACE_VBR_RECORD - 1), vbr_buffer_rest); // Write this to the first sector of the disk.
  562. Master_Boot_record mbr;
  563. fseek( disk , 0 * SECTOR_SIZE, SEEK_SET );
  564. fread(&mbr, 1, sizeof(mbr), disk);
  565. if (mbr.mbr_signature == 0xaa55 )
  566. {
  567. mbr.partitions[0].active_falg = 0x80; // TODO(Jørn) Hardcoded partition.
  568. write_data_to_disk(0, 1, &mbr);
  569. }
  570. else
  571. {
  572. return -EINVAL;
  573. }
  574. return 0;
  575. }
  576. int lsfs_disk_load_disk(char* diskname)
  577. {
  578. // Find the partition talbe:
  579. // This makes is BIOS dependent.
  580. // UEFI is not supported.
  581. if (diskname != NULL)
  582. {
  583. disk = fopen ( diskname , "r+b" );
  584. }
  585. else if (disk == NULL )
  586. {
  587. return -1;
  588. }
  589. time(&timestamp_loading);
  590. Master_Boot_record mbr;
  591. fseek( disk , 0 * SECTOR_SIZE, SEEK_SET );
  592. fread(&mbr, 1, sizeof(mbr), disk);
  593. if (mbr.mbr_signature != 0xaa55 )
  594. {
  595. // Means that it is a sigle partition we try to mount
  596. fseek(disk, (SPACE_VBR_RECORD * SECTOR_SIZE), SEEK_SET );
  597. fread(&p_control.fsci, 1, SECTOR_SIZE , disk);
  598. //printf("next free sector: %d\n", p_control.fsci.next_free_sector);
  599. //printf("next free ID: %d\n", p_control.fsci.next_uniqe_id);
  600. // next we find the Mater Table.
  601. fseek (disk, (p_control.fsci.master_table_index * SECTOR_SIZE), SEEK_SET );
  602. fread(&p_control.master_table, 1, DEFAULT_TABLE_SIZE * SECTOR_SIZE , disk);
  603. return 1;
  604. }
  605. else
  606. {
  607. for (int i = 0; i < NUMBER_OF_MBR_PARTITIONS; ++i)
  608. {
  609. // TODO (Jørn) We maybe wnat to optimize, such that we can detect if we have more than one partition opn the system.
  610. if (mbr.partitions[i].partition_type == 0x18)
  611. {
  612. // First we find the File system control information.
  613. fseek(disk , ((mbr.partitions[i].LBA_abs_first_sector + SPACE_VBR_RECORD) * SECTOR_SIZE), SEEK_SET );
  614. fread(&p_control.fsci, 1, SECTOR_SIZE , disk);
  615. // next we find the Mater Table.
  616. fseek (disk, (p_control.fsci.master_table_index * SECTOR_SIZE), SEEK_SET );
  617. fread(&p_control.master_table, 1, DEFAULT_TABLE_SIZE * SECTOR_SIZE , disk);
  618. return 1;
  619. }
  620. }
  621. }
  622. return 0;
  623. }
  624. int lsfs_disk_create_entry(const char* path, Table_Entry_Kind entry_kind)
  625. {
  626. // First check if file exist:
  627. lsfs_file *file = calloc(1, sizeof(lsfs_file));
  628. if (lsfs_disk_getattr(file, path))
  629. {
  630. return -EINVAL;
  631. }
  632. free(file);
  633. // Start from the master table
  634. int free_index = -1; // -1 is no index found.
  635. Directory_Table *dir_table = calloc(1, sizeof(Directory_Table));
  636. read_data_from_disk(p_control.fsci.master_table_index, DEFAULT_TABLE_SIZE, dir_table);
  637. lsfs_sector_offset table_disk_position = p_control.fsci.master_table_index;
  638. lsfs_string_array split_path = lsfs_string_split_c(path, '/', false);
  639. lsfs_string filename = split_path.strings[split_path.length-1];
  640. //printf("spilt length: %d\n", split_path.length);
  641. for (int i = 0; i < split_path.length -1; ++i)
  642. {
  643. for (int j = 0; j < DEFAULT_TABLE_SIZE; ++j)
  644. {
  645. if (strcmp(dir_table->entries[j].filename, split_path.strings[i].chars) == 0)
  646. {
  647. // We have found the next directory to traverse.
  648. //printf("Get next dir at sector: ");
  649. table_disk_position = dir_table->entries[j].data_pointer[0];
  650. //printf("%d\n", table_disk_position);
  651. read_data_from_disk(table_disk_position, DEFAULT_TABLE_SIZE, dir_table);
  652. break;
  653. }
  654. }
  655. }
  656. for (int table_index = 0; table_index < DEFAULT_TABLE_SIZE; ++table_index)
  657. {
  658. // Find free index.
  659. if (dir_table->entries[table_index].entry_kind == ENTRY_EMPTY)
  660. {
  661. // Set the free index, continue to see if the filename exist.
  662. // if not -1, we have found a better index.
  663. if (free_index == -1)
  664. {
  665. //printf("Index found for file: %d\n", table_index);
  666. table_disk_position += table_index; // Abselout index in file system
  667. free_index = table_index;
  668. }
  669. }
  670. }
  671. if (free_index == -1)
  672. {
  673. // The table is full, and we cannot create an entry
  674. return -EINVAL;
  675. }
  676. // Find the entry for the file in the table structure:
  677. dir_table->entries[free_index].file_id = p_control.fsci.next_uniqe_id;
  678. p_control.fsci.next_uniqe_id++;
  679. sprintf(dir_table->entries[free_index].filename, "%s", filename.chars);
  680. dir_table->entries[free_index].entry_kind = entry_kind;
  681. dir_table->entries[free_index].table_entry_sector_index = table_disk_position;
  682. if (entry_kind == ENTRY_DIRECTORY)
  683. {
  684. dir_table->entries[free_index].data_pointer[0] = get_free_sectors_table();
  685. dir_table->entries[free_index].file_size = DEFAULT_TABLE_SIZE * SECTOR_SIZE;
  686. }
  687. else if (entry_kind == ENTRY_FILE)
  688. {
  689. // We assign one data pointer consiting of DEFAULT_DATA_POINTER_SIZE sectors
  690. dir_table->entries[free_index].file_size = 0;
  691. get_free_sectors(1, &(dir_table->entries[free_index]));
  692. }
  693. else
  694. {
  695. return -EINVAL;
  696. }
  697. /*
  698. find_file->creation_date = (uint64_t) current_time;
  699. find_file->access_time = (uint64_t) current_time;
  700. find_file->modification_time = (uint64_t) current_time;
  701. find_file->data = p_control.master_table.entries[i].data_pointer;
  702. find_file->owner_id = getuid();
  703. new_file_data.owner_id = getuid();
  704. time_t current_time;
  705. time ( &current_time );
  706. */
  707. //printf("File is written to sector: %d\n", table_disk_position);
  708. write_data_to_disk(table_disk_position, DEFAULT_ENTRY_SIZE, &dir_table->entries[free_index]);
  709. return 0;
  710. }
  711. int save_modified_file_information(lsfs_file* file) {
  712. // Write the file struct into the table_entry, such that we can save the data correct.
  713. Table_Entry *entry = calloc(1, sizeof(Table_Entry));
  714. read_data_from_disk(file->table_entry_sector_index, DEFAULT_ENTRY_SIZE, entry);
  715. //entry.file_id = file->file_id;
  716. memcpy(entry->filename, file->filename, 256);
  717. entry->file_size = file->size; // p_control.master_table.entries[i].data_pointer[0]; //;
  718. memcpy(entry->data_pointer, file->data_pointer, NUM_DATA_POINTERS * 8);
  719. write_data_to_disk(file->table_entry_sector_index, DEFAULT_ENTRY_SIZE, entry);
  720. return 0;
  721. }
  722. int write_data_to_disk(lsfs_sector_offset index, uint32_t number_sectors, void* data_to_write) {
  723. fseek ( disk, (index * SECTOR_SIZE), SEEK_SET ); // SEEK_SET start offset at index 0 and move 1 * SECTOR_SIZE, and write here.
  724. int written = fwrite(data_to_write, 1, (number_sectors * SECTOR_SIZE), disk);
  725. return written;
  726. }
  727. int write_data_to_disk_off(lsfs_sector_offset index, uint32_t number_sectors, void* data_to_write, int offset) {
  728. fseek ( disk, ((index * SECTOR_SIZE) + offset), SEEK_SET ); // SEEK_SET start offset at index 0 and move 1 * SECTOR_SIZE, and write here.
  729. int written = fwrite(data_to_write, 1, ((number_sectors * SECTOR_SIZE) - offset), disk);
  730. return written;
  731. }
  732. int read_data_from_disk(lsfs_sector_offset index, uint32_t number_sectors, void* data_buffer) {
  733. fseek ( disk, (index * SECTOR_SIZE ), SEEK_SET ); // SEEK_SET start offset at index 0 and move 1 * SECTOR_SIZE, and write here.
  734. int read = fread(data_buffer, 1, (number_sectors * SECTOR_SIZE), disk);
  735. return read;
  736. }
  737. int read_data_from_disk_off(lsfs_sector_offset index, uint32_t number_sectors, void* data_to_write, int offset) {
  738. fseek ( disk, ((index * SECTOR_SIZE) + offset), SEEK_SET ); // SEEK_SET start offset at index 0 and move 1 * SECTOR_SIZE, and write here.
  739. int written = fread(data_to_write, 1, ((number_sectors * SECTOR_SIZE) - offset), disk);
  740. return written;
  741. }
  742. #endif