SHARE
TWEET

Untitled

a guest May 19th, 2017 92 in 24 days
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /////////////////////////////////////////////////////////////////
  2. //                                                             //
  3. //         Trabalho II: Sistema de Gestão de Ficheiros         //
  4. //                                                             //
  5. // compilação: gcc vfs.c -Wall -lreadline -lcurses -o vfs      //
  6. // utilização: vfs [-b[256|512|1024]] [-f[8|10|12]] FILESYSTEM //
  7. //                                                             //
  8. //                   Aceito nudes em troca                     //
  9. //                                                             //
  10. /////////////////////////////////////////////////////////////////
  11.  
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <fcntl.h>
  15. #include <time.h>
  16. #include <unistd.h>
  17. #include <sys/stat.h>
  18. #include <sys/mman.h>
  19. #include <sys/types.h>
  20. #include <readline/readline.h>
  21. #include <readline/history.h>
  22.  
  23. #define DEBUG 0
  24.  
  25. #define MAXARGS 100
  26. #define CHECK_NUMBER 9999
  27. #define TYPE_DIR 'D'
  28. #define TYPE_FILE 'F'
  29. #define MAX_NAME_LENGHT 20
  30.  
  31. #define FAT_ENTRIES(TYPE) (TYPE == 8 ? 256 : TYPE == 10 ? 1024 : 4096)
  32. #define FAT_SIZE(TYPE) (FAT_ENTRIES(TYPE) * sizeof(int))
  33. #define BLOCK(N) (blocks + N * sb->block_size)
  34. #define DIR_ENTRIES_PER_BLOCK (sb->block_size / sizeof(dir_entry))
  35.  
  36. typedef struct command {
  37.   char *cmd;              // string apenas com o comando
  38.   int argc;               // número de argumentos
  39.   char *argv[MAXARGS+1];  // vector de argumentos do comando
  40. } COMMAND;
  41.  
  42. typedef struct superblock_entry {
  43.   int check_number;   // número que permite identificar o sistema como válido
  44.   int block_size;     // tamanho de um bloco {256, 512(default) ou 1024 bytes}
  45.   int fat_type;       // tipo de FAT {8, 10(default) ou 12}
  46.   int root_block;     // número do 1º bloco a que corresponde o directório raiz
  47.   int free_block;     // número do 1º bloco da lista de blocos não utilizados
  48.   int n_free_blocks;  // total de blocos não utilizados
  49. } superblock;
  50.  
  51. typedef struct directory_entry {
  52.   char type;                   // tipo da entrada (TYPE_DIR ou TYPE_FILE)
  53.   char name[MAX_NAME_LENGHT];  // nome da entrada
  54.   unsigned char day;           // dia em que foi criada (entre 1 e 31)
  55.   unsigned char month;         // mes em que foi criada (entre 1 e 12)
  56.   unsigned char year;          // ano em que foi criada (entre 0 e 255 - 0 representa o ano de 1900)
  57.   int size;                    // tamanho em bytes (0 se TYPE_DIR)
  58.   int first_block;             // primeiro bloco de dados
  59. } dir_entry;
  60.  
  61. // variáveis globais
  62. superblock *sb;   // superblock do sistema de ficheiros
  63. int *fat;         // apontador para a FAT
  64. char *blocks;     // apontador para a região dos dados
  65. int current_dir;  // bloco do directório corrente
  66.  
  67. // funções auxiliares
  68. COMMAND parse(char*);
  69. void parse_argv(int, char*[]);
  70. void init_filesystem(int, int, char*);
  71. void init_superblock(int, int);
  72. void init_fat(void);
  73. void init_dir_block(int, int);
  74. void init_dir_entry(dir_entry*, char, char*, int, int);
  75. void exec_com(COMMAND);
  76.  
  77. // funções de manipulação de directórios
  78. void vfs_ls(void);
  79. void vfs_mkdir(char*);
  80. void vfs_cd(char*);
  81. void vfs_pwd(void);
  82. void vfs_rmdir(char*);
  83.  
  84. // funções de manipulação de ficheiros
  85. void vfs_get(char*, char*);
  86. void vfs_put(char*, char*);
  87. void vfs_cat(char*);
  88. void vfs_cp(char*, char*);
  89. void vfs_mv(char*, char*);
  90. void vfs_rm(char*);
  91.  
  92.  
  93. int main(int argc, char *argv[]) {
  94.   char *linha;
  95.   COMMAND com;
  96.  
  97.   parse_argv(argc, argv);
  98.   while (1) {
  99.     if ((linha = readline("vfs$ ")) == NULL)
  100.       exit(0);
  101.     if (strlen(linha) != 0) {
  102.       add_history(linha);
  103.       com = parse(linha);
  104.       exec_com(com);
  105.     }
  106.     free(linha);
  107.   }
  108.   return 0;
  109. }
  110.  
  111.  
  112. COMMAND parse(char *linha) {
  113.   int i = 0;
  114.   COMMAND com;
  115.  
  116.   com.cmd = strtok(linha, " ");
  117.   com.argv[0] = com.cmd;
  118.   while ((com.argv[++i] = strtok(NULL, " ")) != NULL);
  119.   com.argc = i;
  120.   return com;
  121. }
  122.  
  123.  
  124. void parse_argv(int argc, char *argv[]) {
  125.   int i, block_size, fat_type;
  126.  
  127.   block_size = 512; // valor por omissão
  128.   fat_type = 10;    // valor por omissão
  129.   if (argc < 2 || argc > 4) {
  130.     printf("vfs: invalid number of arguments\n");
  131.     printf("Usage: vfs [-b[256|512|1024]] [-f[8|10|12]] FILESYSTEM\n");
  132.     exit(1);
  133.   }
  134.   for (i = 1; i < argc - 1; i++) {
  135.     if (argv[i][0] == '-') {
  136.       if (argv[i][1] == 'b') {
  137.     block_size = atoi(&argv[i][2]);
  138.     if (block_size != 256 && block_size != 512 && block_size != 1024) {
  139.       printf("vfs: invalid block size (%d)\n", block_size);
  140.       printf("Usage: vfs [-b[256|512|1024]] [-f[8|10|12]] FILESYSTEM\n");
  141.       exit(1);
  142.     }
  143.       } else if (argv[i][1] == 'f') {
  144.     fat_type = atoi(&argv[i][2]);
  145.     if (fat_type != 8 && fat_type != 10 && fat_type != 12) {
  146.       printf("vfs: invalid fat type (%d)\n", fat_type);
  147.       printf("Usage: vfs [-b[256|512|1024]] [-f[8|10|12]] FILESYSTEM\n");
  148.       exit(1);
  149.     }
  150.       } else {
  151.     printf("vfs: invalid argument (%s)\n", argv[i]);
  152.     printf("Usage: vfs [-b[256|512|1024]] [-f[8|10|12]] FILESYSTEM\n");
  153.     exit(1);
  154.       }
  155.     } else {
  156.       printf("vfs: invalid argument (%s)\n", argv[i]);
  157.       printf("Usage: vfs [-b[256|512|1024]] [-f[8|10|12]] FILESYSTEM\n");
  158.       exit(1);
  159.     }
  160.   }
  161.   init_filesystem(block_size, fat_type, argv[argc-1]);
  162.   return;
  163. }
  164.  
  165.  
  166. void init_filesystem(int block_size, int fat_type, char *filesystem_name) {
  167.   int fsd, filesystem_size;
  168.  
  169.   if ((fsd = open(filesystem_name, O_RDWR)) == -1) {
  170.     // o sistema de ficheiros não existe --> é necessário criá-lo e formatá-lo
  171.     if ((fsd = open(filesystem_name, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU)) == -1) {
  172.       printf("vfs: cannot create filesystem (%s)\n", filesystem_name);
  173.       printf("Usage: vfs [-b[256|512|1024]] [-f[8|10|12]] FILESYSTEM\n");
  174.       exit(1);
  175.     }
  176.  
  177.     // calcula o tamanho do sistema de ficheiros
  178.     filesystem_size = block_size + FAT_SIZE(fat_type) + FAT_ENTRIES(fat_type) * block_size;
  179.     printf("vfs: formatting virtual file-system (%d bytes) ... please wait\n", filesystem_size);
  180.  
  181.     // estende o sistema de ficheiros para o tamanho desejado
  182.     lseek(fsd, filesystem_size - 1, SEEK_SET);
  183.     write(fsd, "", 1);
  184.  
  185.     // faz o mapeamento do sistema de ficheiros e inicia as variáveis globais
  186.     if ((sb = (superblock *) mmap(NULL, filesystem_size, PROT_READ | PROT_WRITE, MAP_SHARED, fsd, 0)) == MAP_FAILED) {
  187.       printf("vfs: cannot map filesystem (mmap error)\n");
  188.       close(fsd);
  189.       exit(1);
  190.     }
  191.     fat = (int *) ((unsigned long int) sb + block_size);
  192.     blocks = (char *) ((unsigned long int) fat + FAT_SIZE(fat_type));
  193.    
  194.     // inicia o superblock
  195.     init_superblock(block_size, fat_type);
  196.    
  197.     // inicia a FAT
  198.     init_fat();
  199.    
  200.     // inicia o bloco do directório raiz '/'
  201.     init_dir_block(sb->root_block, sb->root_block);
  202.   } else {
  203.     // calcula o tamanho do sistema de ficheiros
  204.     struct stat buf;
  205.     stat(filesystem_name, &buf);
  206.     filesystem_size = buf.st_size;
  207.  
  208.     // faz o mapeamento do sistema de ficheiros e inicia as variáveis globais
  209.     if ((sb = (superblock *) mmap(NULL, filesystem_size, PROT_READ | PROT_WRITE, MAP_SHARED, fsd, 0)) == MAP_FAILED) {
  210.       printf("vfs: cannot map filesystem (mmap error)\n");
  211.       close(fsd);
  212.       exit(1);
  213.     }
  214.     fat = (int *) ((unsigned long int) sb + sb->block_size);
  215.     blocks = (char *) ((unsigned long int) fat + FAT_SIZE(sb->fat_type));
  216.  
  217.     // testa se o sistema de ficheiros é válido
  218.     if (sb->check_number != CHECK_NUMBER || filesystem_size != sb->block_size + FAT_SIZE(sb->fat_type) + FAT_ENTRIES(sb->fat_type) * sb->block_size) {
  219.       printf("vfs: invalid filesystem (%s)\n", filesystem_name);
  220.       printf("Usage: vfs [-b[256|512|1024]] [-f[8|10|12]] FILESYSTEM\n");
  221.       munmap(sb, filesystem_size);
  222.       close(fsd);
  223.       exit(1);
  224.     }
  225.   }
  226.   close(fsd);
  227.  
  228.   // inicia o directório corrente
  229.   current_dir = sb->root_block;
  230.   return;
  231. }
  232.  
  233.  
  234. void init_superblock(int block_size, int fat_type) {
  235.   sb->check_number = CHECK_NUMBER;
  236.   sb->block_size = block_size;
  237.   sb->fat_type = fat_type;
  238.   sb->root_block = 0;
  239.   sb->free_block = 1;
  240.   sb->n_free_blocks = FAT_ENTRIES(fat_type) - 1;
  241.   return;
  242. }
  243.  
  244.  
  245. void init_fat(void) {
  246.   int i;
  247.  
  248.   fat[0] = -1;
  249.   for (i = 1; i < sb->n_free_blocks; i++)
  250.     fat[i] = i + 1;
  251.   fat[sb->n_free_blocks] = -1;
  252.   return;
  253. }
  254.  
  255.  
  256. void init_dir_block(int block, int parent_block) {
  257.   dir_entry *dir = (dir_entry *) BLOCK(block);
  258.   // o número de entradas no directório (inicialmente 2) fica guardado no campo size da entrada "."
  259.   init_dir_entry(&dir[0], TYPE_DIR, ".", 2, block);
  260.   init_dir_entry(&dir[1], TYPE_DIR, "..", 0, parent_block);
  261.   return;
  262. }
  263.  
  264.  
  265. void init_dir_entry(dir_entry *dir, char type, char *name, int size, int first_block) {
  266.   time_t cur_time = time(NULL);
  267.   struct tm *cur_tm = localtime(&cur_time);
  268.  
  269.   dir->type = type;
  270.   strcpy(dir->name, name);
  271.   dir->day = cur_tm->tm_mday;
  272.   dir->month = cur_tm->tm_mon + 1;
  273.   dir->year = cur_tm->tm_year;
  274.   dir->size = size;
  275.   dir->first_block = first_block;
  276.   return;
  277. }
  278.  
  279. int cstr_cmp(const void *a, const void *b)
  280. {
  281.   const char **ia = (const char **)a;
  282.   const char **ib = (const char **)b;
  283.   return strcmp(*ia, *ib);
  284. }
  285.  
  286. int get_free_block() {
  287.   if (sb->n_free_blocks == 0)
  288.     return -1;
  289.  
  290.   int livre = sb->free_block;
  291.   sb->free_block = fat[livre];
  292.   fat[livre] = -1;
  293.  
  294.   sb->n_free_blocks--;
  295.  
  296.   return livre;
  297. }
  298.  
  299. void delete_block(int block) {
  300.   fat[block] = sb->free_block;
  301.   sb->free_block = block;
  302.  
  303.   sb->n_free_blocks++;
  304.  
  305.   return;
  306. }
  307.  
  308. void exec_com(COMMAND com) {
  309.   // para cada comando invocar a função que o implementa
  310.   if (!strcmp(com.cmd, "exit"))
  311.     exit(0);
  312.   if (!strcmp(com.cmd, "ls")) {
  313.     // falta tratamento de erros
  314.     vfs_ls();
  315.   } else if (!strcmp(com.cmd, "mkdir")) {
  316.     // falta tratamento de erros
  317.     vfs_mkdir(com.argv[1]);
  318.   } else if (!strcmp(com.cmd, "cd")) {
  319.     // falta tratamento de erros
  320.     vfs_cd(com.argv[1]);
  321.   } else if (!strcmp(com.cmd, "pwd")) {
  322.     // falta tratamento de erros
  323.     vfs_pwd();
  324.   } else if (!strcmp(com.cmd, "rmdir")) {
  325.     // falta tratamento de erros
  326.     vfs_rmdir(com.argv[1]);
  327.   } else if (!strcmp(com.cmd, "get")) {
  328.     // falta tratamento de erros
  329.     vfs_get(com.argv[1], com.argv[2]);
  330.   } else if (!strcmp(com.cmd, "put")) {
  331.     // falta tratamento de erros
  332.     vfs_put(com.argv[1], com.argv[2]);
  333.   } else if (!strcmp(com.cmd, "cat")) {
  334.     // falta tratamento de erros
  335.     vfs_cat(com.argv[1]);
  336.   } else if (!strcmp(com.cmd, "cp")) {
  337.     // falta tratamento de erros
  338.     vfs_cp(com.argv[1], com.argv[2]);
  339.   } else if (!strcmp(com.cmd, "mv")) {
  340.     // falta tratamento de erros
  341.     vfs_mv(com.argv[1], com.argv[2]);
  342.   } else if (!strcmp(com.cmd, "rm")) {
  343.     // falta tratamento de erros
  344.     vfs_rm(com.argv[1]);
  345.   } else
  346.     printf("ERROR(input: command not found)\n");
  347.   return;
  348. }
  349.  
  350.  
  351. // ls - lista o conteúdo do directório actual
  352. void vfs_ls(void) {
  353.   dir_entry *dir = (dir_entry *) BLOCK(current_dir);
  354.   int n_entries = dir[0].size, i;
  355.  
  356.   char type_str[100];
  357.   char **content = (char **) malloc(n_entries * sizeof(char *));
  358.   for (i = 0; i < n_entries; i++)
  359.     content[i] = (char * ) malloc(1024 * sizeof(char *));
  360.  
  361.  
  362.   int cur_block = current_dir;
  363.   for (i = 0; i < n_entries; i++)
  364.   {
  365.     if (i % DIR_ENTRIES_PER_BLOCK == 0 && i)
  366.     {
  367.       if (DEBUG)
  368.         printf("Changed Block\n");
  369.       cur_block = fat[cur_block];
  370.       dir = (dir_entry *) BLOCK(cur_block);
  371.     }
  372.  
  373.     int block_i = i % DIR_ENTRIES_PER_BLOCK;
  374.  
  375.     if (dir[block_i].type == TYPE_DIR)
  376.       sprintf(type_str, "DIR");
  377.     else
  378.       sprintf(type_str, "%d", dir[block_i].size);
  379.    
  380.     sprintf(content[i], "%s\t%02d-%02d-%04d\t%s", dir[block_i].name, dir[block_i].day, dir[block_i].month, 1900 + dir[block_i].year, type_str);
  381.   }
  382.  
  383.   qsort(content, n_entries, sizeof(char *), cstr_cmp);
  384.  
  385.   for (i = 0; i < n_entries; i++)
  386.     printf("%s\n", content[i]);
  387.  
  388.   return;
  389. }
  390.  
  391.  
  392. // mkdir dir - cria um subdirectório com nome dir no directório actual
  393. void vfs_mkdir(char *nome_dir) {
  394.   dir_entry *dir = (dir_entry *) BLOCK(current_dir);
  395.   int n_entries = dir[0].size;
  396.   int req_blocks = (n_entries % DIR_ENTRIES_PER_BLOCK == 0) + 1;
  397.  
  398.   if (sb->n_free_blocks < req_blocks)
  399.   {
  400.     printf("ERROR(mkdir: memory full)\n");
  401.     return;
  402.   }
  403.  
  404.   if (DEBUG)
  405.     printf("Blocks: used %d from %lu\n", n_entries + 1, DIR_ENTRIES_PER_BLOCK);
  406.  
  407.   dir[0].size++;
  408.  
  409.   int new_block = get_free_block();
  410.   init_dir_block(new_block, current_dir);
  411.  
  412.   int cur_block = current_dir;
  413.   while (fat[cur_block] != -1)
  414.     cur_block = fat[cur_block];
  415.  
  416.   if (n_entries % DIR_ENTRIES_PER_BLOCK == 0)
  417.   {
  418.     int next_block = get_free_block();
  419.     fat[cur_block] = next_block;
  420.     cur_block = next_block;
  421.   }
  422.  
  423.   dir = (dir_entry *) BLOCK(cur_block);
  424.  
  425.   init_dir_entry(&dir[n_entries % DIR_ENTRIES_PER_BLOCK], TYPE_DIR, nome_dir, 0, new_block);
  426.  
  427.   return;
  428. }
  429.  
  430.  
  431. // cd dir - move o directório actual para dir.
  432. void vfs_cd(char *nome_dir) {
  433.   dir_entry *dir = (dir_entry *) BLOCK(current_dir);
  434.   int n_entries = dir[0].size, i;
  435.  
  436.   int cur_block = current_dir;
  437.   for (i = 0; i < n_entries; i++)
  438.   {
  439.     if (i % DIR_ENTRIES_PER_BLOCK == 0 && i)
  440.     {
  441.       if (DEBUG)
  442.         printf("Changed Block\n");
  443.       cur_block = fat[cur_block];
  444.       dir = (dir_entry *) BLOCK(cur_block);
  445.     }
  446.  
  447.     int block_i = i % DIR_ENTRIES_PER_BLOCK;
  448.        
  449.     if (dir[block_i].type == TYPE_DIR && strcmp(dir[block_i].name, nome_dir) == 0)
  450.     {
  451.       current_dir = dir[block_i].first_block;
  452.       return;
  453.     }
  454.   }
  455.  
  456.   printf("ERROR(cd: directory not found)\n");
  457.  
  458.   return;
  459. }
  460.  
  461.  
  462. // pwd - escreve o caminho absoluto do directório actual
  463. void vfs_pwd(void) {
  464.   char name[1024], tmp[1024];
  465.   name[0] = '/';
  466.   name[1] = '\0';
  467.  
  468.   int it_dir = current_dir;
  469.   int i;
  470.   while (it_dir != 0)
  471.   {
  472.     dir_entry *dir = (dir_entry *) BLOCK(it_dir);
  473.     int prev_dir = dir[1].first_block;
  474.     dir = (dir_entry *) BLOCK(prev_dir);
  475.     int n_entries = dir[0].size;
  476.  
  477.     int cur_block = prev_dir;
  478.     for (i = 0; i < n_entries; i++)
  479.     {
  480.       if (i % DIR_ENTRIES_PER_BLOCK == 0 && i)
  481.       {
  482.         if (DEBUG)
  483.           printf("Changed Block\n");
  484.         cur_block = fat[cur_block];
  485.         dir = (dir_entry *) BLOCK(cur_block);
  486.       }
  487.  
  488.       int block_i = i % DIR_ENTRIES_PER_BLOCK;
  489.  
  490.       if (dir[block_i].first_block == it_dir)
  491.       {
  492.     strcpy(tmp, dir[block_i].name);
  493.     strcat(tmp, name);
  494.     strcpy(name, tmp);
  495.     strcpy(tmp, "/");
  496.     strcat(tmp, name);
  497.     strcpy(name, tmp);
  498.     break;
  499.       }
  500.     }
  501.  
  502.     it_dir = prev_dir;
  503.   }
  504.  
  505.   printf("%s\n", name);
  506.  
  507.   return;
  508. }
  509.  
  510.  
  511. // rmdir dir - remove o subdirectório dir (se vazio) do directório actual
  512. void vfs_rmdir(char *nome_dir) {
  513.   dir_entry *dir = (dir_entry *) BLOCK(current_dir);
  514.   int n_entries = dir[0].size, i;
  515.  
  516.   int cur_block = current_dir;
  517.   for (i = 0; i < n_entries; i++)
  518.   {
  519.     if (i % DIR_ENTRIES_PER_BLOCK == 0 && i)
  520.     {
  521.       if (DEBUG)
  522.         printf("Changed Block\n");
  523.       cur_block = fat[cur_block];
  524.       dir = (dir_entry *) BLOCK(cur_block);
  525.     }
  526.  
  527.     int block_i = i % DIR_ENTRIES_PER_BLOCK;
  528.  
  529.     if (dir[block_i].type == TYPE_DIR && strcmp(dir[block_i].name, nome_dir) == 0)
  530.     {
  531.       dir_entry *del_dir = (dir_entry *) BLOCK(dir[block_i].first_block);
  532.  
  533.       if (del_dir[0].size != 2)
  534.       {
  535.     printf("ERROR(rmdir: directory not empty)\n");
  536.     return;
  537.       }
  538.  
  539.       int last_block = cur_block;
  540.       while (fat[last_block] != -1)
  541.         last_block = fat[last_block];
  542.       dir_entry *last_dir_block = (dir_entry *) BLOCK(last_block);
  543.       dir_entry last_dir = last_dir_block[(n_entries - 1 + DIR_ENTRIES_PER_BLOCK) % DIR_ENTRIES_PER_BLOCK];
  544.  
  545.       if ((n_entries - 1 + DIR_ENTRIES_PER_BLOCK) % DIR_ENTRIES_PER_BLOCK == 0)
  546.         delete_block(last_block);
  547.       delete_block(dir[block_i].first_block);
  548.  
  549.       dir[block_i].type = last_dir.type;
  550.       strcpy(dir[block_i].name, last_dir.name);
  551.       dir[block_i].day = last_dir.day;
  552.       dir[block_i].month = last_dir.month;
  553.       dir[block_i].year = last_dir.year;
  554.       dir[block_i].size = last_dir.size;
  555.       dir[block_i].first_block = last_dir.first_block;
  556.  
  557.       dir = (dir_entry *) BLOCK(current_dir);
  558.       dir[0].size--;
  559.  
  560.       return;
  561.     }
  562.   }
  563.  
  564.   printf("ERROR(rmdir: directory not found)\n");
  565.  
  566.   return;
  567. }
  568.  
  569.  
  570. // get fich1 fich2 - copia um ficheiro normal UNIX fich1 para um ficheiro no nosso sistema fich2
  571. void vfs_get(char *nome_orig, char *nome_dest) {
  572.   dir_entry *dir = (dir_entry *) BLOCK(current_dir);
  573.   int n_entries = dir[0].size;
  574.  
  575.   struct stat statbuf;
  576.   if (stat(nome_orig, &statbuf) == -1)
  577.   {
  578.     printf("ERROR(get: input file not found)\n");
  579.     return;
  580.   }
  581.  
  582.   int req_size = (int)statbuf.st_size;
  583.   int req_blocks = (n_entries % DIR_ENTRIES_PER_BLOCK == 0) + (req_size + sb->block_size - 1) / sb->block_size;
  584.  
  585.   if (sb->n_free_blocks < req_blocks)
  586.   {
  587.     printf("ERROR(get: memory full)\n");
  588.     return;
  589.   }
  590.  
  591.   req_blocks -= (n_entries % DIR_ENTRIES_PER_BLOCK == 0);
  592.  
  593.   if (DEBUG)
  594.     printf("Blocks: used %d from %lu\n", n_entries + 1, DIR_ENTRIES_PER_BLOCK);
  595.  
  596.   dir[0].size++;
  597.  
  598.   int first_block = get_free_block();
  599.   int new_block, next_block = first_block;
  600.   int finput = open(nome_orig, O_RDONLY), count_block = 1, n;
  601.   char msg[4200];
  602.   while ((n = read(finput, msg, sb->block_size)) > 0)
  603.   {
  604.     if (count_block != req_blocks)
  605.     {
  606.       count_block++;
  607.       new_block = get_free_block();
  608.       fat[next_block] = new_block;
  609.     }
  610.  
  611.     strcpy(BLOCK(next_block), msg);
  612.  
  613.     next_block = new_block;
  614.   }
  615.  
  616.   int cur_block = current_dir;
  617.   while (fat[cur_block] != -1)
  618.     cur_block = fat[cur_block];
  619.  
  620.   if (n_entries % DIR_ENTRIES_PER_BLOCK == 0)
  621.   {
  622.     int next_block = get_free_block();
  623.     fat[cur_block] = next_block;
  624.     cur_block = next_block;
  625.   }
  626.  
  627.   dir = (dir_entry *) BLOCK(cur_block);
  628.   init_dir_entry(&dir[n_entries % DIR_ENTRIES_PER_BLOCK], TYPE_FILE, nome_dest, req_size, first_block);
  629.  
  630.   return;
  631. }
  632.  
  633.  
  634. // put fich1 fich2 - copia um ficheiro do nosso sistema fich1 para um ficheiro normal UNIX fich2
  635. void vfs_put(char *nome_orig, char *nome_dest) {
  636.   dir_entry *dir = (dir_entry *) BLOCK(current_dir);
  637.   int n_entries = dir[0].size, i;
  638.  
  639.   int cur_block = current_dir;
  640.   for (i = 0; i < n_entries; i++)
  641.   {
  642.     if (i % DIR_ENTRIES_PER_BLOCK == 0 && i)
  643.     {
  644.       if (DEBUG)
  645.         printf("Changed Block\n");
  646.       cur_block = fat[cur_block];
  647.       dir = (dir_entry *) BLOCK(cur_block);
  648.     }
  649.  
  650.     int block_i = i % DIR_ENTRIES_PER_BLOCK;
  651.        
  652.     if (dir[block_i].type == TYPE_FILE && strcmp(dir[block_i].name, nome_orig) == 0)
  653.     {
  654.       int foutput = open(nome_dest, O_CREAT|O_TRUNC|O_WRONLY, 0644);
  655.       int cur = dir[block_i].first_block;
  656.  
  657.       write(foutput, BLOCK(cur), sb->block_size);
  658.       while (fat[cur] != -1)
  659.       {
  660.         cur = fat[cur];
  661.         write(foutput, BLOCK(cur), sb->block_size);
  662.       }
  663.  
  664.       return;
  665.     }
  666.   }
  667.  
  668.   printf("ERROR(put: file not found)\n");
  669.  
  670.   return;
  671. }
  672.  
  673.  
  674. // cat fich - escreve para o ecrã o conteúdo do ficheiro fich
  675. void vfs_cat(char *nome_fich) {
  676.   dir_entry *dir = (dir_entry *) BLOCK(current_dir);
  677.   int n_entries = dir[0].size, i;
  678.  
  679.   int cur_block = current_dir;
  680.   for (i = 0; i < n_entries; i++)
  681.   {
  682.     if (i % DIR_ENTRIES_PER_BLOCK == 0 && i)
  683.     {
  684.       if (DEBUG)
  685.         printf("Changed Block\n");
  686.       cur_block = fat[cur_block];
  687.       dir = (dir_entry *) BLOCK(cur_block);
  688.     }
  689.  
  690.     int block_i = i % DIR_ENTRIES_PER_BLOCK;
  691.        
  692.     if (dir[block_i].type == TYPE_FILE && strcmp(dir[block_i].name, nome_fich) == 0)
  693.     {
  694.       int next_block = dir[block_i].first_block;
  695.       write(1, BLOCK(next_block), sb->block_size);
  696.  
  697.       while (fat[next_block] != -1)
  698.       {
  699.         if (DEBUG)
  700.           printf("\nNext Block\n");
  701.         next_block = fat[next_block];
  702.  
  703.     int write_size = sb->block_size;
  704.     if (fat[next_block] == -1)
  705.       write_size = dir[block_i].size % sb->block_size;
  706.    
  707.         write(1, BLOCK(next_block), write_size);
  708.       }
  709.  
  710.       return;
  711.     }
  712.   }
  713.  
  714.   printf("ERROR(cat: file not found)\n");
  715.  
  716.   return;
  717. }
  718.  
  719.  
  720. // cp fich1 fich2 - copia o ficheiro fich1 para fich2
  721. // cp fich dir - copia o ficheiro fich para o subdirectório dir
  722. void vfs_cp(char *nome_orig, char *nome_dest) {
  723.   dir_entry *dir = (dir_entry *) BLOCK(current_dir);
  724.   int n_entries = dir[0].size, i, inp_block = -1, exp_dir = current_dir;
  725.  
  726.   int block_i;
  727.   int cur_block = current_dir;
  728.   for (i = 0; i < n_entries; i++)
  729.   {
  730.     if (i % DIR_ENTRIES_PER_BLOCK == 0 && i)
  731.     {
  732.       if (DEBUG)
  733.         printf("Changed Block\n");
  734.       cur_block = fat[cur_block];
  735.       dir = (dir_entry *) BLOCK(cur_block);
  736.     }
  737.  
  738.     block_i = i % DIR_ENTRIES_PER_BLOCK;
  739.        
  740.     if (strcmp(dir[block_i].name, nome_orig) == 0)
  741.     {
  742.       inp_block = dir[block_i].first_block;
  743.       break;
  744.     }
  745.   }
  746.  
  747.   if (inp_block == -1)
  748.   {
  749.     printf("ERROR(cp: input file not found)\n");
  750.     return;
  751.   }
  752.  
  753.   int req_size = dir[block_i].size;
  754.  
  755.   dir = (dir_entry *) BLOCK(current_dir);
  756.   cur_block = current_dir;
  757.   for (i = 0; i < n_entries; i++)
  758.   {
  759.     if (i % DIR_ENTRIES_PER_BLOCK == 0 && i)
  760.     {
  761.       if (DEBUG)
  762.         printf("Changed Block\n");
  763.       cur_block = fat[cur_block];
  764.       dir = (dir_entry *) BLOCK(cur_block);
  765.     }
  766.  
  767.     block_i = i % DIR_ENTRIES_PER_BLOCK;
  768.        
  769.     if (strcmp(dir[block_i].name, nome_dest) == 0)
  770.     {
  771.       if (dir[block_i].type == TYPE_DIR)
  772.       {
  773.         exp_dir = dir[block_i].first_block;
  774.         strcpy(nome_dest, nome_orig);
  775.       }
  776.       else
  777.         vfs_rm(nome_dest);
  778.  
  779.       break;
  780.     }
  781.   }
  782.  
  783.   dir_entry *cur_dir = (dir_entry *) BLOCK(exp_dir);
  784.   n_entries = cur_dir[0].size;
  785.   int req_blocks = (n_entries % DIR_ENTRIES_PER_BLOCK == 0) + (req_size + sb->block_size - 1) / sb->block_size;
  786.  
  787.   if (sb->n_free_blocks < req_blocks)
  788.   {
  789.     printf("ERROR(cp: memory full)\n");
  790.     return;
  791.   }
  792.  
  793.   req_blocks -= (n_entries % DIR_ENTRIES_PER_BLOCK == 0);
  794.  
  795.   cur_dir[0].size++;
  796.  
  797.   int first_block = get_free_block();
  798.   int new_block, next_block = first_block;
  799.   int count_block = 1, cur = inp_block;
  800.  
  801.   strcpy(BLOCK(next_block), BLOCK(cur));
  802.   while (fat[cur] != -1)
  803.   {
  804.     if (count_block != req_blocks)
  805.     {
  806.       count_block++;
  807.       new_block = get_free_block();
  808.       fat[next_block] = new_block;
  809.     }
  810.  
  811.     cur = fat[cur];
  812.     strcpy(BLOCK(next_block), BLOCK(cur));
  813.  
  814.     next_block = new_block;
  815.   }
  816.  
  817.   cur_block = exp_dir;
  818.   while (fat[cur_block] != -1)
  819.     cur_block = fat[cur_block];
  820.  
  821.   if (n_entries % DIR_ENTRIES_PER_BLOCK == 0)
  822.   {
  823.     int next_block = get_free_block();
  824.     fat[cur_block] = next_block;
  825.     cur_block = next_block;
  826.   }
  827.  
  828.   dir = (dir_entry *) BLOCK(cur_block);
  829.   init_dir_entry(&dir[n_entries % DIR_ENTRIES_PER_BLOCK], TYPE_FILE, nome_dest, req_size, first_block);
  830.  
  831.  
  832.   return;
  833. }
  834.  
  835.  
  836. // mv fich1 fich2 - move o ficheiro fich1 para fich2
  837. // mv fich dir - move o ficheiro fich para o subdirectório dir
  838. void vfs_mv(char *nome_orig, char *nome_dest) {
  839.   dir_entry *dir = (dir_entry *) BLOCK(current_dir);
  840.   int n_entries = dir[0].size, i, inp_block = -1, exp_dir = current_dir, req_size = -1;
  841.  
  842.   int block_i;
  843.   int cur_block = current_dir;
  844.   for (i = 0; i < n_entries; i++)
  845.   {
  846.     if (i % DIR_ENTRIES_PER_BLOCK == 0 && i)
  847.     {
  848.       if (DEBUG)
  849.         printf("Changed Block\n");
  850.       cur_block = fat[cur_block];
  851.       dir = (dir_entry *) BLOCK(cur_block);
  852.     }
  853.  
  854.     block_i = i % DIR_ENTRIES_PER_BLOCK;
  855.        
  856.     if (strcmp(dir[block_i].name, nome_orig) == 0)
  857.     {
  858.       int last_block = cur_block;
  859.       while (fat[last_block] != -1)
  860.         last_block = fat[last_block];
  861.       dir_entry *last_dir_block = (dir_entry *) BLOCK(last_block);
  862.       dir_entry last_dir = last_dir_block[(n_entries - 1 + DIR_ENTRIES_PER_BLOCK) % DIR_ENTRIES_PER_BLOCK];
  863.  
  864.       if ((n_entries - 1 + DIR_ENTRIES_PER_BLOCK) % DIR_ENTRIES_PER_BLOCK == 0)
  865.         delete_block(last_block);
  866.  
  867.       req_size = dir[block_i].size;
  868.  
  869.       dir[block_i].type = last_dir.type;
  870.       strcpy(dir[block_i].name, last_dir.name);
  871.       dir[block_i].day = last_dir.day;
  872.       dir[block_i].month = last_dir.month;
  873.       dir[block_i].year = last_dir.year;
  874.       dir[block_i].size = last_dir.size;
  875.       dir[block_i].first_block = last_dir.first_block;
  876.  
  877.       dir = (dir_entry *) BLOCK(current_dir);
  878.       dir[0].size--;
  879.      
  880.       inp_block = dir[block_i].first_block;
  881.       break;
  882.     }
  883.   }
  884.  
  885.   if (inp_block == -1)
  886.   {
  887.     printf("ERROR(mv: input file not found)\n");
  888.     return;
  889.   }
  890.  
  891.   dir = (dir_entry *) BLOCK(current_dir);
  892.   cur_block = current_dir;
  893.   for (i = 0; i < n_entries; i++)
  894.   {
  895.     if (i % DIR_ENTRIES_PER_BLOCK == 0 && i)
  896.     {
  897.       if (DEBUG)
  898.         printf("Changed Block\n");
  899.       cur_block = fat[cur_block];
  900.       dir = (dir_entry *) BLOCK(cur_block);
  901.     }
  902.  
  903.     block_i = i % DIR_ENTRIES_PER_BLOCK;
  904.        
  905.     if (strcmp(dir[block_i].name, nome_dest) == 0)
  906.     {
  907.       if (dir[block_i].type == TYPE_DIR)
  908.       {
  909.         exp_dir = dir[block_i].first_block;
  910.         strcpy(nome_dest, nome_orig);
  911.       }
  912.       else
  913.         vfs_rm(nome_dest);
  914.  
  915.       break;
  916.     }
  917.   }
  918.  
  919.   dir_entry *cur_dir = (dir_entry *) BLOCK(exp_dir);
  920.   n_entries = cur_dir[0].size;
  921.   cur_dir[0].size++;
  922.  
  923.   cur_block = exp_dir;
  924.   while (fat[cur_block] != -1)
  925.     cur_block = fat[cur_block];
  926.  
  927.   if (n_entries % DIR_ENTRIES_PER_BLOCK == 0)
  928.   {
  929.     int next_block = get_free_block();
  930.     fat[cur_block] = next_block;
  931.     cur_block = next_block;
  932.   }
  933.  
  934.   dir = (dir_entry *) BLOCK(cur_block);
  935.   init_dir_entry(&dir[n_entries % DIR_ENTRIES_PER_BLOCK], TYPE_FILE, nome_dest, req_size, inp_block);
  936.    
  937.   return;
  938. }
  939.  
  940.  
  941. // rm fich - remove o ficheiro fich
  942. void vfs_rm(char *nome_fich) {
  943.   dir_entry *dir = (dir_entry *) BLOCK(current_dir);
  944.   int n_entries = dir[0].size, i;
  945.  
  946.   int cur_block = current_dir;
  947.   for (i = 0; i < n_entries; i++)
  948.   {
  949.     if (i % DIR_ENTRIES_PER_BLOCK == 0 && i)
  950.     {
  951.       if (DEBUG)
  952.         printf("Changed Block\n");
  953.       cur_block = fat[cur_block];
  954.       dir = (dir_entry *) BLOCK(cur_block);
  955.     }
  956.  
  957.     int block_i = i % DIR_ENTRIES_PER_BLOCK;
  958.        
  959.     if (dir[block_i].type == TYPE_FILE && strcmp(dir[block_i].name, nome_fich) == 0)
  960.     {
  961.       int next_block = dir[block_i].first_block, count = 1;
  962.  
  963.       while (fat[next_block] != -1)
  964.       {
  965.         next_block = fat[next_block];
  966.         count++;
  967.       }
  968.  
  969.       sb->n_free_blocks += count;
  970.       fat[next_block] = sb->free_block;
  971.       sb->free_block = dir[block_i].first_block;
  972.  
  973.       int last_block = cur_block;
  974.       while (fat[last_block] != -1)
  975.         last_block = fat[last_block];
  976.       dir_entry *last_dir_block = (dir_entry *) BLOCK(last_block);
  977.       dir_entry last_dir = last_dir_block[(n_entries - 1 + DIR_ENTRIES_PER_BLOCK) % DIR_ENTRIES_PER_BLOCK];
  978.  
  979.       if ((n_entries - 1 + DIR_ENTRIES_PER_BLOCK) % DIR_ENTRIES_PER_BLOCK == 0)
  980.         delete_block(last_block);
  981.  
  982.       dir[block_i].type = last_dir.type;
  983.       strcpy(dir[block_i].name, last_dir.name);
  984.       dir[block_i].day = last_dir.day;
  985.       dir[block_i].month = last_dir.month;
  986.       dir[block_i].year = last_dir.year;
  987.       dir[block_i].size = last_dir.size;
  988.       dir[block_i].first_block = last_dir.first_block;
  989.  
  990.       dir = (dir_entry *) BLOCK(current_dir);
  991.       dir[0].size--;
  992.  
  993.       return;
  994.     }
  995.   }
  996.  
  997.   printf("ERROR(rm: file not found)\n");
  998.  
  999.   return;
  1000. }
RAW Paste Data
Want to get better at C?
Learn to code C in 2017
Top