inode * getFile(FILE *fs, char ** path, uint32_t inode_off, uint32_t part_off, uint32_t zone_size) { uint32_t inode_num = ROOT_INODE_NUM; uint8_t *dir_data; inode *Inode; uint32_t i; uint32_t dir_num_entries; FATALCALL((Inode=malloc(INODE_SIZE))==NULL,"malloc"); getInode(Inode, ROOT_INODE_NUM, inode_off, fs); if(path[0] == NULL)/*magic number*/ return Inode; for(i=0; path[i] != NULL; i++) { FATALCALL((dir_data=malloc(Inode->size))==NULL,"malloc"); dir_data = getData(fs, Inode, part_off, zone_size); dir_num_entries = (Inode->size/DIR_ENTRY_SIZE); inode_num = existsInPath(dir_data, dir_num_entries, path[i]); if (inode_num == 0) return NULL; getInode(Inode, inode_num, inode_off, fs); if (path[i+1] == NULL) return Inode; free(dir_data); } return Inode; }
void getDirectZone(uint8_t *data, uint32_t zone_ptr, uint32_t part_off, uint32_t *current_zone, uint32_t zone_size, FILE *fs) { uint32_t file_pos = part_off + (zone_ptr * zone_size); uint8_t * data_pos = data + (*current_zone * zone_size); /*make sure correct add*/ FATALCALL(fseek(fs, file_pos, SEEK_SET)==-1,"fseek"); FATALCALL((fread((uint8_t *)data_pos, 1, zone_size, fs))!=zone_size,"fread");/*magic num*/ (*current_zone) += 1; }
/* * opens a tar file to either be written to or read from * @param path path to the tar file * @param mode mode to open the file, either 'w' or 'r' for writing or reading * @return returns NULL on error otherwise the tar stream */ TAR* opentar( const char * path, char * mode ,int sec ) { TAR *ret; int fd; int flags; errno = 0; switch( mode[0] ) { case 'w': flags = TAR_WRITE; break; case 'r': flags = TAR_READ; break; default: errno = EINVAL; return NULL; } if( (fd = open( path , flags, sec) ) == -1 ) { return NULL; } FATALCALL( (ret =(TAR*) malloc( sizeof( TAR ) )) == NULL,"Error:"); ret->fd = fd; ret->flags = flags; ret->err = 0; ret->eof = 0; ret->bufpos = 0; ret->blockpos = 0; ret->next = 0; ret->strict = 0; ret->bytesRead = 0; return ret; }
/* * Checks of a valid pipes and calls IPC to launch childs and commands * * @param pl pipeline created by the command line phraser * @return exit status of the last child forked in the pipeline */ int process( pipeline pl ) { int totalP, status; Child *myChilds; /* Child ARRAY */ if(pl->cline == NULL) /* check if the cmd arg is not empty , should never happened by main */ return -1; totalP = pl->length; /* perform the build in commands */ /* children info array */ FATALCALL( (myChilds = (Child *) malloc (sizeof(Child) * totalP)) == NULL, "Invalid Malloc"); /* inialize child struct to EMPTY */ FATAL( (newChild( myChilds, totalP)) == -1, "Error") /* create the pipes */ status = IPC( pl, myChilds ); /* free the id's and return status */ free ( myChilds ); return status; }
uint8_t * getData(FILE *fs, inode *Inode, uint32_t part_off, uint32_t zone_size) { uint32_t filesize = Inode->size; uint32_t num_zones = filesize / zone_size; uint32_t current_zone = 0; uint32_t read; uint8_t *data; if (filesize%zone_size > 0) { num_zones++; } FATALCALL((data=malloc(num_zones*zone_size))==NULL, "malloc"); for(read=0; current_zone < num_zones && read<9; read++) { if(read<7) { getDirectZone(data, Inode->zone[read], part_off, ¤t_zone, zone_size, fs); } else if (read == 7) { getIndrZone(data, Inode->ind_zone, part_off, ¤t_zone, zone_size, fs, num_zones); } else { getDblZone(data, Inode->dbl_ind_zone, part_off, ¤t_zone, zone_size, fs, num_zones); } } return data; }
s_block * getSuperBlock(FILE *fs, uint32_t offset) { s_block *S_block; FATALCALL((S_block=(s_block *)malloc(S_BLOCK_SIZE))==NULL,"malloc"); /*Check Super Block - Magic Num Below*/ FATALCALL(fseek(fs, offset + S_BLOCK_BASE, SEEK_SET)==-1,"fseek"); FATALCALL(fread((s_block *)S_block, 1, S_BLOCK_SIZE, fs) < S_BLOCK_SIZE, "fread"); if(S_block->magic != S_BLOCK_MAGIC_LITTLE) { fprintf(stderr, "Super Block - Bad Magic Number"); fprintf(stderr, "(0x%.2X)\n",S_block->magic); return NULL; } return S_block; }
void getIndrZone(uint8_t *data, uint32_t zone_ptr, uint32_t part_off, uint32_t *current_zone, uint32_t zone_size, FILE *fs, uint32_t num_zones) { uint32_t read; uint8_t *zone_ptr_block; uint32_t dummy_curr_zone = 0; FATALCALL((zone_ptr_block=(uint8_t*)malloc(zone_size))==NULL, "malloc"); /*may cause problems double check*/ getDirectZone(zone_ptr_block, zone_ptr, part_off, &dummy_curr_zone, zone_size, fs); for(read=0; *current_zone < num_zones && read < zone_size/INODE_SIZE; read++) { getDirectZone(data, zone_ptr_block[read], part_off, current_zone, zone_size, fs); } free(zone_ptr_block); }
p_table* getPartTable(FILE *fs, uint32_t offset, uint8_t p_table_num) { p_table *P_table; uint8_t ptable_sig_1 = 0; uint8_t ptable_sig_2 = 0; uint32_t ptable_pos; /*partition table position*/ ptable_pos = offset + PART_TABLE_BASE + (p_table_num*P_TABLE_SIZE); FATALCALL((P_table=(p_table *)malloc(P_TABLE_SIZE))==NULL,"partition: malloc"); /*Check Partition Signature 1 - Magic Num Below*/ FATALCALL(fseek(fs, offset + PART_SIG_1_OFF , SEEK_SET)==-1,"fseek"); FATALCALL(fread((uint8_t *)&ptable_sig_1, 1, BYTE, fs) < BYTE,"fread"); /*Check Partition Signature 2 - Magic Num Below*/ FATALCALL(fseek(fs, offset + PART_SIG_2_OFF , SEEK_SET)==-1,"fseek"); FATALCALL(fread((uint8_t *)&ptable_sig_2, 1, BYTE, fs) < BYTE, "fread") if (ptable_sig_1 != PART_SIG_1 || ptable_sig_2 != PART_SIG_2) { fprintf(stderr, "Incorrect Partition Signature(s)"); fprintf(stderr, "Signature at 510 is (0x%X)\n", ptable_sig_1); fprintf(stderr, "Signature at 511 is (0x%X)\n", ptable_sig_2); return NULL; } /*Read in Partition Table*/ FATALCALL(fseek(fs, ptable_pos, SEEK_SET)==-1,"fseek"); FATALCALL(fread((p_table *)P_table, 1, P_TABLE_SIZE, fs) < P_TABLE_SIZE, "fread"); /*Check Partition Table*/ if (P_table->type != MINIX_PART) { fprintf(stderr, "Not Minix Part - Type: (0x%X)\n", P_table->type); return NULL; } return P_table; }
/* * Creates a pipeline, forks, and executes childrens * Note: pl will never be NULL, already checked on process * @param pl pipeline created by the command line phraser * @param child array of child structure with fields for child id and return status * @return exit status of the last child forked in the pipeline */ int IPC( pipeline pl, Child * childs ) { int pipefd[2]; int prevIn = -1, i, child_T, file_In, file_Out; Child *currChild= NULL; struct clstage currStage; int status; sigset_t block; /* set total # of commands/CHILDS */ child_T = pl->length; /* block the SIGINT */ sigemptyset(&block); sigaddset(&block, SIGINT); sigprocmask(SIG_SETMASK, &block, NULL); for(i = 0; i < child_T; i++) { FATALCALL( pipe(pipefd) == -1, "pipe"); /* create the pipe */ currChild = childs+i; /* current child to process */ currStage = pl->stage[i]; /* SET UP THE PREVIOUS PIPE, CHECK FOR INDIRECTION OPEN FILE FD */ if( (currChild->id = fork()) < 0) perror("Child"); else if( currChild->id == 0) /* child */ { close(pipefd[IN]); /* will never use pipe stdin side, next child would */ /* handle input */ if(currStage.inname != NULL) { if ( (file_In = open( currStage.inname, O_RDONLY )) == -1) { perror ( currStage.inname ); exit ( EXIT_FAILURE ); } FATALCALL ( dup2(file_In, STDIN_FILENO) == -1, "DUP" ); close(file_In); } else { if( i > 0) { dup2(prevIn, STDIN_FILENO); /* set up the stdin to be tty on first call and previous pipe-in(0) otherwise */ close ( prevIn ); } } /* middle processes and last process */ if(currStage.outname != NULL) { FATALCALL ( (file_Out = open( currStage.outname, FILETYPE, FILEMODE )) == -1, "Open Error"); FATALCALL ( dup2(file_Out, STDOUT_FILENO) == -1, "DUP Error" ); close( file_Out ); } else { if( i != child_T -1 ) /* no file to output and not last child */ { FATALCALL ( dup2(pipefd[OUT], STDOUT_FILENO) == -1 , "DUP Error" ); /* else set up last in put */ } /* else, last child prints to the terminal, which is inherited */ close( pipefd[OUT]); } /* unBLOCK the SIGNAL */ signal(SIGINT, SIG_DFL); sigemptyset(&block); sigprocmask(SIG_SETMASK, &block, NULL); execvp(currStage.argv[0], currStage.argv); perror(currStage.argv[0]); /* exit with a failure */ exit(EXIT_FAILURE); } else { /* parent */ if( prevIn > -1 ) /* if prevIn wasn't the first child close it */ close(prevIn); prevIn = pipefd[IN]; /* save In End of the last pipe, needed for next child */ close(pipefd[OUT]); /* close out end of the pipe */ if( i == child_T-1) close( prevIn ); /* last unused end of the pipe */ } } for(i = 0; i < child_T; i++) { /* wait and retrieve return status of childrens */ FATALCALL ( wait ( &((childs+i)->status) ) == -1 , "WAIT" ); } /* unblock and reset to clear terminal */ sigemptyset(&block); sigprocmask(SIG_SETMASK, &block, NULL); status = (childs+i-1)->status; /* flush out the data */ fflush( stdout ); /* exit staus checking */ if ( WIFEXITED( status )) return WEXITSTATUS( status ); else if (WIFSIGNALED(status)) return 100 + WTERMSIG( status ); else return EXIT_FAILURE; }
int main(int argc, char *argv[]) { s_block *S_block; p_table *P_table=NULL; inode *Inode = NULL; options *Opt; FILE *fs; FILE *output; /*where all the data will be outputed*/ uint32_t part_start; /*beginning file system*/ uint32_t inode_off; /*beginning of inode zone*/ uint32_t zone_size; uint8_t *data; char **path; if ((Opt = handleOptions(argc, argv))==NULL) { printf("minget [-v] [-p part [-s subpart]] imagefile srcpath [dstpath]\n"); exit(EXIT_FAILURE); } FATALCALL((fs = fopen(Opt->imagefile, "rb"))==NULL,"fopen"); /*check super block*/ output = stdout; if (Opt->dstpath) FATALCALL((output = fopen(Opt->dstpath, "w+b"))==NULL,"fopen"); part_start = 0; /*0 is start of image*/ if (Opt->part_num == -1 && Opt->subpart_num == -1) /*no partition or subpartition*/ { if((S_block = getSuperBlock(fs, 0)) == NULL) /*MAGIC NUMBER*/ { free(S_block); exit(EXIT_FAILURE); } zone_size = S_block->block_size << S_block->log_zone_size; inode_off = part_start + (2 + S_block->imap_blocks + S_block->zmap_blocks) * S_block->block_size; } else if (Opt->part && !Opt->subpart) /*partition but no subpartition*/ { P_table = getPartTable(fs, part_start, Opt->part_num); if (P_table == NULL) exit(EXIT_FAILURE); part_start = P_table->lFirst * SECTOR_SIZE; if((S_block = getSuperBlock(fs, 0)) == NULL) /*MAGIC NUMBER*/ { free(S_block); exit(EXIT_FAILURE); } zone_size = S_block->block_size << S_block->log_zone_size; inode_off = part_start + (2 + S_block->imap_blocks + S_block->zmap_blocks) * S_block->block_size; } else if (Opt->part && Opt->subpart) /* partition and subpartition */ { P_table = getPartTable(fs, part_start, Opt->part_num); /*0 is start of image*/ if (P_table == NULL) { free(P_table); exit(EXIT_FAILURE); } part_start = P_table->lFirst * SECTOR_SIZE; free(P_table); P_table = getPartTable(fs, part_start, Opt->subpart_num); if (P_table == NULL) { free(P_table); exit(EXIT_FAILURE); } part_start = P_table->lFirst * SECTOR_SIZE; if((S_block = getSuperBlock(fs, part_start)) == NULL) /*MAGIC NUMBER*/ { free(S_block); exit(EXIT_FAILURE); } zone_size = S_block->block_size << S_block->log_zone_size; inode_off = part_start + (2 + S_block->imap_blocks + S_block->zmap_blocks) * S_block->block_size; } else { exit(EXIT_FAILURE); } path =tokstr(Opt->path, "/"); if ((Inode = getFile(fs, path, inode_off, part_start, zone_size))==NULL) { fprintf(stderr, "File Doesn't Exist\n"); exit(EXIT_FAILURE); } data = getData(fs, Inode, part_start, zone_size); if (Opt->verbose) verbose(S_block, Inode); printFile(output, data, Inode->size); fclose(fs); /*check for errors*/ if(P_table!=NULL) { free(P_table); } free(Opt); free(S_block); return EXIT_SUCCESS; }
options * handleOptions(int argc, char *argv[]) { uint32_t opt; options *Opt; extern int optind; uint32_t non_opt_args = argc; /*number of non - option arguments*/ FATALCALL((Opt=(options *)malloc(OPTIONS_SIZE))==NULL, "malloc"); Opt->part_num = -1; Opt->subpart_num = -1; Opt->verbose = 0; Opt->imagefile = NULL; Opt->path = NULL; Opt->part = 0; Opt->subpart = 0; while ((opt = getopt(argc, argv, OPT_STR)) != -1) { switch (opt) { case 'v': non_opt_args -= 1; Opt->verbose = 1; break; case 'p': non_opt_args -= 2; if (atoi(argv[optind]) < 0 || atoi(argv[optind]) > 3) return NULL; Opt->part_num = atoi(argv[optind]); Opt->part = 1; break; case 's': non_opt_args -= 2; if (atoi(argv[optind]) < 0 || atoi(argv[optind]) > 3) return NULL; Opt->subpart_num = atoi(argv[optind]); Opt->subpart = 1; break; default: return NULL; break; } } if (Opt->subpart == 1 && Opt->part == 0) { return NULL; } switch (non_opt_args) { case 2: /*imagefile given by user*/ Opt->imagefile = argv[argc-1]; FATALCALL((Opt->path=(char *)calloc(2*sizeof(char), 2*sizeof(char)))==NULL, "calloc"); Opt->path[0] = '/'; break; case 3: /*imagefile and path given by user*/ Opt->imagefile = argv[argc-2]; Opt->path = argv[argc-1]; break; case 4: /*imagefile, path, and dstpath given by user*/ Opt->imagefile = argv[argc-3]; Opt->path = argv[argc-2]; Opt->dstpath = argv[argc-1]; break; default: return NULL; break; } return Opt; }
void getInode(inode * Inode, uint32_t inode_num, uint32_t inode_off, FILE *fs) { uint32_t file_pos = inode_off + (INODE_SIZE * (inode_num -1)); FATALCALL(fseek(fs, file_pos, SEEK_SET)==-1,"fseek"); FATALCALL((fread((inode *)Inode, 1, INODE_SIZE, fs))!=INODE_SIZE,"fread");/*magic num*/ }