⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 de.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************//*								*//*	de.c							*//*								*//*		Main loop of the "Disk editor".			*//*								*//****************************************************************//*  origination         1989-Jan-15        Terrence W. Holm	*//****************************************************************/#include <minix/config.h>#include <sys/types.h>#include <sys/dir.h>#include <sys/stat.h>#include <sys/wait.h>#include <ctype.h>#include <errno.h>#undef ERROR			/* arrgghh, errno.h has this pollution */#include <fcntl.h>#include <limits.h>#include <signal.h>#include <stdarg.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <minix/const.h>#include <minix/type.h>#include "../../fs/const.h"#include "../../fs/type.h"#include "../../fs/inode.h"#include "de.h"static char copyright[] = "de  (c) Terrence W. Holm 1989";_PROTOTYPE(void Push , (de_state *s ));_PROTOTYPE(int Get_Base , (int *base ));_PROTOTYPE(int Get_Filename , (de_state *s ));_PROTOTYPE(int Get_Count , (char *units , unsigned long *result ));_PROTOTYPE(void Exec_Shell , (void));_PROTOTYPE(void Sigint , (int));/****************************************************************//*								*//*	main()							*//*								*//*		Initialize. Handle the "-r" recovery option if	*//*		specified, else enter the main processing loop.	*//*								*//****************************************************************/void main( argc, argv )  int   argc;  char *argv[];  {  static de_state s;		/* it is safer not to put it on the stack				 * and some things probably now rely on zero				 * initialization				 */    char *command_name = argv[0];  int   recover = 0;  s.device_mode = O_RDONLY;  /*  Parse arguments  */  if ( argc == 3  &&  strcmp( argv[1], "-r" ) == 0 )    {    recover = 1;    --argc;    ++argv;    }  else if ( argc == 3  &&  strcmp( argv[1], "-w" ) == 0 )    {    s.device_mode = O_RDWR;    --argc;    ++argv;    }  if ( argc != 2  ||  *argv[1] == '-' )    {    fprintf( stderr, "Usage: %s [-w] /dev/device\n", command_name );    fprintf( stderr, "       %s -r lost_file_name\n", command_name );    exit( 1 );    }  /*  Set the effective id to the real id. This eliminates	*/  /*  any increase in privilege done by a set-uid bit on the	*/  /*  executable file. We want to be "root" for recovering 	*/  /*  files, because we must be able to read the device.	*/  /*  However, in normal usage, de(1) should not let just 	*/  /*  anyone look at a file system, thus we drop the privilege.	*/  /*								*/  /*  NOTE: There is a security hole when using "-r" with a	*/  /*  set-uid de(1). Do not use set-uid root if there is any	*/  /*  way to externally access your Minix system.		*/  if ( ! recover )    {    setuid( getuid() );    setgid( getgid() );    }  /*  Set terminal characteristics, and ^C interrupt handler  */  Save_Term();  if ( signal( SIGINT, SIG_IGN ) != SIG_IGN )    {    signal( SIGINT,  Sigint );    signal( SIGQUIT, Sigint );    }  Set_Term();  if ( ! Init_Termcap() )    Error( "Requires a termcap entry" );  /*  Get the device file name. If recovering, also open an output file.  */  if ( recover )    {    char *dir_name;    char *file_name;    struct stat device_stat;    struct stat tmp_stat;    /*  Split the path name into a directory and a file name.  */    if ( strlen(argv[1]) > MAX_STRING )      Error( "Path name too long" );    if ( ! Path_Dir_File( argv[1], &dir_name, &file_name ) )      Error( "Recover aborted" );    /*  Find the device holding the directory.  */    if ( (s.device_name = File_Device( dir_name )) == NULL )      Error( "Recover aborted" );    /*  The output file will be in /tmp with the same file name.  */    strcpy( s.file_name, TMP );    strcat( s.file_name, "/" );    strcat( s.file_name, file_name );    /*  Make sure /tmp is not on the same device as the file we	   */    /*  are trying to recover (we don't want to use up the free	   */    /*  i-node and blocks before we get a chance to recover them). */    if ( stat( s.device_name, &device_stat ) == -1 )      Error( "Can not stat(2) device %s", s.device_name );    if ( stat( TMP, &tmp_stat ) == -1 )      Error( "Can not stat(2) directory %s", TMP );    if ( device_stat.st_rdev == tmp_stat.st_dev )      Error( "Will not recover files on the same device as %s", TMP );    if ( access( s.file_name, F_OK ) == 0 )      Error( "Will not overwrite file %s", s.file_name );    /*  Open the output file.  */    if ( (s.file_f = fopen( s.file_name, "w" )) == NULL )      Error( "Can not open file %s", s.file_name );    /*  Don't let anyone else look at the recovered file  */    chmod( s.file_name, 0700 );    /*  If running as root then change the owner of the  */    /*  restored file. If not running as root then the   */    /*  chown(2) will fail.				 */    chown( s.file_name, getuid(), getgid() );    }  else    {    s.device_name = argv[1];    s.file_name[ 0 ] = '\0';    }  /*  Open the device file.  */  {  struct stat device_stat;  off_t size;  if ( stat( s.device_name, &device_stat ) == -1 )    Error( "Can not find file %s", s.device_name );  if ( (device_stat.st_mode & S_IFMT) != S_IFBLK  &&       (device_stat.st_mode & S_IFMT) != S_IFREG )    Error( "Can only edit block special or regular files" );  if ( (s.device_d = open( s.device_name, s.device_mode )) == -1 )    Error( "Can not open %s", s.device_name );  if ( (size = lseek( s.device_d, 0L, SEEK_END )) == -1 )    Error( "Error seeking %s", s.device_name );  if ( size % K != 0 )    {    Warning( "Device size is not a multiple of 1024" );    Warning( "The (partial) last block will not be accessible" );    }  }  /*  Initialize the rest of the state record  */  s.mode = WORD;  s.output_base = 10;  s.search_string[ 0 ] = '\0';  {  int i;  for ( i = 0;  i < MAX_PREV;  ++i )    {    s.prev_addr[ i ] = 0L;    s.prev_mode[ i ] = WORD;    }  }  sync();  Read_Super_Block( &s );  Read_Bit_Maps( &s );  s.address = 0L;  /*  Recover mode basically performs an 'x' and an 'X'  */  if ( recover )    {    ino_t inode = Find_Deleted_Entry( &s, argv[1] );    off_t size;    if ( inode == 0 )      {      unlink( s.file_name );      Error( "Recover aborted" );      }    s.address = ( (long) s.first_data - s.inode_blocks ) * K		      + (long) (inode - 1) * s.inode_size;    Read_Block( &s, s.buffer );    /*  Have found the lost i-node, now extract the blocks.  */    if ( (size = Recover_Blocks( &s )) == -1L )      {      unlink( s.file_name );      Error( "Recover aborted" );      }    Reset_Term();    printf( "Recovered %ld bytes, written to file %s\n", size, s.file_name );    exit( 0 );    }  /*  Enter the main loop, first time redraw the screen  */  {  int rc = REDRAW;  do    {    if ( rc == REDRAW )      {      Read_Block( &s, s.buffer );      Draw_Screen( &s );      s.last_addr = s.address;      Draw_Pointers( &s );      }    else if ( rc == REDRAW_POINTERS )      {      s.offset = (unsigned) (s.address & ~ K_MASK);      Draw_Pointers( &s );      }    else if ( rc == ERROR )      {      Erase_Prompt();      putchar( BELL );      }    } while ( (rc = Process( &s, Arrow_Esc(Get_Char()) )) != EOF );  }  /*  If there is an open output file that was never written to  */  /*  then remove its directory entry. This occurs when no 'w' 	 */  /*  or 'W' command occurred between a 'c' command and exiting	 */  /*  the program.						 */  if ( s.file_name[0] != '\0'  &&  ! s.file_written )    unlink( s.file_name );  Reset_Term();	   /*  Restore terminal characteristics  */  exit( 0 );  }/****************************************************************//*								*//*	Get_Base( base )					*//*								*//*		Get a new base value.				*//*		Returns REDRAW or ERROR.			*//*								*//****************************************************************/int Get_Base( base )  int *base;  {	switch ( Get_Char() )	  {	  case 'h' :	*base = 16;			break;	  case 'd' :	*base = 10;			break;	  case 'o' :	*base = 8;			break;	  case 'b' :	*base = 2;			break;	  default  :	return( ERROR );	  }		return( REDRAW );  }/****************************************************************//*								*//*	Process( state, input_char )				*//*								*//*		Determine the function requested by the 	*//*		input character. Returns OK, REDRAW,		*//*		REDRAW_POINTERS,  ERROR or EOF.			*//*								*//****************************************************************/int Process( s, c )  de_state  *s;  int  c;  {  switch ( c )    {    case 'b' :				/*  Back up one block	*/    case ESC_PGUP :		if ( s->address == 0 )		  return( ERROR );		s->address = (s->address - K) & K_MASK;		return( REDRAW );    case 'B' :				/*  Back up to home	*/    case ESC_HOME :		if ( s->address == 0 )		  return( OK );		Push( s );		s->address = 0L;		return( REDRAW );    case 'c' :				/*  Change file name	*/		{		int rc = Get_Filename( s );		return( rc == OK ? REDRAW : rc );		}    case 'd' :				/*  Down		*/    case ESC_DOWN :		{		s->last_addr = s->address;		switch ( s->mode )		  {		  case WORD :	s->address += 2;				if ( (s->address & PAGE_MASK) == 0 )				  return( REDRAW );				return( REDRAW_POINTERS );		  case BLOCK :	s->address += 64;				if ( (s->last_addr & K_MASK) !=				     (s->address   & K_MASK) )				  return( REDRAW );				return( REDRAW_POINTERS );		  case MAP :	s->address += 256;				return( REDRAW );		  default :	Error( "Internal fault (mode)" );		  }		}    case 'f' :				/*  Forward one block	*/    case ' ' :    case ESC_PGDN :		if ( s->block == s->device_size - 1 )		  return( ERROR );		s->address = (s->address + K) & K_MASK;		return( REDRAW );    case 'F' :				/*  Forward to end	*/    case ESC_END :		{		off_t  last_block = ( (long) s->device_size - 1 ) * K;		if ( s->address == last_block )		  return( OK );		Push( s );		s->address = last_block;		return( REDRAW );		}    case 'g' :				/*  Goto block		*/		{		unsigned long block;		if ( Get_Count( "Block?", &block ) )		  {		  if ( block >= s->zones )		    {		    Warning( "Block number too large" );		    return( REDRAW );		    }		  Push( s );		  s->address = (off_t) block * K;		  return( REDRAW );		  }		else		  return( ERROR );		}    case 'G' :				/*  Goto block indirect	*/		{		unsigned block = *( (word_t *) &s->buffer[ s->offset ] );		if ( s->mode != WORD )		  {		  Warning( "Must be in visual mode \"word\"" );		  return( REDRAW );		  }		if ( block >= s->zones )		  {		  Warning( "Block number too large" );		  return( REDRAW );		  }		Push( s );		s->mode = BLOCK;		s->address = (long) block * K;		return( REDRAW );		}    case 'h' :				/*  Help		*/    case '?' :		Draw_Help_Screen( s );		Wait_For_Key();		return( REDRAW );    case 'i' :				/*  Goto i-node		*/		{		unsigned long inode;		if ( Get_Count( "I-node?", &inode ) )		  {		  if ( inode < 1  || inode > s->inodes )		    {		    Warning( "Illegal i-node number" );		    return( REDRAW );		    }		  Push( s );		  s->mode = WORD;		  s->address = (off_t) (s->first_data - s->inode_blocks) * K				  + (off_t) (inode - 1) * s->inode_size;		  return( REDRAW );		  }		else		  return( ERROR );		}    case 'I' :				/*  Filename to i-node	*/		{		ino_t inode;		char *filename;		Draw_Prompt( "File name?" );		filename = Get_Line();		if ( filename == NULL  ||  filename[0] == '\0' )		  return( ERROR );		inode = Find_Inode( s, filename );		if ( inode )		  {		  Push( s );		  s->mode = WORD;		  s->address = ( (long) s->first_data - s->inode_blocks ) * K				  + (long) (inode - 1) * s->inode_size;		  }		return( REDRAW );		}    case 'l' :				/*  Left		*/    case ESC_LEFT :		{		s->last_addr = s->address;		switch ( s->mode )		  {		  case WORD :	s->address = s->address - 32;				return( REDRAW );		  case BLOCK :	s->address -= 1;				if ( (s->last_addr & K_MASK) !=				     (s->address   & K_MASK) )				  return( REDRAW );				return( REDRAW_POINTERS );		  case MAP :	s->address -= 4;				if ( (s->last_addr & ~ MAP_MASK) !=				     (s->address   & ~ MAP_MASK) )				  return( REDRAW );				return( REDRAW_POINTERS );		  default :	Error( "Internal fault (mode)" );		  }		}    case 'm' :				/*  Invoke a Minix shell */		Reset_Term();		Exec_Shell();		Set_Term();		return( REDRAW );    case 'n' :				/*  Search for next	*/		{		off_t addr;		if ( s->search_string[0] == '\0' )		  {		  Warning( "No search string defined" );		  return( REDRAW );		  }		Draw_Prompt( "Searching..." );		if ( (addr = Search( s, s->search_string )) == -1L )		  {		  Warning( "Search string not found" );		  Wait_For_Key();		  return( REDRAW );		  }		Push( s );		s->address = addr;		return( REDRAW );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -