Home | History | Annotate | Download | only in ext2ed
      1 /*
      2 
      3 /usr/src/ext2ed/dir_com.c
      4 
      5 A part of the extended file system 2 disk editor.
      6 
      7 --------------------
      8 Handles directories.
      9 --------------------
     10 
     11 This file contains the codes which allows the user to handle directories.
     12 
     13 Most of the functions use the global variable file_info (along with the special directory fields there) to save
     14 information and pass it between them.
     15 
     16 Since a directory is just a big file which is composed of directory entries, you will find that
     17 the functions here are a superset of those in the file_com.c source.
     18 
     19 We assume that the user reached here using the dir command of the inode type and not by using settype dir, so
     20 that init_dir_info is indeed called to gather the required information.
     21 
     22 type_data is not changed! It still contains the inode of the file - We handle the directory in our own
     23 variables, so that settype ext2_inode will "go back" to the inode of this directory.
     24 
     25 First written on: April 28 1995
     26 
     27 Copyright (C) 1995 Gadi Oxman
     28 
     29 */
     30 
     31 #include <stdio.h>
     32 #include <stdlib.h>
     33 #include <string.h>
     34 
     35 #include "ext2ed.h"
     36 
     37 char name_search [80];
     38 long entry_num_search;
     39 
     40 int init_dir_info (struct struct_file_info *info_ptr)
     41 
     42 /*
     43 
     44 This function is called by the inode of the directory when the user issues the dir command from the inode.
     45 It is used to gather information about the inode and to reset some variables which we need in order to handle
     46 directories.
     47 
     48 */
     49 
     50 {
     51 	struct ext2_inode *ptr;
     52 
     53 	ptr=&type_data.u.t_ext2_inode;					/* type_data contains the inode */
     54 
     55 	info_ptr->inode_ptr=ptr;
     56 	info_ptr->inode_offset=device_offset;				/* device offset contains the inode's offset */
     57 
     58 									/* Reset the current position to the start */
     59 
     60 	info_ptr->global_block_num=ptr->i_block [0];
     61 	info_ptr->global_block_offset=ptr->i_block [0]*file_system_info.block_size;
     62 	info_ptr->block_num=0;
     63 	info_ptr->file_offset=0;
     64 									/* Set the size of the directory */
     65 
     66 	info_ptr->blocks_count=(ptr->i_size+file_system_info.block_size-1)/file_system_info.block_size;
     67 	info_ptr->file_length=ptr->i_size;
     68 
     69 	info_ptr->level=0;						/* We start using direct blocks */
     70 	info_ptr->display=HEX;						/* This is not actually used */
     71 
     72 	info_ptr->dir_entry_num=0;info_ptr->dir_entries_count=0;	/* We'll start at the first directory entry */
     73 	info_ptr->dir_entry_offset=0;
     74 
     75 	/* Find dir_entries_count */
     76 
     77 	info_ptr->dir_entries_count=count_dir_entries (); 		/* Set the total number of entries */
     78 
     79 	return (1);
     80 }
     81 
     82 struct struct_file_info search_dir_entries (int (*action) (struct struct_file_info *info),int *status)
     83 
     84 /*
     85 	This is the main function in this source file. Various actions are implemented using this basic function.
     86 
     87 	This routine runs on all directory entries in the current directory.
     88 	For each entry, action is called. We'll act according to the return code of action:
     89 
     90 		ABORT		-	Current dir entry is returned.
     91 		CONTINUE	-	Continue searching.
     92 		FOUND		-	Current dir entry is returned.
     93 
     94 	If the last entry is reached, it is returned, along with an ABORT status.
     95 
     96 	status is updated to the returned code of action.
     97 */
     98 
     99 {
    100 	struct struct_file_info info;						/* Temporary variables used to */
    101 	struct ext2_dir_entry_2 *dir_entry_ptr;					/* contain the current search entries */
    102 	int return_code, next;
    103 
    104 	info=first_file_info;							/* Start from the first entry - Read it */
    105 	low_read (info.buffer,file_system_info.block_size,info.global_block_offset);
    106 	dir_entry_ptr=(struct ext2_dir_entry_2 *) (info.buffer+info.dir_entry_offset);
    107 
    108 	while (info.file_offset < info.file_length) {				/* While we haven't reached the end */
    109 
    110 		*status=return_code=action (&info);				/* Call the client function to test */
    111 										/* the current entry */
    112 		if (return_code==ABORT || return_code==FOUND)
    113 			return (info);						/* Stop, if so asked */
    114 
    115 										/* Pass to the next entry */
    116 
    117 		dir_entry_ptr=(struct ext2_dir_entry_2 *) (info.buffer+info.dir_entry_offset);
    118 
    119 		info.dir_entry_num++;
    120 		next = dir_entry_ptr->rec_len;
    121 		if (!next)
    122 			next = file_system_info.block_size - info.dir_entry_offset;
    123 		info.dir_entry_offset += next;
    124 		info.file_offset += next;
    125 
    126 		if (info.file_offset >= info.file_length) break;
    127 
    128 		if (info.dir_entry_offset >= file_system_info.block_size) {	/* We crossed a block boundary */
    129 										/* Find the next block, */
    130 			info.block_num++;
    131 			info.global_block_num=file_block_to_global_block (info.block_num,&info);
    132 			info.global_block_offset=info.global_block_num*file_system_info.block_size;
    133 			info.file_offset=info.block_num*file_system_info.block_size;
    134 			info.dir_entry_offset=0;
    135 										/* read it and update the pointer */
    136 
    137 			low_read (info.buffer,file_system_info.block_size,info.global_block_offset);
    138 			dir_entry_ptr=(struct ext2_dir_entry_2 *) (info.buffer+info.dir_entry_offset);
    139 
    140 		}
    141 
    142 	}
    143 
    144 	*status=ABORT;return (info);						/* There was no match */
    145 }
    146 
    147 long count_dir_entries (void)
    148 
    149 /*
    150 
    151 This function counts the number of entries in the directory. We just call search_dir_entries till the end.
    152 The client function is action_count, which just tell search_dir_entries to continue.
    153 
    154 */
    155 
    156 {
    157 	int status;
    158 
    159 	return (search_dir_entries (&action_count,&status).dir_entry_num);
    160 }
    161 
    162 int action_count (struct struct_file_info *info)
    163 
    164 /*
    165 
    166 Used by count_dir_entries above - This function is called by search_dir_entries, and it tells it to continue
    167 searching, until we get to the last entry.
    168 
    169 */
    170 
    171 {
    172 	return (CONTINUE);							/* Just continue searching */
    173 }
    174 
    175 void type_dir___cd (char *command_line)
    176 
    177 /*
    178 	Changes to a directory, relative to the current directory.
    179 
    180 	This is a complicated operation, so I would repeat here the explanation from the design and
    181 	implementation document.
    182 
    183 1.	The path is checked that it is not an absolute path (from /). If it is, we let the general cd to do the job by
    184 	calling directly type_ext2___cd.
    185 
    186 2.	The path is divided into the nearest path and the rest of the path. For example, cd 1/2/3/4 is divided into
    187 	1 and into 2/3/4.
    188 
    189 3.	It is the first part of the path that we need to search for in the current directory. We search for it using
    190 	search_dir_entries, which accepts the action_name function as the client function.
    191 
    192 4.	search_dir_entries will scan the entire entries and will call our action_name function for each entry.
    193 	In action_name, the required name will be checked against the name of the current entry, and FOUND will be
    194 	returned when a match occurs.
    195 
    196 5.	If the required entry is found, we dispatch a remember command to insert the current inode (remember that
    197 	type_data is still intact and contains the inode of the current directory) into the object memory.
    198 	This is required to easily support symbolic links - If we find later that the inode pointed by the entry is
    199 	actually a symbolic link, we'll need to return to this point, and the above inode doesn't have (and can't have,
    200 	because of hard links) the information necessary to "move back".
    201 
    202 6.	We then dispatch a followinode command to reach the inode pointed by the required entry. This command will
    203 	automatically change the type to ext2_inode - We are now at an inode, and all the inode commands are available.
    204 
    205 7.	We check the inode's type to see if it is a directory. If it is, we dispatch a dir command to "enter the directory",
    206 	and recursively call ourself (The type is dir again) by dispatching a cd command, with the rest of the path
    207 	as an argument.
    208 
    209 8.	If the inode's type is a symbolic link (only fast symbolic link were meanwhile implemented. I guess this is
    210 	typically the case.), we note the path it is pointing at, the saved inode is recalled, we dispatch dir to
    211 	get back to the original directory, and we call ourself again with the link path/rest of the path argument.
    212 
    213 9.	In any other case, we just stop at the resulting inode.
    214 
    215 */
    216 
    217 {
    218 	int status;
    219 	char *ptr,full_dir_name [500],dir_name [500],temp [500],temp2 [500];
    220 	struct struct_file_info info;
    221 	struct ext2_dir_entry_2 *dir_entry_ptr;
    222 
    223 	dir_entry_ptr=(struct ext2_dir_entry_2 *) (file_info.buffer+file_info.dir_entry_offset);
    224 
    225 	ptr=parse_word (command_line,dir_name);
    226 
    227 	if (*ptr==0) {						/* cd alone will enter the highlighted directory */
    228 		strncpy (full_dir_name,dir_entry_ptr->name,dir_entry_ptr->name_len);
    229 		full_dir_name [dir_entry_ptr->name_len]=0;
    230 	}
    231 	else
    232 		ptr=parse_word (ptr,full_dir_name);
    233 
    234 	ptr=strchr (full_dir_name,'/');
    235 
    236 	if (ptr==full_dir_name) {				/* Pathname is from root - Let the general cd do the job */
    237 		sprintf (temp,"cd %s",full_dir_name);type_ext2___cd (temp);return;
    238 	}
    239 
    240 	if (ptr==NULL) {
    241 		strcpy (dir_name,full_dir_name);
    242 		full_dir_name [0]=0;
    243 	}
    244 
    245 	else {
    246 		strncpy (dir_name,full_dir_name,ptr-full_dir_name);
    247 		dir_name [ptr-full_dir_name]=0;
    248 		strcpy (full_dir_name,++ptr);
    249 	}
    250 								/* dir_name contains the current entry, while */
    251 								/* full_dir_name contains the rest */
    252 
    253 	strcpy (name_search,dir_name);				/* name_search is used to hold the required entry name */
    254 
    255 	if (dir_entry_ptr->name_len != strlen (dir_name) ||
    256 	    strncmp (dir_name,dir_entry_ptr->name,dir_entry_ptr->name_len)!=0)
    257 		info=search_dir_entries (&action_name,&status);	/* Search for the entry. Answer in info. */
    258 	else {
    259 		status=FOUND;info=file_info;
    260 	}
    261 
    262 	if (status==FOUND) {					/* If found */
    263 		file_info=info;					/* Switch to it, by setting the global file_info */
    264 		dispatch ("remember internal_variable");	/* Move the inode into the objects memory */
    265 
    266 		dispatch ("followinode");			/* Go to the inode pointed by this directory entry */
    267 
    268 		if (S_ISLNK (type_data.u.t_ext2_inode.i_mode)) {/* Symbolic link ? */
    269 
    270 			if (type_data.u.t_ext2_inode.i_size > 60) {	/* I'm lazy, I guess :-) */
    271 				wprintw (command_win,"Error - Sorry, Only fast symbolic link following is currently supported\n");
    272 				refresh_command_win ();
    273 				return;
    274 			}
    275 								/* Get the pointed name and append the previous path */
    276 
    277 			strcpy (temp2,(unsigned char *) &type_data.u.t_ext2_inode.i_block);
    278 			strcat (temp2,"/");
    279 			strcat (temp2,full_dir_name);
    280 
    281 			dispatch ("recall internal_variable");	/* Return to the original inode */
    282 			dispatch ("dir");			/* and to the directory */
    283 
    284 			sprintf (temp,"cd %s",temp2);		/* And continue from there by dispatching a cd command */
    285 			dispatch (temp);			/* (which can call ourself or the general cd) */
    286 
    287 			return;
    288 		}
    289 
    290 		if (S_ISDIR (type_data.u.t_ext2_inode.i_mode)) { /* Is it an inode of a directory ? */
    291 
    292 			dispatch ("dir");			/* Yes - Pass to the pointed directory */
    293 
    294 			if (full_dir_name [0] != 0) {		/* And call ourself with the rest of the pathname */
    295 				sprintf (temp,"cd %s",full_dir_name);
    296 				dispatch (temp);
    297 			}
    298 
    299 			return;
    300 		}
    301 
    302 		else {						/* If we can't continue from here, we'll just stop */
    303 			wprintw (command_win,"Can\'t continue - Stopping at last inode\n");refresh_command_win ();
    304 			return;
    305 		}
    306 	}
    307 
    308 	wprintw (command_win,"Error - Directory entry %s not found.\n",dir_name);	/* Hmm, an invalid path somewhere */
    309 	refresh_command_win ();
    310 }
    311 
    312 int action_name (struct struct_file_info *info)
    313 
    314 /*
    315 
    316 Compares the current search entry name (somewhere inside info) with the required name (in name_search).
    317 Returns FOUND if found, or CONTINUE if not found.
    318 
    319 */
    320 
    321 {
    322 	struct ext2_dir_entry_2 *dir_entry_ptr;
    323 
    324 	dir_entry_ptr=(struct ext2_dir_entry_2 *) (info->buffer+info->dir_entry_offset);
    325 
    326 	if (dir_entry_ptr->name_len != strlen (name_search))
    327 		return (CONTINUE);
    328 
    329 	if (strncmp (dir_entry_ptr->name,name_search,dir_entry_ptr->name_len)==0)
    330 		return (FOUND);
    331 
    332 	return (CONTINUE);
    333 }
    334 
    335 void type_dir___entry (char *command_line)
    336 
    337 /*
    338 
    339 Selects a directory entry according to its number.
    340 search_dir_entries is used along with action_entry_num, in the same fashion as the previous usage of search_dir_entries.
    341 
    342 */
    343 
    344 {
    345 	int status;
    346 	struct struct_file_info info;
    347 	char *ptr,buffer [80];
    348 
    349 	ptr=parse_word (command_line,buffer);
    350 	if (*ptr==0) {
    351 		wprintw (command_win,"Error - Argument_not_specified\n");wrefresh (command_win);
    352 		return;
    353 	}
    354 	ptr=parse_word (ptr,buffer);
    355 	entry_num_search=atol (buffer);
    356 
    357 	if (entry_num_search < 0 || entry_num_search >= file_info.dir_entries_count) {
    358 		wprintw (command_win,"Error - Entry number out of range\n");wrefresh (command_win);
    359 		return;
    360 	}
    361 
    362 	info=search_dir_entries (&action_entry_num,&status);
    363 	if (status==FOUND) {
    364 		file_info=info;
    365 		dispatch ("show");
    366 		return;
    367 	}
    368 #ifdef DEBUG
    369 	internal_error ("dir_com","type_dir___entry","According to our gathered data, we should have found this entry");
    370 #endif
    371 }
    372 
    373 int action_entry_num (struct struct_file_info *info)
    374 
    375 /*
    376 
    377 Used by the above function. Just compares the current number (in info) with the required one.
    378 
    379 */
    380 
    381 {
    382 	if (info->dir_entry_num == entry_num_search)
    383 		return (FOUND);
    384 
    385 	return (CONTINUE);
    386 }
    387 
    388 void type_dir___followinode (char *command_line)
    389 
    390 /*
    391 
    392 Here we pass to the inode pointed by the current entry.
    393 It involves computing the device offset of the inode and using directly the setoffset and settype commands.
    394 
    395 */
    396 {
    397 	long inode_offset;
    398 	char buffer [80];
    399 
    400 	struct ext2_dir_entry_2 *dir_entry_ptr;
    401 
    402 	low_read (file_info.buffer,file_system_info.block_size,file_info.global_block_offset);
    403 	dir_entry_ptr=(struct ext2_dir_entry_2 *) (file_info.buffer+file_info.dir_entry_offset);
    404 
    405 	inode_offset=inode_num_to_inode_offset (dir_entry_ptr->inode);			/* Compute the inode's offset */
    406 	sprintf (buffer,"setoffset %ld",inode_offset);dispatch (buffer);		/* Move to it */
    407 	sprintf (buffer,"settype ext2_inode");dispatch (buffer);			/* and set the type to an inode */
    408 }
    409 
    410 void type_dir___inode (char *command_line)
    411 
    412 /*
    413 
    414 Returns to the parent inode of the current directory.
    415 This is trivial, as we type_data is still intact and contains the parent inode !
    416 
    417 */
    418 
    419 {
    420 	dispatch ("settype ext2_inode");
    421 }
    422 
    423 
    424 void type_dir___show (char *command_line)
    425 
    426 /*
    427 
    428 We use search_dir_entries to run on all the entries. Each time, action_show will be called to show one entry.
    429 
    430 */
    431 
    432 {
    433 	int status;
    434 
    435 	wmove (show_pad,0,0);
    436 	show_pad_info.max_line=-1;
    437 
    438 	search_dir_entries (&action_show,&status);
    439 	show_pad_info.line=file_info.dir_entry_num-show_pad_info.display_lines/2;
    440 	refresh_show_pad ();
    441 	show_dir_status ();
    442 }
    443 
    444 int action_show (struct struct_file_info *info)
    445 
    446 /*
    447 
    448 Show the current search entry (info) in one line. If the entry happens to be the current edited entry, it is highlighted.
    449 
    450 */
    451 
    452 {
    453 	unsigned char temp [80];
    454 	struct ext2_dir_entry_2 *dir_entry_ptr;
    455 
    456 	dir_entry_ptr=(struct ext2_dir_entry_2 *) (info->buffer+info->dir_entry_offset);
    457 
    458 	if (info->dir_entry_num == file_info.dir_entry_num)				/* Highlight the current entry */
    459 		wattrset (show_pad,A_REVERSE);
    460 
    461 	strncpy (temp,dir_entry_ptr->name,dir_entry_ptr->name_len);			/* The name is not terminated */
    462 	temp [dir_entry_ptr->name_len]=0;
    463 	if (dir_entry_ptr->name_len > (COLS - 55) && COLS > 55)
    464 		temp [COLS-55]=0;
    465 	wprintw (show_pad,"inode = %-8lu rec_len = %-4lu name_len = %-3lu name = %s\n",	/* Display the various fields */
    466 		 dir_entry_ptr->inode,dir_entry_ptr->rec_len,dir_entry_ptr->name_len,temp);
    467 
    468 	show_pad_info.max_line++;
    469 
    470 	if (info->dir_entry_num == file_info.dir_entry_num)
    471 		wattrset (show_pad,A_NORMAL);
    472 
    473 	return (CONTINUE);								/* And pass to the next */
    474 }
    475 
    476 void type_dir___next (char *command_line)
    477 
    478 /*
    479 
    480 This function moves to the next directory entry. It just uses the current information and the entry command.
    481 
    482 */
    483 
    484 {
    485 	int offset=1;
    486 	char *ptr,buffer [80];
    487 
    488 	ptr=parse_word (command_line,buffer);
    489 
    490 	if (*ptr!=0) {
    491 		ptr=parse_word (ptr,buffer);
    492 		offset*=atol (buffer);
    493 	}
    494 
    495 	sprintf (buffer,"entry %ld",file_info.dir_entry_num+offset);dispatch (buffer);
    496 
    497 }
    498 
    499 void type_dir___prev (char *command_line)
    500 
    501 {
    502 	int offset=1;
    503 	char *ptr,buffer [80];
    504 
    505 	ptr=parse_word (command_line,buffer);
    506 
    507 	if (*ptr!=0) {
    508 		ptr=parse_word (ptr,buffer);
    509 		offset*=atol (buffer);
    510 	}
    511 
    512 	sprintf (buffer,"entry %ld",file_info.dir_entry_num-offset);dispatch (buffer);
    513 }
    514 
    515 void show_dir_status (void)
    516 
    517 /*
    518 
    519 Various statistics about the directory.
    520 
    521 */
    522 
    523 {
    524 	long inode_num;
    525 
    526 	wmove (show_win,0,0);
    527 	wprintw (show_win,"Directory listing. Block %ld. ",file_info.global_block_num);
    528 	wprintw (show_win,"Directory entry %ld of %ld.\n",file_info.dir_entry_num,file_info.dir_entries_count-1);
    529 	wprintw (show_win,"Directory Offset %ld of %ld. ",file_info.file_offset,file_info.file_length-1);
    530 
    531 	inode_num=inode_offset_to_inode_num (file_info.inode_offset);
    532 	wprintw (show_win,"File inode %ld. Indirection level %ld.\n",inode_num,file_info.level);
    533 
    534 	refresh_show_win ();
    535 }
    536 
    537 void type_dir___remember (char *command_line)
    538 
    539 /*
    540 
    541 This is overrided here because we don't remember a directory - It is too complicated. Instead, we remember the
    542 inode of the current directory.
    543 
    544 */
    545 
    546 {
    547 	int found=0;
    548 	long entry_num;
    549 	char *ptr,buffer [80];
    550 	struct struct_descriptor *descriptor_ptr;
    551 
    552 	ptr=parse_word (command_line,buffer);
    553 
    554 	if (*ptr==0) {
    555 		wprintw (command_win,"Error - Argument not specified\n");wrefresh (command_win);
    556 		return;
    557 	}
    558 
    559 	ptr=parse_word (ptr,buffer);
    560 
    561 	entry_num=remember_lifo.entries_count++;
    562 	if (entry_num>REMEMBER_COUNT-1) {
    563 		entry_num=0;
    564 		remember_lifo.entries_count--;
    565 	}
    566 
    567 	descriptor_ptr=first_type;
    568 	while (descriptor_ptr!=NULL && !found) {
    569 		if (strcmp (descriptor_ptr->name,"ext2_inode")==0)
    570 			found=1;
    571 		else
    572 			descriptor_ptr=descriptor_ptr->next;
    573 	}
    574 
    575 
    576 	remember_lifo.offset [entry_num]=device_offset;
    577 	remember_lifo.type [entry_num]=descriptor_ptr;
    578 	strcpy (remember_lifo.name [entry_num],buffer);
    579 
    580 	wprintw (command_win,"Object %s in Offset %ld remembered as %s\n",descriptor_ptr->name,device_offset,buffer);
    581 	wrefresh (command_win);
    582 }
    583 
    584 void type_dir___set (char *command_line)
    585 
    586 /*
    587 
    588 Since the dir object doesn't have variables, we provide the impression that it has here. ext2_dir_entry was not used
    589 because it is of variable length.
    590 
    591 */
    592 
    593 {
    594 	int found=0;
    595 	unsigned char *ptr,buffer [80],variable [80],value [80],temp [80];
    596 	struct ext2_dir_entry_2 *dir_entry_ptr;
    597 
    598 	dir_entry_ptr=(struct ext2_dir_entry_2 *) (file_info.buffer+file_info.dir_entry_offset);
    599 
    600 	ptr=parse_word (command_line,buffer);
    601 	if (*ptr==0) {
    602 		wprintw (command_win,"Error - Missing arguments\n");refresh_command_win ();
    603 		return;
    604 	}
    605 	parse_word (ptr,buffer);
    606 	ptr=strchr (buffer,'=');
    607 	if (ptr==NULL) {
    608 		wprintw (command_win,"Error - Bad syntax\n");refresh_command_win ();return;
    609 	}
    610 	strncpy (variable,buffer,ptr-buffer);variable [ptr-buffer]=0;
    611 	strcpy (value,++ptr);
    612 
    613 	if (strcasecmp ("inode",variable)==0) {
    614 		found=1;
    615 		dir_entry_ptr->inode=atol (value);
    616 		wprintw (command_win,"Variable %s set to %lu\n",variable,dir_entry_ptr->inode);refresh_command_win ();
    617 
    618 	}
    619 
    620 	if (strcasecmp ("rec_len",variable)==0) {
    621 		found=1;
    622 		dir_entry_ptr->rec_len=(unsigned int) atol (value);
    623 		wprintw (command_win,"Variable %s set to %lu\n",variable,dir_entry_ptr->rec_len);refresh_command_win ();
    624 
    625 	}
    626 
    627 	if (strcasecmp ("name_len",variable)==0) {
    628 		found=1;
    629 		dir_entry_ptr->name_len=(unsigned int) atol (value);
    630 		wprintw (command_win,"Variable %s set to %lu\n",variable,dir_entry_ptr->name_len);refresh_command_win ();
    631 
    632 	}
    633 
    634 	if (strcasecmp ("name",variable)==0) {
    635 		found=1;
    636 		if (strlen (value) > dir_entry_ptr->name_len) {
    637 			wprintw (command_win,"Error - Length of name greater then name_len\n");
    638 			refresh_command_win ();return;
    639 		}
    640 		strncpy (dir_entry_ptr->name,value,strlen (value));
    641 		wprintw (command_win,"Variable %s set to %s\n",variable,value);refresh_command_win ();
    642 
    643 	}
    644 
    645 	if (found) {
    646 		wattrset (show_pad,A_REVERSE);
    647 		strncpy (temp,dir_entry_ptr->name,dir_entry_ptr->name_len);
    648 		temp [dir_entry_ptr->name_len]=0;
    649 		wmove (show_pad,file_info.dir_entry_num,0);
    650 		wprintw (show_pad,"inode = %-8lu rec_len = %-4lu name_len = %-3lu name = %s\n",
    651 			 dir_entry_ptr->inode,dir_entry_ptr->rec_len,dir_entry_ptr->name_len,temp);
    652 		wattrset (show_pad,A_NORMAL);
    653 		show_pad_info.line=file_info.dir_entry_num-show_pad_info.display_lines/2;
    654 		refresh_show_pad ();
    655 		show_dir_status ();
    656 	}
    657 
    658 	else {
    659 		wprintw (command_win,"Error - Variable %s not found\n",variable);
    660 		refresh_command_win ();
    661 	}
    662 
    663 }
    664 
    665 void type_dir___writedata (char *command_line)
    666 
    667 /*
    668 
    669 We need to override this since the data is not in type_data. Instead, we have to write the buffer which corresponds
    670 to the current block.
    671 
    672 */
    673 
    674 {
    675 	low_write (file_info.buffer,file_system_info.block_size,file_info.global_block_offset);
    676 	return;
    677 }
    678