Merge change 9990
[android/platform/external/e2fsprogs.git] / ext2ed / init.c
1 /*
2
3 /usr/src/ext2ed/init.c
4
5 A part of the extended file system 2 disk editor.
6
7 --------------------------------
8 Various initialization routines.
9 --------------------------------
10
11 First written on: April 9 1995
12
13 Copyright (C) 1995 Gadi Oxman
14
15 */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #ifdef HAVE_READLINE
21 #include <readline.h>
22 #endif
23 #include <signal.h>
24 #include <unistd.h>
25
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29
30 #include "ext2ed.h"
31
32 char lines_s [80],cols_s [80];
33
34 void signal_handler (void);
35
36 void prepare_to_close (void)
37
38 {
39         close_windows ();
40         if (device_handle!=NULL)
41                 fclose (device_handle);
42         free_user_commands (&general_commands);
43         free_user_commands (&ext2_commands);
44         free_struct_descriptors ();
45 }
46
47 int init (void)
48
49 {
50         printf ("Initializing ...\n");
51         
52         if (!process_configuration_file ()) {
53                 fprintf (stderr,"Error - Unable to complete configuration. Quitting.\n");
54                 return (0);             
55         };
56         
57         general_commands.last_command=-1;       /* No commands whatsoever meanwhile */
58         ext2_commands.last_command=-1;
59         add_general_commands ();                /* Add the general commands, aviable always */
60         device_handle=NULL;                     /* Notice that our device is still not set up */
61         device_offset=-1;
62         current_type=NULL;                      /* No filesystem specific types yet */
63
64         remember_lifo.entries_count=0;          /* Object memory is empty */
65         
66         init_windows ();                        /* Initialize the NCURSES interface */
67         init_readline ();                       /* Initialize the READLINE interface */
68         init_signals ();                        /* Initialize the signal handlers */
69         write_access=0;                         /* Write access disabled */
70         
71         strcpy (last_command_line,"help");      /* Show the help screen to the user */
72         dispatch ("help");
73         return (1);                             /* Success */
74 }
75
76 void add_general_commands (void)
77
78 {
79         add_user_command (&general_commands,"help","EXT2ED help system",help);
80         add_user_command (&general_commands,"set","Changes a variable in the current object",set);
81         add_user_command (&general_commands,"setdevice","Selects the filesystem block device (e.g. /dev/hda1)",set_device);
82         add_user_command (&general_commands,"setoffset","Moves asynchronicly in the filesystem",set_offset);
83         add_user_command (&general_commands,"settype","Tells EXT2ED how to interpert the current object",set_type);
84         add_user_command (&general_commands,"show","Displays the current object",show);
85         add_user_command (&general_commands,"pgup","Scrolls data one page up",pgup);
86         add_user_command (&general_commands,"pgdn","Scrolls data one page down",pgdn);
87         add_user_command (&general_commands,"redraw","Redisplay the screen",redraw);
88         add_user_command (&general_commands,"remember","Saves the current position and data information",remember);
89         add_user_command (&general_commands,"recall","Gets back to the saved object position",recall);
90         add_user_command (&general_commands,"enablewrite","Enters Read/Write mode - Allows changing the filesystem",enable_write);
91         add_user_command (&general_commands,"disablewrite","Enters read only mode",disable_write);
92         add_user_command (&general_commands,"writedata","Write data back to disk",write_data);
93         add_user_command (&general_commands,"next","Moves to the next byte in hex mode",next);
94         add_user_command (&general_commands,"prev","Moves to the previous byte in hex mode",prev);
95 }
96
97 void add_ext2_general_commands (void)
98
99 {
100         add_user_command (&ext2_commands,"super","Moves to the superblock of the filesystem",type_ext2___super);
101         add_user_command (&ext2_commands,"group","Moves to the first group descriptor",type_ext2___group);
102         add_user_command (&ext2_commands,"cd","Moves to the directory specified",type_ext2___cd);
103 }
104
105 int set_struct_descriptors (char *file_name)
106
107 {
108         FILE *fp;
109         char current_line [500],current_word [50],*ch;
110         char variable_name [50],variable_type [20];
111         struct struct_descriptor *current_descriptor;
112         
113         if ( (fp=fopen (file_name,"rt"))==NULL) {
114                 wprintw (command_win,"Error - Failed to open descriptors file %s\n",file_name);
115                 refresh_command_win (); return (0);
116         };
117         
118         while (!feof (fp)) {
119                 fgets (current_line,500,fp);
120                 if (feof (fp)) break;   
121                 ch=parse_word (current_line,current_word);
122                 if (strcmp (current_word,"struct")==0) {
123                         ch=parse_word (ch,current_word);
124                         current_descriptor=add_new_descriptor (current_word);
125                         
126                         while (strchr (current_line,'{')==NULL) {
127                                 fgets (current_line,500,fp);
128                                 if (feof (fp)) break;
129                         };
130                         if (feof (fp)) break;
131                         
132                         fgets (current_line,500,fp);
133
134                         while (strchr (current_line,'}')==NULL) {
135                                 while (strchr (current_line,';')==NULL) {
136                                         fgets (current_line,500,fp);
137                                         if (strchr (current_line,'}')!=NULL) break;
138                                 };
139                                 if (strchr (current_line,'}') !=NULL) break;
140                                 ch=parse_word (current_line,variable_type);
141                                 ch=parse_word (ch,variable_name);
142                                 while (variable_name [strlen (variable_name)-1]!=';') {
143                                         strcpy (variable_type,variable_name);
144                                         ch=parse_word (ch,variable_name);
145                                 };
146                                 variable_name [strlen (variable_name)-1]=0;
147                                 add_new_variable (current_descriptor,variable_type,variable_name);
148                                 fgets (current_line,500,fp);
149                         };
150                 }; 
151         };
152         
153         fclose (fp);
154         return (1);
155 }
156
157 void free_struct_descriptors (void)
158
159 {
160         struct struct_descriptor *ptr,*next;
161         
162         ptr=first_type;
163         while (ptr!=NULL) {
164                 next=ptr->next;
165                 free_user_commands (&ptr->type_commands);
166                 free (ptr);
167                 ptr=next;
168         }
169         first_type=last_type=current_type=NULL;
170 }
171
172 void free_user_commands (struct struct_commands *ptr)
173
174 {
175         int i;
176         
177         for (i=0;i<=ptr->last_command;i++) {
178                 free (ptr->names [i]);
179                 free (ptr->descriptions [i]);
180         }
181         
182         ptr->last_command=-1;
183 }
184
185 struct struct_descriptor *add_new_descriptor (char *name)
186
187 {
188         struct struct_descriptor *ptr;
189         
190         ptr = malloc (sizeof (struct struct_descriptor));
191         if (ptr == NULL) {
192                 printf ("Error - Can not allocate memory - Quitting\n");
193                 exit (1);
194         }
195         memset(ptr, 0, sizeof(struct struct_descriptor));
196         ptr->prev = ptr->next = NULL;
197         strcpy (ptr->name,name);
198         ptr->length=0;
199         ptr->fields_num=0;
200         if (first_type==NULL) {
201                 first_type = last_type = ptr;
202         } else {
203                 ptr->prev = last_type; last_type->next = ptr; last_type=ptr;
204         }
205         ptr->type_commands.last_command=-1;
206         fill_type_commands (ptr);
207         return (ptr);
208 }
209
210 struct type_table {
211         char    *name;
212         int     field_type;
213         int     len;
214 };
215
216 struct type_table type_table[] = {
217         { "long",   FIELD_TYPE_INT,     4 },
218         { "short",  FIELD_TYPE_INT,     2 },
219         { "char",   FIELD_TYPE_CHAR,    1 },
220         { "__u32",  FIELD_TYPE_UINT,    4 },
221         { "__s32",  FIELD_TYPE_INT,     4 },
222         { "__u16",  FIELD_TYPE_UINT,    2 },
223         { "__s16",  FIELD_TYPE_INT,     2 },
224         { "__u8",   FIELD_TYPE_UINT,    1 },
225         { "__s8",   FIELD_TYPE_INT,     1 },
226         {  0,       0,                  0 }
227 };
228
229 void add_new_variable (struct struct_descriptor *ptr,char *v_type,char *v_name)
230
231 {
232         short   len=1;
233         char    field_type=FIELD_TYPE_INT;
234         struct type_table *p;
235         
236         strcpy (ptr->field_names [ptr->fields_num],v_name);
237         ptr->field_positions [ptr->fields_num]=ptr->length;
238
239         for (p = type_table; p->name; p++) {
240                 if (strcmp(v_type, p->name) == 0) {
241                         len = p->len;
242                         field_type = p->field_type;
243                         break;
244                 }
245         }
246         if (p->name == 0) {
247                 if (strncmp(v_type, "char[", 5) == 0) {
248                         len = atoi(v_type+5);
249                         field_type = FIELD_TYPE_CHAR;
250                 } else {
251                         printf("Unknown type %s for field %s\n", v_type, v_name);
252                         exit(1);
253                 }
254         }
255
256         ptr->field_lengths [ptr->fields_num] = len;
257         ptr->field_types [ptr->fields_num] = field_type;
258
259         ptr->length+=len;
260         ptr->fields_num++; 
261 }
262
263 void fill_type_commands (struct struct_descriptor *ptr)
264
265 /*
266
267 Set specific type user commands.
268
269 */
270
271 {
272
273         if (strcmp ((ptr->name),"file")==0) {
274                 add_user_command (&ptr->type_commands,"show","Shows file data",type_file___show);
275                 add_user_command (&ptr->type_commands,"inode","Returns to the inode of the current file",type_file___inode);
276                 add_user_command (&ptr->type_commands,"display","Specifies data format - text or hex",type_file___display);
277                 add_user_command (&ptr->type_commands,"next","Pass to next byte",type_file___next);
278                 add_user_command (&ptr->type_commands,"prev","Pass to the previous byte",type_file___prev);
279                 add_user_command (&ptr->type_commands,"offset","Pass to a specified byte in the current block",type_file___offset);
280                 add_user_command (&ptr->type_commands,"nextblock","Pass to next file block",type_file___nextblock);
281                 add_user_command (&ptr->type_commands,"prevblock","Pass to the previous file block",type_file___prevblock);
282                 add_user_command (&ptr->type_commands,"block","Specify which file block to edit",type_file___block);
283                 add_user_command (&ptr->type_commands,"remember","Saves the file\'s inode position for later reference",type_file___remember);
284                 add_user_command (&ptr->type_commands,"set","Sets the current byte",type_file___set);
285                 add_user_command (&ptr->type_commands,"writedata","Writes the current block to the disk",type_file___writedata);
286         }
287
288         if (strcmp ((ptr->name),"ext2_inode")==0) {
289                 add_user_command (&ptr->type_commands,"show","Shows inode data",type_ext2_inode___show);
290                 add_user_command (&ptr->type_commands,"next","Move to next inode in current block group",type_ext2_inode___next);
291                 add_user_command (&ptr->type_commands,"prev","Move to next inode in current block group",type_ext2_inode___prev);
292                 add_user_command (&ptr->type_commands,"group","Move to the group descriptors of the current inode table",type_ext2_inode___group);
293                 add_user_command (&ptr->type_commands,"entry","Move to a specified entry in the current inode table",type_ext2_inode___entry);
294                 add_user_command (&ptr->type_commands,"file","Display file data of the current inode",type_ext2_inode___file);
295                 add_user_command (&ptr->type_commands,"dir","Display directory data of the current inode",type_ext2_inode___dir);
296         }
297         
298         if (strcmp ((ptr->name),"dir")==0) {
299                 add_user_command (&ptr->type_commands,"show","Shows current directory data",type_dir___show);
300                 add_user_command (&ptr->type_commands,"inode","Returns to the inode of the current directory",type_dir___inode);
301                 add_user_command (&ptr->type_commands,"next","Pass to the next directory entry",type_dir___next);
302                 add_user_command (&ptr->type_commands,"prev","Pass to the previous directory entry",type_dir___prev);
303                 add_user_command (&ptr->type_commands,"followinode","Follows the inode specified in this directory entry",type_dir___followinode);
304                 add_user_command (&ptr->type_commands,"remember","Remember the inode of the current directory entry",type_dir___remember);
305                 add_user_command (&ptr->type_commands,"cd","Changes directory relative to the current directory",type_dir___cd);
306                 add_user_command (&ptr->type_commands,"entry","Moves to a specified entry in the current directory",type_dir___entry);
307                 add_user_command (&ptr->type_commands,"writedata","Writes the current entry to the disk",type_dir___writedata);
308                 add_user_command (&ptr->type_commands,"set","Changes a variable in the current directory entry",type_dir___set);
309         }
310         
311         if (strcmp ((ptr->name),"ext2_super_block")==0) {
312                 add_user_command (&ptr->type_commands,"show","Displays the super block data",type_ext2_super_block___show);
313                 add_user_command (&ptr->type_commands,"gocopy","Move to another backup copy of the superblock",type_ext2_super_block___gocopy);
314                 add_user_command (&ptr->type_commands,"setactivecopy","Copies the current superblock to the main superblock",type_ext2_super_block___setactivecopy);
315         }
316
317         if (strcmp ((ptr->name),"ext2_group_desc")==0) {
318                 add_user_command (&ptr->type_commands,"next","Pass to the next block group decriptor",type_ext2_group_desc___next);
319                 add_user_command (&ptr->type_commands,"prev","Pass to the previous group descriptor",type_ext2_group_desc___prev);
320                 add_user_command (&ptr->type_commands,"entry","Pass to a specific group descriptor",type_ext2_group_desc___entry);
321                 add_user_command (&ptr->type_commands,"show","Shows the current group descriptor",type_ext2_group_desc___show);
322                 add_user_command (&ptr->type_commands,"inode","Pass to the inode table of the current group block",type_ext2_group_desc___inode);
323                 add_user_command (&ptr->type_commands,"gocopy","Move to another backup copy of the group descriptor",type_ext2_group_desc___gocopy);
324                 add_user_command (&ptr->type_commands,"blockbitmap","Show the block allocation bitmap of the current group block",type_ext2_group_desc___blockbitmap);
325                 add_user_command (&ptr->type_commands,"inodebitmap","Show the inode allocation bitmap of the current group block",type_ext2_group_desc___inodebitmap);
326                 add_user_command (&ptr->type_commands,"setactivecopy","Copies the current group descriptor to the main table",type_ext2_super_block___setactivecopy);
327         }
328
329         if (strcmp ((ptr->name),"block_bitmap")==0) {
330                 add_user_command (&ptr->type_commands,"show","Displays the block allocation bitmap",type_ext2_block_bitmap___show);
331                 add_user_command (&ptr->type_commands,"entry","Moves to a specific bit",type_ext2_block_bitmap___entry);
332                 add_user_command (&ptr->type_commands,"next","Moves to the next bit",type_ext2_block_bitmap___next);
333                 add_user_command (&ptr->type_commands,"prev","Moves to the previous bit",type_ext2_block_bitmap___prev);
334                 add_user_command (&ptr->type_commands,"allocate","Allocates the current block",type_ext2_block_bitmap___allocate);
335                 add_user_command (&ptr->type_commands,"deallocate","Deallocates the current block",type_ext2_block_bitmap___deallocate);
336         }
337
338         if (strcmp ((ptr->name),"inode_bitmap")==0) {
339                 add_user_command (&ptr->type_commands,"show","Displays the inode allocation bitmap",type_ext2_inode_bitmap___show);
340                 add_user_command (&ptr->type_commands,"entry","Moves to a specific bit",type_ext2_inode_bitmap___entry);
341                 add_user_command (&ptr->type_commands,"next","Moves to the next bit",type_ext2_inode_bitmap___next);
342                 add_user_command (&ptr->type_commands,"prev","Moves to the previous bit",type_ext2_inode_bitmap___prev);
343                 add_user_command (&ptr->type_commands,"allocate","Allocates the current inode",type_ext2_inode_bitmap___allocate);
344                 add_user_command (&ptr->type_commands,"deallocate","Deallocates the current inode",type_ext2_inode_bitmap___deallocate);
345         }
346         
347 }
348
349 void add_user_command (struct struct_commands *ptr,char *name,char *description,PF callback)
350
351 {
352         int num;
353         
354         num=ptr->last_command;
355         if (num+1==MAX_COMMANDS_NUM) {
356                 printf ("Internal Error - Can't add command %s\n",name);
357                 return;
358         }
359         
360         ptr->last_command=++num;
361
362         ptr->names [num]=(char *) malloc (strlen (name)+1);
363         strcpy (ptr->names [num],name);
364         
365         if (*description!=0) {
366                 ptr->descriptions [num]=(char *) malloc (strlen (description)+1);
367                 strcpy (ptr->descriptions [num],description);
368         }
369         
370         ptr->callback [num]=callback;
371 }
372
373 static unsigned int div_ceil(unsigned int a, unsigned int b)
374 {
375         if (!a)
376                 return 0;
377         return ((a - 1) / b) + 1;
378 }
379
380 int set_file_system_info (void)
381
382 {
383         int ext2_detected=0;
384         struct ext2_super_block *sb;
385         
386         file_system_info.super_block_offset=1024;
387         file_system_info.file_system_size=DefaultTotalBlocks*DefaultBlockSize;
388
389         low_read ((char *) &file_system_info.super_block,sizeof (struct ext2_super_block),file_system_info.super_block_offset);
390
391         sb=&file_system_info.super_block;
392
393         if (sb->s_magic == EXT2_SUPER_MAGIC) 
394                 ext2_detected=1;
395
396         if (ext2_detected)
397                 wprintw (command_win,"Detected extended 2 file system on device %s\n",device_name);
398         else
399                 wprintw (command_win,"Warning - Extended 2 filesystem not detected on device %s\n",device_name);
400
401         if (!ext2_detected && !ForceExt2)
402                 wprintw (command_win,"You may wish to use the configuration option ForceExt2 on\n");
403
404         if (ForceExt2 && !ext2_detected)
405                 wprintw (command_win,"Forcing extended 2 filesystem\n");
406         
407         if (ForceDefault || !ext2_detected)
408                 wprintw (command_win,"Forcing default parameters\n");
409
410         refresh_command_win ();
411
412         if (ext2_detected || ForceExt2) {
413                 add_ext2_general_commands ();
414                 if (!set_struct_descriptors (Ext2Descriptors))
415                         return (0);
416         }
417         
418         if (!ForceDefault && ext2_detected) {
419         
420                 file_system_info.block_size=EXT2_MIN_BLOCK_SIZE << sb->s_log_block_size;
421                 if (file_system_info.block_size == EXT2_MIN_BLOCK_SIZE)
422                         file_system_info.first_group_desc_offset=2*EXT2_MIN_BLOCK_SIZE;
423                 else
424                         file_system_info.first_group_desc_offset=file_system_info.block_size;
425                 file_system_info.groups_count = div_ceil(sb->s_blocks_count, 
426                                                  sb->s_blocks_per_group);
427         
428                 file_system_info.inodes_per_block=file_system_info.block_size/sizeof (struct ext2_inode);
429                 file_system_info.blocks_per_group=sb->s_inodes_per_group/file_system_info.inodes_per_block;
430                 file_system_info.no_blocks_in_group=sb->s_blocks_per_group;
431                 file_system_info.file_system_size=(sb->s_blocks_count-1)*file_system_info.block_size;
432         }
433
434         else {
435                 file_system_info.file_system_size=DefaultTotalBlocks*DefaultBlockSize;
436                 file_system_info.block_size=DefaultBlockSize;           
437                 file_system_info.no_blocks_in_group=DefaultBlocksInGroup;
438         }
439         
440         if (file_system_info.file_system_size > 2147483647) {
441                 wprintw (command_win,"Sorry, filesystems bigger than 2 GB are currently not supported\n");
442                 return (0);
443         }
444         return (1);
445 }
446
447 void init_readline (void)
448
449 {
450 #ifdef HAVE_READLINE
451         rl_completion_entry_function=(Function *) complete_command;
452 #endif
453 }
454
455 void init_signals (void)
456
457 {
458         signal (SIGWINCH, signal_SIGWINCH_handler);     /* Catch SIGWINCH */
459         signal (SIGTERM, signal_SIGTERM_handler);
460         signal (SIGSEGV, signal_SIGSEGV_handler);
461         
462 }
463
464 void signal_SIGWINCH_handler (int sig_num)
465
466 {
467         redraw_request=1;       /* We will handle it in main.c */
468         
469         /* Reset signal handler */      
470         signal (SIGWINCH, signal_SIGWINCH_handler);     
471         
472 }
473
474 void signal_SIGTERM_handler (int sig_num)
475
476 {
477         prepare_to_close ();
478         printf ("Terminated due to signal %d\n",sig_num);
479         exit (1);
480 }
481
482 void signal_SIGSEGV_handler (int sig_num)
483
484 {
485         prepare_to_close ();
486         printf ("Killed by signal %d!\n",sig_num);
487         exit (1);
488 }
489
490 int process_configuration_file (void)
491
492 {
493         char buffer [300];
494         char option [80],value [80];
495         FILE *fp;
496
497         strcpy (buffer, ETC_DIR);
498         strcat (buffer,"/ext2ed.conf");
499                 
500         if ((fp=fopen (buffer,"rt"))==NULL) {
501                 fprintf (stderr,"Error - Unable to open configuration file %s\n",buffer);
502                 return (0);
503         }
504         
505         while (get_next_option (fp,option,value)) {
506                 if (strcasecmp (option,"Ext2Descriptors")==0) {
507                         strcpy (Ext2Descriptors,value);
508                 }
509
510                 else if (strcasecmp (option,"AlternateDescriptors")==0) {
511                         strcpy (AlternateDescriptors,value);
512                 }
513
514                 else if (strcasecmp (option,"LogFile")==0) {
515                         strcpy (LogFile,value);
516                 }
517
518                 else if (strcasecmp (option,"LogChanges")==0) {
519                         if (strcasecmp (value,"on")==0)
520                                 LogChanges = 1;
521                         else if (strcasecmp (value,"off")==0)
522                                 LogChanges = 0;
523                         else {
524                                 fprintf (stderr,"Error - Illegal value: %s %s\n",option,value);
525                                 fclose (fp);return (0);
526                         }
527                 }
528
529                 else if (strcasecmp (option,"AllowChanges")==0) {
530                         if (strcasecmp (value,"on")==0)
531                                 AllowChanges = 1;
532                         else if (strcasecmp (value,"off")==0)
533                                 AllowChanges = 0;
534                         else {
535                                 fprintf (stderr,"Error - Illegal value: %s %s\n",option,value);
536                                 fclose (fp);return (0);
537                         }
538                 }
539
540                 else if (strcasecmp (option,"AllowMountedRead")==0) {
541                         if (strcasecmp (value,"on")==0)
542                                 AllowMountedRead = 1;
543                         else if (strcasecmp (value,"off")==0)
544                                 AllowMountedRead = 0;
545                         else {
546                                 fprintf (stderr,"Error - Illegal value: %s %s\n",option,value);
547                                 fclose (fp);return (0);
548                         }
549                 }
550
551                 else if (strcasecmp (option,"ForceExt2")==0) {
552                         if (strcasecmp (value,"on")==0)
553                                 ForceExt2 = 1;
554                         else if (strcasecmp (value,"off")==0)
555                                 ForceExt2 = 0;
556                         else {
557                                 fprintf (stderr,"Error - Illegal value: %s %s\n",option,value);
558                                 fclose (fp);return (0);
559                         }
560                 }
561
562                 else if (strcasecmp (option,"DefaultBlockSize")==0) {
563                         DefaultBlockSize = atoi (value);
564                 }
565
566                 else if (strcasecmp (option,"DefaultTotalBlocks")==0) {
567                         DefaultTotalBlocks = strtoul (value,NULL,10);
568                 }
569
570                 else if (strcasecmp (option,"DefaultBlocksInGroup")==0) {
571                         DefaultBlocksInGroup = strtoul (value,NULL,10);
572                 }
573
574                 else if (strcasecmp (option,"ForceDefault")==0) {
575                         if (strcasecmp (value,"on")==0)
576                                 ForceDefault = 1;
577                         else if (strcasecmp (value,"off")==0)
578                                 ForceDefault = 0;
579                         else {
580                                 fprintf (stderr,"Error - Illegal value: %s %s\n",option,value);
581                                 fclose (fp);return (0);
582                         }
583                 }
584                 
585                 else {
586                         fprintf (stderr,"Error - Unknown option: %s\n",option);
587                         fclose (fp);return (0);
588                 }
589         }
590
591         printf ("Configuration completed\n");
592         fclose (fp);
593         return (1);
594 }
595
596 int get_next_option (FILE *fp,char *option,char *value)
597
598 {
599         char *ptr;
600         char buffer [600];
601         
602         if (feof (fp)) return (0);
603         do{
604                 if (feof (fp)) return (0);
605                 fgets (buffer,500,fp);
606         } while (buffer [0]=='#' || buffer [0]=='\n');
607         
608         ptr=parse_word (buffer,option);
609         ptr=parse_word (ptr,value);
610         return (1);
611 }
612
613 void check_mounted (char *name)
614
615 {
616         FILE *fp;
617         char *ptr;
618         char current_line [500],current_word [200];
619
620         mounted=0;
621         
622         if ( (fp=fopen ("/etc/mtab","rt"))==NULL) {
623                 wprintw (command_win,"Error - Failed to open /etc/mtab. Assuming filesystem is mounted.\n");
624                 refresh_command_win ();mounted=1;return;
625         };
626         
627         while (!feof (fp)) {
628                 fgets (current_line,500,fp);
629                 if (feof (fp)) break;   
630                 ptr=parse_word (current_line,current_word);
631                 if (strcasecmp (current_word,name)==0) {
632                         mounted=1;fclose (fp);return;
633                 }
634         };
635
636         fclose (fp);
637         
638         return; 
639 }