Simple File System Simulator ( Virtual File System on linux 2.6 )
Description
Source Code
Makefile
makefile
simple_file_system : main.o vfs.o shell.o disk.o
gcc -o simple_file_system main.o vfs.o shell.o disk.o
main.o : main.c
gcc -c main.c
vfs.o : vfs.h vfs.c
gcc -c vfs.c
shell.o : shell.h shell.c
gcc -c shell.c
disk.o : disk.h disk.c
gcc -c disk.c
main.c
c
/* main.c */
#include "shell.h"
int main(void) {
printf("\n");
printf("\t-+- SFS with mini shell -+-\n");
printf("\n");
printf("\t Command List:$ help\n");
printf("\n");
shell_main();
return 0;
}
shell.h
c
/* shell.h */
#ifndef _SHELL_H_
#define _SHELL_H_
#include "vfs.h"
void shell_main();
#endif
shell.c
c
/* shell.c */
#include "shell.h"
char buf[4][MAX_CHAR];
char buf_line[MAX_CHAR * 4];
char user_name[MAX_CHAR] = "user";
char str[2][3] = {".", ".."};
int buf_size[4];
void shell_print_mode(int mode) {
if(mode / 4) {
putc('r', stdout);
} else {
putc('-', stdout);
}
if((mode % 4) / 2) {
putc('w', stdout);
} else {
putc('-', stdout);
}
if((mode % 4) % 2) {
putc('x', stdout);
} else {
putc('-', stdout);
}
return;
}
void shell_print_name(char name[]) {
int i;
for(i = 0; i < MAX_CHAR; ++i) {
if(name[i] == '|') {
break;
}
putc(name[i], stdout);
}
return;
}
void shell_print_path(struct dentry *d) {
int i;
if(d == d->parent) {
putc('/', stdout);
return;
}
shell_print_path(d->parent);
shell_print_name(d->name);
putc('/', stdout);
return;
}
void shell_print_time(struct tm c) {
printf("%04d-%02d-%02d %02d:%02d:%02d ",
c.tm_year + 1900, c.tm_mon, c.tm_mday,
c.tm_hour, c.tm_min, c.tm_sec);
return;
}
void shell_command_ls(FILE *disk, struct dentry *d) {
int i,x;
// directory mode check
if(d->sb->s_mode == USER_MODE) {
if(!vfs_mode_read(d->d_mode)) {
printf("Permission dennied\n");
return;
}
if(!vfs_mode_excute(d->d_mode)) {
printf("Permission dennied\n");
return;
}
}
vfs_dentry_open(disk, d);
// printf("ls\n");
x = 0;
for(i = 0; i < MAX_D_INODE; ++i) {
if(d->d_inode[i] != NULL) {
shell_print_name(d->d_inode[i]->name);
putc(' ', stdout);
x = 1;
}
}
if(x != 0) {
putc('\n', stdout);
}
// printf("inode:%d, dentry:%d\n", d->num_inode, d->num_dentry);
return;
}
void shell_command_ll(FILE *disk, struct dentry *d) {
int i;
// directory mode check
if(d->sb->s_mode == USER_MODE) {
if(!vfs_mode_read(d->d_mode)) {
printf("Permission dennied\n");
return;
}
if(!vfs_mode_excute(d->d_mode)) {
printf("Permission dennied\n");
return;
}
}
vfs_dentry_open(disk, d);
//printf("%s\n", d->name);
printf("AUTH SIZE CREATED ACCESSED NAME \n");
for(i = -2; i < MAX_D_INODE; ++i) {
if(i < 0) {
shell_print_mode(d->d_dentry[i + 2]->d_mode);
printf(" ");
shell_print_time(d->d_dentry[i + 2]->d_ctime);
shell_print_time(d->d_dentry[i + 2]->d_atime);
printf("%s/\n", str[i + 2]);
} else {
if(d->d_inode[i] != NULL) {
shell_print_mode(d->d_inode[i]->i_mode);
printf(" %7d ", d->d_inode[i]->size);
shell_print_time(d->d_inode[i]->i_ctime);
shell_print_time(d->d_inode[i]->i_atime);
shell_print_name(d->d_inode[i]->name);
if(d->d_inode[i]->i_type == INODE_DIRECTORY) {
putc('/', stdout);
}
putc('\n', stdout);
}
}
}
return;
}
void shell_command_rmdir(FILE *disk, struct dentry *d, char name[]) {
int i;
// directory mode check
if(d->sb->s_mode == USER_MODE) {
if(!vfs_mode_excute(d->d_mode)) {
printf("Permission dennied\n");
return;
}
}
i = vfs_inode_remove(disk, d, name, INODE_DIRECTORY);
if(i < 0) {
if(i == -1) {
printf("rmdir: \'");
shell_print_name(name);
printf("\' cannot remove directory: 파일이 없습니다\n");
}
if(i == -2) {
printf("rmdir: \'");
shell_print_name(name);
printf("\' cannot remove directory: 디렉토리가 아닙니다\n");
}
if(i == -3) {
printf("rmdir: \'");
shell_print_name(name);
printf("\' cannot remove directory: 디렉토리가 비어있지 않습니다\n");
}
if(i == -8) {
printf("Permission dennied\n");
}
}
return;
}
void shell_command_rmfile(FILE *disk, struct dentry *d, char name[]) {
int i;
// directory mode check
if(d->sb->s_mode == USER_MODE) {
if(!vfs_mode_excute(d->d_mode)) {
printf("Permission dennied\n");
return;
}
}
i = vfs_inode_remove(disk, d, name, INODE_FILE);
if(i < 0) {
if(i == -1) {
printf("rmfile: \'");
shell_print_name(name);
printf("\' cannot remove file: 파일이 없습니다\n");
}
if(i == -4) {
printf("rmfile: \'");
shell_print_name(name);
printf("\' cannot remove file: 파일이 아닙니다\n");
}
if(i == -8) {
printf("Permission dennied\n");
}
}
return;
}
void shell_command_mkdir(FILE *disk, struct dentry *d, char name[]) {
int i;
// directory mode check
if(d->sb->s_mode == USER_MODE) {
if(!vfs_mode_excute(d->d_mode)) {
printf("Permission dennied\n");
return;
}
}
if(vfs_compare_name(".|", name) == 0 || vfs_compare_name("..|", name) == 0) {
i = -2;
} else {
vfs_dentry_open(disk, d);
i = vfs_inode_make(disk, d, name, 0, INODE_DIRECTORY);
}
if(i < 0) {
if(i == -1) {
printf("mkdir: \'");
shell_print_name(name);
printf("\' cannot make directory: 파일이 있습니다\n");
}
if(i == -2) {
printf("mkdir: \'");
shell_print_name(name);
printf("\' cannot make directory: 사용할 수 없는 이름입니다\n");
}
if(i == -8) {
printf("Permission dennied\n");
}
return;
}
return;
}
void shell_command_mkfile(FILE *disk, struct dentry *d, char name[], int size) {
int i;
// directory mode check
if(d->sb->s_mode == USER_MODE) {
if(!vfs_mode_excute(d->d_mode)) {
printf("Permission dennied\n");
return;
}
}
if(vfs_compare_name(".|", name) == 0 || vfs_compare_name("..|", name) == 0) {
i = -2;
} else {
vfs_dentry_open(disk, d);
i = vfs_inode_make(disk, d, name, size, INODE_FILE);
}
if(i < 0) {
if(i == -1) {
printf("mkfile: \'");
shell_print_name(name);
printf("\' cannot make file: 파일이 있습니다\n");
}
if(i == -2) {
printf("mkfile: \'");
shell_print_name(name);
printf("\' cannot make file: 사용할 수 없는 이름입니다\n");
}
if(i == -8) {
printf("Permission dennied\n");
}
}
return;
}
void* shell_command_cd(FILE *disk, struct dentry *d, char name[]) {
struct dentry *child;
int i;
// init
child = NULL;
if(vfs_compare_name(".|", name) == 0) {
child = d;
} else if(vfs_compare_name("..|", name) == 0) {
child = d->parent;
} else {
vfs_dentry_open(disk, d);
for(i = 0; i < MAX_D_CHILD; ++i) {
if(d->d_dentry[i] != NULL) {
if(vfs_compare_name(d->d_dentry[i]->name, name) == 0) {
break;
}
}
}
if(i == MAX_D_CHILD) {
printf("cd: ");
shell_print_name(name);
printf(": 디렉토리가 없습니다.\n");
return child;
}
child = d->d_dentry[i];
}
// directory mode check
if(child->sb->s_mode == USER_MODE) {
if(!vfs_mode_excute(child->d_mode)) {
printf("Permission dennied\n");
}
}
// vfs_dentry_open(disk, child);
return child;
}
void shell_command_mv(FILE *disk, struct dentry *d, char name[], char new_name[]) {
int i, j;
// directory mode check
if(d->sb->s_mode == USER_MODE) {
if(!vfs_mode_write(d->d_mode)) {
printf("Permission dennied\n");
return;
}
// if(!vfs_mode_excute(d->d_mode)) {
// printf("Permission dennied\n");
// return;
// }
}
// if name == new_name
if(vfs_compare_name(name, new_name) == 0) {
return;
}
// search by name
for(i = 0; i < MAX_D_INODE; ++i) {
if(d->d_inode[i] != NULL) {
if(vfs_compare_name(d->d_inode[i]->name, new_name) == 0) {
break;
}
}
}
if(i != MAX_D_INODE) {
printf("mv: ");
shell_print_name(name);
printf(": 이미 존재하는 파일명입니다\n");
return;
}
// search by new_name
for(i = 0; i < MAX_D_INODE; ++i) {
if(d->d_inode[i] != NULL) {
if(vfs_compare_name(d->d_inode[i]->name, name) == 0) {
vfs_inode_rename(disk, d->d_inode[i], new_name);
break;
}
}
}
if(i == MAX_D_INODE) {
printf("mv: ");
shell_print_name(name);
printf(": 파일이 없습니다\n");
return;
}
// if it is directory
if(d->d_inode[i]->i_type == INODE_DIRECTORY) {
for(j = 0; j < MAX_D_CHILD; ++i) {
if(d->d_dentry[j] != NULL) {
if(vfs_compare_name(d->d_dentry[j]->name, name) == 0) {
vfs_dentry_rename(d->d_dentry[j], d->d_inode[i]);
break;
}
}
}
}
return;
}
void shell_command_chmod(FILE *disk, struct dentry *d, char mode_str[], char name[]) {
int i, j, mode;
// directory mode check
if(d->sb->s_mode == USER_MODE) {
if(!vfs_mode_write(d->d_mode)) {
printf("Permission dennied\n");
return;
}
// if(!vfs_mode_excute(d->d_mode)) {
// printf("Permission dennied\n");
// return;
// }
}
// decoding option
mode = 0;
if(mode_str[0] == 'r') {
mode += 4;
} else if(mode_str[0] != '-') {
mode = -8;
}
if(mode_str[1] == 'w') {
mode += 2;
} else if(mode_str[1] != '-') {
mode = -8;
}
if(mode_str[2] == 'x') {
mode += 1;
} else if(mode_str[2] != '-') {
mode = -8;
}
if(mode < 0) {
printf("chmod: 옵션이 잘못되었습니다\n");
return;
}
// search by name
for(i = 0; i < MAX_D_INODE; ++i) {
if(d->d_inode[i] != NULL) {
if(vfs_compare_name(d->d_inode[i]->name, name) == 0) {
vfs_inode_chmod(disk, d->d_inode[i], mode);
break;
}
}
}
if(i == MAX_D_INODE) {
printf("chmod: ");
shell_print_name(name);
printf(": 파일이 없습니다\n");
return;
}
// printf("chmod\n");
// if it is directory
if(d->d_inode[i]->i_type == INODE_DIRECTORY) {
for(j = 0; j < MAX_D_CHILD; ++j) {
if(d->d_dentry[j] != NULL) {
if(vfs_compare_name(d->d_dentry[j]->name, name) == 0) {
// printf("chmod\n");
vfs_dentry_chmod(d->d_dentry[j], d->d_inode[i]);
// printf("chmod\n");
break;
}
}
}
}
// printf("chmod\n");
return;
}
void shell_command_df(FILE *disk, struct dentry *d) {
printf("disk.img: %ld / %ld (%ld%%)\n", d->sb->s_blocksize, d->sb->s_maxbytes, (unsigned long)((d->sb->s_blocksize * 100) / d->sb->s_maxbytes));
return;
}
char *indirect_type[] = {"", "single", "double", "triple"};
void shell_print_indirect_block(FILE *disk, int block_addr, int depth) {
int k, addr;
if(block_addr == 0) {
return;
}
if(depth == 0) {
if(block_addr != 0) {
printf(" %08x", block_addr);
}
return;
}
printf("\n [%s:%08x]", indirect_type[depth], block_addr);
for(k = 0; k < DISK_BLOCK_SIZE / 8; ++k) {
fseek(disk, block_addr + k*8, SEEK_SET);
addr = disk_read_int(disk);
if(addr != 0) {
shell_print_indirect_block(disk, addr, depth - 1);
}
}
return;
}
void shell_command_blocks(FILE *disk, struct dentry *d, char name[]) {
struct inode *in;
int i;
// search by name
for(i = 0; i < MAX_D_INODE; ++i) {
if(d->d_inode[i] != NULL) {
if(vfs_compare_name(d->d_inode[i]->name, name) == 0) {
break;
}
}
}
if(i == MAX_D_INODE) {
printf("blocks: ");
shell_print_name(name);
printf(": 파일이 없습니다\n");
return;
}
// mode check
if(d->sb->s_mode == USER_MODE) {
if(!vfs_mode_read(d->d_inode[i]->i_mode)) {
printf("Permission dennied\n");
return;
}
}
// print
in = d->d_inode[i];
if(in->direct_block[0] == NULL) {
printf("0 block");
} else {
printf("direct blocks:\n");
for(i = 0; i < 12; ++i) {
if(in->direct_block[i] != NULL) {
printf(" %08x", (int)in->direct_block[i]);
}
}
if(in->single_block != NULL) {
printf("\nsingle indirect blocks:");
shell_print_indirect_block(disk, (int)in->single_block, 1);
}
if(in->double_block != NULL) {
printf("\ndouble indirect blocks:");
shell_print_indirect_block(disk, (int)in->double_block, 2);
}
if(in->triple_block != NULL) {
printf("\ntriple indirect blocks:");
shell_print_indirect_block(disk, (int)in->triple_block, 3);
}
}
printf("\n");
return;
}
// shell command
const int num_command = 14;
const int num_command_without_permission = 5;
char *command[] =
{"help", "sudo", "su", "cd", "df",
"ls", "ll", "rmdir", "rmfile", "mkdir",
"mkfile", "mv", "chmod", "blocks"};
char *command_help[] =
{"", "\t-Command", "", "\t-Directory", "",
"", "", "\t-Directory", "\t-File", "\t-Directory",
"\t-File\t-Size", "\t-File1\t-File2", "\t-(rwx)\t-File", ""};
void shell_command_help() {
int i;
for(i = 0; i < num_command; ++i) {
printf("%s\t%s\n", command[i], command_help[i]);
}
return;
}
void* shell_command(FILE *disk, struct dentry *current, char buf[][MAX_CHAR], int buf_size[]) {
struct dentry *child;
int i;
// init
child = NULL;
// mod buf
if(buf_size[0] > 64) {
buf_size[0] = 63;
}
buf[0][buf_size[0]] = '\0';
if(buf_size[1] > 64) {
buf_size[1] = 63;
}
buf[1][buf_size[1]] = '|';
if(buf_size[2] > 64) {
buf_size[2] = 63;
}
buf[2][buf_size[2]] = '|';
// check command list
for(i = 0; i < num_command; ++i) {
if(strcmp(buf[0], command[i]) == 0) {
break;
}
}
if(i == num_command) {
i = -1;
}
if(i >= num_command_without_permission) {
// directory mode check
if(current->sb->s_mode == USER_MODE) {
if(!vfs_mode_excute(current->d_mode)) {
printf("Permission dennied\n");
return child;
}
}
}
// excute command
switch(i) {
case 0: shell_command_help(); break;
case 1: current->sb->s_mode = ROOT_MODE;
shell_command(disk, current, buf+1, buf_size+1);
current->sb->s_mode = USER_MODE; break;
case 2: current->sb->s_mode = ROOT_MODE; break;
case 3: child = shell_command_cd(disk, current, buf[1]); break;
case 4: shell_command_df(disk, current); break;
case 5: shell_command_ls(disk, current); break;
case 6: shell_command_ll(disk, current); break;
case 7: shell_command_rmdir(disk, current, buf[1]); break;
case 8: shell_command_rmfile(disk, current, buf[1]); break;
case 9: shell_command_mkdir(disk, current, buf[1]); break;
case 10: if(buf_size[2] > 8) {
buf_size[2] = 8;
}
buf[2][buf_size[2]] = '\0';
// printf("%d\n", atoi(buf[2]));
shell_command_mkfile(disk, current, buf[1], atoi(buf[2])); break;
case 11: shell_command_mv(disk, current, buf[1], buf[2]); break;
case 12: shell_command_chmod(disk, current, buf[1], buf[2]); break;
case 13: shell_command_blocks(disk, current, buf[1]); break;
default: printf("%s: command not found\n", buf[0]); break;
};
//printf("shell_command\n");
return child;
}
void shell_main() {
FILE *disk;
struct super_block *sb;
struct dentry *root;
struct dentry *current;
struct dentry *child;
int num_buf, i, j, k;
// mount disk
disk = disk_init("disk.img");
sb = vfs_sb_init(disk);
root = sb->s_root;
current = root;
while(1) {
if(sb->s_mode == USER_MODE) {
printf("%s:", user_name);
} else {
printf("%s:", "root");
}
shell_print_path(current);
putc('$', stdout);
putc(' ', stdout);
//scanf("%s\n", buf_line);
fgets(buf_line, MAX_CHAR * 4, stdin);
i = 0;
for(j = 0; j < MAX_CHAR * 4; ++j) {
if(buf_line[j] == ' ') {
continue;
}
for(k = 0; k < MAX_CHAR; ++k) {
if(buf_line[j] == '\n' || buf_line[j] == '\0') {
++i;
break;
} else if(buf_line[j] == ' ') {
++i;
break;
}
buf[i][k] = buf_line[j];
++j;
}
// printf("%d %d\n", k, i);
if(k > 0) {
buf_size[i - 1] = k;
}
if(i >= 4) {
break;
}
if(buf_line[j] == '\n') {
for(k = i; k < 4; ++k) {
buf_size[k] = 0;
}
break;
}
}
//num_buf = i + 1;
//printf("num_buf: %d\n", num_buf);
if(strncmp(buf[0], "exit", 4) == 0) {
if(sb->s_mode == USER_MODE) {
break;
} else {
sb->s_mode = USER_MODE;
}
} else if(buf[0][0] != '\n' && buf[0][0] != '\0') {
//printf("sss\n");
child = shell_command(disk, current, buf, buf_size);
if(child != NULL) {
current = child;
}
} else {
}
memset(buf_line, '\0', MAX_CHAR * 4);
memset(buf[0], '\0', MAX_CHAR);
memset(buf[1], '\0', MAX_CHAR);
memset(buf[2], '\0', MAX_CHAR);
}
//fseek(disk, 0, SEEK_END);
// unmount disk
fclose(disk);
}
vfs.h
c
/* vfs.h */
#ifndef _FS_H_
#define _FS_H_
#include "disk.h"
#define MAX_D_CHILD (DISK_BLOCK_SIZE / BYTE) * DIRECTORY_ENTRY_BLOCK_NUM
#define MAX_D_INODE (DISK_BLOCK_SIZE / BYTE) * DIRECTORY_ENTRY_BLOCK_NUM
#define DENTRY_CLOSE 0
#define DENTRY_OPEN 1
#define USER_MODE 0
#define ROOT_MODE 1
// VFS Structure
struct dentry {
int d_type;
int d_mode;
char name[MAX_CHAR];
struct super_block *sb;
struct dentry *parent;
int num_dentry;
struct dentry *d_dentry[MAX_D_CHILD];
int num_inode;
struct inode *d_inode[MAX_D_INODE];
struct tm d_ctime;
struct tm d_atime;
};
struct super_block {
int s_mode;
struct dentry *s_root;
struct inode *s_root_inode;
unsigned long s_blocksize;
unsigned long s_maxbytes;
};
struct inode {
int i_type;
int i_mode;
int id;
char name[MAX_CHAR];
struct tm i_ctime;
struct tm i_atime;
int size;
void* direct_block[12];
void* single_block;
void* double_block;
void* triple_block;
};
// VFS PROC
struct tm vfs_set_time();
int vfs_mode_read(int mode);
int vfs_mode_write(int mode);
int vfs_mode_excute(int mode);
int vfs_compare_name(char name1[], char name2[]);
void vfs_inode_chmod(FILE *disk, struct inode *i, int mode);
void vfs_inode_rename(FILE *disk, struct inode *i, char name[]);
void* vfs_inode_read(FILE *disk, int addr);
int vfs_inode_remove(FILE *disk, struct dentry *d, char name[], int flag);
int vfs_inode_make(FILE *disk, struct dentry *d, char name[], int size, int flag);
void vfs_dentry_chmod(struct dentry *d, struct inode *i);
void vfs_dentry_rename(struct dentry *d, struct inode *i);
void* vfs_dentry_make(struct dentry *p, struct inode *i);
void vfs_dentry_open(FILE *disk, struct dentry *d);
void vfs_sb_refresh(FILE *disk, struct super_block *sb);
void* vfs_sb_init(FILE *disk);
#endif
vfs.c
c
/* vfs.c */
#include "vfs.h"
// VFS PROC
struct tm vfs_set_time() {
time_t timer;
struct tm *c;
timer = time(NULL);
c = localtime(&timer);
//free(c);
return *c;
}
int vfs_mode_read(int mode) {
return (mode / 4);
}
int vfs_mode_write(int mode) {
return ((mode % 4) / 2);
}
int vfs_mode_excute(int mode) {
return (((mode % 4) % 2));
}
int vfs_compare_name(char name1[], char name2[]) {
int i;
for(i = 0; i < MAX_CHAR; ++i) {
if(name1[i] == '|' && name2[i] == '|') {
break;
}
if(name1[i] != name2[i]) {
return -1;
}
}
return 0;
}
void vfs_inode_chmod(FILE *disk, struct inode *i, int mode) {
char buf[MAX_CHAR];
i->i_mode = mode;
i->i_atime = vfs_set_time();
// printf("inode_chmod\n");
fseek(disk, i->id, SEEK_SET);
disk_read_int(disk);
disk = disk_write_int(disk,i->i_mode);
// printf("inode_chmod\n");
disk_read_name(disk, buf);
// printf("inode_chmod\n");
disk_read_time(disk);
disk = disk_write_time(disk, i->i_atime);
// printf("inode_chmod\n");
return;
}
void vfs_inode_rename(FILE *disk, struct inode *i, char name[]) {
strncpy(i->name, name, MAX_CHAR);
i->i_atime = vfs_set_time();
fseek(disk, i->id, SEEK_SET);
disk_read_int(disk);
disk_read_int(disk);
disk = disk_write_name(disk, i->name);
disk_read_time(disk);
disk = disk_write_time(disk, i->i_atime);
return;
}
void* vfs_inode_read(FILE *disk, int addr) {
struct inode *i;
int disk_addr, k;
if(addr == 0) {
return NULL;
}
i = (struct inode*)malloc(sizeof(struct inode));
// disk_addr = addr / BYTE;
disk_addr = addr;
fseek(disk, disk_addr, SEEK_SET);
i->i_type = disk_read_int(disk);
i->i_mode = disk_read_int(disk);
// i->id = (disk_addr - INODE_TABLE_ADDR) / INODE_SIZE;
i->id = disk_addr;
disk_read_name(disk, i->name);
i->i_ctime = disk_read_time(disk);
i->i_atime = disk_read_time(disk);
i->size = disk_read_int(disk);
for(k = 0; k < 12; ++k) {
i->direct_block[k] = (void*)disk_read_int(disk);
}
i->single_block = (void*)disk_read_int(disk);
i->double_block = (void*)disk_read_int(disk);
i->triple_block = (void*)disk_read_int(disk);
return i;
}
int vfs_inode_remove(FILE *disk, struct dentry *d, char name[], int flag) {
struct dentry *p, *i_dentry;
struct inode *i, *d_inode;
int i_addr, block_addr, remain_size, j, k, l;
// directory mode check
if(d->sb->s_mode == USER_MODE) {
if(!vfs_mode_write(d->d_mode)) {
//printf("inode_remove\n");
return -8;
}
}
// search inode with same name
i = NULL;
for(k = 0; k < MAX_D_INODE; ++k) {
if(d->d_inode[k] != NULL) {
//if(strncmp(d->d_inode[k]->name, name, MAX_CHAR) == 0) {
if(vfs_compare_name(d->d_inode[k]->name, name) == 0) {
i = d->d_inode[k];
break;
}
//printf("%s\n", d->d_inode[k]->name);
}
}
if(i == NULL) {
return -1;
}
// inode mode check
if(d->sb->s_mode == USER_MODE) {
if(!vfs_mode_write(i->i_mode)) {
return -8;
}
}
// search dentry with same name
i_dentry = NULL;
for(k = 0; k < MAX_D_CHILD; ++k) {
if(d->d_dentry[k] != NULL) {
//if(strncmp(d->d_dentry[k]->name, name, MAX_CHAR) == 0) {
if(vfs_compare_name(d->d_dentry[k]->name, name) == 0) {
i_dentry = d->d_dentry[k];
break;
}
}
}
if(flag == INODE_DIRECTORY) {
if(i_dentry == NULL) {
return -2;
}
vfs_dentry_open(disk, i_dentry);
if(i_dentry->num_inode != 0) {
return -3;
}
} else {
if(i_dentry != NULL) {
return -4;
}
}
// search directory inode
p = d->parent;
// if(p != NULL) { // not root directory
if(p != d) { // not root directory
for(k = 0; k < MAX_D_INODE; ++k) {
if(vfs_compare_name(d->name, p->d_inode[k]->name) == 0) {
d_inode = p->d_inode[k];
break;
}
}
} else { // root directory
d_inode = d->sb->s_root_inode;
}
// remove inode block addr
for(k = 0; k < DIRECTORY_ENTRY_BLOCK_NUM; ++k) {
// fseek(disk, (int)d_inode->direct_block[k] / BYTE, SEEK_SET);
fseek(disk, (int)d_inode->direct_block[k], SEEK_SET);
for(l = 0; l < DISK_BLOCK_SIZE / BYTE; ++l) {
i_addr = disk_read_int(disk);
if(i_addr == i->id) {
fseek(disk, -BYTE, SEEK_CUR);
disk = disk_write_int(disk, 0);
break;
}
}
if(l != DISK_BLOCK_SIZE / BYTE) {
break;
}
}
// remove inode pointer
--d->num_inode;
for(k = 0; k < MAX_D_INODE; ++k) {
if(d->d_inode[k] == i) {
d->d_inode[k] = NULL;
break;
}
}
// remove dentry pointer
if(flag == INODE_DIRECTORY) {
--d->num_dentry;
for(k = 0; k < MAX_D_CHILD; ++k) {
if(d->d_dentry[k] == i_dentry) {
d->d_dentry[k] = NULL;
break;
}
}
}
// free inode's data blocks
d->sb->s_blocksize -= i->size;
// direct blocks
for(k = 0; k < 12; ++k) {
block_addr = (int)i->direct_block[k];
if(block_addr != 0) {
//d->sb->s_blocksize -= DISK_BLOCK_SIZE;
disk_free_block(disk, (int)i->direct_block[k]);
}
}
// indirect blocks
disk_free_indirect_block(disk, (int)i->single_block, 1);
disk_free_indirect_block(disk, (int)i->double_block, 2);
disk_free_indirect_block(disk, (int)i->triple_block, 3);
//free data block end
// free inode block
disk_free_inode(disk, i->id);
// super_block refresh
vfs_sb_refresh(disk, p->sb);
// debug: inode table address
// printf("%08x \n", i->id);
// free pointers
free(i);
if(flag == INODE_DIRECTORY) {
free(i_dentry);
}
return 0;
}
int vfs_inode_make(FILE *disk, struct dentry *d, char name[], int size, int flag) {
struct dentry *p;
struct inode *i, *d_inode;
int i_addr, remain_size, real_size, block_num, j, k, l;
// directory mode check
if(d->sb->s_mode == USER_MODE) {
if(!vfs_mode_write(d->d_mode)) {
return -8;
}
}
// check inode with same name
for(k = 0; k < MAX_D_INODE; ++k) {
if(d->d_inode[k] != NULL) {
//if(strncmp(d->d_inode[k]->name, name, MAX_CHAR) == 0) {
if(vfs_compare_name(d->d_inode[k]->name, name) == 0) {
return -1;
}
}
}
// search directory inode
p = d->parent;
if(p != d) { // not root directory
for(k = 0; k < MAX_D_INODE; ++k) {
if(vfs_compare_name(d->name, p->d_inode[k]->name) == 0) {
d_inode = p->d_inode[k];
break;
}
}
} else { // root directory
d_inode = d->sb->s_root_inode;
}
// make new inode
i = (struct inode*)malloc(sizeof(struct inode));
// inode block alloc
i->id = disk_alloc_inode(disk);
if(i->id == 0) {
free(i);
return -5;
}
i->i_type = flag;
if(flag == INODE_FILE) {
i->i_mode = 6;
} else {
i->i_mode = 7;
}
//i->id = (disk_addr - INODE_TABLE_ADDR) / INODE_SIZE;
strncpy(i->name, name, MAX_CHAR);
// printf("%s\n", i->name);
i->i_ctime = vfs_set_time();
i->i_atime = i->i_ctime;
// disk block alloc
if(i->i_type == INODE_DIRECTORY) {
i->size = DISK_BLOCK_SIZE * DIRECTORY_ENTRY_BLOCK_NUM;
for(k = 0; k < DIRECTORY_ENTRY_BLOCK_NUM; ++k) {
i->direct_block[k] = (void*)disk_alloc_block(disk);
d->sb->s_blocksize += DISK_BLOCK_SIZE;
}
for(k = DIRECTORY_ENTRY_BLOCK_NUM; k < 12; ++k) {
i->direct_block[k] = NULL;
}
i->single_block = NULL;
i->double_block = NULL;
i->triple_block = NULL;
} else {
i->size = size;
remain_size = i->size;
k = remain_size % DISK_BLOCK_SIZE;
remain_size = remain_size / DISK_BLOCK_SIZE;
if(k != 0) {
remain_size += 1;
}
// direct block
/* for(k = 0; k < 12; ++k) {
i->direct_block[k] = (void*)disk_alloc_block(disk);
//d->sb->s_blocksize += DISK_BLOCK_SIZE;
// fseek(disk, ((int)i->direct_block[k]) / BYTE , SEEK_SET);
if(remain_size == 0 || (remain_size > 0 && i->direct_block[k] == NULL)) {
} else {
fseek(disk, (int)i->direct_block[k], SEEK_SET);
for(l = 0; l < 1024; ++l) {
if(remain_size == 0) {
break;
}
--remain_size;
disk = disk_write_char(disk, '1');
}
}
if(remain_size == 0) {
break;
}
} */
for(k = 0; k < 12; ++k) {
if(remain_size > 0) {
i->direct_block[k] = (void*)disk_alloc_block(disk);
} else {
i->direct_block[k] = NULL;
}
if(i->direct_block[k] != NULL) {
--remain_size;
}
}
// indirect single block
/*
i->single_block = NULL;
i->double_block = NULL;
i->triple_block = NULL; */
//printf("%d\n", remain_size);
i->single_block = (void*)disk_alloc_indirect_block(disk, &remain_size, 1);
//printf("%d\n", remain_size);
// indirect double block
i->double_block = (void*)disk_alloc_indirect_block(disk, &remain_size, 2);
//printf("%d\n", remain_size);
// indirect triple block
i->triple_block = (void*)disk_alloc_indirect_block(disk, &remain_size, 3);
//printf("%d\n", remain_size);
if(remain_size > 0) {
real_size = size / DISK_BLOCK_SIZE;
if(size % DISK_BLOCK_SIZE != 0) {
real_size += 1;
}
i->size = (real_size - remain_size) * DISK_BLOCK_SIZE;
}
}
// write new inode
// fseek(disk, i->id / BYTE, SEEK_SET);
fseek(disk, i->id, SEEK_SET);
disk = disk_write_int(disk, i->i_type);
disk = disk_write_int(disk, i->i_mode);
disk = disk_write_name(disk, i->name);
disk = disk_write_time(disk, i->i_ctime);
disk = disk_write_time(disk, i->i_atime);
disk = disk_write_int(disk, i->size);
for(k = 0; k < 12; ++k) {
disk = disk_write_int(disk, (int)i->direct_block[k]);
}
disk = disk_write_int(disk, (int)i->single_block);
disk = disk_write_int(disk, (int)i->double_block);
disk = disk_write_int(disk, (int)i->triple_block);
// write inode block addr to d_inode
for(k = 0; k < DIRECTORY_ENTRY_BLOCK_NUM; ++k) {
// fseek(disk, (int)d_inode->direct_block[k] / BYTE, SEEK_SET);
fseek(disk, (int)d_inode->direct_block[k], SEEK_SET);
for(l = 0; l < DISK_BLOCK_SIZE / BYTE; ++l) {
i_addr = disk_read_int(disk);
if(i_addr == 0) {
fseek(disk, -BYTE, SEEK_CUR);
disk = disk_write_int(disk, i->id);
break;
}
}
if(l != DISK_BLOCK_SIZE / BYTE) {
break;
}
}
// add inode pointer to d
for(k = 0; k < MAX_D_INODE; ++k) {
if(d->d_inode[k] == NULL) {
break;
}
}
d->d_inode[k] = i;
++d->num_inode;
//debug: p->d_dentry
// for(k = 0; k < MAX_D_CHILD; ++k) {
// if(p->d_dentry[k] != NULL) {
// printf("%s\n", p->d_dentry[k]->name);
// }
// }
// for(k = 0; k < MAX_D_INODE; ++k) {
// if(p->d_inode[k] != NULL) {
// printf("%s\n", p->d_inode[k]->name);
// }
// }
// if i_type is DIRECTORY
// make new dentry
if(i->i_type == INODE_DIRECTORY) {
for(k = 0; k < MAX_D_CHILD; ++k) {
if(d->d_dentry[k] == NULL) {
break;
}
}
d->d_dentry[k] = vfs_dentry_make(d, i);
++d->num_dentry;
}
//endif
d->sb->s_blocksize += i->size;
// super_block refresh
vfs_sb_refresh(disk, d->sb);
// debug: inode table address
// printf("%08x\n", i->id);
//return i;
return 0;
}
void vfs_dentry_chmod(struct dentry *d, struct inode *i) {
d->d_mode = i->i_mode;
d->d_atime = i->i_atime;
return;
}
void vfs_dentry_rename(struct dentry *d, struct inode *i) {
strncpy(d->name, i->name, MAX_CHAR);
d->d_atime = i->i_atime;
return;
}
void* vfs_dentry_make(struct dentry *p, struct inode *i) {
struct dentry *d;
int k;
if(i == NULL) {
return NULL;
}
if(i->i_type != INODE_DIRECTORY) {
// printf("ssss\n");
return NULL;
}
d = (struct dentry*)malloc(sizeof(struct dentry));
d->d_type = DENTRY_CLOSE;
d->d_mode = i->i_mode;
strncpy(d->name, i->name, MAX_CHAR);
if(p != NULL) {
d->sb = p->sb;
} else {
d->sb = 0;
}
d->parent = p;
d->num_dentry = 0;
for(k = 0; k < MAX_D_CHILD; ++k) {
d->d_dentry[k] = NULL;
}
d->num_inode = 0;
for(k = 0; k < MAX_D_INODE; ++k) {
d->d_inode[k] = NULL;
}
d->d_ctime = i->i_ctime;
d->d_atime = i->i_atime;
return d;
}
void vfs_dentry_open(FILE *disk, struct dentry *d) {
struct dentry *p;
struct inode *in;
int i, j, k, l, block_num;
int inode_addr;
// printf("d_open %d\n", d->d_mode);
if(d->d_type == DENTRY_OPEN) {
return;
}
// printf("dentry_open\n");
p = d->parent;
d->d_type = DENTRY_OPEN;
// for(i = 0; i < p->num_inode; ++i) {
for(i = 0; i < MAX_D_INODE; ++i) {
if(p->d_inode != NULL) {
in = p->d_inode[i];
if(vfs_compare_name(d->name, in->name) == 0) {
break;
}
}
}
// printf("d_open\n");
// block_num = (in->size / DISK_BLOCK_SIZE) + 1;
block_num = in->size / DISK_BLOCK_SIZE;
for(i = 0; i < block_num; ++i) {
for(j = 0; j < DISK_BLOCK_SIZE / BYTE; ++j) {
// fseek(disk, ((int)in->direct_block[i] / BYTE) + (j * 8), SEEK_SET);
fseek(disk, (int)in->direct_block[i] + (j * 8), SEEK_SET);
inode_addr = disk_read_int(disk);
if(inode_addr != 0) {
++d->num_inode;
}
d->d_inode[(DISK_BLOCK_SIZE / BYTE)*i + j] = vfs_inode_read(disk, inode_addr);
}
}
d->d_dentry[0] = d;
d->d_dentry[1] = p;
j = 2;
for(i = 0; i < MAX_D_INODE; ++i) {
d->d_dentry[j] = vfs_dentry_make(d, d->d_inode[i]);
if(d->d_dentry[j] != NULL) {
++j;
}
}
d->num_dentry = j;
// printf("d_open\n");
return;
}
void vfs_sb_refresh(FILE *disk, struct super_block *sb) {
int i, k;
fseek(disk, 0, SEEK_SET);
k = disk_read_int(disk);
disk = disk_write_long(disk, sb->s_blocksize);
return;
}
void* vfs_sb_init(FILE *disk) {
struct super_block *sb;
struct dentry *d;
struct inode *in;
int root_inode_addr;
int inode_id;
int inode_addr;
int block_num, i, j;
sb = (struct super_block*)malloc(sizeof(struct super_block));
sb->s_mode = USER_MODE;
root_inode_addr = disk_read_int(disk);
// inode_id = ((root_inode_addr / BYTE) - INODE_TABLE_ADDR) / INODE_SIZE;
inode_id = (root_inode_addr - INODE_TABLE_ADDR) / INODE_SIZE;
sb->s_blocksize = disk_read_long(disk);
sb->s_maxbytes = disk_read_long(disk);
in = vfs_inode_read(disk, root_inode_addr);
sb->s_root = vfs_dentry_make(NULL, in);
d = sb->s_root;
d->sb = sb;
d->parent = d;
d->d_type = DENTRY_OPEN;
d->d_mode = in->i_mode;
block_num = (in->size / DISK_BLOCK_SIZE);
// if(in->size % DISK_BLOCK_SIZE != 0) {
// ++block_num;
// }
for(i = 0; i < block_num; ++i) {
for(j = 0; j < DISK_BLOCK_SIZE / BYTE; ++j) {
// fseek(disk, ((int)in->direct_block[i] / BYTE) + (j * 8), SEEK_SET);
fseek(disk, (int)in->direct_block[i] + (j * 8), SEEK_SET);
inode_addr = disk_read_int(disk);
if(inode_addr != 0) {
++d->num_inode;
}
d->d_inode[(DISK_BLOCK_SIZE / BYTE)*i + j] = vfs_inode_read(disk, inode_addr);
}
}
d->d_dentry[0] = d;
d->d_dentry[1] = d;
j = 2;
for(i = 0; i < MAX_D_INODE; ++i) {
d->d_dentry[j] = vfs_dentry_make(d, d->d_inode[i]);
if(d->d_dentry[j] != NULL) {
++j;
}
}
d->num_dentry = j;
sb->s_root_inode = in;
return sb;
}
disk.h
c
/* disk.h */
#ifndef _DISK_H_
#define _DISK_H_
#define BYTE 8
#define MAX_CHAR 64
#define INDEX_NUM 2
#define INODE_NUM 256
#define INODE_SIZE 512
#define INODE_FILE 0
#define INODE_DIRECTORY 1
#define DIRECTORY_ENTRY_BLOCK_NUM 1
#define DATA_BLOCK_NUM 893
#define DISK_BLOCK_NUM 1024
#define DISK_BLOCK_SIZE 1024
#define SUPER_BLOCK_ADDR 0
#define DISK_BLOCK_INDEX_ADDR 1024
#define INODE_INDEX_ADDR 2048
#define INODE_TABLE_ADDR 3072
#define DATA_BLOCK_ADDR (INODE_TABLE_ADDR + INODE_SIZE * INODE_NUM)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
char disk_read_char(FILE *f);
int disk_read_int(FILE *f);
unsigned long disk_read_long(FILE *f);
char* disk_read_name(FILE *f, char buf[]);
struct tm disk_read_time(FILE *f);
FILE* disk_write_char(FILE *f, char value);
FILE* disk_write_int(FILE *f, int value);
FILE* disk_write_long(FILE *f, unsigned long value);
FILE* disk_write_name(FILE *f, char name[]);
FILE* disk_write_time(FILE *f, struct tm c);
int disk_alloc_inode(FILE *f);
void disk_free_inode(FILE *f, int inode_addr);
int disk_alloc_block(FILE *f);
int disk_alloc_indirect_block(FILE *f, int *block_num, int depth);
void disk_free_block(FILE *f, int block_addr);
void disk_free_indirect_block(FILE *f, int block_addr, int depth);
FILE* disk_init(char disk_name[]);
#endif
disk.c
c
/* disk.c */
#include "disk.h"
char buf_char[1];
char buf_int[8];
char buf_long[16];
char buf_name[MAX_CHAR];
char padding_64[MAX_CHAR] = "0000000000000000000000000000000000000000000000000000000000000000";
char disk_read_char(FILE *f) {
fread(buf_char, 1, 1, f);
return buf_char[0];
}
int disk_read_int(FILE *f) {
int i, t;
fread(buf_int, 1, 8, f);
t = 0;
for(i = 0; i < 8; ++i) {
if(buf_int[i] < 'a') {
t = (t * 16) + buf_int[i] - '0';
} else {
t = (t * 16) + buf_int[i] - 'a' + 10;
}
}
return t;
}
unsigned long disk_read_long(FILE *f) {
int i;
unsigned long t;
fread(buf_long, 1, 16, f);
t = 0;
for(i = 0; i < 16; ++i) {
if(buf_long[i] < 'a') {
t = (t * 16) + buf_long[i] - '0';
} else {
t = (t * 16) + buf_long[i] - 'a' + 10;
}
}
return t;
}
char* disk_read_name(FILE *f, char buf[]) {
int i;
fread(buf_name, 1, MAX_CHAR, f);
for(i = 0; i < MAX_CHAR; ++i) {
buf[i] = buf_name[i];
if(buf_name[i] == '|') {
++i;
break;
}
}
for(;i < MAX_CHAR; ++i) {
buf[i] = '\0';
}
return buf;
}
struct tm disk_read_time(FILE *f) {
struct tm c;
c.tm_sec = disk_read_int(f);
c.tm_min = disk_read_int(f);
c.tm_hour = disk_read_int(f);
c.tm_mday = disk_read_int(f);
c.tm_mon = disk_read_int(f);
c.tm_year = disk_read_int(f);
c.tm_wday = disk_read_int(f);
c.tm_yday = disk_read_int(f);
c.tm_isdst = disk_read_int(f);
return c;
}
FILE* disk_write_char(FILE *f, char value) {
buf_char[0] = value;
fwrite(buf_char, 1, 1 ,f);
return f;
}
FILE* disk_write_int(FILE *f, int value) {
int i, t;
for(i = 7; i >= 0; --i) {
t = value % 16;
if(t < 10) {
buf_int[i] = '0' + t;
} else {
buf_int[i] = 'a' + (t - 10);
}
value = value / 16;
}
fwrite(buf_int, 1, 8, f);
return f;
}
FILE* disk_write_long(FILE *f, unsigned long value) {
int i;
unsigned long t;
for(i = 15; i >= 0; --i) {
t = value % 16;
if(t < 10) {
buf_long[i] = '0' + t;
} else {
buf_long[i] = 'a' + (t - 10);
}
value = value / 16;
}
fwrite(buf_long, 1, 16, f);
return f;
}
FILE* disk_write_name(FILE *f, char name[]) {
int i;
for(i = MAX_CHAR - 1; i >= 0; --i) {
buf_name[i] = name[i];
}
fwrite(buf_name, 1, MAX_CHAR, f);
return f;
}
FILE* disk_write_time(FILE *f, struct tm c) {
f = disk_write_int(f, c.tm_sec);
f = disk_write_int(f, c.tm_min);
f = disk_write_int(f, c.tm_hour);
f = disk_write_int(f, c.tm_mday);
f = disk_write_int(f, c.tm_mon);
f = disk_write_int(f, c.tm_year);
f = disk_write_int(f, c.tm_wday);
f = disk_write_int(f, c.tm_yday);
f = disk_write_int(f, c.tm_isdst);
return f;
}
int disk_alloc_inode(FILE *f) {
int i, inode_addr;
char c;
fseek(f, INODE_INDEX_ADDR, SEEK_SET);
for(i = 0; i < INODE_NUM; ++i) {
c = disk_read_char(f);
if(c == '0') {
break;
}
}
if(i == INODE_NUM) {
return 0;
}
fseek(f, -1, SEEK_CUR);
f = disk_write_char(f, '1');
// inode_addr = (INODE_TABLE_ADDR + (INODE_SIZE * i)) * BYTE;
inode_addr = INODE_TABLE_ADDR + (INODE_SIZE * i);
return inode_addr;
}
void disk_free_inode(FILE *f, int inode_addr) {
int i, index, addr;
if(inode_addr == 0) {
return;
}
// addr = inode_addr / BYTE;
addr = inode_addr;
index = (addr - INODE_TABLE_ADDR) / INODE_SIZE;
fseek(f, addr, SEEK_SET);
for(i = 0; i < INODE_SIZE / 64; ++i) {
f = disk_write_name(f, padding_64);
}
fseek(f, INODE_INDEX_ADDR + index, SEEK_SET);
f = disk_write_char(f, '0');
return;
}
int disk_alloc_block(FILE *f) {
int i, block_addr;
char c;
fseek(f, DISK_BLOCK_INDEX_ADDR, SEEK_SET);
for(i = 0; i < DISK_BLOCK_NUM; ++i) {
c = disk_read_char(f);
if(c == '0') {
break;
}
}
if(i == DISK_BLOCK_NUM) {
return 0;
}
fseek(f, -1, SEEK_CUR);
f = disk_write_char(f, '1');
// block_addr = DISK_BLOCK_SIZE * i * BYTE;
block_addr = DISK_BLOCK_SIZE * i;
return block_addr;
}
int disk_alloc_indirect_block(FILE *f, int *block_num, int depth) {
int i, block_addr, parent_addr, addr, k;
char c;
if(*block_num == 0) {
return 0;
}
if(depth == 0) {
return disk_alloc_block(f);
}
parent_addr = disk_alloc_block(f);
if(parent_addr == 0) {
return parent_addr;
}
for(i = 0; i < DISK_BLOCK_SIZE / 8; ++i) {
addr = (int)disk_alloc_indirect_block(f, block_num, depth - 1);
if(addr == 0) {
return parent_addr;
} else {
if(depth == 1) {
--(*block_num);
}
fseek(f, parent_addr + i*8, SEEK_SET);
f = disk_write_int(f, addr);
if(block_num == 0) {
return parent_addr;
}
}
}
// }
return parent_addr;
}
void disk_free_block(FILE *f, int block_addr) {
int i, index, addr;
if(block_addr == 0) {
return;
}
// addr = block_addr / BYTE;
addr = block_addr;
index = addr / DISK_BLOCK_SIZE;
fseek(f, addr, SEEK_SET);
for(i = 0; i < DISK_BLOCK_SIZE / 64; ++i) {
f = disk_write_name(f, padding_64);
}
fseek(f, DISK_BLOCK_INDEX_ADDR + index, SEEK_SET);
f = disk_write_char(f, '0');
return;
}
void disk_free_indirect_block(FILE *f, int block_addr, int depth) {
int i, index, addr, child_addr;
if(block_addr == 0) {
return;
}
if(depth == 0)
{
disk_free_block(f, block_addr);
return;
}
// addr = block_addr / BYTE;
addr = block_addr;
index = addr / DISK_BLOCK_SIZE;
for(i = 0; i < DISK_BLOCK_SIZE / 8; ++i) {
fseek(f, addr + i*8, SEEK_SET);
child_addr = disk_read_int(f);
disk_free_indirect_block(f, child_addr, depth - 1);
}
disk_free_block(f, addr);
return;
}
FILE* disk_init(char disk_name[]) {
time_t timer;
struct tm c, *t;
FILE *f;
int i, j;
f = fopen(disk_name, "r");
if(!f) {
f = fopen(disk_name, "w");
// c_time
timer = time(NULL);
t = localtime(&timer);
c = *t;
//free(t);
// super_block (1KB)
//f = disk_write_name(f, "2009147093|");// disk_name,64byte
f = disk_write_int(f, INODE_TABLE_ADDR); // root_inode,8byte
f = disk_write_long(f, DISK_BLOCK_SIZE * 132);// block_size,16byte
f = disk_write_long(f, DISK_BLOCK_SIZE * DISK_BLOCK_NUM);// maxbytes,16byte
f = disk_write_int(f, 0); // padding,8byte
f = disk_write_long(f, 0); // padding,16byte
for(i = 0; i < 15; ++i) {
f = disk_write_name(f, padding_64);
} // padding,1024-64
// disk block index block (1KB)
for(i = 0; i < 131; ++i) {
f = disk_write_char(f, '1');
}
for(i = 131; i < 132; ++i) {
f = disk_write_char(f, '1'); // root inode
}
for(i = 132; i < 1024; ++i) { // 0~DISK_BLOCK_NUM-1
f = disk_write_char(f, '0');
//f = disk_write_name(f, padding_64);
} // init by 0
// inode index block (1KB)
f = disk_write_char(f, '1');
for(i = 1; i < 1024; ++i) { // INODE_NUM
f = disk_write_char(f, '0');
//f = disk_write_name(f, padding_64);
} // init by 0
// inode table (inode = 512byte > 8+64+72+72+8+8*15 = 344)
// root inode
f = disk_write_int(f, INODE_DIRECTORY); // i_type,8byte
f = disk_write_int(f, 7); // i_mode,8byte
f = disk_write_name(f, "|"); // i_name,64byte
f = disk_write_time(f, c); // i_ctime,72byte
f = disk_write_time(f, c); // i_atime,72byte
f = disk_write_int(f, DISK_BLOCK_SIZE); // i_size,8byte
for(i = 0; i < 1; ++i) {
// f = disk_write_int(f, (DATA_BLOCK_ADDR + DISK_BLOCK_SIZE*i) * BYTE);
f = disk_write_int(f, DATA_BLOCK_ADDR + DISK_BLOCK_SIZE*i);
}
for(i = 1; i < 15; ++i) { // block,8*15byte
f = disk_write_int(f, 0); // direct X 12
} // indirect X 3
f = disk_write_name(f, padding_64); // padding,64byte
f = disk_write_name(f, padding_64); // padding,64byte
for(i = 0; i < 4; ++i) { // padding
f = disk_write_int(f, 0);
} // 8byte X 4
// root inode end
for(j = 1; j < INODE_NUM; ++j) {
for(i = 0; i < 8; ++i) {
f = disk_write_name(f, padding_64);
}
} // 128KB (INODE_NUM/2 byte)
// inode table end
// remain 1024 - 131 KB = 893KB
// disk blocks
for(j = 0; j < 893; ++j) {
for(i = 0; i < 16; ++i) {
f = disk_write_name(f, padding_64);
} // disk block = 1KB
} // 893KB
}
fclose(f);
f = fopen(disk_name, "r+");
return f;
}