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