/* File: lab3.c Author: Xiuwen Liu Purpose: To implement a virtual file system. Command to complie: see makefile */ #include #include #include #include #include #include #include #include #include #include #include #include "type-def.h" #include "fileSystem.h" int verbose; int interrupted; int Parse_Command(char *buf, char *argv_list[]); void sig_handler(int); /* A signal handler example */ void help(void); #define MAX_LINE 512 #define MAX_ARG 50 int main(int argc, char *argv[]) { int i, j, k, k1; char c; char buf[MAX_LINE]; pid_t pid; int status; int exit_flag; char *my_argv[MAX_ARG]; int my_argc; int fromfileflag; char rwbuf[BLOCK_SIZE*10]; /* Initialization here */ printf("**********************************************************\n"); help(); printf("**********************************************************\n"); printf("\n\n"); verbose = 0; exit_flag = 0; fromfileflag = 0; while ((c = getopt(argc, argv, "v:f:")) != EOF) { switch(c) { case 'v': verbose = atoi(optarg); break; case 'f': i = open(optarg, O_RDONLY); if (i < 0) { fprintf(stderr,"Cannot open file %s.\n", optarg); } else { close(0); dup(i); close(i); fromfileflag = 1; } break; default: printf("%c is not valid option.\n", c); } } /* Initiliaze here */ initDisk(); initFileSystem(); if (signal(SIGINT, sig_handler) == SIG_ERR) fprintf(stderr,"%d: Could not catch signal SIGINT.\n", getpid()); interrupted = 0; exit_flag = 0; while(exit_flag==0) { printf("Next command %% "); /* Display prompt */ fflush(stdout); interrupted = 0; buf[0]='\0'; i = 0; buf[0]='\0'; i = 0; do { /* k = read((int)0, &(buf[i]), (size_t)1);*/ buf[i] = getchar(); if (interrupted) break; if (buf[i] == '\n') break; i++; } while(1); buf[i] = '\0'; if (interrupted) { fflush(stdin); printf("\n"); fflush(stdout); continue; } if (fromfileflag) printf("%s\n", buf); if (buf[0] == '\0') continue; my_argc = Parse_Command(buf, my_argv); if (my_argc == 0) continue; if (strcmp(my_argv[0],"myexit") ==0) { exit_flag = 1; continue; } if (strcmp(my_argv[0],"help")==0) { help(); continue; } if (strcmp(my_argv[0],"myfat")==0) { Print_FAT(); continue; } if (strcmp(my_argv[0],"mycd")==0) { if (my_argc > 2) { fprintf(stderr, "mycd: Too many parameters.\n"); continue; } if (my_argc == 1) { my_argv[1] = getenv("HOME"); if (my_argv[1] == 0) { fprintf(stderr, "mycd: could not get home directory. \n"); continue; } } if (chdir(my_argv[1]) < 0) { perror("mycd"); } continue; } if (strcmp(my_argv[0],"mycd1")==0) { if (my_argc != 2) { fprintf(stderr, "mycd1: Too few or many parameters.\n"); continue; } if (fCd(my_argv[1]) < 0) { printf("Cannot change the current working directory.\n"); } continue; } if (strcmp(my_argv[0],"mycreate")==0) { if (my_argc != 2) { fprintf(stderr, "mycreate: Too many or too few parameters.\n"); continue; } i = fOpen(my_argv[1]); fClose(i); continue; } if (strcmp(my_argv[0],"myseek")==0) { char tmpbuf[2]; if (my_argc != 3) { fprintf(stderr, "myseek: Too many or too few parameters.\n"); continue; } i = fOpen(my_argv[1]); if (i < 0) { fprintf(stderr,"Cannot open virtual file \"%s\".\n", my_argv[1]); continue; } j = atoi(my_argv[2]); k = fSeek(i,j); if (k < 0) { fprintf(stderr,"Invalid myseek parameters.\n"); fClose(i); continue; } j=fRead(i, tmpbuf, (int)1); if (j < 0) { fprintf(stderr,"Reading a byte from virtual file \"%s\" failed.\n", my_argv[1]); fClose(i); continue; } printf("Character at %d from virtual file \"%s\" is %c (%d).\n", (int)atoi(my_argv[2]), my_argv[1], tmpbuf[0], (int)(tmpbuf[0])); fClose(i); continue; } if (strcmp(my_argv[0],"mymkdir")==0) { if (my_argc != 2) { fprintf(stderr, "mymkdir: Too many or too few parameters.\n"); continue; } fMkdir(my_argv[1]); continue; } if (strcmp(my_argv[0],"mypwd1")==0) { printf("Current working directory in the virtual file system:\n\t"); printf("%s\n", Get_Pwd()); continue; } if (strcmp(my_argv[0],"myls")==0) { fLs(); continue; } if (strcmp(my_argv[0],"mycopyfrom") ==0) { int fd, fd1; if (my_argc != 3) { fprintf(stderr, "mycopyfrom: Too many or too few parameters.\n"); continue; } fd = open(my_argv[1],O_RDONLY); if (fd < 0) { fprintf(stderr,"Cannot open file \"%s\" for reading ",my_argv[1]); fprintf(stderr,"in the real system.\n"); continue; } fd1 = fOpen(my_argv[2]); if (fd1 < 0) { fprintf(stderr,"Cannot open file \"%s\" for writing ",my_argv[2]); fprintf(stderr,"in the virtual system.\n"); close(fd); continue; } do { k1 = rand() % (10*BLOCK_SIZE-1) + 1; k = read(fd, rwbuf, (int)k1); if (k>0) { fWrite(fd1, rwbuf, k); } if (k != k1) break; } while (1); close(fd); fClose(fd1); continue; } if (strcmp(my_argv[0],"mycopyto") ==0) { int fd, fd1; if (my_argc != 3) { fprintf(stderr, "mycopyto: Too many or too few parameters.\n"); continue; } fd = open(my_argv[2],O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); if (fd < 0) { fprintf(stderr,"Cannot open file \"%s\" for writing ",my_argv[2]); fprintf(stderr,"in the real system.\n"); continue; } /* Make the sure will be 0755 */ fchmod(fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); fd1 = fOpen(my_argv[1]); if (fd1 < 0) { fprintf(stderr,"Cannot open file \"%s\" for reading ",my_argv[1]); fprintf(stderr,"in the virtual system.\n"); close(fd); continue; } do { k1 = rand() % (10*BLOCK_SIZE-1) + 1; k = fRead(fd1, rwbuf, k1); if (k>0) { write(fd, rwbuf, k); } if (k != k1) break; } while (1); close(fd); fClose(fd1); continue; } if (strcmp(my_argv[0],"mycat") ==0) { int fd1; if (my_argc != 2) { fprintf(stderr, "mycat: Too many or too few parameters.\n"); continue; } fd1 = fOpen(my_argv[1]); if (fd1 < 0) { fprintf(stderr,"Cannot open file \"%s\" for reading ",my_argv[1]); fprintf(stderr,"in the virtual system.\n"); continue; } do { k1 = rand() % (10*BLOCK_SIZE-1) + 1; k = fRead(fd1, rwbuf, k1); if (k>0) { for (i=0; i < k; i++) putchar((int)rwbuf[i]); } if (k != k1) break; } while(1); printf("\n"); fClose(fd1); continue; } /* Run an external command */ if ( (pid = fork()) < 0) { fprintf(stderr,"Counld not create new process."); } else { if (pid ==0) { /* Child */ execvp(my_argv[0],my_argv); fprintf(stderr,"Could not execute \"%s\".\n", my_argv[0]); perror("execvp"); exit(-1); } /* Parent */ if((pid = waitpid(pid, &status, 0)) < 0) { fprintf(stderr,"System call \"waitpid\" error.\n"); } } } /* Release memory here */ freeDisk(); return 0; } int Parse_Command(char *buf, char *argv_list[]) { int now_argc = 0; char *bufp; bufp = strtok(buf, " \t"); argv_list[now_argc] = bufp; if (bufp == NULL) return now_argc; now_argc++; while (bufp != NULL && now_argc < MAX_ARG) { bufp = strtok(NULL," \t"); argv_list[now_argc++] = bufp; } now_argc --; /* Because the last one is an empty string */ if (bufp != NULL) { fprintf(stderr,"Argument list too long.\n"); } return now_argc; } void sig_handler(int signo) /* signo: Signal number defined in */ { /* Reset to the interpret handler */ signal(signo, sig_handler); switch(signo) { case SIGINT: interrupted = 1; break; default: printf("%d received signal %d with unknown type.\n", getpid(), signo); } return; } void help(void) { printf("Usage: lab3 -v verbose -f command-file\n"); printf(" Implemented internal commands:\n"); printf("\thelp - Show this information.\n"); printf("\tmyexit - Exit from this program.\n"); printf("\tmyfat - Show the FAT table structure (only used blocks).\n"); printf("\tmycd [dir] - Change the current working directory on the UNIX system.\n"); printf("\tmycd1 dir - Change the current working directory on the "); printf("virtual file system.\n"); printf("\tmycreate file - Create an empty with the specified name.\n"); printf("\tmyseek virtualfile position - Show the character at the given position\n"); printf("\t\tof the virtual file.\n"); printf("\tmymkdir dir - Create a subdirectory under the the current \n"); printf("\t\tworking directory on the "); printf("virtual file system.\n"); printf("\tmyls - List the files under the current working directory on the \n"); printf("\t\tvirtual file system.\n"); printf("\tmycopyfrom realfile vfile - Copy a unix file to the virtual file system.\n"); printf("\tmycopyto vfile realfile - Copy a virtual file to the unix system.\n"); printf("\tmycat vfile - Display the content of the virtual file.\n"); printf(" All other commands will be executed as an external unix command.\n"); return; }