Codi C del sistema de fitxers: inicialització, depuració i operacions bàsiques
Inicialització i creació del sistema de fitxers
static int sb_init(struct file_system *fs, int num_blocks, int percent_inodes) {
fs->sb.block_size = block_get_block_size(fs->dev);
fs->sb.num_inodes = num_blocks * percent_inodes / 100;
fs->sb.num_bitmap = num_blocks - 1 /* superbloc */ - fs->sb.num_inodes; /* blocs utilitzats pels inodes */
fs->sb.num_bitmap = fs->sb.num_bitmap + fs->sb.block_size - 1;
fs->sb.num_bitmap = fs->sb.num_bitmap / fs->sb.block_size;
fs->sb.num_data_blocks = num_blocks - fs->sb.num_inodes - fs->sb.num_bitmap - 1;
fs->sb.root_inode = 0;
return sb_write(fs->dev, &(fs->sb));
}
Inicialització del mapa de bits
static int bitmap_init(struct file_system *fs) {
int size = block_get_block_size(fs->dev);
char *block = malloc(size);
int i;
if (block == NULL) return -ENOMEM;
memset(block, '\0', size);
for (i = 0; i < fs->sb.num_bitmap; i++)
block_write(fs->dev, block, 1 + i);
bitmap_read(fs);
return 1;
}
Inicialització dels inodes
static int inodes_init(struct file_system *fs) {
struct disk_inode ino;
int i;
ino.size = -1; /* buit */
ino.e.start = -1;
ino.e.size = -1;
for (i = 0; i < fs->sb.num_inodes; i++)
inode_write(fs, &ino, i);
return 1;
}
Inicialització dels blocs de dades
static int data_init(struct file_system *fs) {
int size = block_get_block_size(fs->dev);
char *block = malloc(size);
int i;
if (block == NULL) return -ENOMEM;
memset(block, '@', size);
for (i = 0; i < fs->sb.num_data_blocks; i++)
data_write(fs, block, i);
return 1;
}
Creació del directori arrel
static int root_dir_create(struct file_system *fs) {
struct disk_inode root;
int i;
char block[fs->sb.block_size];
struct entry *dir = (struct entry *)block;
for (i = 0; i < fs->sb.block_size / sizeof(struct entry); i++)
dir[i].inode = -1;
root.size = 0;
root.e.start = 0;
root.e.size = 8; /* 8 blocs per defecte */
for (i = 0; i < root.e.size; i++) {
bitmap_set(fs, root.e.start + i);
data_write(fs, block, root.e.start + i);
}
bitmap_write(fs);
inode_write(fs, &root, fs->sb.root_inode);
return 1;
}
Funció principal de formatatge
int mfs_mkfs(char *name, int num_blocks, int size_block, int percent_inodes) {
printf("Creant sistema de fitxers %s amb %d blocs de " "mida %d i percentatge d'inodes %d\n", name, num_blocks, size_block, percent_inodes);
fs = malloc(sizeof(struct file_system));
if (fs == NULL) return -ENOMEM;
memset(fs, '\0', sizeof(struct file_system));
fs->dev = block_create(name, num_blocks, size_block);
if (fs->dev == NULL) {
printf("Error creant el sistema de fitxers %s\n", name);
perror("creant");
return -1;
}
if (sb_init(fs, num_blocks, percent_inodes) <= 0) return -1;
if (bitmap_init(fs) <= 0) return -1;
if (inodes_init(fs) <= 0) return -1;
if (data_init(fs) <= 0) return -1;
if (root_dir_create(fs) <= 0) return -1;
return 0;
}
Funcions de depuració
Impressió del superbloc
static int sb_print(struct file_system *fs) {
printf("Mostrant informació del superbloc:\n");
printf("block_size = %d\n", fs->sb.block_size);
printf("num_inodes = %d\n", fs->sb.num_inodes);
printf("num_bitmap = %d\n", fs->sb.num_bitmap);
printf("num_data_blocks = %d\n", fs->sb.num_data_blocks);
return 1;
}
Impressió del mapa de bits
static int bitmap_print(struct file_system *fs) {
int i;
for (i = 0; i < fs->sb.num_data_blocks; i++)
if (bitmap_get(fs, i)) printf("Bloc de dades %i utilitzat\n", i);
return 1;
}
Impressió dels inodes
static int inodes_print(struct file_system *fs) {
int i;
for (i = 0; i < fs->sb.num_inodes; i++) {
struct disk_inode ino;
inode_read(fs, &ino, i);
if (ino.size == -1) continue;
printf("Inode %d utilitzat\n", i);
printf("\tsize = %d\n", ino.size);
printf("\tstart = %d\n", ino.e.start);
printf("\tnum = %d\n", ino.e.size);
}
return 1;
}
Impressió dels blocs de dades
static int data_print(struct file_system *fs) {
int i;
char unitialized[fs->sb.block_size];
memset(unitialized, '@', fs->sb.block_size);
for (i = 0; i < fs->sb.num_data_blocks; i++) {
char block[fs->sb.block_size];
data_read(fs, block, i);
if (memcmp(block, unitialized, fs->sb.block_size) == 0) continue;
printf("Bloc de dades %d utilitzat\n", i);
printf("*****\n\n");
printf("%s", block);
printf("\n\n*****\n");
}
return 1;
}
Impressió del directori arrel
static int root_dir_print(struct file_system *fs) {
struct disk_inode root;
int i, j;
char block[fs->sb.block_size];
struct entry *dir = (struct entry *)block;
printf("Mostrant el directori arrel:\n");
inode_read(fs, &root, fs->sb.root_inode);
for (i = 0; i < root.e.size; i++) {
data_read(fs, block, root.e.start + i);
for (j = 0; j < fs->sb.block_size / sizeof(struct entry); j++)
if (dir[j].inode != -1)
printf("\t%s : inode %d\n", dir[j].name, dir[j].inode);
}
return 1;
}
int mfs_debug(char *name) {
printf("Depurant sistema de fitxers %s\n", name);
fs_init();
if (sb_print(fs) <= 0) return -1;
if (bitmap_print(fs) <= 0) return -1;
if (inodes_print(fs) <= 0) return -1;
if (data_print(fs) <= 0) return -1;
if (root_dir_print(fs) <= 0) return -1;
return 0;
}
Operacions sobre fitxers
Obertura de fitxers
int mfs_open(const char *pathname, int flags) {
fs_init();
int inode;
int fd = -1;
int i, j;
char block[fs->sb.block_size];
struct entry *dir = (struct entry *)block;
inode = namei(fs, &fs->root, pathname);
if (inode == -1 && (flags & O_CREAT)) {
for (i = 0; i < fs->root.e.size && inode == -1; i++) {
data_read(fs, block, fs->root.e.start + i);
for (j = 0; j < fs->sb.block_size / sizeof(struct entry); j++)
if (dir[j].inode == -1) {
inode = get_free_inode(fs);
if (inode == -1) return -1;
dir[j].inode = inode;
strncpy(dir[j].name, pathname, ENTRY_SIZE);
data_write(fs, block, fs->root.e.start + i);
inode = dir[j].inode;
break;
}
}
}
if (inode == -1) return -1;
for (i = 0; i < NUM_FILES; i++)
if (fs->file[i].num == -1) {
fd = i;
break;
}
if (fd != -1) {
inode_read(fs, &fs->file[fd].ino, inode);
fs->file[fd].pos = 0;
fs->file[fd].num = inode;
}
return fd;
}
Tancament de fitxers
int mfs_close(int fd) {
if (fd < 0 || fd >= NUM_FILES) return -1;
if (fs->file[fd].num == -1) {
printf("S'intenta tancar un fd no obert\n");
return -1;
}
inode_write(fs, &fs->file[fd].ino, fs->file[fd].num);
return 0;
}
Lectura de fitxers
int mfs_read(int fd, void *buf, size_t count) {
int start, not_done;
int num_block;
char block[fs->sb.block_size];
char *next;
if (fd < 0 || fd >= NUM_FILES) return -1;
if (fs->file[fd].num == -1) {
printf("S'intenta llegir un fd no obert\n");
return -1;
}
if (count > fs->file[fd].ino.size - fs->file[fd].pos)
count = fs->file[fd].ino.size - fs->file[fd].pos;
start = fs->file[fd].pos % fs->sb.block_size;
num_block = (fs->file[fd].pos / fs->sb.block_size) + fs->file[fd].ino.e.start;
not_done = count;
next = buf;
while (not_done) {
int len;
if (not_done > fs->sb.block_size - start)
len = fs->sb.block_size - start;
else
len = not_done;
if (len != fs->sb.block_size) {
data_read(fs, block, num_block);
memcpy(next, block + start, len);
} else {
data_read(fs, next, num_block);
}
num_block++;
not_done -= len;
next += len;
start = 0;
}
fs->file[fd].pos += count;
return count;
}