| /* |
| |
| /usr/src/ext2ed/file_com.c |
| |
| A part of the extended file system 2 disk editor. |
| |
| ---------------------------- |
| Commands which handle a file |
| ---------------------------- |
| |
| First written on: April 18 1995 |
| |
| Copyright (C) 1995 Gadi Oxman |
| |
| */ |
| |
| #include "config.h" |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include "ext2ed.h" |
| |
| int init_file_info (void) |
| |
| { |
| struct ext2_inode *ptr; |
| |
| ptr=&type_data.u.t_ext2_inode; |
| |
| file_info.inode_ptr=ptr; |
| file_info.inode_offset=device_offset; |
| |
| file_info.global_block_num=ptr->i_block [0]; |
| file_info.global_block_offset=ptr->i_block [0]*file_system_info.block_size; |
| file_info.block_num=0; |
| file_info.blocks_count=(ptr->i_size+file_system_info.block_size-1)/file_system_info.block_size; |
| file_info.file_offset=0; |
| file_info.file_length=ptr->i_size; |
| file_info.level=0; |
| file_info.offset_in_block=0; |
| |
| file_info.display=HEX; |
| |
| low_read (file_info.buffer,file_system_info.block_size,file_info.global_block_offset); |
| |
| return (1); |
| } |
| |
| |
| void type_file___inode (char *command_line) |
| |
| { |
| dispatch ("settype ext2_inode"); |
| } |
| |
| void type_file___show (char *command_line) |
| |
| { |
| if (file_info.display==HEX) |
| file_show_hex (); |
| if (file_info.display==TEXT) |
| file_show_text (); |
| } |
| |
| void type_file___nextblock (char *command_line) |
| |
| { |
| long block_offset=1; |
| char *ptr,buffer [80]; |
| |
| ptr=parse_word (command_line,buffer); |
| |
| if (*ptr!=0) { |
| ptr=parse_word (ptr,buffer); |
| block_offset*=atol (buffer); |
| } |
| |
| if (file_info.block_num+block_offset >= file_info.blocks_count) { |
| wprintw (command_win,"Error - Block offset out of range\n");wrefresh (command_win); |
| return; |
| } |
| |
| file_info.block_num+=block_offset; |
| file_info.global_block_num=file_block_to_global_block (file_info.block_num,&file_info); |
| file_info.global_block_offset=file_info.global_block_num*file_system_info.block_size; |
| file_info.file_offset=file_info.block_num*file_system_info.block_size; |
| |
| low_read (file_info.buffer,file_system_info.block_size,file_info.global_block_offset); |
| |
| strcpy (buffer,"show");dispatch (buffer); |
| } |
| |
| void type_file___next (char *command_line) |
| |
| { |
| int offset=1; |
| char *ptr,buffer [80]; |
| |
| ptr=parse_word (command_line,buffer); |
| |
| if (*ptr!=0) { |
| ptr=parse_word (ptr,buffer); |
| offset*=atol (buffer); |
| } |
| |
| if (file_info.offset_in_block+offset < file_system_info.block_size) { |
| file_info.offset_in_block+=offset; |
| sprintf (buffer,"show");dispatch (buffer); |
| } |
| |
| else { |
| wprintw (command_win,"Error - Offset out of block\n");refresh_command_win (); |
| } |
| } |
| |
| void type_file___offset (char *command_line) |
| |
| { |
| unsigned long offset; |
| char *ptr,buffer [80]; |
| |
| ptr=parse_word (command_line,buffer); |
| |
| if (*ptr!=0) { |
| ptr=parse_word (ptr,buffer); |
| offset=atol (buffer); |
| } |
| else { |
| wprintw (command_win,"Error - Argument not specified\n");refresh_command_win (); |
| return; |
| } |
| |
| if (offset < file_system_info.block_size) { |
| file_info.offset_in_block=offset; |
| sprintf (buffer,"show");dispatch (buffer); |
| } |
| |
| else { |
| wprintw (command_win,"Error - Offset out of block\n");refresh_command_win (); |
| } |
| } |
| |
| void type_file___prev (char *command_line) |
| |
| { |
| int offset=1; |
| char *ptr,buffer [80]; |
| |
| ptr=parse_word (command_line,buffer); |
| |
| if (*ptr!=0) { |
| ptr=parse_word (ptr,buffer); |
| offset*=atol (buffer); |
| } |
| |
| if (file_info.offset_in_block-offset >= 0) { |
| file_info.offset_in_block-=offset; |
| sprintf (buffer,"show");dispatch (buffer); |
| } |
| |
| else { |
| wprintw (command_win,"Error - Offset out of block\n");refresh_command_win (); |
| } |
| } |
| |
| void type_file___prevblock (char *command_line) |
| |
| { |
| long block_offset=1; |
| char *ptr,buffer [80]; |
| |
| ptr=parse_word (command_line,buffer); |
| |
| if (*ptr!=0) { |
| ptr=parse_word (ptr,buffer); |
| block_offset*=atol (buffer); |
| } |
| |
| if (file_info.block_num-block_offset < 0) { |
| wprintw (command_win,"Error - Block offset out of range\n");wrefresh (command_win); |
| return; |
| } |
| |
| file_info.block_num-=block_offset; |
| file_info.global_block_num=file_block_to_global_block (file_info.block_num,&file_info); |
| file_info.global_block_offset=file_info.global_block_num*file_system_info.block_size; |
| file_info.file_offset=file_info.block_num*file_system_info.block_size; |
| |
| low_read (file_info.buffer,file_system_info.block_size,file_info.global_block_offset); |
| |
| strcpy (buffer,"show");dispatch (buffer); |
| } |
| |
| void type_file___block (char *command_line) |
| |
| { |
| long block_offset=1; |
| char *ptr,buffer [80]; |
| |
| ptr=parse_word (command_line,buffer); |
| |
| if (*ptr==0) { |
| wprintw (command_win,"Error - Invalid arguments\n");wrefresh (command_win); |
| return; |
| } |
| |
| ptr=parse_word (ptr,buffer); |
| block_offset=atol (buffer); |
| |
| if (block_offset < 0 || block_offset >= file_info.blocks_count) { |
| wprintw (command_win,"Error - Block offset out of range\n");wrefresh (command_win); |
| return; |
| } |
| |
| file_info.block_num=block_offset; |
| file_info.global_block_num=file_block_to_global_block (file_info.block_num,&file_info); |
| file_info.global_block_offset=file_info.global_block_num*file_system_info.block_size; |
| file_info.file_offset=file_info.block_num*file_system_info.block_size; |
| |
| low_read (file_info.buffer,file_system_info.block_size,file_info.global_block_offset); |
| |
| strcpy (buffer,"show");dispatch (buffer); |
| } |
| |
| void type_file___display (char *command_line) |
| |
| { |
| char *ptr,buffer [80]; |
| |
| ptr=parse_word (command_line,buffer); |
| if (*ptr==0) |
| strcpy (buffer,"hex"); |
| else |
| ptr=parse_word (ptr,buffer); |
| |
| if (strcasecmp (buffer,"hex")==0) { |
| wprintw (command_win,"Display set to hex\n");wrefresh (command_win); |
| file_info.display=HEX; |
| sprintf (buffer,"show");dispatch (buffer); |
| } |
| |
| else if (strcasecmp (buffer,"text")==0) { |
| wprintw (command_win,"Display set to text\n");wrefresh (command_win); |
| file_info.display=TEXT; |
| sprintf (buffer,"show");dispatch (buffer); |
| } |
| |
| else { |
| wprintw (command_win,"Error - Invalid arguments\n");wrefresh (command_win); |
| } |
| } |
| |
| void file_show_hex (void) |
| |
| { |
| long offset=0,l,i; |
| unsigned char *ch_ptr; |
| |
| /* device_offset and type_data points to the inode */ |
| |
| show_pad_info.line=0; |
| |
| wmove (show_pad,0,0); |
| ch_ptr=file_info.buffer; |
| for (l=0;l<file_system_info.block_size/16;l++) { |
| if (file_info.file_offset+offset>file_info.file_length-1) break; |
| wprintw (show_pad,"%08ld : ",offset); |
| for (i=0;i<16;i++) { |
| |
| if (file_info.file_offset+offset+i>file_info.file_length-1) { |
| wprintw (show_pad," "); |
| } |
| |
| else { |
| if (file_info.offset_in_block==offset+i) |
| wattrset (show_pad,A_REVERSE); |
| |
| if (ch_ptr [i]>=' ' && ch_ptr [i]<='z') |
| wprintw (show_pad,"%c",ch_ptr [i]); |
| else |
| wprintw (show_pad,"."); |
| |
| if (file_info.offset_in_block==offset+i) |
| wattrset (show_pad,A_NORMAL); |
| } |
| } |
| |
| wprintw (show_pad," "); |
| for (i=0;i<16;i++) { |
| if (file_info.file_offset+offset+i>file_info.file_length-1) break; |
| if (file_info.offset_in_block==offset+i) |
| wattrset (show_pad,A_REVERSE); |
| |
| wprintw (show_pad,"%02x",ch_ptr [i]); |
| |
| if (file_info.offset_in_block==offset+i) { |
| wattrset (show_pad,A_NORMAL); |
| show_pad_info.line=l-l % show_pad_info.display_lines; |
| } |
| |
| wprintw (show_pad," "); |
| |
| } |
| |
| wprintw (show_pad,"\n"); |
| offset+=i; |
| ch_ptr+=i; |
| } |
| |
| show_pad_info.max_line=l-1; |
| |
| refresh_show_pad (); |
| |
| show_status (); |
| } |
| |
| void file_show_text (void) |
| |
| { |
| long offset=0,last_offset,l=0,cols=0; |
| unsigned char *ch_ptr; |
| |
| /* device_offset and type_data points to the inode */ |
| |
| show_pad_info.line=0; |
| wmove (show_pad,0,0); |
| ch_ptr=file_info.buffer; |
| |
| last_offset=file_system_info.block_size-1; |
| |
| if (file_info.file_offset+last_offset > file_info.file_length-1) |
| last_offset=file_info.file_length-1-file_info.file_offset; |
| |
| while ( (offset <= last_offset) && l<SHOW_PAD_LINES) { |
| |
| if (cols==SHOW_PAD_COLS-1) { |
| wprintw (show_pad,"\n"); |
| l++;cols=0; |
| } |
| |
| |
| if (file_info.offset_in_block==offset) |
| wattrset (show_pad,A_REVERSE); |
| |
| if (*ch_ptr >= ' ' && *ch_ptr <= 'z') |
| wprintw (show_pad,"%c",*ch_ptr); |
| |
| |
| else { |
| if (*ch_ptr == 0xa) { |
| wprintw (show_pad,"\n"); |
| l++;cols=0; |
| } |
| |
| else if (*ch_ptr == 0x9) |
| wprintw (show_pad," "); |
| |
| else |
| wprintw (show_pad,"."); |
| } |
| |
| if (file_info.offset_in_block==offset) { |
| wattrset (show_pad,A_NORMAL); |
| show_pad_info.line=l-l % show_pad_info.display_lines; |
| } |
| |
| |
| offset++;cols++;ch_ptr++; |
| } |
| |
| wprintw (show_pad,"\n"); |
| show_pad_info.max_line=l; |
| |
| refresh_show_pad (); |
| |
| show_status (); |
| } |
| |
| void show_status (void) |
| |
| { |
| long inode_num; |
| |
| werase (show_win);wmove (show_win,0,0); |
| wprintw (show_win,"File contents. Block %ld. ",file_info.global_block_num); |
| wprintw (show_win,"File block %ld of %ld. ",file_info.block_num,file_info.blocks_count-1); |
| wprintw (show_win,"File Offset %ld of %ld.",file_info.file_offset,file_info.file_length-1); |
| |
| wmove (show_win,1,0); |
| inode_num=inode_offset_to_inode_num (file_info.inode_offset); |
| wprintw (show_win,"File inode %ld. Indirection level %ld.",inode_num,file_info.level); |
| |
| refresh_show_win (); |
| } |
| |
| void type_file___remember (char *command_line) |
| |
| { |
| int found=0; |
| long entry_num; |
| char *ptr,buffer [80]; |
| struct struct_descriptor *descriptor_ptr; |
| |
| ptr=parse_word (command_line,buffer); |
| |
| if (*ptr==0) { |
| wprintw (command_win,"Error - Argument not specified\n");wrefresh (command_win); |
| return; |
| } |
| |
| ptr=parse_word (ptr,buffer); |
| |
| entry_num=remember_lifo.entries_count++; |
| if (entry_num>REMEMBER_COUNT-1) { |
| entry_num=0; |
| remember_lifo.entries_count--; |
| } |
| |
| descriptor_ptr=first_type; |
| while (descriptor_ptr!=NULL && !found) { |
| if (strcmp (descriptor_ptr->name,"ext2_inode")==0) |
| found=1; |
| else |
| descriptor_ptr=descriptor_ptr->next; |
| } |
| |
| |
| remember_lifo.offset [entry_num]=device_offset; |
| remember_lifo.type [entry_num]=descriptor_ptr; |
| strcpy (remember_lifo.name [entry_num],buffer); |
| |
| wprintw (command_win,"Object %s in Offset %ld remembered as %s\n",descriptor_ptr->name,device_offset,buffer); |
| wrefresh (command_win); |
| } |
| |
| void type_file___set (char *command_line) |
| |
| { |
| unsigned char tmp; |
| char *ptr,buffer [80],*ch_ptr; |
| int mode=HEX; |
| |
| ptr=parse_word (command_line,buffer); |
| if (*ptr==0) { |
| wprintw (command_win,"Error - Argument not specified\n");refresh_command_win ();return; |
| } |
| |
| ptr=parse_word (ptr,buffer); |
| |
| if (strcasecmp (buffer,"text")==0) { |
| mode=TEXT; |
| strcpy (buffer,ptr); |
| } |
| |
| else if (strcasecmp (buffer,"hex")==0) { |
| mode=HEX; |
| ptr=parse_word (ptr,buffer); |
| } |
| |
| if (*buffer==0) { |
| wprintw (command_win,"Error - Data not specified\n");refresh_command_win ();return; |
| } |
| |
| if (mode==HEX) { |
| do { |
| tmp=(unsigned char) strtol (buffer,NULL,16); |
| file_info.buffer [file_info.offset_in_block]=tmp; |
| file_info.offset_in_block++; |
| ptr=parse_word (ptr,buffer); |
| if (file_info.offset_in_block==file_system_info.block_size) { |
| if (*ptr) { |
| wprintw (command_win,"Error - Ending offset outside block, only partial string changed\n"); |
| refresh_command_win (); |
| } |
| file_info.offset_in_block--; |
| } |
| } while (*buffer) ; |
| } |
| |
| else { |
| ch_ptr=buffer; |
| while (*ch_ptr) { |
| tmp=(unsigned char) *ch_ptr++; |
| file_info.buffer [file_info.offset_in_block]=tmp; |
| file_info.offset_in_block++; |
| if (file_info.offset_in_block==file_system_info.block_size) { |
| if (*ch_ptr) { |
| wprintw (command_win,"Error - Ending offset outside block, only partial string changed\n"); |
| refresh_command_win (); |
| } |
| file_info.offset_in_block--; |
| } |
| } |
| } |
| |
| strcpy (buffer,"show");dispatch (buffer); |
| } |
| |
| void type_file___writedata (char *command_line) |
| |
| { |
| low_write (file_info.buffer,file_system_info.block_size,file_info.global_block_offset); |
| return; |
| } |
| |
| long file_block_to_global_block (long file_block,struct struct_file_info *file_info_ptr) |
| |
| { |
| long last_direct,last_indirect,last_dindirect; |
| |
| last_direct=EXT2_NDIR_BLOCKS-1; |
| last_indirect=last_direct+file_system_info.block_size/4; |
| last_dindirect=last_indirect+(file_system_info.block_size/4)*(file_system_info.block_size/4); |
| |
| if (file_block <= last_direct) { |
| file_info_ptr->level=0; |
| return (file_info_ptr->inode_ptr->i_block [file_block]); |
| } |
| |
| if (file_block <= last_indirect) { |
| file_info_ptr->level=1; |
| file_block=file_block-last_direct-1; |
| return (return_indirect (file_info_ptr->inode_ptr->i_block [EXT2_IND_BLOCK],file_block)); |
| } |
| |
| if (file_block <= last_dindirect) { |
| file_info_ptr->level=2; |
| file_block=file_block-last_indirect-1; |
| return (return_dindirect (file_info_ptr->inode_ptr->i_block [EXT2_DIND_BLOCK],file_block)); |
| } |
| |
| file_info_ptr->level=3; |
| file_block=file_block-last_dindirect-1; |
| return (return_tindirect (file_info_ptr->inode_ptr->i_block [EXT2_TIND_BLOCK],file_block)); |
| } |
| |
| long return_indirect (long table_block,long block_num) |
| |
| { |
| long block_table [EXT2_MAX_BLOCK_SIZE/4]; |
| |
| low_read ((char *) block_table,file_system_info.block_size,table_block*file_system_info.block_size); |
| return (block_table [block_num]); |
| } |
| |
| long return_dindirect (long table_block,long block_num) |
| |
| { |
| long f_indirect; |
| |
| f_indirect=block_num/(file_system_info.block_size/4); |
| f_indirect=return_indirect (table_block,f_indirect); |
| return (return_indirect (f_indirect,block_num%(file_system_info.block_size/4))); |
| } |
| |
| long return_tindirect (long table_block,long block_num) |
| |
| { |
| long s_indirect; |
| |
| s_indirect=block_num/((file_system_info.block_size/4)*(file_system_info.block_size/4)); |
| s_indirect=return_indirect (table_block,s_indirect); |
| return (return_dindirect (s_indirect,block_num%((file_system_info.block_size/4)*(file_system_info.block_size/4)))); |
| } |