Merge change 9990
[android/platform/external/e2fsprogs.git] / ext2ed / file_com.c
1 /*
2
3 /usr/src/ext2ed/file_com.c
4
5 A part of the extended file system 2 disk editor.
6
7 ----------------------------
8 Commands which handle a file
9 ----------------------------
10
11 First written on: April 18 1995
12
13 Copyright (C) 1995 Gadi Oxman
14
15 */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20
21 #include "ext2ed.h"
22
23 int init_file_info (void)
24
25 {
26         struct ext2_inode *ptr;
27         
28         ptr=&type_data.u.t_ext2_inode;
29         
30         file_info.inode_ptr=ptr;
31         file_info.inode_offset=device_offset;
32
33         file_info.global_block_num=ptr->i_block [0];
34         file_info.global_block_offset=ptr->i_block [0]*file_system_info.block_size;
35         file_info.block_num=0;
36         file_info.blocks_count=(ptr->i_size+file_system_info.block_size-1)/file_system_info.block_size;
37         file_info.file_offset=0;
38         file_info.file_length=ptr->i_size;
39         file_info.level=0;
40         file_info.offset_in_block=0;
41         
42         file_info.display=HEX;
43
44         low_read (file_info.buffer,file_system_info.block_size,file_info.global_block_offset);
45         
46         return (1);
47 }
48
49
50 void type_file___inode (char *command_line)
51
52 {
53         dispatch ("settype ext2_inode");
54 }
55
56 void type_file___show (char *command_line)
57
58 {
59         if (file_info.display==HEX)
60                 file_show_hex ();
61         if (file_info.display==TEXT)
62                 file_show_text ();
63 }
64
65 void type_file___nextblock (char *command_line)
66
67 {
68         long block_offset=1;
69         char *ptr,buffer [80];
70
71         ptr=parse_word (command_line,buffer);
72         
73         if (*ptr!=0) {
74                 ptr=parse_word (ptr,buffer);
75                 block_offset*=atol (buffer);
76         }
77
78         if (file_info.block_num+block_offset >= file_info.blocks_count) {
79                 wprintw (command_win,"Error - Block offset out of range\n");wrefresh (command_win);
80                 return;
81         }
82         
83         file_info.block_num+=block_offset;
84         file_info.global_block_num=file_block_to_global_block (file_info.block_num,&file_info);
85         file_info.global_block_offset=file_info.global_block_num*file_system_info.block_size;
86         file_info.file_offset=file_info.block_num*file_system_info.block_size;
87
88         low_read (file_info.buffer,file_system_info.block_size,file_info.global_block_offset);
89
90         strcpy (buffer,"show");dispatch (buffer);
91 }
92
93 void type_file___next (char *command_line)
94
95 {
96         int offset=1;
97         char *ptr,buffer [80];
98
99         ptr=parse_word (command_line,buffer);
100         
101         if (*ptr!=0) {
102                 ptr=parse_word (ptr,buffer);
103                 offset*=atol (buffer);
104         }
105         
106         if (file_info.offset_in_block+offset < file_system_info.block_size) {
107                 file_info.offset_in_block+=offset;
108                 sprintf (buffer,"show");dispatch (buffer);
109         }
110                 
111         else {
112                 wprintw (command_win,"Error - Offset out of block\n");refresh_command_win ();
113         }
114 }
115
116 void type_file___offset (char *command_line)
117
118 {
119         unsigned long offset;
120         char *ptr,buffer [80];
121
122         ptr=parse_word (command_line,buffer);
123         
124         if (*ptr!=0) {
125                 ptr=parse_word (ptr,buffer);
126                 offset=atol (buffer);
127         }
128         else {
129                 wprintw (command_win,"Error - Argument not specified\n");refresh_command_win ();
130                 return;
131         }
132         
133         if (offset < file_system_info.block_size) {
134                 file_info.offset_in_block=offset;
135                 sprintf (buffer,"show");dispatch (buffer);
136         }
137
138         else {
139                 wprintw (command_win,"Error - Offset out of block\n");refresh_command_win ();
140         }
141 }
142
143 void type_file___prev (char *command_line)
144
145 {
146         int offset=1;
147         char *ptr,buffer [80];
148
149         ptr=parse_word (command_line,buffer);
150         
151         if (*ptr!=0) {
152                 ptr=parse_word (ptr,buffer);
153                 offset*=atol (buffer);
154         }
155         
156         if (file_info.offset_in_block-offset >= 0) {
157                 file_info.offset_in_block-=offset;
158                 sprintf (buffer,"show");dispatch (buffer);
159         }
160         
161         else {
162                 wprintw (command_win,"Error - Offset out of block\n");refresh_command_win ();
163         }
164 }
165
166 void type_file___prevblock (char *command_line)
167
168 {
169         long block_offset=1;
170         char *ptr,buffer [80];
171
172         ptr=parse_word (command_line,buffer);
173         
174         if (*ptr!=0) {
175                 ptr=parse_word (ptr,buffer);
176                 block_offset*=atol (buffer);
177         }
178
179         if (file_info.block_num-block_offset < 0) {
180                 wprintw (command_win,"Error - Block offset out of range\n");wrefresh (command_win);
181                 return;
182         }
183         
184         file_info.block_num-=block_offset;
185         file_info.global_block_num=file_block_to_global_block (file_info.block_num,&file_info);
186         file_info.global_block_offset=file_info.global_block_num*file_system_info.block_size;
187         file_info.file_offset=file_info.block_num*file_system_info.block_size;
188
189         low_read (file_info.buffer,file_system_info.block_size,file_info.global_block_offset);
190
191         strcpy (buffer,"show");dispatch (buffer);
192 }
193
194 void type_file___block (char *command_line)
195
196 {
197         long block_offset=1;
198         char *ptr,buffer [80];
199
200         ptr=parse_word (command_line,buffer);
201         
202         if (*ptr==0) {
203                 wprintw (command_win,"Error - Invalid arguments\n");wrefresh (command_win);
204                 return;
205         }
206         
207         ptr=parse_word (ptr,buffer);
208         block_offset=atol (buffer);
209
210         if (block_offset < 0 || block_offset >= file_info.blocks_count) {
211                 wprintw (command_win,"Error - Block offset out of range\n");wrefresh (command_win);
212                 return;
213         }
214
215         file_info.block_num=block_offset;
216         file_info.global_block_num=file_block_to_global_block (file_info.block_num,&file_info);
217         file_info.global_block_offset=file_info.global_block_num*file_system_info.block_size;
218         file_info.file_offset=file_info.block_num*file_system_info.block_size;
219
220         low_read (file_info.buffer,file_system_info.block_size,file_info.global_block_offset);
221
222         strcpy (buffer,"show");dispatch (buffer);
223 }
224
225 void type_file___display (char *command_line)
226
227 {
228         char *ptr,buffer [80];
229         
230         ptr=parse_word (command_line,buffer);
231         if (*ptr==0) 
232                 strcpy (buffer,"hex");
233         else
234                 ptr=parse_word (ptr,buffer);
235         
236         if (strcasecmp (buffer,"hex")==0) {
237                 wprintw (command_win,"Display set to hex\n");wrefresh (command_win);
238                 file_info.display=HEX;
239                 sprintf (buffer,"show");dispatch (buffer);
240         }
241         
242         else if (strcasecmp (buffer,"text")==0) {
243                 wprintw (command_win,"Display set to text\n");wrefresh (command_win);
244                 file_info.display=TEXT;
245                 sprintf (buffer,"show");dispatch (buffer);
246         }
247         
248         else {
249                 wprintw (command_win,"Error - Invalid arguments\n");wrefresh (command_win);
250         }
251 }
252
253 void file_show_hex (void)
254
255 {
256         long offset=0,l,i;
257         unsigned char *ch_ptr;
258         
259         /* device_offset and type_data points to the inode */
260
261         show_pad_info.line=0;
262         
263         wmove (show_pad,0,0);
264         ch_ptr=file_info.buffer;
265         for (l=0;l<file_system_info.block_size/16;l++) {
266                 if (file_info.file_offset+offset>file_info.file_length-1) break;
267                 wprintw (show_pad,"%08ld :  ",offset);
268                 for (i=0;i<16;i++) {
269                         
270                         if (file_info.file_offset+offset+i>file_info.file_length-1) {
271                                 wprintw (show_pad," ");
272                         }
273                         
274                         else {
275                                 if (file_info.offset_in_block==offset+i)
276                                         wattrset (show_pad,A_REVERSE);
277
278                                 if (ch_ptr [i]>=' ' && ch_ptr [i]<='z')
279                                         wprintw (show_pad,"%c",ch_ptr [i]);
280                                 else
281                                         wprintw (show_pad,".");
282
283                                 if (file_info.offset_in_block==offset+i)
284                                         wattrset (show_pad,A_NORMAL);
285                         }
286                 }
287
288                 wprintw (show_pad,"   ");
289                 for (i=0;i<16;i++) {
290                         if (file_info.file_offset+offset+i>file_info.file_length-1) break;
291                         if (file_info.offset_in_block==offset+i)
292                                 wattrset (show_pad,A_REVERSE);
293
294                         wprintw (show_pad,"%02x",ch_ptr [i]);
295
296                         if (file_info.offset_in_block==offset+i) {
297                                 wattrset (show_pad,A_NORMAL);
298                                 show_pad_info.line=l-l % show_pad_info.display_lines;
299                         }
300                         
301                         wprintw (show_pad," ");
302                         
303                 }
304
305                 wprintw (show_pad,"\n");
306                 offset+=i;
307                 ch_ptr+=i;
308         }
309         
310         show_pad_info.max_line=l-1;
311         
312         refresh_show_pad ();
313         
314         show_status ();
315 }
316
317 void file_show_text (void)
318
319 {
320         long offset=0,last_offset,l=0,cols=0;
321         unsigned char *ch_ptr;
322         
323         /* device_offset and type_data points to the inode */
324
325         show_pad_info.line=0;
326         wmove (show_pad,0,0);
327         ch_ptr=file_info.buffer;
328
329         last_offset=file_system_info.block_size-1;
330
331         if (file_info.file_offset+last_offset > file_info.file_length-1)
332                 last_offset=file_info.file_length-1-file_info.file_offset;
333                 
334         while ( (offset <= last_offset) && l<SHOW_PAD_LINES) {
335
336                 if (cols==SHOW_PAD_COLS-1) {
337                         wprintw (show_pad,"\n");
338                         l++;cols=0;
339                 }
340                 
341
342                 if (file_info.offset_in_block==offset)
343                         wattrset (show_pad,A_REVERSE);
344
345                 if (*ch_ptr >= ' ' && *ch_ptr <= 'z')
346                         wprintw (show_pad,"%c",*ch_ptr);
347
348
349                 else {
350                         if (*ch_ptr == 0xa) {
351                                 wprintw (show_pad,"\n");
352                                 l++;cols=0;
353                         }
354
355                         else if (*ch_ptr == 0x9)
356                                 wprintw (show_pad,"    ");
357                         
358                         else
359                                 wprintw (show_pad,".");
360                 }
361
362                 if (file_info.offset_in_block==offset) {
363                         wattrset (show_pad,A_NORMAL);
364                         show_pad_info.line=l-l % show_pad_info.display_lines;
365                 }
366                         
367
368                 offset++;cols++;ch_ptr++;
369         }
370         
371         wprintw (show_pad,"\n");
372         show_pad_info.max_line=l;
373         
374         refresh_show_pad ();
375         
376         show_status (); 
377 }
378
379 void show_status (void)
380
381 {
382         long inode_num;
383         
384         werase (show_win);wmove (show_win,0,0);
385         wprintw (show_win,"File contents. Block %ld. ",file_info.global_block_num);
386         wprintw (show_win,"File block %ld of %ld. ",file_info.block_num,file_info.blocks_count-1);
387         wprintw (show_win,"File Offset %ld of %ld.",file_info.file_offset,file_info.file_length-1);
388         
389         wmove (show_win,1,0);
390         inode_num=inode_offset_to_inode_num (file_info.inode_offset);
391         wprintw (show_win,"File inode %ld. Indirection level %ld.",inode_num,file_info.level);
392
393         refresh_show_win ();
394 }
395
396 void type_file___remember (char *command_line)
397
398 {
399         int found=0;
400         long entry_num;
401         char *ptr,buffer [80];
402         struct struct_descriptor *descriptor_ptr;
403         
404         ptr=parse_word (command_line,buffer);
405         
406         if (*ptr==0) {
407                 wprintw (command_win,"Error - Argument not specified\n");wrefresh (command_win);
408                 return;         
409         }
410         
411         ptr=parse_word (ptr,buffer);
412
413         entry_num=remember_lifo.entries_count++;
414         if (entry_num>REMEMBER_COUNT-1) {
415                 entry_num=0;
416                 remember_lifo.entries_count--;
417         }
418         
419         descriptor_ptr=first_type;
420         while (descriptor_ptr!=NULL && !found) {
421                 if (strcmp (descriptor_ptr->name,"ext2_inode")==0)
422                         found=1;
423                 else
424                         descriptor_ptr=descriptor_ptr->next;
425         }
426
427
428         remember_lifo.offset [entry_num]=device_offset;
429         remember_lifo.type [entry_num]=descriptor_ptr;
430         strcpy (remember_lifo.name [entry_num],buffer);
431         
432         wprintw (command_win,"Object %s in Offset %ld remembered as %s\n",descriptor_ptr->name,device_offset,buffer);
433         wrefresh (command_win);
434 }
435
436 void type_file___set (char *command_line)
437
438 {
439         unsigned char tmp;
440         char *ptr,buffer [80],*ch_ptr;
441         int mode=HEX;
442         
443         ptr=parse_word (command_line,buffer);
444         if (*ptr==0) {
445                 wprintw (command_win,"Error - Argument not specified\n");refresh_command_win ();return;
446         }
447
448         ptr=parse_word (ptr,buffer);
449
450         if (strcasecmp (buffer,"text")==0) {
451                 mode=TEXT;
452                 strcpy (buffer,ptr);
453         }
454
455         else if (strcasecmp (buffer,"hex")==0) {
456                 mode=HEX;
457                 ptr=parse_word (ptr,buffer);
458         }
459
460         if (*buffer==0) {
461                 wprintw (command_win,"Error - Data not specified\n");refresh_command_win ();return;
462         }
463
464         if (mode==HEX) {
465                 do {
466                         tmp=(unsigned char) strtol (buffer,NULL,16);
467                         file_info.buffer [file_info.offset_in_block]=tmp;
468                         file_info.offset_in_block++;
469                         ptr=parse_word (ptr,buffer);
470                         if (file_info.offset_in_block==file_system_info.block_size) {
471                                 if (*ptr) {
472                                         wprintw (command_win,"Error - Ending offset outside block, only partial string changed\n");
473                                         refresh_command_win ();
474                                 }
475                                 file_info.offset_in_block--;
476                         }
477                 } while (*buffer) ;
478         }
479
480         else {
481                 ch_ptr=buffer;
482                 while (*ch_ptr) {
483                         tmp=(unsigned char) *ch_ptr++;
484                         file_info.buffer [file_info.offset_in_block]=tmp;
485                         file_info.offset_in_block++;
486                         if (file_info.offset_in_block==file_system_info.block_size) {
487                                 if (*ch_ptr) {
488                                         wprintw (command_win,"Error - Ending offset outside block, only partial string changed\n");
489                                         refresh_command_win ();
490                                 }
491                                 file_info.offset_in_block--;
492                         }
493                 }
494         }
495         
496         strcpy (buffer,"show");dispatch (buffer);
497 }
498
499 void type_file___writedata (char *command_line)
500
501 {
502         low_write (file_info.buffer,file_system_info.block_size,file_info.global_block_offset);
503         return;
504 }
505
506 long file_block_to_global_block (long file_block,struct struct_file_info *file_info_ptr)
507
508 {
509         long last_direct,last_indirect,last_dindirect;
510         
511         last_direct=EXT2_NDIR_BLOCKS-1;
512         last_indirect=last_direct+file_system_info.block_size/4;
513         last_dindirect=last_indirect+(file_system_info.block_size/4)*(file_system_info.block_size/4);
514
515         if (file_block <= last_direct) {
516                 file_info_ptr->level=0;
517                 return (file_info_ptr->inode_ptr->i_block [file_block]);
518         }
519         
520         if (file_block <= last_indirect) {
521                 file_info_ptr->level=1;
522                 file_block=file_block-last_direct-1;
523                 return (return_indirect (file_info_ptr->inode_ptr->i_block [EXT2_IND_BLOCK],file_block));
524         }
525
526         if (file_block <= last_dindirect) {
527                 file_info_ptr->level=2;
528                 file_block=file_block-last_indirect-1;
529                 return (return_dindirect (file_info_ptr->inode_ptr->i_block [EXT2_DIND_BLOCK],file_block));
530         }
531
532         file_info_ptr->level=3;
533         file_block=file_block-last_dindirect-1;
534         return (return_tindirect (file_info_ptr->inode_ptr->i_block [EXT2_TIND_BLOCK],file_block));
535 }
536
537 long return_indirect (long table_block,long block_num)
538
539 {
540         long block_table [EXT2_MAX_BLOCK_SIZE/4];
541         
542         low_read ((char *) block_table,file_system_info.block_size,table_block*file_system_info.block_size);
543         return (block_table [block_num]);               
544 }
545
546 long return_dindirect (long table_block,long block_num)
547
548 {
549         long f_indirect;
550         
551         f_indirect=block_num/(file_system_info.block_size/4);
552         f_indirect=return_indirect (table_block,f_indirect);
553         return (return_indirect (f_indirect,block_num%(file_system_info.block_size/4)));
554 }
555
556 long return_tindirect (long table_block,long block_num)
557
558 {
559         long s_indirect;
560         
561         s_indirect=block_num/((file_system_info.block_size/4)*(file_system_info.block_size/4));
562         s_indirect=return_indirect (table_block,s_indirect);
563         return (return_dindirect (s_indirect,block_num%((file_system_info.block_size/4)*(file_system_info.block_size/4))));
564 }