1/*
2
3/usr/src/ext2ed/file_com.c
4
5A part of the extended file system 2 disk editor.
6
7----------------------------
8Commands which handle a file
9----------------------------
10
11First written on: April 18 1995
12
13Copyright (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
23int 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
50void type_file___inode (char *command_line)
51
52{
53	dispatch ("settype ext2_inode");
54}
55
56void 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
65void 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
93void 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
116void 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
143void 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
166void 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
194void 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
225void 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
253void 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
317void 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
379void 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
396void 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
436void 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
499void 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
506long 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
537long 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
546long 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
556long 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}
565