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