5 A part of the extended file system 2 disk editor.
7 --------------------------------
8 Various initialization routines.
9 --------------------------------
11 First written on: April 9 1995
13 Copyright (C) 1995 Gadi Oxman
27 #include <sys/types.h>
33 char lines_s
[80],cols_s
[80];
35 void signal_handler (void);
37 void prepare_to_close (void)
41 if (device_handle
!=NULL
)
42 fclose (device_handle
);
43 free_user_commands (&general_commands
);
44 free_user_commands (&ext2_commands
);
45 free_struct_descriptors ();
51 printf ("Initializing ...\n");
53 if (!process_configuration_file ()) {
54 fprintf (stderr
,"Error - Unable to complete configuration. Quitting.\n");
58 general_commands
.last_command
=-1; /* No commands whatsoever meanwhile */
59 ext2_commands
.last_command
=-1;
60 add_general_commands (); /* Add the general commands, available always */
61 device_handle
=NULL
; /* Notice that our device is still not set up */
63 current_type
=NULL
; /* No filesystem specific types yet */
65 remember_lifo
.entries_count
=0; /* Object memory is empty */
67 init_windows (); /* Initialize the NCURSES interface */
68 init_readline (); /* Initialize the READLINE interface */
69 init_signals (); /* Initialize the signal handlers */
70 write_access
=0; /* Write access disabled */
72 strcpy (last_command_line
,"help"); /* Show the help screen to the user */
74 return (1); /* Success */
77 void add_general_commands (void)
80 add_user_command (&general_commands
,"help","EXT2ED help system",help
);
81 add_user_command (&general_commands
,"set","Changes a variable in the current object",set
);
82 add_user_command (&general_commands
,"setdevice","Selects the filesystem block device (e.g. /dev/hda1)",set_device
);
83 add_user_command (&general_commands
,"setoffset","Moves asynchronously in the filesystem",set_offset
);
84 add_user_command (&general_commands
,"settype","Tells EXT2ED how to interpret the current object",set_type
);
85 add_user_command (&general_commands
,"show","Displays the current object",show
);
86 add_user_command (&general_commands
,"pgup","Scrolls data one page up",pgup
);
87 add_user_command (&general_commands
,"pgdn","Scrolls data one page down",pgdn
);
88 add_user_command (&general_commands
,"redraw","Redisplay the screen",redraw
);
89 add_user_command (&general_commands
,"remember","Saves the current position and data information",remember
);
90 add_user_command (&general_commands
,"recall","Gets back to the saved object position",recall
);
91 add_user_command (&general_commands
,"enablewrite","Enters Read/Write mode - Allows changing the filesystem",enable_write
);
92 add_user_command (&general_commands
,"disablewrite","Enters read only mode",disable_write
);
93 add_user_command (&general_commands
,"writedata","Write data back to disk",write_data
);
94 add_user_command (&general_commands
,"next","Moves to the next byte in hex mode",next
);
95 add_user_command (&general_commands
,"prev","Moves to the previous byte in hex mode",prev
);
98 void add_ext2_general_commands (void)
101 add_user_command (&ext2_commands
,"super","Moves to the superblock of the filesystem",type_ext2___super
);
102 add_user_command (&ext2_commands
,"group","Moves to the first group descriptor",type_ext2___group
);
103 add_user_command (&ext2_commands
,"cd","Moves to the directory specified",type_ext2___cd
);
106 int set_struct_descriptors (char *file_name
)
110 char current_line
[500],current_word
[50],*ch
;
111 char variable_name
[50],variable_type
[20];
112 struct struct_descriptor
*current_descriptor
;
114 if ( (fp
=fopen (file_name
,"rt"))==NULL
) {
115 wprintw (command_win
,"Error - Failed to open descriptors file %s\n",file_name
);
116 refresh_command_win (); return (0);
120 fgets (current_line
,500,fp
);
121 if (feof (fp
)) break;
122 ch
=parse_word (current_line
,current_word
);
123 if (strcmp (current_word
,"struct")==0) {
124 ch
=parse_word (ch
,current_word
);
125 current_descriptor
=add_new_descriptor (current_word
);
127 while (strchr (current_line
,'{')==NULL
) {
128 fgets (current_line
,500,fp
);
129 if (feof (fp
)) break;
131 if (feof (fp
)) break;
133 fgets (current_line
,500,fp
);
135 while (strchr (current_line
,'}')==NULL
) {
136 while (strchr (current_line
,';')==NULL
) {
137 fgets (current_line
,500,fp
);
138 if (strchr (current_line
,'}')!=NULL
) break;
140 if (strchr (current_line
,'}') !=NULL
) break;
141 ch
=parse_word (current_line
,variable_type
);
142 ch
=parse_word (ch
,variable_name
);
143 while (variable_name
[strlen (variable_name
)-1]!=';') {
144 strcpy (variable_type
,variable_name
);
145 ch
=parse_word (ch
,variable_name
);
147 variable_name
[strlen (variable_name
)-1]=0;
148 add_new_variable (current_descriptor
,variable_type
,variable_name
);
149 fgets (current_line
,500,fp
);
158 void free_struct_descriptors (void)
161 struct struct_descriptor
*ptr
,*next
;
166 free_user_commands (&ptr
->type_commands
);
170 first_type
=last_type
=current_type
=NULL
;
173 void free_user_commands (struct struct_commands
*ptr
)
178 for (i
=0;i
<=ptr
->last_command
;i
++) {
179 free (ptr
->names
[i
]);
180 free (ptr
->descriptions
[i
]);
183 ptr
->last_command
=-1;
186 struct struct_descriptor
*add_new_descriptor (char *name
)
189 struct struct_descriptor
*ptr
;
191 ptr
= malloc (sizeof (struct struct_descriptor
));
193 printf ("Error - Can not allocate memory - Quitting\n");
196 memset(ptr
, 0, sizeof(struct struct_descriptor
));
197 ptr
->prev
= ptr
->next
= NULL
;
198 strcpy (ptr
->name
,name
);
201 if (first_type
==NULL
) {
202 first_type
= last_type
= ptr
;
204 ptr
->prev
= last_type
; last_type
->next
= ptr
; last_type
=ptr
;
206 ptr
->type_commands
.last_command
=-1;
207 fill_type_commands (ptr
);
217 struct type_table type_table
[] = {
218 { "long", FIELD_TYPE_INT
, 4 },
219 { "short", FIELD_TYPE_INT
, 2 },
220 { "char", FIELD_TYPE_CHAR
, 1 },
221 { "__u32", FIELD_TYPE_UINT
, 4 },
222 { "__s32", FIELD_TYPE_INT
, 4 },
223 { "__u16", FIELD_TYPE_UINT
, 2 },
224 { "__s16", FIELD_TYPE_INT
, 2 },
225 { "__u8", FIELD_TYPE_UINT
, 1 },
226 { "__s8", FIELD_TYPE_INT
, 1 },
230 void add_new_variable (struct struct_descriptor
*ptr
,char *v_type
,char *v_name
)
234 char field_type
=FIELD_TYPE_INT
;
235 struct type_table
*p
;
237 strcpy (ptr
->field_names
[ptr
->fields_num
],v_name
);
238 ptr
->field_positions
[ptr
->fields_num
]=ptr
->length
;
240 for (p
= type_table
; p
->name
; p
++) {
241 if (strcmp(v_type
, p
->name
) == 0) {
243 field_type
= p
->field_type
;
248 if (strncmp(v_type
, "char[", 5) == 0) {
249 len
= atoi(v_type
+5);
250 field_type
= FIELD_TYPE_CHAR
;
252 printf("Unknown type %s for field %s\n", v_type
, v_name
);
257 ptr
->field_lengths
[ptr
->fields_num
] = len
;
258 ptr
->field_types
[ptr
->fields_num
] = field_type
;
264 void fill_type_commands (struct struct_descriptor
*ptr
)
268 Set specific type user commands.
274 if (strcmp ((ptr
->name
),"file")==0) {
275 add_user_command (&ptr
->type_commands
,"show","Shows file data",type_file___show
);
276 add_user_command (&ptr
->type_commands
,"inode","Returns to the inode of the current file",type_file___inode
);
277 add_user_command (&ptr
->type_commands
,"display","Specifies data format - text or hex",type_file___display
);
278 add_user_command (&ptr
->type_commands
,"next","Pass to next byte",type_file___next
);
279 add_user_command (&ptr
->type_commands
,"prev","Pass to the previous byte",type_file___prev
);
280 add_user_command (&ptr
->type_commands
,"offset","Pass to a specified byte in the current block",type_file___offset
);
281 add_user_command (&ptr
->type_commands
,"nextblock","Pass to next file block",type_file___nextblock
);
282 add_user_command (&ptr
->type_commands
,"prevblock","Pass to the previous file block",type_file___prevblock
);
283 add_user_command (&ptr
->type_commands
,"block","Specify which file block to edit",type_file___block
);
284 add_user_command (&ptr
->type_commands
,"remember","Saves the file\'s inode position for later reference",type_file___remember
);
285 add_user_command (&ptr
->type_commands
,"set","Sets the current byte",type_file___set
);
286 add_user_command (&ptr
->type_commands
,"writedata","Writes the current block to the disk",type_file___writedata
);
289 if (strcmp ((ptr
->name
),"ext2_inode")==0) {
290 add_user_command (&ptr
->type_commands
,"show","Shows inode data",type_ext2_inode___show
);
291 add_user_command (&ptr
->type_commands
,"next","Move to next inode in current block group",type_ext2_inode___next
);
292 add_user_command (&ptr
->type_commands
,"prev","Move to next inode in current block group",type_ext2_inode___prev
);
293 add_user_command (&ptr
->type_commands
,"group","Move to the group descriptors of the current inode table",type_ext2_inode___group
);
294 add_user_command (&ptr
->type_commands
,"entry","Move to a specified entry in the current inode table",type_ext2_inode___entry
);
295 add_user_command (&ptr
->type_commands
,"file","Display file data of the current inode",type_ext2_inode___file
);
296 add_user_command (&ptr
->type_commands
,"dir","Display directory data of the current inode",type_ext2_inode___dir
);
299 if (strcmp ((ptr
->name
),"dir")==0) {
300 add_user_command (&ptr
->type_commands
,"show","Shows current directory data",type_dir___show
);
301 add_user_command (&ptr
->type_commands
,"inode","Returns to the inode of the current directory",type_dir___inode
);
302 add_user_command (&ptr
->type_commands
,"next","Pass to the next directory entry",type_dir___next
);
303 add_user_command (&ptr
->type_commands
,"prev","Pass to the previous directory entry",type_dir___prev
);
304 add_user_command (&ptr
->type_commands
,"followinode","Follows the inode specified in this directory entry",type_dir___followinode
);
305 add_user_command (&ptr
->type_commands
,"remember","Remember the inode of the current directory entry",type_dir___remember
);
306 add_user_command (&ptr
->type_commands
,"cd","Changes directory relative to the current directory",type_dir___cd
);
307 add_user_command (&ptr
->type_commands
,"entry","Moves to a specified entry in the current directory",type_dir___entry
);
308 add_user_command (&ptr
->type_commands
,"writedata","Writes the current entry to the disk",type_dir___writedata
);
309 add_user_command (&ptr
->type_commands
,"set","Changes a variable in the current directory entry",type_dir___set
);
312 if (strcmp ((ptr
->name
),"ext2_super_block")==0) {
313 add_user_command (&ptr
->type_commands
,"show","Displays the super block data",type_ext2_super_block___show
);
314 add_user_command (&ptr
->type_commands
,"gocopy","Move to another backup copy of the superblock",type_ext2_super_block___gocopy
);
315 add_user_command (&ptr
->type_commands
,"setactivecopy","Copies the current superblock to the main superblock",type_ext2_super_block___setactivecopy
);
318 if (strcmp ((ptr
->name
),"ext2_group_desc")==0) {
319 add_user_command (&ptr
->type_commands
,"next","Pass to the next block group descriptor",type_ext2_group_desc___next
);
320 add_user_command (&ptr
->type_commands
,"prev","Pass to the previous group descriptor",type_ext2_group_desc___prev
);
321 add_user_command (&ptr
->type_commands
,"entry","Pass to a specific group descriptor",type_ext2_group_desc___entry
);
322 add_user_command (&ptr
->type_commands
,"show","Shows the current group descriptor",type_ext2_group_desc___show
);
323 add_user_command (&ptr
->type_commands
,"inode","Pass to the inode table of the current group block",type_ext2_group_desc___inode
);
324 add_user_command (&ptr
->type_commands
,"gocopy","Move to another backup copy of the group descriptor",type_ext2_group_desc___gocopy
);
325 add_user_command (&ptr
->type_commands
,"blockbitmap","Show the block allocation bitmap of the current group block",type_ext2_group_desc___blockbitmap
);
326 add_user_command (&ptr
->type_commands
,"inodebitmap","Show the inode allocation bitmap of the current group block",type_ext2_group_desc___inodebitmap
);
327 add_user_command (&ptr
->type_commands
,"setactivecopy","Copies the current group descriptor to the main table",type_ext2_super_block___setactivecopy
);
330 if (strcmp ((ptr
->name
),"block_bitmap")==0) {
331 add_user_command (&ptr
->type_commands
,"show","Displays the block allocation bitmap",type_ext2_block_bitmap___show
);
332 add_user_command (&ptr
->type_commands
,"entry","Moves to a specific bit",type_ext2_block_bitmap___entry
);
333 add_user_command (&ptr
->type_commands
,"next","Moves to the next bit",type_ext2_block_bitmap___next
);
334 add_user_command (&ptr
->type_commands
,"prev","Moves to the previous bit",type_ext2_block_bitmap___prev
);
335 add_user_command (&ptr
->type_commands
,"allocate","Allocates the current block",type_ext2_block_bitmap___allocate
);
336 add_user_command (&ptr
->type_commands
,"deallocate","Deallocates the current block",type_ext2_block_bitmap___deallocate
);
339 if (strcmp ((ptr
->name
),"inode_bitmap")==0) {
340 add_user_command (&ptr
->type_commands
,"show","Displays the inode allocation bitmap",type_ext2_inode_bitmap___show
);
341 add_user_command (&ptr
->type_commands
,"entry","Moves to a specific bit",type_ext2_inode_bitmap___entry
);
342 add_user_command (&ptr
->type_commands
,"next","Moves to the next bit",type_ext2_inode_bitmap___next
);
343 add_user_command (&ptr
->type_commands
,"prev","Moves to the previous bit",type_ext2_inode_bitmap___prev
);
344 add_user_command (&ptr
->type_commands
,"allocate","Allocates the current inode",type_ext2_inode_bitmap___allocate
);
345 add_user_command (&ptr
->type_commands
,"deallocate","Deallocates the current inode",type_ext2_inode_bitmap___deallocate
);
350 void add_user_command (struct struct_commands
*ptr
,char *name
,char *description
,PF callback
)
355 num
=ptr
->last_command
;
356 if (num
+1==MAX_COMMANDS_NUM
) {
357 printf ("Internal Error - Can't add command %s\n",name
);
361 ptr
->last_command
=++num
;
363 ptr
->names
[num
]=(char *) malloc (strlen (name
)+1);
364 strcpy (ptr
->names
[num
],name
);
366 if (*description
!=0) {
367 ptr
->descriptions
[num
]=(char *) malloc (strlen (description
)+1);
368 strcpy (ptr
->descriptions
[num
],description
);
371 ptr
->callback
[num
]=callback
;
374 int set_file_system_info (void)
378 struct ext2_super_block
*sb
;
380 file_system_info
.super_block_offset
=1024;
381 file_system_info
.file_system_size
=DefaultTotalBlocks
*DefaultBlockSize
;
383 low_read ((char *) &file_system_info
.super_block
,sizeof (struct ext2_super_block
),file_system_info
.super_block_offset
);
385 sb
=&file_system_info
.super_block
;
387 if (sb
->s_magic
== EXT2_SUPER_MAGIC
)
391 wprintw (command_win
,"Detected extended 2 file system on device %s\n",device_name
);
393 wprintw (command_win
,"Warning - Extended 2 filesystem not detected on device %s\n",device_name
);
395 if (!ext2_detected
&& !ForceExt2
)
396 wprintw (command_win
,"You may wish to use the configuration option ForceExt2 on\n");
398 if (ForceExt2
&& !ext2_detected
)
399 wprintw (command_win
,"Forcing extended 2 filesystem\n");
401 if (ForceDefault
|| !ext2_detected
)
402 wprintw (command_win
,"Forcing default parameters\n");
404 refresh_command_win ();
406 if (ext2_detected
|| ForceExt2
) {
407 add_ext2_general_commands ();
408 if (!set_struct_descriptors (Ext2Descriptors
))
412 if (!ForceDefault
&& ext2_detected
) {
414 file_system_info
.block_size
=EXT2_MIN_BLOCK_SIZE
<< sb
->s_log_block_size
;
415 if (file_system_info
.block_size
== EXT2_MIN_BLOCK_SIZE
)
416 file_system_info
.first_group_desc_offset
=2*EXT2_MIN_BLOCK_SIZE
;
418 file_system_info
.first_group_desc_offset
=file_system_info
.block_size
;
419 file_system_info
.groups_count
= ext2fs_div64_ceil(ext2fs_blocks_count(sb
),
420 sb
->s_blocks_per_group
);
422 file_system_info
.inodes_per_block
=file_system_info
.block_size
/sizeof (struct ext2_inode
);
423 file_system_info
.blocks_per_group
=sb
->s_inodes_per_group
/file_system_info
.inodes_per_block
;
424 file_system_info
.no_blocks_in_group
=sb
->s_blocks_per_group
;
425 file_system_info
.file_system_size
=(ext2fs_blocks_count(sb
)-1)*file_system_info
.block_size
;
429 file_system_info
.file_system_size
=DefaultTotalBlocks
*DefaultBlockSize
;
430 file_system_info
.block_size
=DefaultBlockSize
;
431 file_system_info
.no_blocks_in_group
=DefaultBlocksInGroup
;
434 if (file_system_info
.file_system_size
> 2147483647) {
435 wprintw (command_win
,"Sorry, filesystems bigger than 2 GB are currently not supported\n");
441 void init_readline (void)
445 rl_completion_entry_function
=(Function
*) complete_command
;
449 void init_signals (void)
452 signal (SIGWINCH
, signal_SIGWINCH_handler
); /* Catch SIGWINCH */
453 signal (SIGTERM
, signal_SIGTERM_handler
);
454 signal (SIGSEGV
, signal_SIGSEGV_handler
);
458 void signal_SIGWINCH_handler (int sig_num
)
461 redraw_request
=1; /* We will handle it in main.c */
463 /* Reset signal handler */
464 signal (SIGWINCH
, signal_SIGWINCH_handler
);
468 void signal_SIGTERM_handler (int sig_num
)
472 printf ("Terminated due to signal %d\n",sig_num
);
476 void signal_SIGSEGV_handler (int sig_num
)
480 printf ("Killed by signal %d!\n",sig_num
);
484 int process_configuration_file (void)
488 char option
[80],value
[80];
491 strcpy (buffer
, ROOT_SYSCONFDIR
);
492 strcat (buffer
,"/ext2ed.conf");
494 if ((fp
=fopen (buffer
,"rt"))==NULL
) {
495 fprintf (stderr
,"Error - Unable to open configuration file %s\n",buffer
);
499 while (get_next_option (fp
,option
,value
)) {
500 if (strcasecmp (option
,"Ext2Descriptors")==0) {
501 strcpy (Ext2Descriptors
,value
);
504 else if (strcasecmp (option
,"AlternateDescriptors")==0) {
505 strcpy (AlternateDescriptors
,value
);
508 else if (strcasecmp (option
,"LogFile")==0) {
509 strcpy (LogFile
,value
);
512 else if (strcasecmp (option
,"LogChanges")==0) {
513 if (strcasecmp (value
,"on")==0)
515 else if (strcasecmp (value
,"off")==0)
518 fprintf (stderr
,"Error - Illegal value: %s %s\n",option
,value
);
519 fclose (fp
);return (0);
523 else if (strcasecmp (option
,"AllowChanges")==0) {
524 if (strcasecmp (value
,"on")==0)
526 else if (strcasecmp (value
,"off")==0)
529 fprintf (stderr
,"Error - Illegal value: %s %s\n",option
,value
);
530 fclose (fp
);return (0);
534 else if (strcasecmp (option
,"AllowMountedRead")==0) {
535 if (strcasecmp (value
,"on")==0)
536 AllowMountedRead
= 1;
537 else if (strcasecmp (value
,"off")==0)
538 AllowMountedRead
= 0;
540 fprintf (stderr
,"Error - Illegal value: %s %s\n",option
,value
);
541 fclose (fp
);return (0);
545 else if (strcasecmp (option
,"ForceExt2")==0) {
546 if (strcasecmp (value
,"on")==0)
548 else if (strcasecmp (value
,"off")==0)
551 fprintf (stderr
,"Error - Illegal value: %s %s\n",option
,value
);
552 fclose (fp
);return (0);
556 else if (strcasecmp (option
,"DefaultBlockSize")==0) {
557 DefaultBlockSize
= atoi (value
);
560 else if (strcasecmp (option
,"DefaultTotalBlocks")==0) {
561 DefaultTotalBlocks
= strtoul (value
,NULL
,10);
564 else if (strcasecmp (option
,"DefaultBlocksInGroup")==0) {
565 DefaultBlocksInGroup
= strtoul (value
,NULL
,10);
568 else if (strcasecmp (option
,"ForceDefault")==0) {
569 if (strcasecmp (value
,"on")==0)
571 else if (strcasecmp (value
,"off")==0)
574 fprintf (stderr
,"Error - Illegal value: %s %s\n",option
,value
);
575 fclose (fp
);return (0);
580 fprintf (stderr
,"Error - Unknown option: %s\n",option
);
581 fclose (fp
);return (0);
585 printf ("Configuration completed\n");
590 int get_next_option (FILE *fp
,char *option
,char *value
)
596 if (feof (fp
)) return (0);
598 if (feof (fp
)) return (0);
599 fgets (buffer
,500,fp
);
600 } while (buffer
[0]=='#' || buffer
[0]=='\n');
602 ptr
=parse_word (buffer
,option
);
603 ptr
=parse_word (ptr
,value
);
607 void check_mounted (char *name
)
612 char current_line
[500],current_word
[200];
616 if ( (fp
=fopen ("/etc/mtab","rt"))==NULL
) {
617 wprintw (command_win
,"Error - Failed to open /etc/mtab. Assuming filesystem is mounted.\n");
618 refresh_command_win ();mounted
=1;return;
622 fgets (current_line
,500,fp
);
623 if (feof (fp
)) break;
624 ptr
=parse_word (current_line
,current_word
);
625 if (strcasecmp (current_word
,name
)==0) {
626 mounted
=1;fclose (fp
);return;