Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!cornell!rochester!rutgers!att!alberta!ubc-cs!ubc-bdcvax!holm From: holm@ubc-bdcvax.UUCP (Terrence W. Holm) Newsgroups: comp.os.minix Subject: de(1) minix disk editor (part 5 of 5) Message-ID: <420@ubc-bdcvax.UUCP> Date: 3 Feb 89 01:51:13 GMT Lines: 1121 --------------------------------------------------------------- X X#include X#include X#include X#include X#include X#include X#include X X#include X#include X#include X X#include "de.h" X X X/****************************************************************/ X/* Code for handling termcap */ X/****************************************************************/ X X X#define TC_BUFFER 1024 /* Size of termcap(3) buffer */ X#define TC_STRINGS 200 /* Enough room for cm,cl,so,se */ X X Xstatic char *Tmove; /* (cm) - Format for tgoto */ Xstatic char *Tclr_all; /* (cl) - Clear screen */ Xstatic char *Treverse; /* (so) - Start reverse mode */ Xstatic char *Tnormal; /* (se) - End reverse mode */ X Xchar Kup = 0; /* (ku) - Up arrow key */ Xchar Kdown = 0; /* (kd) - Down arrow key */ Xchar Kleft = 0; /* (kl) - Left arrow key */ Xchar Kright = 0; /* (kr) - Right arrow key */ X X X X/****************************************************************/ X/* */ X/* Init_Termcap() */ X/* */ X/* Initializes the external variables for the */ X/* current terminal. */ X/* */ X/****************************************************************/ X X Xint Init_Termcap() X X { X char *term; X char buffer[ TC_BUFFER ]; X static char strings[ TC_STRINGS ]; X char *s = &strings[0]; X char *Kcode; X X X term = getenv( "TERM" ); X X if ( term == NULL ) X return( 0 ); X X if ( tgetent( buffer, term ) != 1 ) X return( 0 ); X X X if ( (Tmove = tgetstr( "cm", &s )) == NULL ) X return( 0 ); X X if ( (Tclr_all = tgetstr( "cl", &s )) == NULL ) X return( 0 ); X X if ( (Treverse = tgetstr( "so", &s )) == NULL ) X { X Treverse = Tnormal = s; X *s = '\0'; X ++s; X } X else if ( (Tnormal = tgetstr( "se", &s )) == NULL ) X return( 0 ); X X X /* See if there are single character arrow key codes */ X X if ( (Kcode = tgetstr( "ku", &s )) != NULL && strlen( Kcode ) == 1 ) X Kup = Kcode[0]; X X if ( (Kcode = tgetstr( "kd", &s )) != NULL && strlen( Kcode ) == 1 ) X Kdown = Kcode[0]; X X if ( (Kcode = tgetstr( "kl", &s )) != NULL && strlen( Kcode ) == 1 ) X Kleft = Kcode[0]; X X if ( (Kcode = tgetstr( "kr", &s )) != NULL && strlen( Kcode ) == 1 ) X Kright = Kcode[0]; X X X return( 1 ); X } X X X X X X X/****************************************************************/ X/* */ X/* Goto( column, line ) */ X/* */ X/* Use the termcap string to move the cursor. */ X/* */ X/****************************************************************/ X X Xvoid Goto( column, line ) X int column; X int line; X X { X fputs( tgoto( Tmove, column, line ), stdout ); X } X X X X X X X/****************************************************************/ X/* Output routines */ X/****************************************************************/ X X X X X/****************************************************************/ X/* */ X/* Draw_Help_Screen() */ X/* */ X/****************************************************************/ X X Xvoid Draw_Help_Screen( s ) X de_state *s; X X { X int down; X int right; X X switch ( s->mode ) X { X case WORD : down = 2; right = 32; break; X case BLOCK : down = 64; right = 1; break; X case MAP : down = 256; right = 4; break; X } X X printf( "%s ", Tclr_all ); X printf( "%sDE COMMANDS%s\r\n\n\n", Treverse, Tnormal ); X X X printf( " PGUP b Back one block h Help\r\n" ); X printf( " PGDN f Forward one block q Quit\r\n" ); X printf( " HOME B Goto first block m Minix shell\r\n" ); X printf( " END F Goto last block\r\n" ); X printf( " v Visual mode (w b m)\r\n" ); X printf( " g Goto specified block o Output base (h d o b)\r\n" ); X printf( " G Goto block indirectly\r\n" ); X printf( " i Goto i-node c Change file name\r\n" ); X printf( " I Filename to i-node w Write ASCII block\r\n" ); X printf( " W Write block exactly\r\n" ); X printf( " / Search\r\n" ); X printf( " n Next occurrence x Extract lost entry\r\n" ); X printf( " p Previous address X Extract lost blocks\r\n" ); X printf( " s Store word\r\n" ); X printf( " UP u Move back %d bytes\r\n", down ); X printf( " DOWN d Move forward %d bytes\r\n", down ); X printf( " LEFT l Move back %d byte%s\r\n", right, X right == 1 ? "" : "s" ); X printf( " RIGHT r Move forward %d byte%s\r\n\n\n", right, X right == 1 ? "" : "s" ); X } X X X X X X X/****************************************************************/ X/* */ X/* Wait_For_Key() */ X/* */ X/* The user must press a key to continue. */ X/* */ X/****************************************************************/ X X Xvoid Wait_For_Key() X X { X Draw_Prompt( "Press a key to continue..." ); X X Get_Char(); X } X X X X X X X/****************************************************************/ X/* */ X/* Draw_Prompt( string ) */ X/* */ X/* Write a message in the "prompt" area. */ X/* */ X/****************************************************************/ X X Xvoid Draw_Prompt( string ) X char *string; X X { X Goto( PROMPT_COLUMN, PROMPT_LINE ); X X printf( "%s%s%s ", Treverse, string, Tnormal ); X } X X X X X X X/****************************************************************/ X/* */ X/* Erase_Prompt() */ X/* */ X/* Erase the message in the "prompt" area. */ X/* */ X/****************************************************************/ X X Xvoid Erase_Prompt() X X { X Goto( PROMPT_COLUMN, PROMPT_LINE ); X X printf( "%77c", ' ' ); X X Goto( PROMPT_COLUMN, PROMPT_LINE ); X } X X X X X X X/****************************************************************/ X/* */ X/* Draw_Screen( state ) */ X/* */ X/* Redraw everything, except pointers. */ X/* */ X/****************************************************************/ X X Xvoid Draw_Screen( s ) X de_state *s; X X { X fputs( Tclr_all, stdout ); X X Draw_Strings( s ); X Block_Type( s ); X X switch ( s->mode ) X { X case WORD : Draw_Words( s ); X Draw_Info( s ); X break; X X case BLOCK : Draw_Block( s->buffer ); X break; X X case MAP : { X int max_bits = 2 * K; X X /* Don't display the bits after the end */ X /* of the i-node or zone bit maps. */ X X if ( s->block == 2 + s->inode_maps - 1 ) X max_bits = s->inodes_in_map - 8 * K * (s->inode_maps - 1) X - 8 * (s->offset & ~ MAP_MASK); X X else if ( s->block == 2 + s->inode_maps + s->zone_maps - 1 ) X max_bits = s->zones_in_map - 8 * K * (s->zone_maps - 1) X - 8 * (s->offset & ~ MAP_MASK); X X if ( max_bits < 0 ) X max_bits = 0; X X Draw_Map( &s->buffer[ s->offset & ~ MAP_MASK ], max_bits ); X break; X } X } X } X X X X X X X/****************************************************************/ X/* */ X/* Draw_Strings( state ) */ X/* */ X/* The first status line contains the device name, */ X/* the current write file name (if one is open) */ X/* and the current search string (if one has */ X/* been defined). */ X/* */ X/* Long strings are truncated. */ X/* */ X/****************************************************************/ X X Xvoid Draw_Strings( s ) X de_state *s; X X { X int len; X int i; X X Goto( STATUS_COLUMN, STATUS_LINE ); X X printf( "Device %s= %-14.14s ", X s->device_mode == O_RDONLY ? "" : "(w) ", s->device_name ); X X X len = strlen( s->file_name ); X X if ( len == 0 ) X printf( "%29s", " " ); X else if ( len <= 20 ) X printf( "File = %-20s ", s->file_name ); X else X printf( "File = ...%17.17s ", s->file_name + len - 17 ); X X X len = strlen( s->search_string ); X X if ( len == 0 ) X printf( "%20s", " " ); X else X { X printf( "Search = " ); X X if ( len <= 11 ) X { X for ( i = 0; i < len; ++i ) X Print_Ascii( s->search_string[ i ] ); X X for ( ; i < 11; ++i ) X putchar( ' ' ); X } X else X { X for ( i = 0; i < 8; ++i ) X Print_Ascii( s->search_string[ i ] ); X X printf( "..." ); X } X } X } X X X X X X X/****************************************************************/ X/* */ X/* Block_Type( state ) */ X/* */ X/* Display the current block type. */ X/* */ X/****************************************************************/ X X Xvoid Block_Type( s ) X de_state *s; X X { X Goto( STATUS_COLUMN, STATUS_LINE + 1 ); X X printf( "Block = %5u of %-5u ", s->block, s->zones ); X X X if ( s->block == BOOT_BLOCK ) X printf( "Boot block" ); X X else if ( s->block == SUPER_BLOCK ) X printf( "Super block" ); X X else if ( s->block < 2 + s->inode_maps ) X printf( "I-node bit map" ); X X else if ( s->block < 2 + s->inode_maps + s->zone_maps ) X printf( "Zone bit map" ); X X else if ( s->block < s->first_data ) X printf( "I-nodes" ); X X else X printf( "Data block (%sin use)", X In_Use(s->block - s->first_data + 1, s->zone_map) ? "" : "not " ); X } X X X X X X X/****************************************************************/ X/* */ X/* Draw_Words( state ) */ X/* */ X/* Draw a page in word format. */ X/* */ X/****************************************************************/ X X Xvoid Draw_Words( s ) X de_state *s; X X { X int line; X int addr = s->offset & ~ PAGE_MASK; X X X for ( line = 0; line < 16; ++line, addr += 2 ) X { X Goto( BLOCK_COLUMN, BLOCK_LINE + line ); X X printf( "%5d ", addr ); X X Print_Number( *( (unsigned *) &s->buffer[ addr ] ), s->output_base ); X } X X Goto( BLOCK_COLUMN + 64, BLOCK_LINE + 6 ); X printf( "(base %d)", s->output_base ); X } X X X X X X X/****************************************************************/ X/* */ X/* Draw_Info( state ) */ X/* */ X/* Add information to a page drawn in word format. */ X/* The routine recognizes the super block, inodes, */ X/* executables and "ar" archives. If the current */ X/* page is not one of these, then ASCII characters */ X/* are printed from the data words. */ X/* */ X/****************************************************************/ X X Xchar *super_block_info[] = { "number of inodes", X "number of zones", X "inode bit map blocks", X "zone bit map blocks", X "first data zone", X "blocks per zone shift", X "maximum file size", X "", X "magic number" }; X X Xchar *inode_info[] = { "", X "", X "", X "", X "", X "", X "", X "zone 0", X "zone 1", X "zone 2", X "zone 3", X "zone 4", X "zone 5", X "zone 6", X "indirect", X "double indirect" }; X X X Xvoid Draw_Info( s ) X de_state *s; X X { X int i; X int page = s->offset >> PAGE_SHIFT; X X X if ( s->block == SUPER_BLOCK && page == 0 ) X for ( i = 0; i < 9; ++i ) X { X Goto( INFO_COLUMN, INFO_LINE + i ); X printf( "%s", super_block_info[ i ] ); X } X X else if ( s->block >= s->first_data - s->inode_blocks && X s->block < s->first_data ) X { X d_inode *inode = (d_inode *) &s->buffer[ s->offset & ~ PAGE_MASK ]; X int special = 0; X int m; X struct passwd *user = getpwuid( inode->i_uid ); X struct group *grp = getgrgid( inode->i_gid ); X X for ( i = 0; i < 16; ++i ) X { X Goto( INFO_COLUMN, INFO_LINE + i ); X printf( "%s", inode_info[ i ] ); X } X X Goto( INFO_COLUMN, INFO_LINE ); X X switch( inode->i_mode & S_IFMT ) X { X case S_IFDIR : printf( "directory " ); X break; X X case S_IFCHR : printf( "character " ); X special = 1; X break; X X case S_IFBLK : printf( "block " ); X special = 1; X break; X X case S_IFREG : printf( "regular " ); X break; X#ifdef S_IFIFO X case S_IFIFO : printf( "fifo " ); X break; X#endif X default : printf( "unknown " ); X } X X X for ( m = 11; m >= 0; --m ) X putchar( (inode->i_mode & (1<pw_name : "" ); X X Goto( INFO_COLUMN, INFO_LINE + 2 ); X printf( "file size %lu", inode->i_size ); X X Goto( INFO_COLUMN, INFO_LINE + 4 ); X printf( "%s", ctime( &inode->i_modtime ) ); X X Goto( INFO_COLUMN, INFO_LINE + 6 ); X printf( "links %d, group %s", inode->i_nlinks, grp ? grp->gr_name : "" ); X X if ( special ) X { X Goto( INFO_COLUMN, INFO_LINE + 7 ); X printf( "major %d, minor %d", major( inode->i_zone[0] ), X minor( inode->i_zone[0] ) ); X } X } X X else /* Print ASCII characters for each byte in page */ X { X char *p = &s->buffer[ s->offset & ~ PAGE_MASK ]; X X for ( i = 0; i < 16; ++i ) X { X Goto( INFO_COLUMN, INFO_LINE + i ); X Print_Ascii( *p++ ); X Print_Ascii( *p++ ); X } X X if ( s->block >= s->first_data && page == 0 ) X { X int magic = (s->buffer[1] << 8) | (s->buffer[0] & 0xff); X int second = (s->buffer[3] << 8) | (s->buffer[2] & 0xff); X X /* Is this block the start of an "ar" archive? */ X X if ( magic == ARMAG ) X { X Goto( INFO_COLUMN, INFO_LINE ); X printf( "\"ar\" archive" ); X } X X /* Is this block the start of an executable file? */ X X else if ( magic == A_OUT ) X { X Goto( INFO_COLUMN, INFO_LINE ); X printf( "executable" ); X X Goto( INFO_COLUMN, INFO_LINE + 1 ); X X if ( second == SPLIT ) X printf( "separate I & D" ); X else X printf( "combined I & D" ); X } X } X } X } X X X X X X X/****************************************************************/ X/* */ X/* Draw_Block( block ) */ X/* */ X/* Redraw a 1k block in character format. */ X/* */ X/****************************************************************/ X X Xvoid Draw_Block( block ) X char *block; X X { X int line; X int column; X int reverse = 0; X int msb_flag = 0; X X X for ( line = 0; line < 16; ++line ) X { X Goto( BLOCK_COLUMN, BLOCK_LINE + line ); X X for ( column = 0; column < 64; ++column ) X { X char c = *block++; X X if ( c & 0x80 ) X { X msb_flag = 1; X c &= 0x7f; X } X X if ( c >= ' ' && c < DEL ) X { X if ( reverse ) X { fputs( Tnormal, stdout ); reverse = 0; } X X putchar( c ); X } X else X { X if ( ! reverse ) X { fputs( Treverse, stdout ); reverse = 1; } X X putchar( c == DEL ? '?' : '@' + c ); X } X } /* end for ( column ) */ X } /* end for ( line ) */ X X if ( reverse ) X { fputs( Tnormal, stdout ); reverse = 0; } X X if ( msb_flag ) X { X Goto( BLOCK_COLUMN + 68, BLOCK_LINE + 6 ); X fputs( "(MSB)", stdout ); X } X } X X X X X X X/****************************************************************/ X/* */ X/* Draw_Map( block, max_bits ) */ X/* */ X/* Redraw a block in a bit map format. */ X/* Display min( max_bits, 2048 ) bits. */ X/* */ X/* The 256 bytes in "block" are displayed from */ X/* top to bottom and left to right. Bit 0 of */ X/* a byte is towards the top of the screen. */ X/* */ X/* Special graphic codes are used to generate */ X/* two "bits" per character position. So a 16 */ X/* line by 64 column display is 32 "bits" by */ X/* 64 "bits". Or 4 bytes by 64 bytes. */ X/* */ X/****************************************************************/ X X Xvoid Draw_Map( block, max_bits ) X char *block; X int max_bits; X X { X int line; X int column; X int bit_count = 0; X X for ( line = 0; line < 16; ++line ) X { X char *p = &block[ (line & 0xC) >> 2 ]; X int shift = (line & 0x3) << 1; X X Goto( BLOCK_COLUMN, BLOCK_LINE + line ); X X for ( column = 0; column < 64; ++column, p += 4 ) X { X char c = (*p >> shift) & 0x3; X int current_bit = ((p - block) << 3) + shift; X X /* Don't display bits past "max_bits" */ X X if ( current_bit >= max_bits ) X break; X X /* If "max_bits" occurs in between the two bits */ X /* I am trying to display as one character, then */ X /* zero off the high-order bit. */ X X if ( current_bit + 1 == max_bits ) X c &= 1; X X switch ( c ) X { X case 0 : putchar( BOX_CLR ); X break; X X case 1 : putchar( BOX_TOP ); X ++bit_count; X break; X X case 2 : putchar( BOX_BOT ); X ++bit_count; X break; X X case 3 : putchar( BOX_ALL ); X bit_count += 2; X break; X } X } /* end for ( column ) */ X } /* end for ( line ) */ X X X Goto( BLOCK_COLUMN + 68, BLOCK_LINE + 6 ); X printf( "(%d)", bit_count ); X } X X X X X X X/****************************************************************/ X/* */ X/* Draw_Pointers( state ) */ X/* */ X/* Redraw the pointers and the offset field. */ X/* The rest of the screen stays intact. */ X/* */ X/****************************************************************/ X X Xvoid Draw_Pointers( s ) X de_state *s; X X { X Draw_Offset( s ); X X switch ( s->mode ) X { X case WORD : Word_Pointers( s->last_addr, s->address ); X break; X X case BLOCK : Block_Pointers( s->last_addr, s->address ); X break; X X case MAP : Map_Pointers( s->last_addr, s->address ); X break; X } X X Goto( PROMPT_COLUMN, PROMPT_LINE ); X } X X X X X X X/****************************************************************/ X/* */ X/* Draw_Offset( state ) */ X/* */ X/* Display the offset in the current buffer */ X/* and the relative position if within a map */ X/* or i-node block. */ X/* */ X/****************************************************************/ X X Xvoid Draw_Offset( s ) X de_state *s; X X { X Goto( STATUS_COLUMN, STATUS_LINE + 2 ); X X printf( "Offset = %5d ", s->offset ); X X X if ( s->block < 2 ) X return; X X if ( s->block < 2 + s->inode_maps ) X { X long bit = (s->address - 2 * K) * 8; X X if ( bit < s->inodes_in_map ) X printf( "I-node %ld of %d ", bit, s->inodes ); X else X printf( "(padding) " ); X } X X else if ( s->block < 2 + s->inode_maps + s->zone_maps ) X { X long bit = (s->address - (2 + s->inode_maps) * K) * 8; X X if ( bit < s->zones_in_map ) X printf( "Block %ld of %u ", bit + s->first_data - 1, s->zones ); X else X printf( "(padding) " ); X } X X else if ( s->block < s->first_data ) X { X int node = (s->address - (2 + s->inode_maps + s->zone_maps) * K) / X INODE_SIZE + 1; X X if ( node <= s->inodes ) X printf( "I-node %d of %d (%sin use) ", node, s->inodes, X In_Use(node, s->inode_map) ? "" : "not " ); X else X printf( "(padding) " ); X } X } X X X X X X X/****************************************************************/ X/* */ X/* Word_Pointers( old_addr, new_addr ) */ X/* */ X/* Block_Pointers( old_addr, new_addr ) */ X/* */ X/* Map_Pointers( old_addr, new_addr ) */ X/* */ X/* Redraw the index pointers for a each type */ X/* of display. The pointer at "old_addr" is */ X/* erased and a new pointer is positioned */ X/* for "new_addr". This makes the screen */ X/* update faster and more pleasant for the user. */ X/* */ X/****************************************************************/ X X Xvoid Word_Pointers( old_addr, new_addr ) X off_t old_addr; X off_t new_addr; X X { X int from = ( (int) old_addr & PAGE_MASK ) >> 1; X int to = ( (int) new_addr & PAGE_MASK ) >> 1; X X Goto( BLOCK_COLUMN - 2, BLOCK_LINE + from ); X putchar( ' ' ); X X Goto( BLOCK_COLUMN - 2, BLOCK_LINE + to ); X putchar( '>' ); X } X X X X Xvoid Block_Pointers( old_addr, new_addr ) X off_t old_addr; X off_t new_addr; X X { X int from = (int) old_addr & ~K_MASK; X int to = (int) new_addr & ~K_MASK; X X Goto( BLOCK_COLUMN - 2, BLOCK_LINE + from / 64 ); X putchar( ' ' ); X X Goto( BLOCK_COLUMN - 2, BLOCK_LINE + to / 64 ); X putchar( '>' ); X X Goto( BLOCK_COLUMN + from % 64, BLOCK_LINE + 17 ); X putchar( ' ' ); X X Goto( BLOCK_COLUMN + to % 64, BLOCK_LINE + 17 ); X putchar( '^' ); X } X X X X Xvoid Map_Pointers( old_addr, new_addr ) X off_t old_addr; X off_t new_addr; X X { X int from = ( (int) old_addr & MAP_MASK ) >> 2; X int to = ( (int) new_addr & MAP_MASK ) >> 2; X X Goto( BLOCK_COLUMN + from, BLOCK_LINE + 17 ); X putchar( ' ' ); X X Goto( BLOCK_COLUMN + to, BLOCK_LINE + 17 ); X putchar( '^' ); X } X X X X X X X/****************************************************************/ X/* */ X/* Print_Number( number, output_base ) */ X/* */ X/* Output "number" in the output base. */ X/* */ X/****************************************************************/ X X Xvoid Print_Number( number, output_base ) X int number; X int output_base; X X { X switch ( output_base ) X { X case 16 : printf( "%5x", number ); X break; X X case 10 : printf( "%7u", number ); X break; X X case 8 : printf( "%7o", number ); X break; X X case 2 : { X unsigned int mask; X char pad = ' '; X X for ( mask = 0x8000; mask > 1; mask >>= 1 ) X putchar( (mask & number) ? (pad = '0', '1') : pad ); X X putchar( (0x01 & number) ? '1' : '0' ); X X break; X } X X default : Error( "Internal fault (output_base)" ); X } X } X X X X X X X/****************************************************************/ X/* */ X/* Print_Ascii( char ) */ X/* */ X/* Display a character in reverse mode if it */ X/* is not a normal printable ASCII character. */ X/* */ X/****************************************************************/ X X Xvoid Print_Ascii( c ) X char c; X X { X c &= 0x7f; X X if ( c < ' ' ) X printf( "%s%c%s", Treverse, '@' + c, Tnormal ); X else if ( c == DEL ) X printf( "%s?%s", Treverse, Tnormal ); X else X putchar( c ); X } X X X X X X X/****************************************************************/ X/* */ X/* Warning( message, arg1, arg2 ) */ X/* */ X/* Display a message for 2 seconds. */ X/* */ X/****************************************************************/ X X Xvoid Warning( message, arg1, arg2 ) X char *message; X char *arg1; X char *arg2; X X { X printf( "%c%s", BELL, Tclr_all ); X X Goto( WARNING_COLUMN, WARNING_LINE ); X X printf( "%s Warning: ", Treverse ); X printf( message, arg1, arg2 ); X printf( " %s", Tnormal ); X X sleep( 2 ); X } / echo x - link.cdiff sed '/^X/s///' > link.cdiff << '/' X*** link.c.1.3 Wed Jan 18 22:08:09 1989 X--- link.c Wed Jan 18 22:08:01 1989 X*************** X*** 189,193 **** X * be cleared immediately, even though these fields are also cleared by X * alloc_inode(). The function wipe_inode() does the dirty work in both cases. X */ X! wipe_inode(rip); X! } X--- 189,198 ---- X * be cleared immediately, even though these fields are also cleared by X * alloc_inode(). The function wipe_inode() does the dirty work in both cases. X */ X! #ifdef RECOVER X! /* Leave zone numbers for de(1) to recover file after an unlink(2). */ X! rip->i_dirt = DIRTY; X! #else X! wipe_inode(rip); X! #endif X! } / echo x - open.cdiff sed '/^X/s///' > open.cdiff << '/' X*** open.c.1.3 Mon Aug 1 19:10:58 1988 X--- open.c Wed Jan 18 22:01:47 1989 X*************** X*** 56,62 **** X /* File exists already. */ X switch (rip->i_mode & I_TYPE) { X case I_REGULAR: /* truncate regular file */ X! if ( (r = forbidden(rip, W_BIT, 0)) == OK) truncate(rip); X break; X X case I_DIRECTORY: /* can't truncate directory */ X--- 56,69 ---- X /* File exists already. */ X switch (rip->i_mode & I_TYPE) { X case I_REGULAR: /* truncate regular file */ X! #ifdef RECOVER X! if ( (r = forbidden(rip, W_BIT, 0)) == OK) { X! truncate(rip); X! wipe_inode(rip); X! } X! #else X! if ( (r = forbidden(rip, W_BIT, 0)) == OK) truncate(rip); X! #endif X break; X X case I_DIRECTORY: /* can't truncate directory */ / echo x - path.cdiff sed '/^X/s///' > path.cdiff << '/' X*** path.c.1.3 Mon Aug 1 19:10:58 1988 X--- path.c Wed Jan 18 21:58:21 1989 X*************** X*** 266,271 **** X--- 266,275 ---- X && cmp_string(dp->d_name, string, NAME_SIZE)) { X /* LOOK_UP or DELETE found what it wanted. */ X if (flag == DELETE) { X+ #ifdef RECOVER X+ *( (inode_nr *) &dp->d_name[ NAME_SIZE - X+ sizeof(inode_nr) ] ) = dp->d_inum; X+ #endif X dp->d_inum = 0; /* erase entry */ X bp->b_dirt = DIRTY; X ldir_ptr->i_modtime = clock_time(); / exit 0 ----------------------------------------------------------