/* /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)))); }