Home | History | Annotate | Download | only in doc
      1 <!DOCTYPE Article PUBLIC "-//Davenport//DTD DocBook V3.0//EN">
      2 
      3 <Article>
      4 
      5 <ArtHeader>
      6 
      7 <Title>EXT2ED - The Extended-2 filesystem editor - Design and implementation</Title>
      8 <AUTHOR
      9 >
     10 <FirstName>Programmed by Gadi Oxman, with the guide of Avner Lottem</FirstName>
     11 </AUTHOR
     12 >
     13 <PubDate>v0.1, August 3 1995</PubDate>
     14 
     15 </ArtHeader>
     16 
     17 <Sect1>
     18 <Title>About EXT2ED documentation</Title>
     19 
     20 <Para>
     21 The EXT2ED documentation consists of three parts:
     22 
     23 <ItemizedList>
     24 <ListItem>
     25 
     26 <Para>
     27 	The ext2 filesystem overview.
     28 </Para>
     29 </ListItem>
     30 <ListItem>
     31 
     32 <Para>
     33 	The EXT2ED user's guide.
     34 </Para>
     35 </ListItem>
     36 <ListItem>
     37 
     38 <Para>
     39 	The EXT2ED design and implementation.
     40 </Para>
     41 </ListItem>
     42 
     43 </ItemizedList>
     44 
     45 </Para>
     46 
     47 <Para>
     48 This document is not the user's guide. If you just intend to use EXT2ED, you
     49 may not want to read it.
     50 </Para>
     51 
     52 <Para>
     53 However, if you intend to browse and modify the source code, this document is
     54 for you.
     55 </Para>
     56 
     57 <Para>
     58 In any case, If you intend to read this article, I strongly suggest that you
     59 will be familiar with the material presented in the other two articles as well.
     60 </Para>
     61 
     62 </Sect1>
     63 
     64 <Sect1>
     65 <Title>Preface</Title>
     66 
     67 <Para>
     68 In this document I will try to explain how EXT2ED is constructed.
     69 At this time of writing, the initial version is finished and ready
     70 for distribution; It is fully functional. However, this was not always the
     71 case.
     72 </Para>
     73 
     74 <Para>
     75 At first, I didn't know much about Unix, much less about Unix filesystems,
     76 and even less about Linux and the extended-2 filesystem. While working
     77 on this project, I gradually acquired knowledge about all of the above
     78 subjects. I can think of two ways in which I could have made my project:
     79 
     80 <OrderedList>
     81 <ListItem>
     82 
     83 <Para>
     84 	The "Engineer" way
     85 
     86 Learn the subject throughly before I get to the programming itself.
     87 Then, I could easily see the entire picture and select the best
     88 course of action, taking all the factors into account.
     89 </Para>
     90 </ListItem>
     91 <ListItem>
     92 
     93 <Para>
     94 	The "Explorer - Progressive" way.
     95 
     96 Jump immediately into the cold water - Start programming and
     97 learning the material parallelly.
     98 </Para>
     99 </ListItem>
    100 
    101 </OrderedList>
    102 
    103 </Para>
    104 
    105 <Para>
    106 I guess that the above dilemma is typical and appears all through science and
    107 technology.
    108 </Para>
    109 
    110 <Para>
    111 However, I didn't have the luxury of choice when I started my project -
    112 Linux is a relatively new (and great!) operating system. The extended-2
    113 filesystem is even newer - Its first release lies somewhere in 1993 - Only
    114 passed two years until I started working on my project.
    115 </Para>
    116 
    117 <Para>
    118 The situation I found myself at the beginning was that I didn't have a fully
    119 detailed document which describes the ext2 filesystem. In fact, I didn't
    120 have any ext2 document at all. When I asked Avner about documentation, he
    121 suggested two references:
    122 
    123 <ItemizedList>
    124 <ListItem>
    125 
    126 <Para>
    127 	A general Unix book - THE DESIGN OF THE UNIX OPERATING SYSTEM, by
    128 Maurice J. Bach.
    129 </Para>
    130 </ListItem>
    131 <ListItem>
    132 
    133 <Para>
    134 	The kernel sources.
    135 </Para>
    136 </ListItem>
    137 
    138 </ItemizedList>
    139 
    140 I read the relevant parts of the book before I started my project - It is a
    141 bit old now, but the principles are still the same. However, I needed
    142 more than just the principles.
    143 </Para>
    144 
    145 <Para>
    146 The kernel sources are a rare bonus! You don't get everyday the full
    147 sources of the operating system. There is so much that can be learned from
    148 them, and it is the ultimate source - The exact answer how the kernel
    149 works is there, with all the fine details. At the first week I started to
    150 look at random at the relevant parts of the sources. However, it is difficult
    151 to understand the global picture from direct reading of over one hundred
    152 page sources. Then, I started to do some programming. I didn't know
    153 yet what I was looking for, and I started to work on the project like a kid
    154 who starts to build a large puzzle.
    155 </Para>
    156 
    157 <Para>
    158 However, this was exactly the interesting part! It is frustrating to know
    159 it all from advance - I think that the discovery itself, bit by bit, is the
    160 key to a true learning and understanding.
    161 </Para>
    162 
    163 <Para>
    164 Now, in this document, I am trying to present the subject. Even though I
    165 developed EXT2ED progressively, I now can see the entire subject much
    166 brighter than I did before, and though I do have the option of presenting it
    167 only in the "engineer" way. However, I will not do that.
    168 </Para>
    169 
    170 <Para>
    171 My presentation will be mixed - Sometimes I will present a subject with an
    172 incremental perspective, and sometimes from a "top down" view. I'll leave
    173 you to decide if my presentation choice was wise :-)
    174 </Para>
    175 
    176 <Para>
    177 In addition, you'll notice that the sections tend to get shorter as we get
    178 closer to the end. The reason is simply that I started to feel that I was
    179 repeating myself so I decided to present only the new ideas.
    180 </Para>
    181 
    182 </Sect1>
    183 
    184 <Sect1>
    185 <Title>Getting started ...</Title>
    186 
    187 <Para>
    188 Getting started is almost always the most difficult task. Once you get
    189 started, things start "running" ...
    190 </Para>
    191 
    192 <Sect2>
    193 <Title>Before the actual programming</Title>
    194 
    195 <Para>
    196 From mine talking with Avner, I understood that Linux, like any other Unix
    197 system, provides accesses to the entire disk as though it were a general
    198 file - Accessing the device. It is surely a nice idea. Avner suggested two
    199 ways of action:
    200 
    201 <ItemizedList>
    202 <ListItem>
    203 
    204 <Para>
    205 	Opening the device like a regular file in the user space.
    206 </Para>
    207 </ListItem>
    208 <ListItem>
    209 
    210 <Para>
    211 	Constructing a device driver which will run in the kernel space and
    212 provide hooks for the user space program. The advantage is that it
    213 will be a part of the kernel, and would be able to use the ext2
    214 kernel functions to do some of the work.
    215 </Para>
    216 </ListItem>
    217 
    218 </ItemizedList>
    219 
    220 I chose the first way. I think that the basic reason was simplicity - Learning
    221 the ext2 filesystem was complicated enough, and adding to it the task of
    222 learning how to program in the kernel space was too much. I still don't know
    223 how to program a device driver, and this is perhaps the bad part, but
    224 concerning the project in a back-perspective, I think that the first way is
    225 superior to the second; Ironically, because of the very reason I chose it -
    226 Simplicity. EXT2ED can now run entirely in the user space (which I think is
    227 a point in favor, because it doesn't require the user to recompile its
    228 kernel), and the entire hard work is mine, which fitted nicely into the
    229 learning experience - I didn't use other code to do the job (aside from
    230 looking at the sources, of-course).
    231 </Para>
    232 
    233 </Sect2>
    234 
    235 <Sect2>
    236 <Title>Jumping into the cold water</Title>
    237 
    238 <Para>
    239 I didn't know almost anything of the structure of the ext2 filesystem.
    240 Reading the sources was not enough - I needed to experiment. However, a tool
    241 for experiments in the ext2 filesystem was exactly my project! - Kind of a
    242 paradox.
    243 </Para>
    244 
    245 <Para>
    246 I started immediately with constructing a simple <Literal remap="tt">hex editor</Literal> - It would
    247 open the device as a regular file, provide means of moving inside the
    248 filesystem with a simple <Literal remap="tt">offset</Literal> method, and just show a
    249 <Literal remap="tt"> hex dump</Literal> of the contents at this point. Programming this was trivially
    250 simple of-course. At this point, the user-interface didn't matter to me - I
    251 wanted a fast way to interact. As a result, I chose a simple command line
    252 parser. Of course, there where no windows at this point.
    253 </Para>
    254 
    255 <Para>
    256 A hex editor is nice, but is not enough. It indeed enabled me to see each part
    257 of the filesystem, but the format of the viewed data was difficult to
    258 analyze. I wanted to see the data in a more intuitive way.
    259 </Para>
    260 
    261 <Para>
    262 At this point of time, the most helpful file in the sources was the ext2
    263 main include file - <Literal remap="tt">/usr/include/linux/ext2&lowbar;fs.h</Literal>. Among its contents
    264 there were various structures which I assumed they are disk images - Appear
    265 exactly like that on the disk.
    266 </Para>
    267 
    268 <Para>
    269 I wanted a <Literal remap="tt">quick</Literal> way to get going. I didn't have the patience to learn
    270 each of the structures use in the code. Rather, I wanted to see them in action,
    271 so that I could explore the connections between them - Test my assumptions,
    272 and reach other assumptions.
    273 </Para>
    274 
    275 <Para>
    276 So after the <Literal remap="tt">hex editor</Literal>, EXT2ED progressed into a tool which has some
    277 elements of a compiler. I programmed EXT2ED to <Literal remap="tt">dynamically read the kernel
    278 ext2 main include file in run time</Literal>, and process the information. The goal
    279 was to <Literal remap="tt">imply a structure-definition on the current offset at the
    280 filesystem</Literal>. EXT2ED would then display the structure as a list of its
    281 variables names and contents, instead of a meaningless hex dump.
    282 </Para>
    283 
    284 <Para>
    285 The format of the include file is not very complicated - The structures
    286 are mostly <Literal remap="tt">flat</Literal> - Didn't contain a lot of recursive structure; Only a
    287 global structure definition, and some variables. There were cases of
    288 structures inside structures, I treated them in a somewhat non-elegant way - I
    289 made all the structures flat, and expanded the arrays. As a result, the parser
    290 was very simple. After all, this was not an exercise in compiling, and I
    291 wanted to quickly get some results.
    292 </Para>
    293 
    294 <Para>
    295 To handle the task, I constructed the <Literal remap="tt">struct&lowbar;descriptor</Literal> structure.
    296 Each <Literal remap="tt">struct&lowbar;descriptor instance</Literal> contained information which is needed
    297 in order to format a block of data according to the C structure contained in 
    298 the kernel source. The information contained:
    299 
    300 <ItemizedList>
    301 <ListItem>
    302 
    303 <Para>
    304 	The descriptor name, used to reference to the structure in EXT2ED.
    305 </Para>
    306 </ListItem>
    307 <ListItem>
    308 
    309 <Para>
    310 	The name of each variable.
    311 </Para>
    312 </ListItem>
    313 <ListItem>
    314 
    315 <Para>
    316 	The relative offset of the each variable in the data block.
    317 </Para>
    318 </ListItem>
    319 <ListItem>
    320 
    321 <Para>
    322 	The length, in bytes, of each variable.
    323 </Para>
    324 </ListItem>
    325 
    326 </ItemizedList>
    327 
    328 Since I didn't want to limit the number of structures, I chose a simple
    329 double linked list to store the information. One variable contained the
    330 <Literal remap="tt">current structure type</Literal> - A pointer to the relevant
    331 <Literal remap="tt">struct&lowbar;descriptor</Literal>.
    332 </Para>
    333 
    334 <Para>
    335 Now EXT2ED contained basically three command line operations:
    336 
    337 <ItemizedList>
    338 <ListItem>
    339 
    340 <Para>
    341 	setdevice
    342 
    343 Used to open a device for reading only. Write access was postponed
    344 to a very advanced state in the project, simply because I didn't
    345 know a thing of the filesystem structure, and I believed that
    346 making actual changes would do nothing but damage :-)
    347 </Para>
    348 </ListItem>
    349 <ListItem>
    350 
    351 <Para>
    352 	setoffset
    353 
    354 Used to move in the device.
    355 </Para>
    356 </ListItem>
    357 <ListItem>
    358 
    359 <Para>
    360 	settype
    361 
    362 Used to imply a structure definition on the current place.
    363 </Para>
    364 </ListItem>
    365 <ListItem>
    366 
    367 <Para>
    368 	show
    369 
    370 Used to display the data. It displayed the data in a simple hex dump
    371 if there was no type set, or in a nice formatted way - As a list of
    372 the variable contents, if there was.
    373 </Para>
    374 </ListItem>
    375 
    376 </ItemizedList>
    377 
    378 </Para>
    379 
    380 <Para>
    381 Command line analyzing was primitive back then - A simple switch, as far as
    382 I can remember - Nothing alike the current flow control, but it was enough
    383 at the time.
    384 </Para>
    385 
    386 <Para>
    387 At the end, I had something to start working with. It knew to format many
    388 structures - None of which I understood - and provided me, without too much
    389 work, something to start with.
    390 </Para>
    391 
    392 </Sect2>
    393 
    394 </Sect1>
    395 
    396 <Sect1>
    397 <Title>Starting to explore</Title>
    398 
    399 <Para>
    400 With the above tool in my pocket, I started to explore the ext2 filesystem
    401 structure. From the brief reading in Bach's book, I got familiar to some
    402 basic concepts - The <Literal remap="tt">superblock</Literal>, for example. It seems that the
    403 superblock is an important part of the filesystem. I decided to start
    404 exploring with that.
    405 </Para>
    406 
    407 <Para>
    408 I realized that the superblock should be at a fixed location in the
    409 filesystem - Probably near the beginning. There can be no other way -
    410 The kernel should start at some place to find it. A brief looking in
    411 the kernel sources revealed that the superblock is signed by a special
    412 signature - A <Literal remap="tt">magic number</Literal> - EXT2&lowbar;SUPER&lowbar;MAGIC (0xEF53 - EF probably
    413 stands for Extended Filesystem). I quickly found the superblock at the
    414 fixed offset 1024 in the filesystem - The <Literal remap="tt">s&lowbar;magic</Literal> variable in the
    415 superblock was set exactly to the above value.
    416 </Para>
    417 
    418 <Para>
    419 It seems that starting with the <Literal remap="tt">superblock</Literal> was a good bet - Just from
    420 the list of variables, one can learn a lot. I didn't understand all of them
    421 at the time, but it seemed that the following keywords were repeating themself
    422 in various variables:
    423 
    424 <ItemizedList>
    425 <ListItem>
    426 
    427 <Para>
    428 	block
    429 </Para>
    430 </ListItem>
    431 <ListItem>
    432 
    433 <Para>
    434 	inode
    435 </Para>
    436 </ListItem>
    437 <ListItem>
    438 
    439 <Para>
    440 	group
    441 </Para>
    442 </ListItem>
    443 
    444 </ItemizedList>
    445 
    446 At this point, I started to explore the block groups. I will not detail here
    447 the technical design of the ext2 filesystem. I have written a special
    448 article which explains just that, in the "engineering" way. Please refer to it
    449 if you feel that you are lacking knowledge in the structure of the ext2
    450 filesystem.
    451 </Para>
    452 
    453 <Para>
    454 I was exploring the filesystem in this way for some time, along with reading
    455 the sources. This lead naturally to the next step.
    456 </Para>
    457 
    458 </Sect1>
    459 
    460 <Sect1>
    461 <Title>Object specific commands</Title>
    462 
    463 <Para>
    464 What has become clear is that the above way of exploring is not powerful
    465 enough - I found myself doing various calculations manually in order to pass
    466 between related structures. I needed to replace some tasks with an automated
    467 procedure.
    468 </Para>
    469 
    470 <Para>
    471 In addition, it also became clear that (of-course) each key object in the
    472 filesystem has its special place in regard to the overall ext2 filesystem
    473 design, and needs a <Literal remap="tt">fine tuned handling</Literal>. It is at this point that the
    474 structure definitions <Literal remap="tt">came to life</Literal> - They became <Literal remap="tt">object
    475 definitions</Literal>, making EXT2ED <Literal remap="tt">object oriented</Literal>.
    476 </Para>
    477 
    478 <Para>
    479 The actual meaning of the breathtaking words above, is that each structure
    480 now had a list of <Literal remap="tt">private commands</Literal>, which ended up in
    481 <Literal remap="tt">calling special fine-tuned C functions</Literal>. This approach was
    482 found to be very powerful and is <Literal remap="tt">the heart of EXT2ED even now</Literal>.
    483 </Para>
    484 
    485 <Para>
    486 In order to implement the above concepts, I added the structure
    487 <Literal remap="tt">struct&lowbar;commands</Literal>. The role of this structure is to group together a
    488 group of commands, which can be later assigned to a specific type. Each
    489 structure had:
    490 
    491 <ItemizedList>
    492 <ListItem>
    493 
    494 <Para>
    495 	A list of command names.
    496 </Para>
    497 </ListItem>
    498 <ListItem>
    499 
    500 <Para>
    501 	A list of pointers to functions, which binds each command to its
    502 special fine-tuned C function.
    503 </Para>
    504 </ListItem>
    505 
    506 </ItemizedList>
    507 
    508 In order to relate a list of commands to a type definition, each
    509 <Literal remap="tt">struct&lowbar;descriptor</Literal> structure (explained earlier) was added a private
    510 <Literal remap="tt">struct&lowbar;commands</Literal> structure.
    511 </Para>
    512 
    513 <Para>
    514 Follows the current definitions of <Literal remap="tt">struct&lowbar;descriptor</Literal> and of
    515 <Literal remap="tt">struct&lowbar;command</Literal>:
    516 
    517 <ProgramListing>
    518 struct struct_descriptor {
    519         unsigned long length;
    520         unsigned char name [60];
    521         unsigned short fields_num;
    522         unsigned char field_names [MAX_FIELDS][80];
    523         unsigned short field_lengths [MAX_FIELDS];
    524         unsigned short field_positions [MAX_FIELDS];
    525         struct struct_commands type_commands;
    526         struct struct_descriptor *prev,*next;
    527 };
    528 
    529 typedef void (*PF) (char *);
    530 
    531 struct struct_commands {
    532         int last_command;
    533         char *names [MAX_COMMANDS_NUM];
    534         char *descriptions [MAX_COMMANDS_NUM];
    535         PF callback [MAX_COMMANDS_NUM];
    536 };
    537 </ProgramListing>
    538 
    539 
    540 </Para>
    541 
    542 </Sect1>
    543 
    544 <Sect1 id="flow-control">
    545 <Title>Program flow control</Title>
    546 
    547 <Para>
    548 Obviously the above approach lead to a major redesign of EXT2ED. The
    549 main engine of the resulting design is basically the same even now.
    550 </Para>
    551 
    552 <Para>
    553 I redesigned the program flow control. Up to now, I analyzed the user command
    554 line with the simple switch method. Now I used the far superior callback
    555 method.
    556 </Para>
    557 
    558 <Para>
    559 I divided the available user commands into two groups:
    560 
    561 <OrderedList>
    562 <ListItem>
    563 
    564 <Para>
    565 	General commands.
    566 </Para>
    567 </ListItem>
    568 <ListItem>
    569 
    570 <Para>
    571 	Type specific commands.
    572 </Para>
    573 </ListItem>
    574 
    575 </OrderedList>
    576 
    577 As a result, at each point in time, the user was able to enter a
    578 <Literal remap="tt">general command</Literal>, selectable from a list of general commands which was
    579 always available, or a <Literal remap="tt">type specific command</Literal>, selectable from a list of
    580 commands which <Literal remap="tt">changed in time</Literal> according to the current type that the
    581 user was editing. The special <Literal remap="tt">type specific command</Literal> "knew" how to
    582 handle the object in the best possible way - It was "fine tuned" for the
    583 object's place in the ext2 filesystem design.
    584 </Para>
    585 
    586 <Para>
    587 In order to implement the above idea, I constructed a global variable of
    588 type <Literal remap="tt">struct&lowbar;commands</Literal>, which contained the <Literal remap="tt">general commands</Literal>.
    589 The <Literal remap="tt">type specific commands</Literal> were accessible through the <Literal remap="tt">struct
    590 descriptors</Literal>, as explained earlier.
    591 </Para>
    592 
    593 <Para>
    594 The program flow was now done according to the following algorithm:
    595 
    596 <OrderedList>
    597 <ListItem>
    598 
    599 <Para>
    600 	Ask the user for a command line.
    601 </Para>
    602 </ListItem>
    603 <ListItem>
    604 
    605 <Para>
    606 	Analyze the user command - Separate it into <Literal remap="tt">command</Literal> and
    607 <Literal remap="tt">arguments</Literal>.
    608 </Para>
    609 </ListItem>
    610 <ListItem>
    611 
    612 <Para>
    613 	Trace the list of known objects to match the command name to a type.
    614 If the type is found, call the callback function, with the arguments
    615 as a parameter. Then go back to step (1).
    616 </Para>
    617 </ListItem>
    618 <ListItem>
    619 
    620 <Para>
    621 	If the command is not type specific, try to find it in the general
    622 commands, and call it if found. Go back to step (1).
    623 </Para>
    624 </ListItem>
    625 <ListItem>
    626 
    627 <Para>
    628 	If the command is not found, issue a short error message, and return
    629 to step (1).
    630 </Para>
    631 </ListItem>
    632 
    633 </OrderedList>
    634 
    635 Note the <Literal remap="tt">order</Literal> of the above steps. In particular, note that a command
    636 is first assumed to be a type-specific command and only if this fails, a
    637 general command is searched. The "<Literal remap="tt">side-effect</Literal>" (main effect, actually)
    638 is that when we have two commands with the <Literal remap="tt">same name</Literal> - One that is a 
    639 type specific command, and one that is a general command, the dispatching
    640 algorithm will call the <Literal remap="tt">type specific command</Literal>. This allows
    641 <Literal remap="tt">overriding</Literal> of a command to provide <Literal remap="tt">fine-tuned</Literal> operation.
    642 For example, the <Literal remap="tt">show</Literal> command is overridden nearly everywhere,
    643 to accommodate for the different ways in which different objects are displayed,
    644 in order to provide an intuitive fine-tuned display.
    645 </Para>
    646 
    647 <Para>
    648 The above is done in the <Literal remap="tt">dispatch</Literal> function, in <Literal remap="tt">main.c</Literal>. Since
    649 it is a very important function in EXT2ED, and it is relatively short, I will
    650 list it entirely here. Note that a redesign was made since then - Another
    651 level was added between the two described, but I'll elaborate more on this
    652 later. However, the basic structure follows the explanation described above.
    653 
    654 <ProgramListing>
    655 int dispatch (char *command_line)
    656 
    657 {
    658 	int i,found=0;
    659 	char command [80];
    660 
    661 	parse_word (command_line,command);
    662 			
    663 	if (strcmp (command,"quit")==0) return (1);	
    664 
    665 	/* 1. Search for type specific commands FIRST - Allows overriding of a general command */
    666 
    667 	if (current_type != NULL)
    668 		for (i=0;i&#60;=current_type-&#62;type_commands.last_command &#38;&#38; !found;i++) {
    669 			if (strcmp (command,current_type-&#62;type_commands.names [i])==0) {
    670 				(*current_type-&#62;type_commands.callback [i]) (command_line);
    671 				found=1;
    672 			}
    673 		}
    674 
    675 	/* 2. Now search for ext2 filesystem general commands */
    676 
    677 	if (!found)
    678 		for (i=0;i&#60;=ext2_commands.last_command &#38;&#38; !found;i++) {
    679 			if (strcmp (command,ext2_commands.names [i])==0) {
    680 				(*ext2_commands.callback [i]) (command_line);
    681 				found=1;
    682 			}
    683 		}
    684 
    685 	
    686 	/* 3. If not found, search the general commands */
    687 	
    688 	if (!found)
    689 		for (i=0;i&#60;=general_commands.last_command &#38;&#38; !found;i++) {
    690 			if (strcmp (command,general_commands.names [i])==0) {
    691 				(*general_commands.callback [i]) (command_line);
    692 				found=1;
    693 			}
    694 		}
    695 
    696 	if (!found) {
    697 		wprintw (command_win,"Error: Unknown command\n");
    698 		refresh_command_win ();
    699 	}
    700 	
    701 	return (0);
    702 }
    703 </ProgramListing>
    704 
    705 </Para>
    706 
    707 </Sect1>
    708 
    709 <Sect1>
    710 <Title>Source files in EXT2ED</Title>
    711 
    712 <Para>
    713 The project was getting large enough to be splitted into several source
    714 files. I splitted the source as much as I could into self-contained
    715 source files. The source files consist of the following blocks:
    716 
    717 <ItemizedList>
    718 <ListItem>
    719 
    720 <Para>
    721 	<Literal remap="tt">Main include file - ext2ed.h</Literal>
    722 
    723 This file contains the definitions of the various structures,
    724 variables and functions used in EXT2ED. It is included by all source
    725 files in EXT2ED.
    726 
    727 </Para>
    728 </ListItem>
    729 <ListItem>
    730 
    731 <Para>
    732 	<Literal remap="tt">Main block - main.c</Literal>
    733 
    734 <Literal remap="tt">main.c</Literal> handles the upper level of the program flow control.
    735 It contains the <Literal remap="tt">parser</Literal> and the <Literal remap="tt">dispatcher</Literal>. Its task is
    736 to ask the user for a required action, and to pass control to other
    737 lower level functions in order to do the actual job.
    738 
    739 </Para>
    740 </ListItem>
    741 <ListItem>
    742 
    743 <Para>
    744 	<Literal remap="tt">Initialization - init.c</Literal>
    745 
    746 The init source is responsible for the various initialization
    747 actions which need to be done through the program. For example,
    748 auto detection of an ext2 filesystem when selecting a device and
    749 initialization of the filesystem-specific structures described
    750 earlier.
    751 
    752 </Para>
    753 </ListItem>
    754 <ListItem>
    755 
    756 <Para>
    757 	<Literal remap="tt">Disk activity - disk.c</Literal>
    758 
    759 <Literal remap="tt">disk.c</Literal> is handles the lower level interaction with the
    760 device. All disk activity is passed through this file - The various
    761 functions through the source code request disk actions from the
    762 functions in this file. In this way, for example, we can easily block
    763 the write access to the device.
    764 
    765 </Para>
    766 </ListItem>
    767 <ListItem>
    768 
    769 <Para>
    770 	<Literal remap="tt">Display output activity - win.c</Literal>
    771 	
    772 In a similar way to <Literal remap="tt">disk.c</Literal>, the user-interface functions and
    773 most of the interaction with the <Literal remap="tt">ncurses library</Literal> are done
    774 here. Nothing will be actually written to a specific window without
    775 calling a function from this file.
    776 
    777 </Para>
    778 </ListItem>
    779 <ListItem>
    780 
    781 <Para>
    782 	<Literal remap="tt">Commands available through dispatching - *&lowbar;com.c </Literal>
    783 
    784 The above file name is generic - Each file which ends with
    785 <Literal remap="tt">&lowbar;com.c</Literal> contains a group of related commands which can be
    786 called through <Literal remap="tt">the dispatching function</Literal>.
    787 
    788 Each object typically has its own file. A separate file is also
    789 available for the general commands.
    790 </Para>
    791 </ListItem>
    792 
    793 </ItemizedList>
    794 
    795 The entire list of source files available at this time is:
    796 
    797 <ItemizedList>
    798 <ListItem>
    799 
    800 <Para>
    801 	blockbitmap&lowbar;com.c
    802 </Para>
    803 </ListItem>
    804 <ListItem>
    805 
    806 <Para>
    807 	dir&lowbar;com.c
    808 </Para>
    809 </ListItem>
    810 <ListItem>
    811 
    812 <Para>
    813 	disk.c
    814 </Para>
    815 </ListItem>
    816 <ListItem>
    817 
    818 <Para>
    819 	ext2&lowbar;com.c
    820 </Para>
    821 </ListItem>
    822 <ListItem>
    823 
    824 <Para>
    825 	file&lowbar;com.c
    826 </Para>
    827 </ListItem>
    828 <ListItem>
    829 
    830 <Para>
    831 	general&lowbar;com.c
    832 </Para>
    833 </ListItem>
    834 <ListItem>
    835 
    836 <Para>
    837 	group&lowbar;com.c
    838 </Para>
    839 </ListItem>
    840 <ListItem>
    841 
    842 <Para>
    843 	init.c
    844 </Para>
    845 </ListItem>
    846 <ListItem>
    847 
    848 <Para>
    849 	inode&lowbar;com.c
    850 </Para>
    851 </ListItem>
    852 <ListItem>
    853 
    854 <Para>
    855 	inodebitmap&lowbar;com.c
    856 </Para>
    857 </ListItem>
    858 <ListItem>
    859 
    860 <Para>
    861 	main.c
    862 </Para>
    863 </ListItem>
    864 <ListItem>
    865 
    866 <Para>
    867 	super&lowbar;com.c
    868 </Para>
    869 </ListItem>
    870 <ListItem>
    871 
    872 <Para>
    873 	win.c
    874 </Para>
    875 </ListItem>
    876 
    877 </ItemizedList>
    878 
    879 </Para>
    880 
    881 </Sect1>
    882 
    883 <Sect1>
    884 <Title>User interface</Title>
    885 
    886 <Para>
    887 The user interface is text-based only and is based on the following
    888 libraries:
    889 </Para>
    890 
    891 <Para>
    892 
    893 <ItemizedList>
    894 <ListItem>
    895 
    896 <Para>
    897 	The <Literal remap="tt">ncurses</Literal> library, developed by <Literal remap="tt">Zeyd Ben-Halim</Literal>.
    898 </Para>
    899 </ListItem>
    900 <ListItem>
    901 
    902 <Para>
    903 	The <Literal remap="tt">GNU readline</Literal> library.
    904 </Para>
    905 </ListItem>
    906 
    907 </ItemizedList>
    908 
    909 </Para>
    910 
    911 <Para>
    912 The user interaction is command line based - The user enters a command
    913 line, which consists of a <Literal remap="tt">command</Literal> and of <Literal remap="tt">arguments</Literal>. This fits
    914 nicely with the program flow control described earlier - The <Literal remap="tt">command</Literal>
    915 is used by <Literal remap="tt">dispatch</Literal> to select the right function, and the
    916 <Literal remap="tt">arguments</Literal> are interpreted by the function itself.
    917 </Para>
    918 
    919 <Sect2>
    920 <Title>The ncurses library</Title>
    921 
    922 <Para>
    923 The <Literal remap="tt">ncurses</Literal> library enables me to divide the screen into "windows".
    924 The main advantage is that I treat the "window" in a virtual way, asking
    925 the ncurses library to "write to a window". However, the ncurses
    926 library internally buffers the requests, and nothing is actually passed to the
    927 terminal until an explicit refresh is requested. When the refresh request is
    928 made, ncurses compares the current terminal state (as known in the last time
    929 that a refresh was done) with the new to be shown state, and passes to the
    930 terminal the minimal information required to update the display. As a
    931 result, the display output is optimized behind the scenes by the
    932 <Literal remap="tt">ncurses</Literal> library, while I can still treat it in a virtual way.
    933 </Para>
    934 
    935 <Para>
    936 There are two basic concepts in the <Literal remap="tt">ncurses</Literal> library:
    937 
    938 <ItemizedList>
    939 <ListItem>
    940 
    941 <Para>
    942 	A window.
    943 </Para>
    944 </ListItem>
    945 <ListItem>
    946 
    947 <Para>
    948 	A pad.
    949 </Para>
    950 </ListItem>
    951 
    952 </ItemizedList>
    953 
    954 A window can be no bigger than the actual terminal size. A pad, however, is
    955 not limited in its size.
    956 </Para>
    957 
    958 <Para>
    959 The user screen is divided by EXT2ED into three windows and one pad:
    960 
    961 <ItemizedList>
    962 <ListItem>
    963 
    964 <Para>
    965 	Title window.
    966 </Para>
    967 </ListItem>
    968 <ListItem>
    969 
    970 <Para>
    971 	Status window.
    972 </Para>
    973 </ListItem>
    974 <ListItem>
    975 
    976 <Para>
    977 	Main display pad.
    978 </Para>
    979 </ListItem>
    980 <ListItem>
    981 
    982 <Para>
    983 	Command window.
    984 </Para>
    985 </ListItem>
    986 
    987 </ItemizedList>
    988 
    989 </Para>
    990 
    991 <Para>
    992 The <Literal remap="tt">title window</Literal> is static - It just displays the current version
    993 of EXT2ED.
    994 </Para>
    995 
    996 <Para>
    997 The user interaction is done in the <Literal remap="tt">command window</Literal>. The user enters a
    998 <Literal remap="tt">command line</Literal>, feedback is usually displayed there, and then relevant
    999 data is usually displayed in the main display and in the status window.
   1000 </Para>
   1001 
   1002 <Para>
   1003 The <Literal remap="tt">main display</Literal> is using a <Literal remap="tt">pad</Literal> instead of a window because
   1004 the amount of information which is written to it is not known in advance.
   1005 Therefor, the user treats the main display as a "window" into a bigger
   1006 display and can <Literal remap="tt">scroll vertically</Literal> using the <Literal remap="tt">pgdn</Literal> and <Literal remap="tt">pgup</Literal>
   1007 commands. Although the <Literal remap="tt">pad</Literal> mechanism enables me to use horizontal
   1008 scrolling, I have not utilized this.
   1009 </Para>
   1010 
   1011 <Para>
   1012 When I need to show something to the user, I use the ncurses <Literal remap="tt">wprintw</Literal>
   1013 command. Then an explicit refresh command is required. As explained before,
   1014 the refresh commands is piped through <Literal remap="tt">win.c</Literal>. For example, to update
   1015 the command window, <Literal remap="tt">refresh&lowbar;command&lowbar;win ()</Literal> is used.
   1016 </Para>
   1017 
   1018 </Sect2>
   1019 
   1020 <Sect2>
   1021 <Title>The readline library</Title>
   1022 
   1023 <Para>
   1024 Avner suggested me to integrate the GNU <Literal remap="tt">readline</Literal> library in my project.
   1025 The <Literal remap="tt">readline</Literal> library is designed specifically for programs which use
   1026 command line interface. It provides a nice package of <Literal remap="tt">command line editing
   1027 tools</Literal> - Inserting, deleting words, and the whole package of editing tools
   1028 which are normally available in the <Literal remap="tt">bash</Literal> shell (Refer to the readline
   1029 documentation for details). In addition, I utilized the <Literal remap="tt">history</Literal>
   1030 feature of the readline library - The entered commands are saved in a
   1031 <Literal remap="tt">command history</Literal>, and can be called later by whatever means that the
   1032 readline package provides. Command completion is also supported - When the
   1033 user enters a partial command name, EXT2ED will provide the readline library
   1034 with the possible completions.
   1035 </Para>
   1036 
   1037 </Sect2>
   1038 
   1039 </Sect1>
   1040 
   1041 <Sect1>
   1042 <Title>Possible support of other filesystems</Title>
   1043 
   1044 <Para>
   1045 The entire ext2 layer is provided through specific objects. Given another
   1046 set of objects, support of other filesystem can be provided using the same
   1047 dispatching mechanism. In order to prepare the surface for this option, I
   1048 added yet another layer to the two-layer structure presented earlier. EXT2ED
   1049 commands now consist of three layers:
   1050 
   1051 <ItemizedList>
   1052 <ListItem>
   1053 
   1054 <Para>
   1055 	The general commands.
   1056 </Para>
   1057 </ListItem>
   1058 <ListItem>
   1059 
   1060 <Para>
   1061 	The ext2 general commands.
   1062 </Para>
   1063 </ListItem>
   1064 <ListItem>
   1065 
   1066 <Para>
   1067 	The ext2 object specific commands.
   1068 </Para>
   1069 </ListItem>
   1070 
   1071 </ItemizedList>
   1072 
   1073 The general commands are provided by the <Literal remap="tt">general&lowbar;com.c</Literal> source file,
   1074 and are always available. The two other levels are not present when EXT2ED
   1075 loads - They are dynamically added by <Literal remap="tt">init.c</Literal> when EXT2ED detects an
   1076 ext2 filesystem on the device.
   1077 </Para>
   1078 
   1079 <Para>
   1080 The abstraction levels presented above helps to extend EXT2ED to fully
   1081 support a new filesystem, with its own specific type commands. 
   1082 </Para>
   1083 
   1084 <Para>
   1085 Even without any source code modification, the user is free to add structure
   1086 definitions in a separate file (specified in the configuration file), 
   1087 which will be added to the list of available objects. The added objects will
   1088 consist only of variables, of-course, and will be used through the more
   1089 primitive <Literal remap="tt">setoffset</Literal> and <Literal remap="tt">settype</Literal> commands.
   1090 </Para>
   1091 
   1092 </Sect1>
   1093 
   1094 <Sect1>
   1095 <Title>On the implementation of the various commands</Title>
   1096 
   1097 <Para>
   1098 This section points out some typical programming style that I used in many
   1099 places at the code.
   1100 </Para>
   1101 
   1102 <Sect2>
   1103 <Title>The explicit use of the dispatch function</Title>
   1104 
   1105 <Para>
   1106 The various commands are reached by the user through the <Literal remap="tt">dispatch</Literal>
   1107 function. This is not surprising. The fact that can be surprising, at least in
   1108 a first look, is that <Literal remap="tt">you'll find the dispatch call in many of my
   1109 own functions!</Literal>.
   1110 </Para>
   1111 
   1112 <Para>
   1113 I am in fact using my own implemented functions to construct higher
   1114 level operations. I am heavily using the fact that the dispatching mechanism
   1115 is object oriented ant that the <Literal remap="tt">overriding</Literal> principle takes place and
   1116 selects the proper function to call when several commands with the same name
   1117 are accessible.
   1118 </Para>
   1119 
   1120 <Para>
   1121 Sometimes, however, I call the explicit command directly, without passing
   1122 through <Literal remap="tt">dispatch</Literal>. This is typically done when I want to bypass the
   1123 <Literal remap="tt">overriding</Literal> effect.
   1124 </Para>
   1125 
   1126 <Para>
   1127 
   1128 This is used, for example, in the interaction between the global cd command
   1129 and the dir object specific cd command. You will see there that in order
   1130 to implement the "entire" cd command, the type specific cd command uses both
   1131 a dispatching mechanism to call itself recursively if a relative path is
   1132 used, or a direct call of the general cd handling function if an explicit path
   1133 is used.
   1134 
   1135 </Para>
   1136 
   1137 </Sect2>
   1138 
   1139 <Sect2>
   1140 <Title>Passing information between handling functions</Title>
   1141 
   1142 <Para>
   1143 Typically, every source code file which handles one object type has a global
   1144 structure specifically designed for it which is used by most of the
   1145 functions in that file. This is used to pass information between the various
   1146 functions there, and to physically provide the link to other related
   1147 objects, typically for initialization use.
   1148 </Para>
   1149 
   1150 <Para>
   1151 
   1152 For example, in order to edit a file, information about the
   1153 inode is needed - The file command is available only when editing an
   1154 inode. When the file command is issued, the handling function (found,
   1155 according to the source division outlined above, in inode_com.c) will
   1156 store the necessary information about the inode in a specific structure
   1157 of type struct_file_info which will be available for use by the file_com.c
   1158 functions. Only then it will set the type to file. This is also the reason
   1159 that a direct asynchronic set of the object type to a file through a settype
   1160 command will fail - The above data structure will not be initialized
   1161 properly because the user never was at the inode of the file. 
   1162 
   1163 </Para>
   1164 
   1165 </Sect2>
   1166 
   1167 <Sect2>
   1168 <Title>A very simplified overview of a typical command handling function</Title>
   1169 
   1170 <Para>
   1171 This is a very simplified overview. Detailed information will follow
   1172 where appropriate.
   1173 </Para>
   1174 
   1175 <Sect3>
   1176 <Title>The prototype of a typical handling function</Title>
   1177 
   1178 <Para>
   1179 
   1180 <OrderedList>
   1181 <ListItem>
   1182 
   1183 <Para>
   1184  	I chose a unified <Literal remap="tt">naming convention</Literal> for the various object
   1185 specific commands. It is perhaps best showed with an example:
   1186 
   1187 The prototype of the handling function of the command <Literal remap="tt">next</Literal> of
   1188 the type <Literal remap="tt">file</Literal> is:
   1189 
   1190 <Screen>
   1191 		extern void type_file___next (char *command_line);
   1192 	
   1193 </Screen>
   1194 
   1195 
   1196 For other types and commands, the words <Literal remap="tt">file</Literal> and <Literal remap="tt">next</Literal>
   1197 should 	be replaced accordingly.
   1198 
   1199 </Para>
   1200 </ListItem>
   1201 <ListItem>
   1202 
   1203 <Para>
   1204 	The ext2 general commands syntax is similar. For example, the ext2
   1205 general command <Literal remap="tt">super</Literal> results in calling:
   1206 
   1207 <Screen>
   1208 		extern void type_ext2___super (char *command_line);
   1209 	
   1210 </Screen>
   1211 
   1212 Those functions are available in <Literal remap="tt">ext2&lowbar;com.c</Literal>.
   1213 </Para>
   1214 </ListItem>
   1215 <ListItem>
   1216 
   1217 <Para>
   1218 	The general commands syntax is even simpler - The name of the
   1219 handling function is exactly the name of the commands. Those
   1220 functions are available in <Literal remap="tt">general&lowbar;com.c</Literal>.
   1221 </Para>
   1222 </ListItem>
   1223 
   1224 </OrderedList>
   1225 
   1226 </Para>
   1227 
   1228 </Sect3>
   1229 
   1230 <Sect3>
   1231 <Title>"Typical" algorithm</Title>
   1232 
   1233 <Para>
   1234 This section can't of-course provide meaningful information - Each
   1235 command is handled differently, but the following frame is typical:
   1236 
   1237 <OrderedList>
   1238 <ListItem>
   1239 
   1240 <Para>
   1241 	Parse command line arguments and analyze them. Return with an error
   1242 message if the syntax is wrong.
   1243 </Para>
   1244 </ListItem>
   1245 <ListItem>
   1246 
   1247 <Para>
   1248 	"Act accordingly", perhaps making use of the global variable available
   1249 to this type.
   1250 </Para>
   1251 </ListItem>
   1252 <ListItem>
   1253 
   1254 <Para>
   1255 	Use some <Literal remap="tt">dispatch / direct </Literal> calls in order to pass control to
   1256 other lower-level user commands.
   1257 </Para>
   1258 </ListItem>
   1259 <ListItem>
   1260 
   1261 <Para>
   1262 	Sometimes <Literal remap="tt">dispatch</Literal> to the object's <Literal remap="tt">show</Literal> command to
   1263 display the resulting data to the user.
   1264 </Para>
   1265 </ListItem>
   1266 
   1267 </OrderedList>
   1268 
   1269 I told you it is meaningless :-)
   1270 </Para>
   1271 
   1272 </Sect3>
   1273 
   1274 </Sect2>
   1275 
   1276 </Sect1>
   1277 
   1278 <Sect1>
   1279 <Title>Initialization overview</Title>
   1280 
   1281 <Para>
   1282 In this section I will discuss some aspects of the various initialization
   1283 routines available in the source file <Literal remap="tt">init.c</Literal>.
   1284 </Para>
   1285 
   1286 <Sect2>
   1287 <Title>Upon startup</Title>
   1288 
   1289 <Para>
   1290 Follows the function <Literal remap="tt">main</Literal>, appearing of-course in <Literal remap="tt">main.c</Literal>:
   1291 
   1292 
   1293 <ProgramListing>
   1294 int main (void)
   1295 
   1296 {
   1297 	if (!init ()) return (0);	/* Perform some initial initialization */
   1298 					/* Quit if failed */
   1299 
   1300 	parser ();			/* Get and parse user commands */
   1301 	
   1302 	prepare_to_close ();		/* Do some cleanup */
   1303 	printf ("Quitting ...\n");
   1304 	return (1);			/* And quit */
   1305 }
   1306 </ProgramListing>
   1307 
   1308 </Para>
   1309 
   1310 <Para>
   1311 The two initialization functions, which are called by <Literal remap="tt">main</Literal>, are:
   1312 
   1313 <ItemizedList>
   1314 <ListItem>
   1315 
   1316 <Para>
   1317 	init
   1318 </Para>
   1319 </ListItem>
   1320 <ListItem>
   1321 
   1322 <Para>
   1323 	prepare&lowbar;to&lowbar;close
   1324 </Para>
   1325 </ListItem>
   1326 
   1327 </ItemizedList>
   1328 
   1329 </Para>
   1330 
   1331 <Sect3>
   1332 <Title>The init function</Title>
   1333 
   1334 <Para>
   1335 <Literal remap="tt">init</Literal> is called from <Literal remap="tt">main</Literal> upon startup. It initializes the
   1336 following tasks / subsystems:
   1337 
   1338 <OrderedList>
   1339 <ListItem>
   1340 
   1341 <Para>
   1342 	Processing of the <Literal remap="tt">user configuration file</Literal>, by using the
   1343 <Literal remap="tt">process&lowbar;configuration&lowbar;file</Literal> function. Failing to complete the
   1344 configuration file processing is considered a <Literal remap="tt">fatal error</Literal>,
   1345 and EXT2ED is aborted. I did it this way because the configuration
   1346 file has some sensitive user options like write access behavior, and
   1347 I wanted to be sure that the user is aware of them.
   1348 </Para>
   1349 </ListItem>
   1350 <ListItem>
   1351 
   1352 <Para>
   1353 	Registration of the <Literal remap="tt">general commands</Literal> through the use of
   1354 the <Literal remap="tt">add&lowbar;general&lowbar;commands</Literal> function.
   1355 </Para>
   1356 </ListItem>
   1357 <ListItem>
   1358 
   1359 <Para>
   1360 	Reset of the object memory rotating lifo structure.
   1361 </Para>
   1362 </ListItem>
   1363 <ListItem>
   1364 
   1365 <Para>
   1366 	Reset of the device parameters and of the current type.
   1367 </Para>
   1368 </ListItem>
   1369 <ListItem>
   1370 
   1371 <Para>
   1372 	Initialization of the windows subsystem - The interface between the
   1373 ncurses library and EXT2ED, through the use of the <Literal remap="tt">init&lowbar;windows</Literal>
   1374 function, available in <Literal remap="tt">win.c</Literal>.
   1375 </Para>
   1376 </ListItem>
   1377 <ListItem>
   1378 
   1379 <Para>
   1380 	Initialization of the interface between the readline library and
   1381 EXT2ED, through <Literal remap="tt">init&lowbar;readline</Literal>.
   1382 </Para>
   1383 </ListItem>
   1384 <ListItem>
   1385 
   1386 <Para>
   1387 	Initialization of the <Literal remap="tt">signals</Literal> subsystem, through
   1388 <Literal remap="tt">init&lowbar;signals</Literal>.
   1389 </Para>
   1390 </ListItem>
   1391 <ListItem>
   1392 
   1393 <Para>
   1394 	Disabling write access. Write access needs to be explicitly enabled
   1395 using a user command, to prevent accidental user mistakes.
   1396 </Para>
   1397 </ListItem>
   1398 
   1399 </OrderedList>
   1400 
   1401 When <Literal remap="tt">init</Literal> is finished, it dispatches the <Literal remap="tt">help</Literal> command in order
   1402 to show the available commands to the user. Note that the ext2 layer is still
   1403 not added; It will be added if and when EXT2ED will detect an ext2
   1404 filesystem on a device.
   1405 </Para>
   1406 
   1407 </Sect3>
   1408 
   1409 <Sect3>
   1410 <Title>The prepare&lowbar;to&lowbar;close function</Title>
   1411 
   1412 <Para>
   1413 The <Literal remap="tt">prepare&lowbar;to&lowbar;close</Literal> function reverses some of the actions done
   1414 earlier in EXT2ED and freeing the dynamically allocated memory.
   1415 Specifically, it:
   1416 
   1417 <OrderedList>
   1418 <ListItem>
   1419 
   1420 <Para>
   1421 	Closes the open device, if any.
   1422 </Para>
   1423 </ListItem>
   1424 <ListItem>
   1425 
   1426 <Para>
   1427 	Removes the first level - Removing the general commands, through
   1428 the use of <Literal remap="tt">free&lowbar;user&lowbar;commands</Literal>, with a pointer to the
   1429 general&lowbar;commands structure as a parameter.
   1430 </Para>
   1431 </ListItem>
   1432 <ListItem>
   1433 
   1434 <Para>
   1435 	Removes of the second level - Removing the ext2 ext2 general
   1436 commands, in much the same way.
   1437 </Para>
   1438 </ListItem>
   1439 <ListItem>
   1440 
   1441 <Para>
   1442 	Removes of the third level - Removing the objects and the object
   1443 specific commands, by using <Literal remap="tt">free&lowbar;struct&lowbar;descriptors</Literal>.
   1444 </Para>
   1445 </ListItem>
   1446 <ListItem>
   1447 
   1448 <Para>
   1449 	Closes the window subsystem, and deattaches EXT2ED from the ncurses
   1450 library, through the use of the <Literal remap="tt">close&lowbar;windows</Literal> function,
   1451 available in <Literal remap="tt">win.c</Literal>.
   1452 </Para>
   1453 </ListItem>
   1454 
   1455 </OrderedList>
   1456 
   1457 </Para>
   1458 
   1459 </Sect3>
   1460 
   1461 </Sect2>
   1462 
   1463 <Sect2>
   1464 <Title>Registration of commands</Title>
   1465 
   1466 <Para>
   1467 Addition of a user command is done through the <Literal remap="tt">add&lowbar;user&lowbar;command</Literal>
   1468 function. The prototype is:
   1469 
   1470 <Screen>
   1471 void add_user_command (struct struct_commands *ptr,char *name,char
   1472 *description,PF callback);
   1473 </Screen>
   1474 
   1475 The function receives a pointer to a structure of type
   1476 <Literal remap="tt">struct&lowbar;commands</Literal>, a desired name for the command which will be used by
   1477 the user to identify the command, a short description which is utilized by the
   1478 <Literal remap="tt">help</Literal> subsystem, and a pointer to a C function which will be called if
   1479 <Literal remap="tt">dispatch</Literal> decides that this command was requested.
   1480 </Para>
   1481 
   1482 <Para>
   1483 The <Literal remap="tt">add&lowbar;user&lowbar;command</Literal> is a <Literal remap="tt">low level function</Literal> used in the three
   1484 levels to add user commands. For example, addition of the <Literal remap="tt">ext2
   1485 general commands is done by:</Literal>
   1486 
   1487 <ProgramListing>
   1488 void add_ext2_general_commands (void)
   1489 
   1490 {
   1491 	add_user_command (&amp;ext2_commands,"super","Moves to the superblock of the filesystem",type_ext2___super);
   1492 	add_user_command (&amp;ext2_commands,"group","Moves to the first group descriptor",type_ext2___group);
   1493 	add_user_command (&amp;ext2_commands,"cd","Moves to the directory specified",type_ext2___cd);
   1494 }
   1495 </ProgramListing>
   1496 
   1497 </Para>
   1498 
   1499 </Sect2>
   1500 
   1501 <Sect2>
   1502 <Title>Registration of objects</Title>
   1503 
   1504 <Para>
   1505 Registration of objects is based, as explained earlier, on the "compilation"
   1506 of an external user file, which has a syntax similar to the C language
   1507 <Literal remap="tt">struct</Literal> keyword. The primitive parser I have implemented detects the
   1508 definition of structures, and calls some lower level functions to actually
   1509 register the new detected object. The parser's prototype is:
   1510 
   1511 <Screen>
   1512 int set_struct_descriptors (char *file_name)
   1513 </Screen>
   1514 
   1515 It opens the given file name, and calls, when appropriate:
   1516 
   1517 <ItemizedList>
   1518 <ListItem>
   1519 
   1520 <Para>
   1521 	add&lowbar;new&lowbar;descriptor
   1522 </Para>
   1523 </ListItem>
   1524 <ListItem>
   1525 
   1526 <Para>
   1527 	add&lowbar;new&lowbar;variable
   1528 </Para>
   1529 </ListItem>
   1530 
   1531 </ItemizedList>
   1532 
   1533 <Literal remap="tt">add&lowbar;new&lowbar;descriptor</Literal> is a low level function which adds a new descriptor
   1534 to the doubly linked list of the available objects. It will then call
   1535 <Literal remap="tt">fill&lowbar;type&lowbar;commands</Literal>, which will add specific commands to the object,
   1536 if the object is known.
   1537 </Para>
   1538 
   1539 <Para>
   1540 <Literal remap="tt">add&lowbar;new&lowbar;variable</Literal> will add a new variable of the requested length to the
   1541 specified descriptor.
   1542 </Para>
   1543 
   1544 </Sect2>
   1545 
   1546 <Sect2>
   1547 <Title>Initialization upon specification of a device</Title>
   1548 
   1549 <Para>
   1550 When the general command <Literal remap="tt">setdevice</Literal> is used to open a device, some
   1551 initialization sequence takes place, which is intended to determine two
   1552 factors:
   1553 
   1554 <ItemizedList>
   1555 <ListItem>
   1556 
   1557 <Para>
   1558 	Are we dealing with an ext2 filesystem ?
   1559 </Para>
   1560 </ListItem>
   1561 <ListItem>
   1562 
   1563 <Para>
   1564 	What are the basic filesystem parameters, such as its total size and
   1565 its block size ?
   1566 </Para>
   1567 </ListItem>
   1568 
   1569 </ItemizedList>
   1570 
   1571 This questions are answered by the <Literal remap="tt">set&lowbar;file&lowbar;system&lowbar;info</Literal>, possibly
   1572 using some <Literal remap="tt">help from the user</Literal>, through the configuration file.
   1573 The answers are placed in the <Literal remap="tt">file&lowbar;system&lowbar;info</Literal> structure, which is of
   1574 type <Literal remap="tt">struct&lowbar;file&lowbar;system&lowbar;info</Literal>:
   1575 
   1576 <ProgramListing>
   1577 struct struct_file_system_info {
   1578 	unsigned long file_system_size;
   1579 	unsigned long super_block_offset;
   1580 	unsigned long first_group_desc_offset;
   1581 	unsigned long groups_count;
   1582 	unsigned long inodes_per_block;
   1583 	unsigned long blocks_per_group;		/* The name is misleading; beware */
   1584 	unsigned long no_blocks_in_group;
   1585 	unsigned short block_size;
   1586 	struct ext2_super_block super_block;
   1587 };
   1588 </ProgramListing>
   1589 
   1590 </Para>
   1591 
   1592 <Para>
   1593 Autodetection of an ext2 filesystem is usually recommended. However, on a damaged
   1594 filesystem I can't assure a success. That's were the user comes in - He can
   1595 <Literal remap="tt">override</Literal> the auto detection procedure and force an ext2 filesystem, by
   1596 selecting the proper options in the configuration file.
   1597 </Para>
   1598 
   1599 <Para>
   1600 If auto detection succeeds, the second question above is automatically
   1601 answered - I get all the information I need from the filesystem itself. In
   1602 any case, default parameters can be supplied in the configuration file and
   1603 the user can select the required behavior.
   1604 </Para>
   1605 
   1606 <Para>
   1607 If we decide to treat the filesystem as an ext2 filesystem, <Literal remap="tt">registration of
   1608 the ext2 specific objects</Literal> is done at this point, by calling the
   1609 <Literal remap="tt">set&lowbar;struct&lowbar;descriptors</Literal> outlined earlier, with the name of the file
   1610 which describes the ext2 objects, and is basically based on the ext2 sources
   1611 main include file. At this point, EXT2ED can be fully used by the user.
   1612 </Para>
   1613 
   1614 <Para>
   1615 If we do not register the ext2 specific objects, the user can still provide
   1616 object definitions in a separate file, and will be able to use EXT2ED in a
   1617 <Literal remap="tt">limited form</Literal>, but more sophisticated than a simple hex editor.
   1618 </Para>
   1619 
   1620 </Sect2>
   1621 
   1622 </Sect1>
   1623 
   1624 <Sect1>
   1625 <Title>main.c</Title>
   1626 
   1627 <Para>
   1628 As described earlier, <Literal remap="tt">main.c</Literal> is used as a front-head to the entire
   1629 program. <Literal remap="tt">main.c</Literal> contains the following elements:
   1630 </Para>
   1631 
   1632 <Sect2>
   1633 <Title>The main routine</Title>
   1634 
   1635 <Para>
   1636 The <Literal remap="tt">main</Literal> routine was displayed above. Its task is to pass control to
   1637 the initialization routines and to the parser.
   1638 </Para>
   1639 
   1640 </Sect2>
   1641 
   1642 <Sect2>
   1643 <Title>The parser</Title>
   1644 
   1645 <Para>
   1646 The parser consists of the following functions:
   1647 
   1648 <ItemizedList>
   1649 <ListItem>
   1650 
   1651 <Para>
   1652 	The <Literal remap="tt">parser</Literal> function, which reads the command line from the
   1653 user and saves it in readline's history buffer and in the internal
   1654 last-command buffer.
   1655 </Para>
   1656 </ListItem>
   1657 <ListItem>
   1658 
   1659 <Para>
   1660 	The <Literal remap="tt">parse&lowbar;word</Literal> function, which receives a string and parses
   1661 the first word from it, ignoring whitespaces, and returns a pointer
   1662 to the rest of the string.
   1663 </Para>
   1664 </ListItem>
   1665 <ListItem>
   1666 
   1667 <Para>
   1668 	The <Literal remap="tt">complete&lowbar;command</Literal> function, which is used by the readline
   1669 library for command completion. It scans the available commands at
   1670 this point and determines the possible completions.
   1671 </Para>
   1672 </ListItem>
   1673 
   1674 </ItemizedList>
   1675 
   1676 </Para>
   1677 
   1678 </Sect2>
   1679 
   1680 <Sect2>
   1681 <Title>The dispatcher</Title>
   1682 
   1683 <Para>
   1684 The dispatcher was already explained in the flow control section - section
   1685 <XRef LinkEnd="flow-control">. Its task is to pass control to the proper command
   1686 handling function, based on the command line's command.
   1687 </Para>
   1688 
   1689 </Sect2>
   1690 
   1691 <Sect2>
   1692 <Title>The self-sanity control</Title>
   1693 
   1694 <Para>
   1695 This is not fully implemented.
   1696 </Para>
   1697 
   1698 <Para>
   1699 The general idea was to provide a control system which will supervise the
   1700 internal work of EXT2ED. Since I am pretty sure that bugs exist, I have
   1701 double checked myself in a few instances, and issued an <Literal remap="tt">internal
   1702 error</Literal> warning if I reached the conclusion that something is not logical.
   1703 The internal error is reported by the function <Literal remap="tt">internal&lowbar;error</Literal>,
   1704 available in <Literal remap="tt">main.c</Literal>. 
   1705 </Para>
   1706 
   1707 <Para>
   1708 The self sanity check is compiled only if the compile time option
   1709 <Literal remap="tt">DEBUG</Literal> is selected.
   1710 </Para>
   1711 
   1712 </Sect2>
   1713 
   1714 </Sect1>
   1715 
   1716 <Sect1>
   1717 <Title>The windows interface</Title>
   1718 
   1719 <Para>
   1720 Screen handling and interfacing to the <Literal remap="tt">ncurses</Literal> library is done in
   1721 <Literal remap="tt">win.c</Literal>.
   1722 </Para>
   1723 
   1724 <Sect2>
   1725 <Title>Initialization</Title>
   1726 
   1727 <Para>
   1728 Opening of the windows is done in <Literal remap="tt">init&lowbar;windows</Literal>. In
   1729 <Literal remap="tt">close&lowbar;windows</Literal>, we just close our windows. The various window lengths
   1730 with an exception to the <Literal remap="tt">show pad</Literal> are defined in the main header file.
   1731 The rest of the display will be used by the <Literal remap="tt">show pad</Literal>.
   1732 </Para>
   1733 
   1734 </Sect2>
   1735 
   1736 <Sect2>
   1737 <Title>Display output</Title>
   1738 
   1739 <Para>
   1740 Each actual refreshing of the terminal monitor is done by using the
   1741 appropriate refresh function from this file: <Literal remap="tt">refresh&lowbar;title&lowbar;win</Literal>,
   1742 <Literal remap="tt">refresh&lowbar;show&lowbar;win</Literal>, <Literal remap="tt">refresh&lowbar;show&lowbar;pad</Literal> and
   1743 <Literal remap="tt">refresh&lowbar;command&lowbar;win</Literal>.
   1744 </Para>
   1745 
   1746 <Para>
   1747 With the exception of the <Literal remap="tt">show pad</Literal>, each function simply calls the
   1748 <Literal remap="tt">ncurses refresh command</Literal>. In order to provide to <Literal remap="tt">scrolling</Literal> in
   1749 the <Literal remap="tt">show pad</Literal>, some information about its status is constantly updated
   1750 by the various functions which display output in it. <Literal remap="tt">refresh&lowbar;show&lowbar;pad</Literal>
   1751 passes this information to <Literal remap="tt">ncurses</Literal> so that the correct part of the pad
   1752 is actually copied to the display.
   1753 </Para>
   1754 
   1755 <Para>
   1756 The above information is saved in a global variable of type <Literal remap="tt">struct
   1757 struct&lowbar;pad&lowbar;info</Literal>:
   1758 </Para>
   1759 
   1760 <Para>
   1761 
   1762 <ProgramListing>
   1763 struct struct_pad_info {
   1764 	int display_lines,display_cols;
   1765 	int line,col;
   1766 	int max_line,max_col;
   1767 	int disable_output;
   1768 };
   1769 </ProgramListing>
   1770 
   1771 </Para>
   1772 
   1773 </Sect2>
   1774 
   1775 <Sect2>
   1776 <Title>Screen redraw</Title>
   1777 
   1778 <Para>
   1779 The <Literal remap="tt">redraw&lowbar;all</Literal> function will just reopen the windows. This action is
   1780 necessary if the display gets garbled from some reason.
   1781 </Para>
   1782 
   1783 </Sect2>
   1784 
   1785 </Sect1>
   1786 
   1787 <Sect1>
   1788 <Title>The disk interface</Title>
   1789 
   1790 <Para>
   1791 All the disk activity with regard to the filesystem passes through the file
   1792 <Literal remap="tt">disk.c</Literal>. This is done that way to provide additional levels of safety
   1793 concerning the disk access. This way, global decisions considering the disk
   1794 can be easily accomplished. The benefits of this isolation will become even
   1795 clearer in the next sections.
   1796 </Para>
   1797 
   1798 <Sect2>
   1799 <Title>Low level functions</Title>
   1800 
   1801 <Para>
   1802 Read requests are ultimately handled by <Literal remap="tt">low&lowbar;read</Literal> and write requests
   1803 are handled by <Literal remap="tt">low&lowbar;write</Literal>. They just receive the length of the data
   1804 block, the offset in the filesystem and a pointer to the buffer and pass the
   1805 request to the <Literal remap="tt">fread</Literal> or <Literal remap="tt">fwrite</Literal> standard library functions.
   1806 </Para>
   1807 
   1808 </Sect2>
   1809 
   1810 <Sect2>
   1811 <Title>Mounted filesystems</Title>
   1812 
   1813 <Para>
   1814 EXT2ED design assumes that the edited filesystem is not mounted. Even if
   1815 a <Literal remap="tt">reasonably simple</Literal> way to handle mounted filesystems exists, it is
   1816 probably <Literal remap="tt">too complicated</Literal> :-)
   1817 </Para>
   1818 
   1819 <Para>
   1820 Write access to a mounted filesystem will be denied. Read access can be
   1821 allowed by using a configuration file option. The mount status is determined
   1822 by reading the file /etc/mtab.
   1823 </Para>
   1824 
   1825 </Sect2>
   1826 
   1827 <Sect2>
   1828 <Title>Write access</Title>
   1829 
   1830 <Para>
   1831 Write access is the most sensitive part in the program. This program is
   1832 intended for <Literal remap="tt">editing filesystems</Literal>. It is obvious that a small mistake
   1833 in this regard can make the filesystem not usable anymore.
   1834 </Para>
   1835 
   1836 <Para>
   1837 The following safety measures are added, of-course, to the general Unix
   1838 permission protection - The user can always disable write access on the
   1839 device file itself.
   1840 </Para>
   1841 
   1842 <Para>
   1843 Considering the user, the following safety measures were taken:
   1844 
   1845 <OrderedList>
   1846 <ListItem>
   1847 
   1848 <Para>
   1849 	The filesystem is <Literal remap="tt">never</Literal> opened with write-access enables.
   1850 Rather, the user must explicitly request to enable write-access.
   1851 </Para>
   1852 </ListItem>
   1853 <ListItem>
   1854 
   1855 <Para>
   1856 	The user can <Literal remap="tt">disable</Literal> write access entirely by using a
   1857 <Literal remap="tt">configuration file option</Literal>.
   1858 </Para>
   1859 </ListItem>
   1860 <ListItem>
   1861 
   1862 <Para>
   1863 	Changes are never done automatically - Whenever the user makes
   1864 changes, they are done in memory. An explicit <Literal remap="tt">writedata</Literal>
   1865 command should be issued to make the changes active in the disk.
   1866 </Para>
   1867 </ListItem>
   1868 
   1869 </OrderedList>
   1870 
   1871 Considering myself, I tried to protect against my bugs by:
   1872 
   1873 <ItemizedList>
   1874 <ListItem>
   1875 
   1876 <Para>
   1877 	Opening the device in read-only mode until a write request is
   1878 issued by the user.
   1879 </Para>
   1880 </ListItem>
   1881 <ListItem>
   1882 
   1883 <Para>
   1884 	Limiting <Literal remap="tt">actual</Literal> filesystem access to two functions only -
   1885 <Literal remap="tt">low&lowbar;read</Literal> for reading, and <Literal remap="tt">low&lowbar;write</Literal> for writing. Those
   1886 functions were programmed carefully, and I added the self
   1887 sanity checks there. In addition, this is the only place in which I
   1888 need to check the user options described above - There can be no
   1889 place in which I can "forget" to check them.
   1890 
   1891 Note that The disabling of write-access through the configuration file
   1892 is double checked here only as a <Literal remap="tt">self-sanity</Literal> check - If
   1893 <Literal remap="tt">DEBUG</Literal> is selected, since write enable should have been refused
   1894 and write-access is always disabled at startup, hence finding
   1895 <Literal remap="tt">here</Literal> that the user has write access disabled through the
   1896 configuration file clearly indicates that I have a bug somewhere.
   1897 </Para>
   1898 </ListItem>
   1899 
   1900 </ItemizedList>
   1901 
   1902 </Para>
   1903 
   1904 <Para>
   1905 The following safety measure can provide protection against <Literal remap="tt">both</Literal> user
   1906 mistakes and my own bugs:
   1907 
   1908 <ItemizedList>
   1909 <ListItem>
   1910 
   1911 <Para>
   1912 	I added a <Literal remap="tt">logging option</Literal>, which logs every actual write
   1913 access to the disk in the lowest level - In <Literal remap="tt">low&lowbar;write</Literal> itself.
   1914 
   1915 The logging has nothing to do with the current type and the various
   1916 other higher level operations of EXT2ED - It is simply a hex dump of
   1917 the contents which will be overwritten; Both the original contents
   1918 and the new written data.
   1919 
   1920 In that case, even if the user makes a 	mistake, the original data
   1921 can be retrieved.
   1922 
   1923 Even If I have a bug somewhere which causes incorrect data to be
   1924 written to the disk, the logging option will still log exactly the
   1925 original contents at the place were data was incorrectly overwritten.
   1926 (This assumes, of-course, that <Literal remap="tt">low-write</Literal> and the <Literal remap="tt">logging
   1927 itself</Literal> work correctly. I have done my best to verify that this is
   1928 indeed the case).
   1929 
   1930 The <Literal remap="tt">logging</Literal> option is implemented in the <Literal remap="tt">log&lowbar;changes</Literal>
   1931 function.
   1932 </Para>
   1933 </ListItem>
   1934 
   1935 </ItemizedList>
   1936 
   1937 </Para>
   1938 
   1939 </Sect2>
   1940 
   1941 <Sect2>
   1942 <Title>Reading / Writing objects</Title>
   1943 
   1944 <Para>
   1945 Usually <Literal remap="tt">(not always)</Literal>, the current object data is available in the
   1946 global variable <Literal remap="tt">type&lowbar;data</Literal>, which is of the type:
   1947 
   1948 <ProgramListing>
   1949 struct struct_type_data {
   1950 	long offset_in_block;
   1951 
   1952 	union union_type_data {
   1953 		char buffer [EXT2_MAX_BLOCK_SIZE];
   1954 		struct ext2_acl_header t_ext2_acl_header;
   1955 		struct ext2_acl_entry t_ext2_acl_entry;
   1956 		struct ext2_old_group_desc t_ext2_old_group_desc;
   1957 		struct ext2_group_desc t_ext2_group_desc;
   1958 		struct ext2_inode t_ext2_inode;
   1959 		struct ext2_super_block t_ext2_super_block;
   1960 		struct ext2_dir_entry t_ext2_dir_entry;
   1961 	} u;
   1962 };
   1963 </ProgramListing>
   1964 
   1965 The above union enables me, in the program, to treat the data as raw data or
   1966 as a meaningful filesystem object.
   1967 </Para>
   1968 
   1969 <Para>
   1970 The reading and writing, if done to this global variable, are done through
   1971 the functions <Literal remap="tt">load&lowbar;type&lowbar;data</Literal> and <Literal remap="tt">write&lowbar;type&lowbar;data</Literal>, available in
   1972 <Literal remap="tt">disk.c</Literal>.
   1973 </Para>
   1974 
   1975 </Sect2>
   1976 
   1977 </Sect1>
   1978 
   1979 <Sect1>
   1980 <Title>The general commands</Title>
   1981 
   1982 <Para>
   1983 The <Literal remap="tt">general commands</Literal> are handled in the file <Literal remap="tt">general&lowbar;com.c</Literal>.
   1984 </Para>
   1985 
   1986 <Sect2>
   1987 <Title>The help system</Title>
   1988 
   1989 <Para>
   1990 The help command is handled by the function <Literal remap="tt">help</Literal>. The algorithm is as
   1991 follows:
   1992 </Para>
   1993 
   1994 <Para>
   1995 
   1996 <OrderedList>
   1997 <ListItem>
   1998 
   1999 <Para>
   2000 	Check the command line arguments. If there is an argument, pass
   2001 control to the <Literal remap="tt">detailed&lowbar;help</Literal> function, in order to provide
   2002 help on the specific command.
   2003 </Para>
   2004 </ListItem>
   2005 <ListItem>
   2006 
   2007 <Para>
   2008 	If general help was requested, display a list of the available
   2009 commands at this point. The three levels are displayed in reverse
   2010 order - First the commands which are specific to the current type
   2011 (If a current type is defined), then the ext2 general commands (If
   2012 we decided that the filesystem should be treated like an ext2
   2013 filesystem), then the general commands.
   2014 </Para>
   2015 </ListItem>
   2016 <ListItem>
   2017 
   2018 <Para>
   2019 	Display information about EXT2ED - Current version, general
   2020 information about the project, etc.
   2021 </Para>
   2022 </ListItem>
   2023 
   2024 </OrderedList>
   2025 
   2026 </Para>
   2027 
   2028 </Sect2>
   2029 
   2030 <Sect2>
   2031 <Title>The setdevice command</Title>
   2032 
   2033 <Para>
   2034 The <Literal remap="tt">setdevice</Literal> commands result in calling the <Literal remap="tt">set&lowbar;device</Literal>
   2035 function. The algorithm is:
   2036 </Para>
   2037 
   2038 <Para>
   2039 
   2040 <OrderedList>
   2041 <ListItem>
   2042 
   2043 <Para>
   2044 	Parse the command line argument. If it isn't available report the
   2045 error and return.
   2046 </Para>
   2047 </ListItem>
   2048 <ListItem>
   2049 
   2050 <Para>
   2051 	Close the current open device, if there is one.
   2052 </Para>
   2053 </ListItem>
   2054 <ListItem>
   2055 
   2056 <Para>
   2057 	Open the new device in read-only mode. Update the global variables
   2058 <Literal remap="tt">device&lowbar;name</Literal> and <Literal remap="tt">device&lowbar;handle</Literal>.
   2059 </Para>
   2060 </ListItem>
   2061 <ListItem>
   2062 
   2063 <Para>
   2064 	Disable write access.
   2065 </Para>
   2066 </ListItem>
   2067 <ListItem>
   2068 
   2069 <Para>
   2070 	Empty the object memory.
   2071 </Para>
   2072 </ListItem>
   2073 <ListItem>
   2074 
   2075 <Para>
   2076 	Unregister the ext2 general commands, using
   2077 <Literal remap="tt">free&lowbar;user&lowbar;commands</Literal>.
   2078 </Para>
   2079 </ListItem>
   2080 <ListItem>
   2081 
   2082 <Para>
   2083 	Unregister the current objects, using <Literal remap="tt">free&lowbar;struct&lowbar;descriptors</Literal>
   2084 </Para>
   2085 </ListItem>
   2086 <ListItem>
   2087 
   2088 <Para>
   2089 	Call <Literal remap="tt">set&lowbar;file&lowbar;system&lowbar;info</Literal> to auto-detect an ext2 filesystem
   2090 and set the basic filesystem values.
   2091 </Para>
   2092 </ListItem>
   2093 <ListItem>
   2094 
   2095 <Para>
   2096 	Add the <Literal remap="tt">alternate descriptors</Literal>, supplied by the user.
   2097 </Para>
   2098 </ListItem>
   2099 <ListItem>
   2100 
   2101 <Para>
   2102 	Set the device offset to the filesystem start by dispatching
   2103 <Literal remap="tt">setoffset 0</Literal>.
   2104 </Para>
   2105 </ListItem>
   2106 <ListItem>
   2107 
   2108 <Para>
   2109 	Show the new available commands by dispatching the <Literal remap="tt">help</Literal>
   2110 command.
   2111 </Para>
   2112 </ListItem>
   2113 
   2114 </OrderedList>
   2115 
   2116 </Para>
   2117 
   2118 </Sect2>
   2119 
   2120 <Sect2>
   2121 <Title>Basic maneuvering</Title>
   2122 
   2123 <Para>
   2124 Basic maneuvering is done using the <Literal remap="tt">setoffset</Literal> and the <Literal remap="tt">settype</Literal>
   2125 user commands.
   2126 </Para>
   2127 
   2128 <Para>
   2129 <Literal remap="tt">set&lowbar;offset</Literal> accepts some alternative forms of specifying the new
   2130 offset. They all ultimately lead to changing the <Literal remap="tt">device&lowbar;offset</Literal>
   2131 global variable and seeking to the new position. <Literal remap="tt">set&lowbar;offset</Literal> also
   2132 calls <Literal remap="tt">load&lowbar;type&lowbar;data</Literal> to read a block ahead of the new position into
   2133 the <Literal remap="tt">type&lowbar;data</Literal> global variable.
   2134 </Para>
   2135 
   2136 <Para>
   2137 <Literal remap="tt">set&lowbar;type</Literal> will point the global variable <Literal remap="tt">current&lowbar;type</Literal> to the
   2138 correct entry in the double linked list of the known objects. If the
   2139 requested type is <Literal remap="tt">hex</Literal> or <Literal remap="tt">none</Literal>, <Literal remap="tt">current&lowbar;type</Literal> will be
   2140 initialized to <Literal remap="tt">NULL</Literal>. <Literal remap="tt">set&lowbar;type</Literal> will also dispatch <Literal remap="tt">show</Literal>,
   2141 so that the object data will be re-formatted in the new format.
   2142 </Para>
   2143 
   2144 <Para>
   2145 When editing an ext2 filesystem, it is not intended that those commands will
   2146 be used directly, and it is usually not required. My implementation of the
   2147 ext2 layer, on the other hand, uses this lower level commands on countless
   2148 occasions.
   2149 </Para>
   2150 
   2151 </Sect2>
   2152 
   2153 <Sect2>
   2154 <Title>The display functions</Title>
   2155 
   2156 <Para>
   2157 The general command version of <Literal remap="tt">show</Literal> is handled by the <Literal remap="tt">show</Literal>
   2158 function. This command is overridden by various objects to provide a display
   2159 which is better suited to the object.
   2160 </Para>
   2161 
   2162 <Para>
   2163 The general show command will format the data in <Literal remap="tt">type&lowbar;data</Literal> according
   2164 to the structure definition of the current type and show it on the <Literal remap="tt">show
   2165 pad</Literal>. If there is no current type, the data will be shown as a simple hex
   2166 dump; Otherwise, the list of variables, along with their values will be shown.
   2167 </Para>
   2168 
   2169 <Para>
   2170 A call to <Literal remap="tt">show&lowbar;info</Literal> is also made - <Literal remap="tt">show&lowbar;info</Literal> will provide
   2171 <Literal remap="tt">general statistics</Literal> on the <Literal remap="tt">show&lowbar;window</Literal>, such as the current
   2172 block, current type, current offset and current page.
   2173 </Para>
   2174 
   2175 <Para>
   2176 The <Literal remap="tt">pgup</Literal> and <Literal remap="tt">pgdn</Literal> general commands just update the
   2177 <Literal remap="tt">show&lowbar;pad&lowbar;info</Literal> global variable - We just increment
   2178 <Literal remap="tt">show&lowbar;pad&lowbar;info.line</Literal> with the number of lines in the screen -
   2179 <Literal remap="tt">show&lowbar;pad&lowbar;info.display&lowbar;lines</Literal>, which was initialized in
   2180 <Literal remap="tt">init&lowbar;windows</Literal>.
   2181 </Para>
   2182 
   2183 </Sect2>
   2184 
   2185 <Sect2>
   2186 <Title>Changing data</Title>
   2187 
   2188 <Para>
   2189 Data change is done in memory only. An update to the disk if followed by an
   2190 explicit <Literal remap="tt">writedata</Literal> command to the disk. The <Literal remap="tt">write&lowbar;data</Literal>
   2191 function simple calls the <Literal remap="tt">write&lowbar;type&lowbar;data</Literal> function, outlined earlier.
   2192 </Para>
   2193 
   2194 <Para>
   2195 The <Literal remap="tt">set</Literal> command is used for changing the data.
   2196 </Para>
   2197 
   2198 <Para>
   2199 If there is no current type, control is passed to the <Literal remap="tt">hex&lowbar;set</Literal> function,
   2200 which treats the data as a block of bytes and uses the
   2201 <Literal remap="tt">type&lowbar;data.offset&lowbar;in&lowbar;block</Literal> variable to write the new text or hex string
   2202 to the correct place in the block.
   2203 </Para>
   2204 
   2205 <Para>
   2206 If a current type is defined, the requested variable is searched in the
   2207 current object, and the desired new valued is entered.
   2208 </Para>
   2209 
   2210 <Para>
   2211 The <Literal remap="tt">enablewrite</Literal> commands just sets the global variable
   2212 <Literal remap="tt">write&lowbar;access</Literal> to <Literal remap="tt">1</Literal> and re-opens the filesystem in read-write
   2213 mode, if possible.
   2214 </Para>
   2215 
   2216 <Para>
   2217 If the current type is NULL, a hex-mode is assumed - The <Literal remap="tt">next</Literal> and
   2218 <Literal remap="tt">prev</Literal> commands will just update <Literal remap="tt">type&lowbar;data.offset&lowbar;in&lowbar;block</Literal>.
   2219 </Para>
   2220 
   2221 <Para>
   2222 If the current type is not NULL, the The <Literal remap="tt">next</Literal> and <Literal remap="tt">prev</Literal> command
   2223 are usually overridden anyway. If they are not overridden, it will be assumed
   2224 that the user is editing an array of such objects, and they will just pass
   2225 to the next / prev element by dispatching to <Literal remap="tt">setoffset</Literal> using the
   2226 <Literal remap="tt">setoffset type + / - X</Literal> syntax.
   2227 </Para>
   2228 
   2229 </Sect2>
   2230 
   2231 </Sect1>
   2232 
   2233 <Sect1>
   2234 <Title>The ext2 general commands</Title>
   2235 
   2236 <Para>
   2237 The ext2 general commands are contained in the <Literal remap="tt">ext2&lowbar;general&lowbar;commands</Literal>
   2238 global variable (which is of type <Literal remap="tt">struct struct&lowbar;commands</Literal>).
   2239 </Para>
   2240 
   2241 <Para>
   2242 The handling functions are implemented in the source file <Literal remap="tt">ext2&lowbar;com.c</Literal>.
   2243 I will include the entire source code since it is relatively short.
   2244 </Para>
   2245 
   2246 <Sect2>
   2247 <Title>The super command</Title>
   2248 
   2249 <Para>
   2250 The super command just "brings the user" to the main superblock and set the
   2251 type to ext2&lowbar;super&lowbar;block. The implementation is trivial:
   2252 </Para>
   2253 
   2254 <Para>
   2255 
   2256 <ProgramListing>
   2257 void type_ext2___super (char *command_line)
   2258 
   2259 {
   2260 	char buffer [80];
   2261 	
   2262 	super_info.copy_num=0;
   2263 	sprintf (buffer,"setoffset %ld",file_system_info.super_block_offset);dispatch (buffer);
   2264 	sprintf (buffer,"settype ext2_super_block");dispatch (buffer);
   2265 }
   2266 </ProgramListing>
   2267 
   2268 It involves only setting the <Literal remap="tt">copy&lowbar;num</Literal> variable to indicate the main
   2269 copy, dispatching a <Literal remap="tt">setoffset</Literal> command to reach the superblock, and
   2270 dispatching a <Literal remap="tt">settype</Literal> to enable the superblock specific commands.
   2271 This last command will also call the <Literal remap="tt">show</Literal> command of the
   2272 <Literal remap="tt">ext2&lowbar;super&lowbar;block</Literal> type, through dispatching at the general command
   2273 <Literal remap="tt">settype</Literal>.
   2274 </Para>
   2275 
   2276 </Sect2>
   2277 
   2278 <Sect2>
   2279 <Title>The group command</Title>
   2280 
   2281 <Para>
   2282 The group command will bring the user to the specified group descriptor in
   2283 the main copy of the group descriptors. The type will be set to
   2284 <Literal remap="tt">ext2&lowbar;group&lowbar;desc</Literal>:
   2285 
   2286 <ProgramListing>
   2287 void type_ext2___group (char *command_line)
   2288 
   2289 {
   2290 	long group_num=0;
   2291 	char *ptr,buffer [80];
   2292 	
   2293 	ptr=parse_word (command_line,buffer);
   2294 	if (*ptr!=0) {
   2295 		ptr=parse_word (ptr,buffer);
   2296 		group_num=atol (buffer);
   2297 	}
   2298 
   2299 	group_info.copy_num=0;group_info.group_num=0;
   2300 	sprintf (buffer,"setoffset %ld",file_system_info.first_group_desc_offset);dispatch (buffer);
   2301 	sprintf (buffer,"settype ext2_group_desc");dispatch (buffer);
   2302 	sprintf (buffer,"entry %ld",group_num);dispatch (buffer);
   2303 }
   2304 </ProgramListing>
   2305 
   2306 The implementation is as trivial as the <Literal remap="tt">super</Literal> implementation. Note
   2307 the use of the <Literal remap="tt">entry</Literal> command, which is a command of the
   2308 <Literal remap="tt">ext2&lowbar;group&lowbar;desc</Literal> object, to pass to the correct group descriptor.
   2309 </Para>
   2310 
   2311 </Sect2>
   2312 
   2313 <Sect2>
   2314 <Title>The cd command</Title>
   2315 
   2316 <Para>
   2317 The <Literal remap="tt">cd</Literal> command performs the usual cd function. The path to the global
   2318 cd command is a path from <Literal remap="tt">/</Literal>.
   2319 </Para>
   2320 
   2321 <Para>
   2322 <Literal remap="tt">This is one of the best examples of the power of the object oriented
   2323 design and of the dispatching mechanism. The operation is complicated, yet the
   2324 implementation is surprisingly short!</Literal>
   2325 </Para>
   2326 
   2327 <Para>
   2328 
   2329 <ProgramListing>
   2330 void type_ext2___cd (char *command_line)
   2331 
   2332 {
   2333 	char temp [80],buffer [80],*ptr;
   2334 	
   2335 	ptr=parse_word (command_line,buffer);
   2336 	if (*ptr==0) {
   2337 		wprintw (command_win,"Error - No argument specified\n");
   2338 		refresh_command_win ();return;
   2339 	}
   2340 	ptr=parse_word (ptr,buffer);
   2341 	
   2342 	if (buffer [0] != '/') {
   2343 		wprintw (command_win,"Error - Use a full pathname (begin with '/')\n");
   2344 		refresh_command_win ();return;
   2345 	}
   2346 
   2347 	dispatch ("super");dispatch ("group");dispatch ("inode");
   2348 	dispatch ("next");dispatch ("dir");
   2349 	if (buffer [1] != 0) {
   2350 		sprintf (temp,"cd %s",buffer+1);dispatch (temp);
   2351 	}
   2352 }
   2353 </ProgramListing>
   2354 
   2355 </Para>
   2356 
   2357 <Para>
   2358 Note the number of the dispatch calls! 
   2359 </Para>
   2360 
   2361 <Para>
   2362 <Literal remap="tt">super</Literal> is used to get to the superblock. <Literal remap="tt">group</Literal> to get to the
   2363 first group descriptor. <Literal remap="tt">inode</Literal> brings us to the first inode - The bad
   2364 blocks inode. A <Literal remap="tt">next</Literal> is command to pass to the root directory inode,
   2365 a <Literal remap="tt">dir</Literal> command "enters" the directory, and then we let the <Literal remap="tt">object
   2366 specific cd command</Literal> to take us from there (The object is <Literal remap="tt">dir</Literal>, so
   2367 that <Literal remap="tt">dispatch</Literal> will call the <Literal remap="tt">cd</Literal> command of the <Literal remap="tt">dir</Literal> type).
   2368 Note that a symbolic link following could bring us back to the root directory,
   2369 thus the innocent calls above treats nicely such a recursive case!
   2370 </Para>
   2371 
   2372 <Para>
   2373 I feel that the above is <Literal remap="tt">intuitive</Literal> - I was expressing myself "in the
   2374 language" of the ext2 filesystem - (Go to the inode, etc), and the code was
   2375 written exactly in this spirit!
   2376 </Para>
   2377 
   2378 <Para>
   2379 I can write more at this point, but I guess I am already a bit carried
   2380 away with the self compliments :-)
   2381 </Para>
   2382 
   2383 </Sect2>
   2384 
   2385 </Sect1>
   2386 
   2387 <Sect1>
   2388 <Title>The superblock</Title>
   2389 
   2390 <Para>
   2391 This section details the handling of the superblock.
   2392 </Para>
   2393 
   2394 <Sect2>
   2395 <Title>The superblock variables</Title>
   2396 
   2397 <Para>
   2398 The superblock object is <Literal remap="tt">ext2&lowbar;super&lowbar;block</Literal>. The definition is just
   2399 taken from the kernel ext2 main include file - /usr/include/linux/ext2&lowbar;fs.h.
   2400 <FOOTNOTE>
   2401 
   2402 <Para>
   2403 Those lines of source are copyrighted by <Literal remap="tt">Remy Card</Literal> - The author of the
   2404 ext2 filesystem, and by <Literal remap="tt">Linus Torvalds</Literal> - The first author of the Linux
   2405 operating system. Please cross reference the section Acknowledgments for the
   2406 full copyright.
   2407 </Para>
   2408 
   2409 </FOOTNOTE>
   2410 
   2411 
   2412 
   2413 <ProgramListing>
   2414 struct ext2_super_block {
   2415 	__u32	s_inodes_count;		/* Inodes count */
   2416 	__u32	s_blocks_count;		/* Blocks count */
   2417 	__u32	s_r_blocks_count;	/* Reserved blocks count */
   2418 	__u32	s_free_blocks_count;	/* Free blocks count */
   2419 	__u32	s_free_inodes_count;	/* Free inodes count */
   2420 	__u32	s_first_data_block;	/* First Data Block */
   2421 	__u32	s_log_block_size;	/* Block size */
   2422 	__s32	s_log_frag_size;	/* Fragment size */
   2423 	__u32	s_blocks_per_group;	/* # Blocks per group */
   2424 	__u32	s_frags_per_group;	/* # Fragments per group */
   2425 	__u32	s_inodes_per_group;	/* # Inodes per group */
   2426 	__u32	s_mtime;		/* Mount time */
   2427 	__u32	s_wtime;		/* Write time */
   2428 	__u16	s_mnt_count;		/* Mount count */
   2429 	__s16	s_max_mnt_count;	/* Maximal mount count */
   2430 	__u16	s_magic;		/* Magic signature */
   2431 	__u16	s_state;		/* File system state */
   2432 	__u16	s_errors;		/* Behavior when detecting errors */
   2433 	__u16	s_pad;
   2434 	__u32	s_lastcheck;		/* time of last check */
   2435 	__u32	s_checkinterval;	/* max. time between checks */
   2436 	__u32	s_creator_os;		/* OS */
   2437 	__u32	s_rev_level;		/* Revision level */
   2438 	__u16	s_def_resuid;		/* Default uid for reserved blocks */
   2439 	__u16	s_def_resgid;		/* Default gid for reserved blocks */
   2440 	__u32	s_reserved[0];		/* Padding to the end of the block */
   2441 	__u32	s_reserved[1];		/* Padding to the end of the block */
   2442 	.
   2443 	.
   2444 	.
   2445 	__u32	s_reserved[234];	/* Padding to the end of the block */
   2446 };
   2447 </ProgramListing>
   2448 
   2449 </Para>
   2450 
   2451 <Para>
   2452 Note that I <Literal remap="tt">expanded</Literal> the array due to my primitive parser
   2453 implementation. The various fields are described in the <Literal remap="tt">technical
   2454 document</Literal>.
   2455 </Para>
   2456 
   2457 </Sect2>
   2458 
   2459 <Sect2>
   2460 <Title>The superblock commands</Title>
   2461 
   2462 <Para>
   2463 This section explains the commands available in the <Literal remap="tt">ext2&lowbar;super&lowbar;block</Literal>
   2464 type. They all appear in <Literal remap="tt">super&lowbar;com.c</Literal>
   2465 </Para>
   2466 
   2467 <Sect3>
   2468 <Title>The show command</Title>
   2469 
   2470 <Para>
   2471 The <Literal remap="tt">show</Literal> command is overridden here in order to provide more
   2472 information than just the list of variables. A <Literal remap="tt">show</Literal> command will end
   2473 up in calling <Literal remap="tt">type&lowbar;super&lowbar;block&lowbar;&lowbar;&lowbar;show</Literal>.
   2474 </Para>
   2475 
   2476 <Para>
   2477 The first thing that we do is calling the <Literal remap="tt">general show command</Literal> in
   2478 order to display the list of variables.
   2479 </Para>
   2480 
   2481 <Para>
   2482 We then add some interpretation to the various lines to make the data
   2483 somewhat more intuitive (Expansion of the time variables and the creator
   2484 operating system code, for example).
   2485 </Para>
   2486 
   2487 <Para>
   2488 We also display the <Literal remap="tt">backup copy number</Literal> of the superblock in the status
   2489 window. This copy number is saved in the <Literal remap="tt">super&lowbar;info</Literal> global variable -
   2490 <Literal remap="tt">super&lowbar;info.copy&lowbar;num</Literal>. Currently, this is the only variable there ...
   2491 but this type of internal variable saving is typical through my
   2492 implementation.
   2493 </Para>
   2494 
   2495 </Sect3>
   2496 
   2497 <Sect3>
   2498 <Title>The backup copies handling commands</Title>
   2499 
   2500 <Para>
   2501 The <Literal remap="tt">current copy number</Literal> is available in <Literal remap="tt">super&lowbar;info.copy&lowbar;num</Literal>. It
   2502 was initialized in the ext2 command <Literal remap="tt">super</Literal>, and is used by the various
   2503 superblock routines.
   2504 </Para>
   2505 
   2506 <Para>
   2507 The <Literal remap="tt">gocopy</Literal> routine will pass to another copy of the superblock. The
   2508 new device offset will be computed with the aid of the variables in the
   2509 <Literal remap="tt">file&lowbar;system&lowbar;info</Literal> structure. Then the routine will <Literal remap="tt">dispatch</Literal> to
   2510 the <Literal remap="tt">setoffset</Literal> and the <Literal remap="tt">show</Literal> routines.
   2511 </Para>
   2512 
   2513 <Para>
   2514 The <Literal remap="tt">setactivecopy</Literal> routine will just save the current superblock data
   2515 in a temporary variable of type <Literal remap="tt">ext2&lowbar;super&lowbar;block</Literal>, and will dispatch
   2516 <Literal remap="tt">gocopy 0</Literal> to pass to the main superblock. Then it will place the saved
   2517 data in place of the actual data.
   2518 </Para>
   2519 
   2520 <Para>
   2521 The above two commands can be used if the main superblock is corrupted.
   2522 </Para>
   2523 
   2524 </Sect3>
   2525 
   2526 </Sect2>
   2527 
   2528 </Sect1>
   2529 
   2530 <Sect1>
   2531 <Title>The group descriptors</Title>
   2532 
   2533 <Para>
   2534 The group descriptors handling mechanism allows the user to take a tour in
   2535 the group descriptors table, stopping at each point, and examining the
   2536 relevant inode table, block allocation map or inode allocation map through
   2537 dispatching to the relevant objects.
   2538 </Para>
   2539 
   2540 <Para>
   2541 Some information about the group descriptors is available in the global
   2542 variable <Literal remap="tt">group&lowbar;info</Literal>, which is of type <Literal remap="tt">struct&lowbar;group&lowbar;info</Literal>:
   2543 </Para>
   2544 
   2545 <Para>
   2546 
   2547 <ProgramListing>
   2548 struct struct_group_info {
   2549 	unsigned long copy_num;
   2550 	unsigned long group_num;
   2551 };
   2552 </ProgramListing>
   2553 
   2554 </Para>
   2555 
   2556 <Para>
   2557 <Literal remap="tt">group&lowbar;num</Literal> is the index of the current descriptor in the table.
   2558 </Para>
   2559 
   2560 <Para>
   2561 <Literal remap="tt">copy&lowbar;num</Literal> is the number of the current backup copy.
   2562 </Para>
   2563 
   2564 <Sect2>
   2565 <Title>The group descriptor's variables</Title>
   2566 
   2567 <Para>
   2568 
   2569 <ProgramListing>
   2570 struct ext2_group_desc
   2571 {
   2572 	__u32	bg_block_bitmap;		/* Blocks bitmap block */
   2573 	__u32	bg_inode_bitmap;		/* Inodes bitmap block */
   2574 	__u32	bg_inode_table;			/* Inodes table block */
   2575 	__u16	bg_free_blocks_count;		/* Free blocks count */
   2576 	__u16	bg_free_inodes_count;		/* Free inodes count */
   2577 	__u16	bg_used_dirs_count;		/* Directories count */
   2578 	__u16	bg_pad;
   2579 	__u32	bg_reserved[3];
   2580 };
   2581 </ProgramListing>
   2582 
   2583 </Para>
   2584 
   2585 <Para>
   2586 The first three variables are used to provide the links to the
   2587 <Literal remap="tt">blockbitmap, inodebitmap and inode</Literal> objects.
   2588 </Para>
   2589 
   2590 </Sect2>
   2591 
   2592 <Sect2>
   2593 <Title>Movement in the table</Title>
   2594 
   2595 <Para>
   2596 Movement in the group descriptors table is done using the <Literal remap="tt">next, prev and
   2597 entry</Literal> commands. Note that the first two commands <Literal remap="tt">override</Literal> the
   2598 general commands of the same name. The <Literal remap="tt">next and prev</Literal> command are just
   2599 calling the <Literal remap="tt">entry</Literal> function to do the job. I will show <Literal remap="tt">next</Literal>,
   2600 for example:
   2601 </Para>
   2602 
   2603 <Para>
   2604 
   2605 <ProgramListing>
   2606 void type_ext2_group_desc___next (char *command_line)
   2607  
   2608 {
   2609 	long entry_offset=1;
   2610 	char *ptr,buffer [80];
   2611 	
   2612 	ptr=parse_word (command_line,buffer);
   2613 	if (*ptr!=0) {
   2614 		ptr=parse_word (ptr,buffer);
   2615 		entry_offset=atol (buffer);
   2616 	}
   2617 
   2618 	sprintf (buffer,"entry %ld",group_info.group_num+entry_offset);
   2619 	dispatch (buffer);
   2620 }
   2621 </ProgramListing>
   2622 
   2623 The <Literal remap="tt">entry</Literal> function is also simple - It just calculates the offset
   2624 using the information in <Literal remap="tt">group&lowbar;info</Literal> and in <Literal remap="tt">file&lowbar;system&lowbar;info</Literal>,
   2625 and uses the usual <Literal remap="tt">setoffset / show</Literal> pair. 
   2626 </Para>
   2627 
   2628 </Sect2>
   2629 
   2630 <Sect2>
   2631 <Title>The show command</Title>
   2632 
   2633 <Para>
   2634 As usual, the <Literal remap="tt">show</Literal> command is overridden. The implementation is
   2635 similar to the superblock's show implementation - We just call the general
   2636 show command, and add some information in the status window - The contents of
   2637 the <Literal remap="tt">group&lowbar;info</Literal> structure.
   2638 </Para>
   2639 
   2640 </Sect2>
   2641 
   2642 <Sect2>
   2643 <Title>Moving between backup copies</Title>
   2644 
   2645 <Para>
   2646 This is done exactly like the superblock case. Please refer to explanation
   2647 there.
   2648 </Para>
   2649 
   2650 </Sect2>
   2651 
   2652 <Sect2>
   2653 <Title>Links to the available friends</Title>
   2654 
   2655 <Para>
   2656 From a group descriptor, one typically wants to reach an <Literal remap="tt">inode</Literal>, or
   2657 one of the <Literal remap="tt">allocation bitmaps</Literal>. This is done using the <Literal remap="tt">inode,
   2658 blockbitmap or inodebitmap</Literal> commands. The implementation is again trivial
   2659 - Get the necessary information from the group descriptor, initialize the
   2660 structures of the next type, and issue the <Literal remap="tt">setoffset / settype</Literal> pair.
   2661 </Para>
   2662 
   2663 <Para>
   2664 For example, here is the implementation of the <Literal remap="tt">blockbitmap</Literal> command:
   2665 </Para>
   2666 
   2667 <Para>
   2668 
   2669 <ProgramListing>
   2670 void type_ext2_group_desc___blockbitmap (char *command_line)
   2671 
   2672 {
   2673 	long block_bitmap_offset;
   2674 	char buffer [80];
   2675 	
   2676 	block_bitmap_info.entry_num=0;
   2677 	block_bitmap_info.group_num=group_info.group_num;
   2678 
   2679 	block_bitmap_offset=type_data.u.t_ext2_group_desc.bg_block_bitmap;
   2680 	sprintf (buffer,"setoffset block %ld",block_bitmap_offset);dispatch (buffer);
   2681 	sprintf (buffer,"settype block_bitmap");dispatch (buffer);
   2682 }
   2683 </ProgramListing>
   2684 
   2685 </Para>
   2686 
   2687 </Sect2>
   2688 
   2689 </Sect1>
   2690 
   2691 <Sect1>
   2692 <Title>The inode table</Title>
   2693 
   2694 <Para>
   2695 The inode handling enables the user to move in the inode table, edit the
   2696 various attributes of the inode, and follow to the next stage - A file or a
   2697 directory.
   2698 </Para>
   2699 
   2700 <Sect2>
   2701 <Title>The inode variables</Title>
   2702 
   2703 <Para>
   2704 
   2705 <ProgramListing>
   2706 struct ext2_inode {
   2707 	__u16	i_mode;		/* File mode */
   2708 	__u16	i_uid;		/* Owner Uid */
   2709 	__u32	i_size;		/* Size in bytes */
   2710 	__u32	i_atime;	/* Access time */
   2711 	__u32	i_ctime;	/* Creation time */
   2712 	__u32	i_mtime;	/* Modification time */
   2713 	__u32	i_dtime;	/* Deletion Time */
   2714 	__u16	i_gid;		/* Group Id */
   2715 	__u16	i_links_count;	/* Links count */
   2716 	__u32	i_blocks;	/* Blocks count */
   2717 	__u32	i_flags;	/* File flags */
   2718 	union {
   2719 		struct {
   2720 			__u32  l_i_reserved1;
   2721 		} linux1;
   2722 		struct {
   2723 			__u32  h_i_translator;
   2724 		} hurd1;
   2725 	} osd1;				/* OS dependent 1 */
   2726 	__u32	i_block[EXT2_N_BLOCKS];	/* Pointers to blocks */
   2727 	__u32	i_version;		/* File version (for NFS) */
   2728 	__u32	i_file_acl;		/* File ACL */
   2729 	__u32	i_dir_acl;		/* Directory ACL */
   2730 	__u32	i_faddr;		/* Fragment address */
   2731 	union {
   2732 		struct {
   2733 			__u8	l_i_frag;	/* Fragment number */
   2734 			__u8	l_i_fsize;	/* Fragment size */
   2735 			__u16	i_pad1;
   2736 			__u32	l_i_reserved2[2];
   2737 		} linux2;
   2738 		struct {
   2739 			__u8	h_i_frag;	/* Fragment number */
   2740 			__u8	h_i_fsize;	/* Fragment size */
   2741 			__u16	h_i_mode_high;
   2742 			__u16	h_i_uid_high;
   2743 			__u16	h_i_gid_high;
   2744 			__u32	h_i_author;
   2745 		} hurd2;
   2746 	} osd2;				/* OS dependent 2 */
   2747 };
   2748 </ProgramListing>
   2749 
   2750 </Para>
   2751 
   2752 <Para>
   2753 The above is the original source code definition. We can see that the inode
   2754 supports <Literal remap="tt">Operating systems specific structures</Literal>. In addition to the
   2755 expansion of the arrays, I have <Literal remap="tt">"flattened</Literal> the inode to support only
   2756 the <Literal remap="tt">Linux</Literal> declaration. It seemed that this one occasion of multiple
   2757 variable aliases didn't justify the complication of generally supporting
   2758 aliases. In any case, the above system specific variables are not used
   2759 internally by EXT2ED, and the user is free to change the definition in
   2760 <Literal remap="tt">ext2.descriptors</Literal> to accommodate for his needs.
   2761 </Para>
   2762 
   2763 </Sect2>
   2764 
   2765 <Sect2>
   2766 <Title>The handling functions</Title>
   2767 
   2768 <Para>
   2769 The user interface to <Literal remap="tt">movement</Literal> is the usual <Literal remap="tt">next / prev /
   2770 entry</Literal> interface. There is really nothing special in those functions - The
   2771 size of the inode is fixed, the total number of inodes is known from the
   2772 superblock information, and the current entry can be figured up from the
   2773 device offset and the inode table start offset, which is known from the
   2774 corresponding group descriptor. Those functions are a bit older then some
   2775 other implementations of <Literal remap="tt">next</Literal> and <Literal remap="tt">prev</Literal>, and they do not save
   2776 information in a special structure. Rather, they recompute it when
   2777 necessary.
   2778 </Para>
   2779 
   2780 <Para>
   2781 The <Literal remap="tt">show</Literal> command is overridden here, and provides a lot of additional
   2782 information about the inode - Its type, interpretation of the permissions,
   2783 special ext2 attributes (Immutable file, for example), and a lot more.
   2784 Again, the <Literal remap="tt">general show</Literal> is called first, and then the additional
   2785 information is written.
   2786 </Para>
   2787 
   2788 </Sect2>
   2789 
   2790 <Sect2>
   2791 <Title>Accessing files and directories</Title>
   2792 
   2793 <Para>
   2794 From the inode, a <Literal remap="tt">file</Literal> or a <Literal remap="tt">directory</Literal> can typically be reached.
   2795 In order to treat a file, for example, its inode needs to be constantly
   2796 accessed. To satisfy that need, when editing a file or a directory, the
   2797 inode is still saved in memory - <Literal remap="tt">type&lowbar;data</Literal> is not overwritten.
   2798 Rather, the following takes place:
   2799 
   2800 <ItemizedList>
   2801 <ListItem>
   2802 
   2803 <Para>
   2804 	An internal global structure which is used by the types <Literal remap="tt">file</Literal>
   2805 and <Literal remap="tt">dir</Literal> handling functions is initialized by calling the
   2806 appropriate function.
   2807 </Para>
   2808 </ListItem>
   2809 <ListItem>
   2810 
   2811 <Para>
   2812 	The type is changed accordingly.
   2813 </Para>
   2814 </ListItem>
   2815 
   2816 </ItemizedList>
   2817 
   2818 The result is that a <Literal remap="tt">settype ext2&lowbar;inode</Literal> is the only action necessary
   2819 to return to the inode - We actually never left it.
   2820 </Para>
   2821 
   2822 <Para>
   2823 Follows the implementation of the inode's <Literal remap="tt">file</Literal> command:
   2824 </Para>
   2825 
   2826 <Para>
   2827 
   2828 <ProgramListing>
   2829 void type_ext2_inode___file (char *command_line)
   2830 
   2831 {
   2832 	char buffer [80];
   2833 	
   2834 	if (!S_ISREG (type_data.u.t_ext2_inode.i_mode)) {
   2835 		wprintw (command_win,"Error - Inode type is not file\n");
   2836 		refresh_command_win ();	return;		
   2837 	}
   2838 	
   2839 	if (!init_file_info ()) {
   2840 		wprintw (command_win,"Error - Unable to show file\n");
   2841 		refresh_command_win ();return;
   2842 	}
   2843 	
   2844 	sprintf (buffer,"settype file");dispatch (buffer);
   2845 }
   2846 </ProgramListing>
   2847 
   2848 </Para>
   2849 
   2850 <Para>
   2851 As we can see - We just call <Literal remap="tt">init&lowbar;file&lowbar;info</Literal> to get the necessary
   2852 information from the inode, and set the type to <Literal remap="tt">file</Literal>. The next call
   2853 to <Literal remap="tt">show</Literal>, will dispatch to the <Literal remap="tt">file's show</Literal> implementation.
   2854 </Para>
   2855 
   2856 </Sect2>
   2857 
   2858 </Sect1>
   2859 
   2860 <Sect1>
   2861 <Title>Viewing a file</Title>
   2862 
   2863 <Para>
   2864 There isn't an ext2 kernel structure which corresponds to a file - A file is
   2865 just a series of blocks which are determined by its inode. As explained in
   2866 the last section, the inode is never actually left - The type is changed to
   2867 <Literal remap="tt">file</Literal> - A type which contains no variables, and a special structure is
   2868 initialized:
   2869 </Para>
   2870 
   2871 <Para>
   2872 
   2873 <ProgramListing>
   2874 struct struct_file_info {
   2875 
   2876 	struct ext2_inodes *inode_ptr;
   2877 	
   2878 	long inode_offset;
   2879 	long global_block_num,global_block_offset;
   2880 	long block_num,blocks_count;
   2881 	long file_offset,file_length;
   2882 	long level;
   2883 	unsigned char buffer [EXT2_MAX_BLOCK_SIZE];
   2884 	long offset_in_block;
   2885 
   2886 	int display;
   2887 	/* The following is used if the file is a directory */
   2888 	
   2889 	long dir_entry_num,dir_entries_count;
   2890 	long dir_entry_offset;
   2891 };
   2892 </ProgramListing>
   2893 
   2894 </Para>
   2895 
   2896 <Para>
   2897 The <Literal remap="tt">inode&lowbar;ptr</Literal> will just point to the inode in <Literal remap="tt">type&lowbar;data</Literal>, which
   2898 is not overwritten while the user is editing the file, as the
   2899 <Literal remap="tt">setoffset</Literal> command is not internally used. The <Literal remap="tt">buffer</Literal>
   2900 will contain the current viewed block of the file. The other variables
   2901 contain information about the current place in the file. For example,
   2902 <Literal remap="tt">global&lowbar;block&lowbar;num</Literal> just contains the current block number.
   2903 </Para>
   2904 
   2905 <Para>
   2906 The general idea is that the above data structure will provide the file
   2907 handling functions all the accurate information which is needed to accomplish
   2908 their task.
   2909 </Para>
   2910 
   2911 <Para>
   2912 The global structure of the above type, <Literal remap="tt">file&lowbar;info</Literal>, is initialized by
   2913 <Literal remap="tt">init&lowbar;file&lowbar;info</Literal> in <Literal remap="tt">file&lowbar;com.c</Literal>, which is called by the
   2914 <Literal remap="tt">type&lowbar;ext2&lowbar;inode&lowbar;&lowbar;&lowbar;file</Literal> function when the user requests to watch the
   2915 file. <Literal remap="tt">It is updated as necessary to provide accurate information as long as
   2916 the file is edited.</Literal>
   2917 </Para>
   2918 
   2919 <Sect2>
   2920 <Title>Returning to the file's inode</Title>
   2921 
   2922 <Para>
   2923 Concerning the method I used to handle files, the above task is trivial:
   2924 
   2925 <ProgramListing>
   2926 void type_file___inode (char *command_line)
   2927 
   2928 {
   2929 	dispatch ("settype ext2_inode");
   2930 }
   2931 </ProgramListing>
   2932 
   2933 </Para>
   2934 
   2935 </Sect2>
   2936 
   2937 <Sect2>
   2938 <Title>File movement</Title>
   2939 
   2940 <Para>
   2941 EXT2ED keeps track of the current position in the file. Movement inside the
   2942 current block is done using <Literal remap="tt">next, prev and offset</Literal> - They just change
   2943 <Literal remap="tt">file&lowbar;info.offset&lowbar;in&lowbar;block</Literal>.
   2944 </Para>
   2945 
   2946 <Para>
   2947 Movement between blocks is done using <Literal remap="tt">nextblock, prevblock and block</Literal>.
   2948 To accomplish this, the direct blocks, indirect blocks, etc, need to be
   2949 traced. This is done by <Literal remap="tt">file&lowbar;block&lowbar;to&lowbar;global&lowbar;block</Literal>, which accepts a
   2950 file's internal block number, and converts it to the actual filesystem block
   2951 number.
   2952 </Para>
   2953 
   2954 <Para>
   2955 
   2956 <ProgramListing>
   2957 long file_block_to_global_block (long file_block,struct struct_file_info *file_info_ptr)
   2958 
   2959 {
   2960 	long last_direct,last_indirect,last_dindirect;
   2961 	long f_indirect,s_indirect;
   2962 	
   2963 	last_direct=EXT2_NDIR_BLOCKS-1;
   2964 	last_indirect=last_direct+file_system_info.block_size/4;
   2965 	last_dindirect=last_indirect+(file_system_info.block_size/4) \
   2966 		*(file_system_info.block_size/4);
   2967 
   2968 	if (file_block &#60;= last_direct) {
   2969 		file_info_ptr-&#62;level=0;
   2970 		return (file_info_ptr-&#62;inode_ptr-&#62;i_block [file_block]);
   2971 	}
   2972 	
   2973 	if (file_block &#60;= last_indirect) {
   2974 		file_info_ptr-&#62;level=1;
   2975 		file_block=file_block-last_direct-1;
   2976 		return (return_indirect (file_info_ptr-&#62;inode_ptr-&#62; \
   2977 			i_block [EXT2_IND_BLOCK],file_block));
   2978 	}
   2979 
   2980 	if (file_block &#60;= last_dindirect) {
   2981 		file_info_ptr-&#62;level=2;
   2982 		file_block=file_block-last_indirect-1;
   2983 		return (return_dindirect (file_info_ptr-&#62;inode_ptr-&#62; \
   2984 			i_block [EXT2_DIND_BLOCK],file_block));
   2985 	}
   2986 
   2987 	file_info_ptr-&#62;level=3;
   2988 	file_block=file_block-last_dindirect-1;
   2989 	return (return_tindirect (file_info_ptr-&#62;inode_ptr-&#62; \
   2990 		i_block [EXT2_TIND_BLOCK],file_block));
   2991 }
   2992 </ProgramListing>
   2993 
   2994 <Literal remap="tt">last&lowbar;direct, last&lowbar;indirect, etc</Literal>, contain the last internal block number
   2995 which is accessed by this method - If the requested block is smaller then
   2996 <Literal remap="tt">last&lowbar;direct</Literal>, for example, it is a direct block.
   2997 </Para>
   2998 
   2999 <Para>
   3000 If the block is a direct block, its number is just taken from the inode.
   3001 A non-direct block is handled by <Literal remap="tt">return&lowbar;indirect, return&lowbar;dindirect and
   3002 return&lowbar;tindirect</Literal>, which correspond to indirect, double-indirect and
   3003 triple-indirect. Each of the above functions is constructed using the lower
   3004 level functions. For example, <Literal remap="tt">return&lowbar;dindirect</Literal> is constructed as
   3005 follows:
   3006 </Para>
   3007 
   3008 <Para>
   3009 
   3010 <ProgramListing>
   3011 long return_dindirect (long table_block,long block_num)
   3012 
   3013 {
   3014 	long f_indirect;
   3015 	
   3016 	f_indirect=block_num/(file_system_info.block_size/4);
   3017 	f_indirect=return_indirect (table_block,f_indirect);
   3018 	return (return_indirect (f_indirect,block_num%(file_system_info.block_size/4)));
   3019 }
   3020 </ProgramListing>
   3021 
   3022 </Para>
   3023 
   3024 </Sect2>
   3025 
   3026 <Sect2>
   3027 <Title>Object memory</Title>
   3028 
   3029 <Para>
   3030 The <Literal remap="tt">remember</Literal> command is overridden here and in the <Literal remap="tt">dir</Literal> type -
   3031 We just remember the inode of the file. It is just simpler to implement, and
   3032 doesn't seem like a big limitation.
   3033 </Para>
   3034 
   3035 </Sect2>
   3036 
   3037 <Sect2>
   3038 <Title>Changing data</Title>
   3039 
   3040 <Para>
   3041 The <Literal remap="tt">set</Literal> command is overridden, and provides the same functionality
   3042 like the usage of the <Literal remap="tt">general set</Literal> command with no type declared. The
   3043 <Literal remap="tt">writedata</Literal> is overridden so that we'll write the edited block
   3044 (file&lowbar;info.buffer) and not <Literal remap="tt">type&lowbar;data</Literal> (Which contains the inode).
   3045 </Para>
   3046 
   3047 </Sect2>
   3048 
   3049 </Sect1>
   3050 
   3051 <Sect1>
   3052 <Title>Directories</Title>
   3053 
   3054 <Para>
   3055 A directory is just a file which is formatted according to a special format.
   3056 As such, EXT2ED handles directories and files quite alike. Specifically, the
   3057 same variable of type <Literal remap="tt">struct&lowbar;file&lowbar;info</Literal> which is used in the
   3058 <Literal remap="tt">file</Literal>, is used here.
   3059 </Para>
   3060 
   3061 <Para>
   3062 The <Literal remap="tt">dir</Literal> type uses all the variables in the above structure, as
   3063 opposed to the <Literal remap="tt">file</Literal> type, which didn't use the last ones.
   3064 </Para>
   3065 
   3066 <Sect2>
   3067 <Title>The search&lowbar;dir&lowbar;entries function</Title>
   3068 
   3069 <Para>
   3070 The entire situation is similar to that which was described in the
   3071 <Literal remap="tt">file</Literal> type, with one main change:
   3072 </Para>
   3073 
   3074 <Para>
   3075 The main function in <Literal remap="tt">dir&lowbar;com.c</Literal> is <Literal remap="tt">search&lowbar;dir&lowbar;entries</Literal>. This
   3076 function will <Literal remap="tt">"run"</Literal> on the entire entries in the directory, and will
   3077 call a client's function each time. The client's function is supplied as an
   3078 argument, and will check the current entry for a match, based on its own
   3079 criterion. It will then signal <Literal remap="tt">search&lowbar;dir&lowbar;entries</Literal> whether to
   3080 <Literal remap="tt">ABORT</Literal> the search, whether it <Literal remap="tt">FOUND</Literal> the entry it was looking
   3081 for, or that the entry is still not found, and we should <Literal remap="tt">CONTINUE</Literal>
   3082 searching. Follows the declaration:
   3083 
   3084 <ProgramListing>
   3085 struct struct_file_info search_dir_entries \ 
   3086 	(int (*action) (struct struct_file_info *info),int *status)
   3087 
   3088 /*
   3089 	This routine runs on all directory entries in the current directory.
   3090 	For each entry, action is called. The return code of action is one of
   3091 	the following:
   3092 	
   3093 		ABORT		-	Current dir entry is returned.
   3094 		CONTINUE	-	Continue searching.
   3095 		FOUND		-	Current dir entry is returned.
   3096 		
   3097 	If the last entry is reached, it is returned, along with an ABORT status.
   3098 	
   3099 	status is updated to the returned code of action.	
   3100 */
   3101 </ProgramListing>
   3102 
   3103 </Para>
   3104 
   3105 <Para>
   3106 With the above tool in hand, many operations are simple to perform - Here is
   3107 the way I counted the entries in the current directory:
   3108 </Para>
   3109 
   3110 <Para>
   3111 
   3112 <ProgramListing>
   3113 long count_dir_entries (void)
   3114 
   3115 {
   3116 	int status;
   3117 	
   3118 	return (search_dir_entries (&amp;action_count,&amp;status).dir_entry_num);
   3119 }
   3120 
   3121 int action_count (struct struct_file_info *info)
   3122 
   3123 {
   3124 	return (CONTINUE);
   3125 }
   3126 </ProgramListing>
   3127 
   3128 It will just <Literal remap="tt">CONTINUE</Literal> until the last entry. The returned structure
   3129 (of type <Literal remap="tt">struct&lowbar;file&lowbar;info</Literal>) will have its number in the
   3130 <Literal remap="tt">dir&lowbar;entry&lowbar;num</Literal> field, and this is exactly the required number!
   3131 </Para>
   3132 
   3133 </Sect2>
   3134 
   3135 <Sect2>
   3136 <Title>The cd command</Title>
   3137 
   3138 <Para>
   3139 The <Literal remap="tt">cd</Literal> command accepts a relative path, and moves there ...
   3140 The implementation is of-course a bit more complicated:
   3141 
   3142 <OrderedList>
   3143 <ListItem>
   3144 
   3145 <Para>
   3146 	The path is checked that it is not an absolute path (from <Literal remap="tt">/</Literal>).
   3147 If it is, we let the <Literal remap="tt">general cd</Literal> to do the job by calling
   3148 directly <Literal remap="tt">type&lowbar;ext2&lowbar;&lowbar;&lowbar;cd</Literal>.
   3149 </Para>
   3150 </ListItem>
   3151 <ListItem>
   3152 
   3153 <Para>
   3154 	The path is divided into the nearest path and the rest of the path.
   3155 For example, cd 1/2/3/4 is divided into <Literal remap="tt">1</Literal> and into
   3156 <Literal remap="tt">2/3/4</Literal>.
   3157 </Para>
   3158 </ListItem>
   3159 <ListItem>
   3160 
   3161 <Para>
   3162 	It is the first part of the path that we need to search for in the
   3163 current directory. We search for it using <Literal remap="tt">search&lowbar;dir&lowbar;entries</Literal>,
   3164 which accepts the <Literal remap="tt">action&lowbar;name</Literal> function as the user defined
   3165 function.
   3166 </Para>
   3167 </ListItem>
   3168 <ListItem>
   3169 
   3170 <Para>
   3171 	<Literal remap="tt">search&lowbar;dir&lowbar;entries</Literal> will scan the entire entries and will call
   3172 our <Literal remap="tt">action&lowbar;name</Literal> function for each entry. In
   3173 <Literal remap="tt">action&lowbar;name</Literal>, the required name will be checked against the
   3174 name of the current entry, and <Literal remap="tt">FOUND</Literal> will be returned when a
   3175 match occurs.
   3176 </Para>
   3177 </ListItem>
   3178 <ListItem>
   3179 
   3180 <Para>
   3181 	If the required entry is found, we dispatch a <Literal remap="tt">remember</Literal>
   3182 command to insert the current <Literal remap="tt">inode</Literal> into the object memory.
   3183 This is required to easily support <Literal remap="tt">symbolic links</Literal> - If we
   3184 find later that the inode pointed by the entry is actually a
   3185 symbolic link, we'll need to return to this point, and the above
   3186 inode doesn't have (and can't have, because of <Literal remap="tt">hard links</Literal>) the
   3187 information necessary to "move back".
   3188 </Para>
   3189 </ListItem>
   3190 <ListItem>
   3191 
   3192 <Para>
   3193 	We then dispatch a <Literal remap="tt">followinode</Literal> command to reach the inode
   3194 pointed by the required entry. This command will automatically
   3195 change the type to <Literal remap="tt">ext2&lowbar;inode</Literal> - We are now at an inode, and
   3196 all the inode commands are available.
   3197 </Para>
   3198 </ListItem>
   3199 <ListItem>
   3200 
   3201 <Para>
   3202 	We check the inode's type to see if it is a directory. If it is, we
   3203 dispatch a <Literal remap="tt">dir</Literal> command to "enter the directory", and
   3204 recursively call ourself (The type is <Literal remap="tt">dir</Literal> again) by
   3205 dispatching a <Literal remap="tt">cd</Literal> command, with the rest of the path as an
   3206 argument.
   3207 </Para>
   3208 </ListItem>
   3209 <ListItem>
   3210 
   3211 <Para>
   3212 	If the inode's type is a symbolic link (only fast symbolic link were
   3213 meanwhile implemented. I guess this is typically the case.), we note
   3214 the path it is pointing at, the	saved inode is recalled, we dispatch
   3215 <Literal remap="tt">dir</Literal> to get back to the original directory, and we call
   3216 ourself again with the <Literal remap="tt">link path/rest of the path</Literal> argument.
   3217 </Para>
   3218 </ListItem>
   3219 <ListItem>
   3220 
   3221 <Para>
   3222 	In any other case, we just stop at the resulting inode.
   3223 </Para>
   3224 </ListItem>
   3225 
   3226 </OrderedList>
   3227 
   3228 </Para>
   3229 
   3230 </Sect2>
   3231 
   3232 </Sect1>
   3233 
   3234 <Sect1>
   3235 <Title>The block and inode allocation bitmaps</Title>
   3236 
   3237 <Para>
   3238 The block allocation bitmap is reached by the corresponding group descriptor.
   3239 The group descriptor handling functions will save the necessary information
   3240 into a structure of the <Literal remap="tt">struct&lowbar;block&lowbar;bitmap&lowbar;info</Literal> type:
   3241 </Para>
   3242 
   3243 <Para>
   3244 
   3245 <ProgramListing>
   3246 struct struct_block_bitmap_info {
   3247 	unsigned long entry_num;
   3248 	unsigned long group_num;
   3249 };
   3250 </ProgramListing>
   3251 
   3252 </Para>
   3253 
   3254 <Para>
   3255 The <Literal remap="tt">show</Literal> command is overridden, and will show the block as a series of
   3256 bits, each bit corresponding to a block. The main variable is the
   3257 <Literal remap="tt">entry&lowbar;num</Literal> variable, declared above, which is just the current block
   3258 number in this block group. The current entry is highlighted, and the
   3259 <Literal remap="tt">next, prev and entry</Literal> commands just change the above variable.
   3260 </Para>
   3261 
   3262 <Para>
   3263 The <Literal remap="tt">allocate and deallocate</Literal> change the specified bits. Nothing
   3264 special about them - They just contain code which converts between bit and
   3265 byte locations.
   3266 </Para>
   3267 
   3268 <Para>
   3269 The <Literal remap="tt">inode allocation bitmap</Literal> is treated in much the same fashion, with
   3270 the same commands available.
   3271 </Para>
   3272 
   3273 </Sect1>
   3274 
   3275 <Sect1>
   3276 <Title>Filesystem size limitation</Title>
   3277 
   3278 <Para>
   3279 While an ext2 filesystem has a size limit of <Literal remap="tt">4 TB</Literal>, EXT2ED currently
   3280 <Literal remap="tt">can't</Literal> handle filesystems which are <Literal remap="tt">bigger than 2 GB</Literal>.
   3281 </Para>
   3282 
   3283 <Para>
   3284 This limitation results from my usage of <Literal remap="tt">32 bit long variables</Literal> and
   3285 of the <Literal remap="tt">fseek</Literal> filesystem call, which can't seek up to 4 TB.
   3286 </Para>
   3287 
   3288 <Para>
   3289 By looking in the <Literal remap="tt">ext2 library</Literal> source code by <Literal remap="tt">Theodore Ts'o</Literal>,
   3290 I discovered the <Literal remap="tt">llseek</Literal> system call which can seek to a
   3291 <Literal remap="tt">64 bit unsigned long long</Literal> offset. Correcting the situation is not
   3292 difficult in concept - I need to change long into unsigned long long where
   3293 appropriate and modify <Literal remap="tt">disk.c</Literal> to use the llseek system call.
   3294 </Para>
   3295 
   3296 <Para>
   3297 However, fixing the above limitation involves making changes in many places
   3298 in the code and will obviously make the entire code less stable. For that
   3299 reason, I chose to release EXT2ED as it is now and to postpone the above fix
   3300 to the next release.
   3301 </Para>
   3302 
   3303 </Sect1>
   3304 
   3305 <Sect1>
   3306 <Title>Conclusion</Title>
   3307 
   3308 <Para>
   3309 Had I known in advance the structure of the ext2 filesystem, I feel that
   3310 the resulting design would have been quite different from the presented
   3311 design above.
   3312 </Para>
   3313 
   3314 <Para>
   3315 EXT2ED has now two levels of abstraction - A <Literal remap="tt">general</Literal> filesystem, and an
   3316 <Literal remap="tt">ext2</Literal> filesystem, and the surface is more or less prepared for additions
   3317 of other filesystems. Had I approached the design in the "engineering" way,
   3318 I guess that the first level above would not have existed.
   3319 </Para>
   3320 
   3321 </Sect1>
   3322 
   3323 <Sect1>
   3324 <Title>Copyright</Title>
   3325 
   3326 <Para>
   3327 EXT2ED is Copyright (C) 1995 Gadi Oxman.
   3328 </Para>
   3329 
   3330 <Para>
   3331 EXT2ED is hereby placed under the GPL - Gnu Public License. You are free and
   3332 welcome to copy, view and modify the sources. My only wish is that my
   3333 copyright presented above will be left and that a list of the bug fixes,
   3334 added features, etc, will be provided.
   3335 </Para>
   3336 
   3337 <Para>
   3338 The entire EXT2ED project is based, of-course, on the kernel sources. The
   3339 <Literal remap="tt">ext2.descriptors</Literal> distributed with EXT2ED is a slightly modified
   3340 version of the main ext2 include file, /usr/include/linux/ext2&lowbar;fs.h. Follows
   3341 the original copyright:
   3342 </Para>
   3343 
   3344 <Para>
   3345 
   3346 <ProgramListing>
   3347 /*
   3348  *  linux/include/linux/ext2_fs.h
   3349  *
   3350  * Copyright (C) 1992, 1993, 1994, 1995
   3351  * Remy Card (card (a] masi.ibp.fr)
   3352  * Laboratoire MASI - Institut Blaise Pascal
   3353  * Universite Pierre et Marie Curie (Paris VI)
   3354  *
   3355  *  from
   3356  *
   3357  *  linux/include/linux/minix_fs.h
   3358  *
   3359  *  Copyright (C) 1991, 1992  Linus Torvalds
   3360  */
   3361 
   3362 </ProgramListing>
   3363 
   3364 </Para>
   3365 
   3366 </Sect1>
   3367 
   3368 <Sect1>
   3369 <Title>Acknowledgments</Title>
   3370 
   3371 <Para>
   3372 EXT2ED was constructed as a student project in the software
   3373 laboratory of the faculty of electrical-engineering in the
   3374 <Literal remap="tt">Technion - Israel's institute of technology</Literal>.
   3375 </Para>
   3376 
   3377 <Para>
   3378 At first, I would like to thank <Literal remap="tt">Avner Lottem</Literal> and <Literal remap="tt">Doctor Ilana
   3379 David</Literal> for their interest and assistance in this project.
   3380 </Para>
   3381 
   3382 <Para>
   3383 I would also like to thank the following people, who were involved in the
   3384 design and implementation of the ext2 filesystem kernel code and support
   3385 utilities:
   3386 
   3387 <ItemizedList>
   3388 <ListItem>
   3389 
   3390 <Para>
   3391 	<Literal remap="tt">Remy Card</Literal>
   3392 
   3393 Who designed, implemented and maintains the ext2 filesystem kernel
   3394 code, and some of the ext2 utilities. <Literal remap="tt">Remy Card</Literal> is also the
   3395 author 	of several helpful slides concerning the ext2 filesystem.
   3396 Specifically, he is the author of <Literal remap="tt">File Management in the Linux
   3397 Kernel</Literal> and of <Literal remap="tt">The Second Extended File System - Current
   3398 State, Future Development</Literal>.
   3399 
   3400 </Para>
   3401 </ListItem>
   3402 <ListItem>
   3403 
   3404 <Para>
   3405 	<Literal remap="tt">Wayne Davison</Literal>
   3406 
   3407 Who designed the ext2 filesystem.
   3408 </Para>
   3409 </ListItem>
   3410 <ListItem>
   3411 
   3412 <Para>
   3413 	<Literal remap="tt">Stephen Tweedie</Literal>
   3414 
   3415 Who helped designing the ext2 filesystem kernel code and wrote the
   3416 slides <Literal remap="tt">Optimizations in File Systems</Literal>.
   3417 </Para>
   3418 </ListItem>
   3419 <ListItem>
   3420 
   3421 <Para>
   3422 	<Literal remap="tt">Theodore Ts'o</Literal>
   3423 
   3424 Who is the author of several ext2 utilities and of the ext2 library
   3425 <Literal remap="tt">libext2fs</Literal> (which I didn't use, simply because I didn't know
   3426 it exists when I started to work on my project).
   3427 </Para>
   3428 </ListItem>
   3429 
   3430 </ItemizedList>
   3431 
   3432 </Para>
   3433 
   3434 <Para>
   3435 Lastly, I would like to thank, of-course, <Literal remap="tt">Linus Torvalds</Literal> and the
   3436 <Literal remap="tt">Linux community</Literal> for providing all of us with such a great operating
   3437 system.
   3438 </Para>
   3439 
   3440 <Para>
   3441 Please contact me in a case of bug report, suggestions, or just about
   3442 anything concerning EXT2ED.
   3443 </Para>
   3444 
   3445 <Para>
   3446 Enjoy,
   3447 </Para>
   3448 
   3449 <Para>
   3450 Gadi Oxman &lt;tgud (a] tochnapc2.technion.ac.il&gt;
   3451 </Para>
   3452 
   3453 <Para>
   3454 Haifa, August 95
   3455 </Para>
   3456 
   3457 </Sect1>
   3458 
   3459 </Article>
   3460