blob: ba8526764add1e0c5bc6d9f866eba0e51b149ddb [file] [log] [blame]
Theodore Ts'o583a1ce2002-05-11 13:00:22 -04001/*
2
3/usr/src/ext2ed/dir_com.c
4
5A part of the extended file system 2 disk editor.
6
7--------------------
8Handles directories.
9--------------------
10
11This file contains the codes which allows the user to handle directories.
12
13Most of the functions use the global variable file_info (along with the special directory fields there) to save
14information and pass it between them.
15
16Since a directory is just a big file which is composed of directory entries, you will find that
17the functions here are a superset of those in the file_com.c source.
18
19We assume that the user reached here using the dir command of the inode type and not by using settype dir, so
20that init_dir_info is indeed called to gather the required information.
21
Theodore Ts'o598ff012005-12-09 19:16:40 -050022type_data is not changed! It still contains the inode of the file - We handle the directory in our own
Theodore Ts'o583a1ce2002-05-11 13:00:22 -040023variables, so that settype ext2_inode will "go back" to the inode of this directory.
24
25First written on: April 28 1995
26
27Copyright (C) 1995 Gadi Oxman
28
29*/
30
Theodore Ts'od1154eb2011-09-18 17:34:37 -040031#include "config.h"
Theodore Ts'o583a1ce2002-05-11 13:00:22 -040032#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35
36#include "ext2ed.h"
37
38char name_search [80];
39long entry_num_search;
40
41int init_dir_info (struct struct_file_info *info_ptr)
42
43/*
44
45This function is called by the inode of the directory when the user issues the dir command from the inode.
46It is used to gather information about the inode and to reset some variables which we need in order to handle
47directories.
48
49*/
50
51{
52 struct ext2_inode *ptr;
Theodore Ts'oefc6f622008-08-27 23:07:54 -040053
Theodore Ts'o583a1ce2002-05-11 13:00:22 -040054 ptr=&type_data.u.t_ext2_inode; /* type_data contains the inode */
Theodore Ts'oefc6f622008-08-27 23:07:54 -040055
Theodore Ts'o583a1ce2002-05-11 13:00:22 -040056 info_ptr->inode_ptr=ptr;
57 info_ptr->inode_offset=device_offset; /* device offset contains the inode's offset */
Theodore Ts'oefc6f622008-08-27 23:07:54 -040058
Theodore Ts'o583a1ce2002-05-11 13:00:22 -040059 /* Reset the current position to the start */
60
Theodore Ts'oefc6f622008-08-27 23:07:54 -040061 info_ptr->global_block_num=ptr->i_block [0];
Theodore Ts'o583a1ce2002-05-11 13:00:22 -040062 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 */
Theodore Ts'oefc6f622008-08-27 23:07:54 -040066
Theodore Ts'o583a1ce2002-05-11 13:00:22 -040067 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 */
Theodore Ts'oefc6f622008-08-27 23:07:54 -040077
Theodore Ts'o583a1ce2002-05-11 13:00:22 -040078 info_ptr->dir_entries_count=count_dir_entries (); /* Set the total number of entries */
Theodore Ts'oefc6f622008-08-27 23:07:54 -040079
Theodore Ts'o583a1ce2002-05-11 13:00:22 -040080 return (1);
81}
82
83struct 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:
Theodore Ts'oefc6f622008-08-27 23:07:54 -040090
Theodore Ts'o583a1ce2002-05-11 13:00:22 -040091 ABORT - Current dir entry is returned.
92 CONTINUE - Continue searching.
93 FOUND - Current dir entry is returned.
Theodore Ts'oefc6f622008-08-27 23:07:54 -040094
Theodore Ts'o583a1ce2002-05-11 13:00:22 -040095 If the last entry is reached, it is returned, along with an ABORT status.
Theodore Ts'oefc6f622008-08-27 23:07:54 -040096
97 status is updated to the returned code of action.
Theodore Ts'o583a1ce2002-05-11 13:00:22 -040098*/
99
100{
101 struct struct_file_info info; /* Temporary variables used to */
Theodore Ts'o0f31c732002-05-11 13:03:25 -0400102 struct ext2_dir_entry_2 *dir_entry_ptr; /* contain the current search entries */
Theodore Ts'o93599d02002-09-30 00:12:10 -0400103 int return_code, next;
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400104
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400105 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);
Theodore Ts'o0f31c732002-05-11 13:03:25 -0400107 dir_entry_ptr=(struct ext2_dir_entry_2 *) (info.buffer+info.dir_entry_offset);
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400108
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400109 while (info.file_offset < info.file_length) { /* While we haven't reached the end */
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400110
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400111 *status=return_code=action (&info); /* Call the client function to test */
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400112 /* the current entry */
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400113 if (return_code==ABORT || return_code==FOUND)
114 return (info); /* Stop, if so asked */
115
116 /* Pass to the next entry */
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400117
Theodore Ts'o0f31c732002-05-11 13:03:25 -0400118 dir_entry_ptr=(struct ext2_dir_entry_2 *) (info.buffer+info.dir_entry_offset);
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400119
120 info.dir_entry_num++;
Theodore Ts'o93599d02002-09-30 00:12:10 -0400121 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;
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400126
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;
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400135 info.dir_entry_offset=0;
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400136 /* read it and update the pointer */
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400137
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400138 low_read (info.buffer,file_system_info.block_size,info.global_block_offset);
Theodore Ts'o0f31c732002-05-11 13:03:25 -0400139 dir_entry_ptr=(struct ext2_dir_entry_2 *) (info.buffer+info.dir_entry_offset);
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400140
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400141 }
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400142
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400143 }
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400144
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400145 *status=ABORT;return (info); /* There was no match */
146}
147
148long count_dir_entries (void)
149
150/*
151
152This function counts the number of entries in the directory. We just call search_dir_entries till the end.
153The client function is action_count, which just tell search_dir_entries to continue.
154
155*/
156
157{
158 int status;
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400159
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400160 return (search_dir_entries (&action_count,&status).dir_entry_num);
161}
162
163int action_count (struct struct_file_info *info)
164
165/*
166
167Used by count_dir_entries above - This function is called by search_dir_entries, and it tells it to continue
168searching, until we get to the last entry.
169
170*/
171
172{
173 return (CONTINUE); /* Just continue searching */
174}
175
176void 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
1841. 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
1872. 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
1903. It is the first part of the path that we need to search for in the current directory. We search for it using
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400191 search_dir_entries, which accepts the action_name function as the client function.
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400192
1934. 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
1975. 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
2036. 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
2067. 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.
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400209
Theodore Ts'o583a1ce2002-05-11 13:00:22 -04002108. 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
2149. 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;
Theodore Ts'o0f31c732002-05-11 13:03:25 -0400222 struct ext2_dir_entry_2 *dir_entry_ptr;
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400223
Theodore Ts'o0f31c732002-05-11 13:03:25 -0400224 dir_entry_ptr=(struct ext2_dir_entry_2 *) (file_info.buffer+file_info.dir_entry_offset);
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400225
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400226 ptr=parse_word (command_line,dir_name);
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400227
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400228 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,'/');
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400236
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400237 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 }
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400240
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400241 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 */
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400255
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400256 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 */
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400266
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400267 dispatch ("followinode"); /* Go to the inode pointed by this directory entry */
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400268
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400269 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 ();
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400274 return;
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400275 }
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 */
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400284
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400285 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) */
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400287
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400288 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 }
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400299
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400300 return;
301 }
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400302
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400303 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 }
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400308
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400309 wprintw (command_win,"Error - Directory entry %s not found.\n",dir_name); /* Hmm, an invalid path somewhere */
310 refresh_command_win ();
311}
312
313int action_name (struct struct_file_info *info)
314
315/*
316
317Compares the current search entry name (somewhere inside info) with the required name (in name_search).
318Returns FOUND if found, or CONTINUE if not found.
319
320*/
321
322{
Theodore Ts'o0f31c732002-05-11 13:03:25 -0400323 struct ext2_dir_entry_2 *dir_entry_ptr;
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400324
Theodore Ts'o0f31c732002-05-11 13:03:25 -0400325 dir_entry_ptr=(struct ext2_dir_entry_2 *) (info->buffer+info->dir_entry_offset);
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400326
327 if (dir_entry_ptr->name_len != strlen (name_search))
328 return (CONTINUE);
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400329
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400330 if (strncmp (dir_entry_ptr->name,name_search,dir_entry_ptr->name_len)==0)
331 return (FOUND);
332
333 return (CONTINUE);
334}
335
336void type_dir___entry (char *command_line)
337
338/*
339
340Selects a directory entry according to its number.
341search_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];
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400349
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400350 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);
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400357
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400358 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
374int action_entry_num (struct struct_file_info *info)
375
376/*
377
378Used 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
389void type_dir___followinode (char *command_line)
390
391/*
392
393Here we pass to the inode pointed by the current entry.
394It 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
Theodore Ts'o0f31c732002-05-11 13:03:25 -0400401 struct ext2_dir_entry_2 *dir_entry_ptr;
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400402
403 low_read (file_info.buffer,file_system_info.block_size,file_info.global_block_offset);
Theodore Ts'o0f31c732002-05-11 13:03:25 -0400404 dir_entry_ptr=(struct ext2_dir_entry_2 *) (file_info.buffer+file_info.dir_entry_offset);
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400405
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
411void type_dir___inode (char *command_line)
412
413/*
414
415Returns to the parent inode of the current directory.
416This 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
425void type_dir___show (char *command_line)
426
427/*
428
429We 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;
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400435
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400436 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
445int action_show (struct struct_file_info *info)
446
447/*
448
449Show 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];
Theodore Ts'o0f31c732002-05-11 13:03:25 -0400455 struct ext2_dir_entry_2 *dir_entry_ptr;
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400456
Theodore Ts'o0f31c732002-05-11 13:03:25 -0400457 dir_entry_ptr=(struct ext2_dir_entry_2 *) (info->buffer+info->dir_entry_offset);
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400458
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
477void type_dir___next (char *command_line)
478
479/*
480
481This 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);
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400490
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400491 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
500void 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);
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400507
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400508 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
516void show_dir_status (void)
517
518/*
519
520Various statistics about the directory.
521
522*/
523
524{
525 long inode_num;
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400526
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400527 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);
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400531
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400532 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
538void type_dir___remember (char *command_line)
539
540/*
541
542This is overrided here because we don't remember a directory - It is too complicated. Instead, we remember the
543inode 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;
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400552
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400553 ptr=parse_word (command_line,buffer);
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400554
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400555 if (*ptr==0) {
556 wprintw (command_win,"Error - Argument not specified\n");wrefresh (command_win);
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400557 return;
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400558 }
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400559
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400560 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 }
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400567
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400568 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);
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400580
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400581 wprintw (command_win,"Object %s in Offset %ld remembered as %s\n",descriptor_ptr->name,device_offset,buffer);
582 wrefresh (command_win);
583}
584
585void type_dir___set (char *command_line)
586
587/*
588
589Since the dir object doesn't have variables, we provide the impression that it has here. ext2_dir_entry was not used
590because 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];
Theodore Ts'o0f31c732002-05-11 13:03:25 -0400597 struct ext2_dir_entry_2 *dir_entry_ptr;
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400598
Theodore Ts'o0f31c732002-05-11 13:03:25 -0400599 dir_entry_ptr=(struct ext2_dir_entry_2 *) (file_info.buffer+file_info.dir_entry_offset);
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400600
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400601 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 }
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400645
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400646 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 }
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400658
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400659 else {
660 wprintw (command_win,"Error - Variable %s not found\n",variable);
661 refresh_command_win ();
662 }
663
664}
665
666void type_dir___writedata (char *command_line)
667
668/*
669
670We need to override this since the data is not in type_data. Instead, we have to write the buffer which corresponds
671to 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}