📄 command.c
字号:
/* command.c */
#include "command.h"
struct sh_command entry[] = {
{ "exit", 1, "", "exit this program"},
{ "echo", 2, "word", "echo words"},
{ "help", 3, "", "print this message"},
{ "mkdir", 4, "dir", "make dir"},
{ "mkfile", 5, "file (size)", "make file, init size"},
{ "ls", 6, "", "list files and dirs"},
{ "date", 7, "", "print date and time"},
{ "cd", 8, "(path)", "change dir"},
{ "status", 9, "", "show filesystem status"},
{ "rm", 10, "file", "remove file"},
{ "rn", 11, "file1 file2", "rename file1 to file2"},
{ "pwd", 12, "", "print full path"},
{ "mv", 13, "file path", "move file to path"},
{ "link", 14, "file path", "link file to path" },
{ "ZZZZ", 0, "", ""}};
/* split the given argv, then return the certain one. */
char* pick_arg( int argc, char *argv)
{
int i, catch_len, step;
char work_path[MAX_COMMAND_LEN], token[]=" ", *file, *ptr;
strcpy( work_path, argv);
for( step = 1, catch_len=0, ptr=work_path;
catch_len<strlen(work_path);
ptr++, step++)
{
strcpy( argv, ptr);
file = strtok( argv, token);
if(step == argc)
return file;
for( i=0; i<strlen(file); i++)
ptr++;
catch_len = catch_len + strlen(file) +1;
}
return NULL;
}
/* parser the command to relative programs. */
void processor( const char *command, FILE *fp, int *pd_ind_no, char *path)
{
char argv1[MAX_COMMAND_LEN], argv2[MAX_COMMAND_LEN];
strcpy( argv1, command);
strcpy( argv2, command);
int i;
for( i=0; entry[i].no != 0; i++){
if(!strcmp( entry[i].com, pick_arg( 1, argv1))){
strcpy( argv1, command);
strcpy( argv2, command);
switch(entry[i].no){
case 1: printf("Goodbye user. Logout in " __DATE__ " " __TIME__".\n");exit(1);break;
case 2: printf("%s\n", pick_arg( 2, argv1)); break;
case 3: help(); break;
case 4: create_fd( fp, *pd_ind_no, pick_arg(2,argv1), 'd', "0"); break;
case 5: create_fd( fp, *pd_ind_no, pick_arg(2,argv1), 'f', pick_arg(3,argv2)); break;
case 6: list_dir( fp, *pd_ind_no); break;
case 7: printf(__DATE__ " " __TIME__ "\n"); break;
case 8: if(cd_path( fp, pd_ind_no, pick_arg( 2, argv1)) != -1) list_dir( fp, *pd_ind_no); break;
case 9: status(fp); break;
case 10: remove_fd( fp, *pd_ind_no, pick_arg( 2, argv1)); break;
case 11: re_name( fp, *pd_ind_no, pick_arg(2,argv1), pick_arg(3,argv2)); break;
case 12: printf("%s\n", path); break;
case 13: move_file( fp, pd_ind_no, pick_arg(2,argv1), pick_arg(3,argv2)); break;
case 14: link_file( fp, pd_ind_no, pick_arg(2,argv1), pick_arg(3,argv2)); break;
};
}
} /* end of for */
}
/* else read the dir's entries and print it one by one. */
void list_dir( FILE *fp, int dir_ind_no)
{
char *type, *file="file", *dir="dir";
int blk_no;
long offset;
struct fd_entry entry;
struct fs_inode dir_inode, tmp_inode;
dir_inode = find_inode( fp, dir_ind_no);
printf("%-5s %-5s %-5s %-5s %-5s %-5s %-5s\n",
"type", "user", "link", "size", "name", "inode", "blocks");
for( offset=0; offset<dir_inode.size; offset+=sizeof(entry)){
blk_no = blk_map( fp, dir_ind_no, offset);
fseek( fp, (SEEK_BLK(blk_no) + (offset%BLOCK_SIZE)), SEEK_SET);
fread( &entry, sizeof(entry), 1, fp);
tmp_inode = find_inode( fp, entry.inode_no);
if(tmp_inode.type == 'd')
type = dir;
else
type = file;
/* type, user, link, size, name, inode, blocks */
printf("%-5s %-5s %-5d %-5d %-7s %-7d", type, tmp_inode.user,
tmp_inode.links, tmp_inode.size, entry.name, entry.inode_no);
int offset;
for( offset=0; offset<=tmp_inode.size; offset+=BLOCK_SIZE){
printf("%d ", blk_map( fp, entry.inode_no, offset));
}
printf("\n");
}
return;
}
/* BETA VERTION
th cd_path BASE on the given_path, maybe from ROOT, or from CURRENT DIR.
Then SPLIT given_path to components by slash('/'), CHECK whether it exist in
the work_inode, if NOT print error and return -1, else change the work_inode
to the MATCHING one, then shift to next component, repeat until reach
given_path's end, finally recover from the old one and return the target's inode
number. */
int cd_path( FILE *fp, int *pd_ind_no, char *given_path)
{
char work_path[PATH_LEN];
if(given_path == NULL)
strcpy( work_path, ".");
else
strcpy( work_path, given_path);
int tmp_ind_no = *pd_ind_no;
if(work_path[0] == '/') /* root inode */
*pd_ind_no = STACK_MAX - 1;
int i, catch_len;
char token[]="/", tmp_path[PATH_LEN], *file, *ptr;
struct fs_inode file_inode;
for( catch_len=0, ptr=work_path; catch_len<strlen(work_path); ptr++){
strcpy( tmp_path, ptr); /* copy the rest component to tmp from ptr */
file = strtok( tmp_path, token);
if((*pd_ind_no=fd_exist( fp, *pd_ind_no, file)) == -1){
fprintf( stderr, "%s does not exist!\n", file);
*pd_ind_no = tmp_ind_no;
return -1; /* if no this file */
}
file_inode = find_inode( fp, *pd_ind_no);
if(file_inode.type != 'd'){
fprintf( stderr, "%s is not a dir!\n", file);
*pd_ind_no = tmp_ind_no;
return -1;
}
for( i=0; i<strlen(file); i++) /* update the ptr and catch_len */
ptr++;
catch_len = catch_len + strlen(file) + 1;
}
return *pd_ind_no;
}
void help()
{
printf("All commands list here, some support\n"
"arguments. Arguments which follows ()\n"
"means omitted to the default.\n\n"
"COMMAND PATAMETER DESCRIPTION\n");
int i;
for( i=0 ; entry[i].no > 0; i++)
printf( "%-8s %-12s %-s\n", entry[i].com, entry[i].argv, entry[i].description);
}
/* print the filesystem's status */
void status( FILE *fp)
{
struct fs_super super;
fseek( fp, sizeof(struct fs_boot), SEEK_SET);
fread( &super, sizeof(super), 1, fp);
int i;
printf("filesystem usage : %f%%\n",
(double)(super.total_block_count - super.free_block_count) / (double)super.total_block_count);
printf("total block count: %d\n", super.total_block_count);
printf("free block count : %d\n", super.free_block_count);
printf("free inode count : %d\n", super.free_inode_count);
printf("remembered inode : %d\n", super.remembered_inode);
printf("free block stack : \n");
for( i=1; i<=super.free_block_stack[0]; i++){
printf("%3d ", super.free_block_stack[i]);
if(i % 12 == 0)
printf("\n");
}
printf("\n");
printf("free inode stack : \n");
for( i=1; i<=super.free_inode_stack[0]; i++){
printf("%3d ", super.free_inode_stack[i]);
if(i % 12 == 0)
printf("\n");
}
printf("\n");
}
void re_name( FILE *fp, int dir_ind_no, char *f1, char *f2)
{
int file_ind_no;
if(f1 == NULL || f2 == NULL){
fprintf( stderr, "invalid command, please see help in detail.\n");
return;
}
else if((file_ind_no=fd_exist(fp, dir_ind_no, f1)) == -1){ /* if f1 do not exist */
fprintf( stderr, "%s have not exist!\n", f1);
return;
}
else if(fd_exist(fp, dir_ind_no, f2) != -1){ /* if f2 have exist */
fprintf( stderr, "%s have exist!\n", f2);
return;
}
else if(!strcmp(f1,".") || !strcmp(f1,"..") ||
!strcmp(f2,".") || !strcmp(f2,".."))
{
fprintf( stderr, "invalid command!\n");
return;
}
int blk_no;
long offset;
struct fd_entry file_entry;
struct fs_inode dir_inode = find_inode( fp, dir_ind_no);
for( offset=2*sizeof(file_entry); offset<dir_inode.size; offset+=sizeof(file_entry)){
blk_no = blk_map( fp, dir_ind_no, offset);
fseek( fp, (SEEK_BLK(blk_no) + offset%BLOCK_SIZE), SEEK_SET);
fread( &file_entry, sizeof(file_entry), 1, fp);
if(!strcmp( f1, file_entry.name)){ /* locate file */
strcpy( file_entry.name, f2);
fseek( fp, (SEEK_BLK(blk_no) + offset%BLOCK_SIZE), SEEK_SET);
fwrite( &file_entry, sizeof(file_entry), 1, fp);
return;
}
}
}
/* recurse to parent dir, until reach the root. */
void pwd( FILE *fp, int *pd_ind_no, char *path)
{
int stack[STACK_MAX], i, current_ind = *pd_ind_no;
stack[0] = *pd_ind_no; /* current ind */
for( i=1; i<STACK_MAX && (fd_exist(fp,*pd_ind_no,".")!=fd_exist(fp,*pd_ind_no,"..")); i++){
*pd_ind_no = fd_exist( fp, *pd_ind_no, "..");
stack[i] = *pd_ind_no;
}
struct fd_entry file_entry;
if(i == 1){
strcpy( path, "/");
*pd_ind_no = current_ind;
return;
}
else{
strcpy( path, "");
for( i--; i>0; i--){
file_entry = find_entry( fp, stack[i], stack[i-1]);
strcat( path, "/");
strcat( path, file_entry.name);
}
*pd_ind_no = current_ind;
}
}
/* BETA
check whether the file was exist or the path was exist, if NOT, print error
then return, else record the moving file entry, rm it in the current dir,
then insert it to the giving path dir, if the moving entry was a dir, update
its 'parents' entry instead of to path's. */
void move_file( FILE *fp, int *pd_ind_no, char *file, char *to_path)
{
int file_ind_no, tmp_pd_ind_no=*pd_ind_no;
if(!strcmp(file,".")||!strcmp(file,"..")){
fprintf( stderr, "invalid command!\n");
return;
}
else if((file_ind_no=fd_exist( fp, *pd_ind_no, file)) == -1){
fprintf( stderr, "%s doesn't exist!\n", file);
return;
}
else if((cd_path(fp, pd_ind_no, to_path)) == -1){
fprintf( stderr, "%sd doesn't exist!\n", to_path);
return;
}
/* get mv file's entry and its inode */
struct fd_entry mv_file_entry = find_entry( fp, tmp_pd_ind_no, file_ind_no);
struct fs_inode mv_file_inode = find_inode( fp, mv_file_entry.inode_no);
/* add the file entry to the to_path's dir */
struct fs_inode to_dir_inode = find_inode( fp, *pd_ind_no);
fseek( fp,
((SEEK_BLK(blk_map(fp,*pd_ind_no,to_dir_inode.size)))+to_dir_inode.size%BLOCK_SIZE),
SEEK_SET);
fwrite( &mv_file_entry, sizeof(mv_file_entry), 1, fp);
to_dir_inode.size += sizeof(mv_file_entry); /* update remote dir's size */
update_ind( fp, *pd_ind_no, to_dir_inode);
/* add the mv_file_inode's links, then rm it in the current dir */
mv_file_inode.links++;
update_ind( fp, mv_file_entry.inode_no, mv_file_inode);
/* remove the mv_file_entry in the current dir */
remove_fd( fp, tmp_pd_ind_no, file);
/* if the mv_file was a dir, change it's 'parents' entry */
struct fd_entry parents_entry;
strcpy( parents_entry.name, "..");
parents_entry.inode_no = *pd_ind_no;
if( to_dir_inode.type == 'd'){
fseek( fp,
((SEEK_BLK(blk_map(fp,mv_file_entry.inode_no,sizeof(parents_entry))))+sizeof(parents_entry)),
SEEK_SET);
fwrite( &parents_entry, sizeof(parents_entry), 1, fp);
}
*pd_ind_no = tmp_pd_ind_no; /* return */
}
/* BETA
check the file to be linked whether exist, if NOT print error and exit, else
check the to_path whether exist, if NOT print error too, and exit, else add
the file's links and add the file entry into the to_path dir. */
void link_file( FILE *fp, int *pd_ind_no, char *file, char *to_path)
{
int file_ind_no, tmp_pd_ind_no=*pd_ind_no;
if(!strcmp(file,".") || !strcmp(file,"..") || file==NULL){
fprintf( stderr, "invalid command!\n");
return;
}
else if((file_ind_no=fd_exist( fp, *pd_ind_no, file)) == -1){ /* if file do not exist */
fprintf( stderr, "%s doesn't exist!\n", file);
return;
}
else if(cd_path( fp, pd_ind_no, to_path) == -1){ /* if path do not exist */
fprintf( stderr, "%s doesn't exist!\n", to_path);
return;
}
/* get the linked file's entry */
struct fd_entry linked_file_entry = find_entry( fp, tmp_pd_ind_no, file_ind_no);
/* write the file entry to the to_path's dir */
struct fs_inode to_dir_inode = find_inode( fp, *pd_ind_no);
fseek( fp,
(SEEK_BLK(blk_map( fp, *pd_ind_no, to_dir_inode.size))+to_dir_inode.size%BLOCK_SIZE),
SEEK_SET);
fwrite( &linked_file_entry, sizeof(linked_file_entry), 1, fp);
/* increase the to_path dir's file size */
to_dir_inode.size += sizeof(linked_file_entry);
update_ind( fp, *pd_ind_no, to_dir_inode);
/* increase the linked file's linking count */
struct fs_inode linked_file_inode = find_inode( fp, linked_file_entry.inode_no);
linked_file_inode.links++;
update_ind( fp, linked_file_entry.inode_no, linked_file_inode);
/* get the old *pd_ind_no */
*pd_ind_no = tmp_pd_ind_no;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -