1/*
2
3/usr/src/ext2ed/inode_com.c
4
5A part of the extended file system 2 disk editor.
6
7Commands relevant to ext2_inode type.
8
9First written on: April 9 1995
10
11Copyright (C) 1995 Gadi Oxman
12
13*/
14
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18#include <time.h>
19
20#include "ext2ed.h"
21
22void type_ext2_inode___prev (char *command_line)
23
24{
25
26	char *ptr,buffer [80];
27
28	long group_num,group_offset,entry_num,block_num,first_entry,last_entry;
29	long inode_num,mult=1;
30	struct ext2_group_desc desc;
31
32	ptr=parse_word (command_line,buffer);
33
34	if (*ptr!=0) {
35		ptr=parse_word (ptr,buffer);
36		mult=atol (buffer);
37	}
38
39	block_num=device_offset/file_system_info.block_size;
40
41	group_num=inode_offset_to_group_num (device_offset);
42	group_offset=file_system_info.first_group_desc_offset+group_num*sizeof (struct ext2_group_desc);
43
44	low_read ((char *) &desc,sizeof (struct ext2_group_desc),group_offset);
45
46	entry_num=(device_offset-desc.bg_inode_table*file_system_info.block_size)/sizeof (struct ext2_inode);
47
48	first_entry=0;last_entry=file_system_info.super_block.s_inodes_per_group-1;
49	inode_num=0;
50
51	if (entry_num-mult+1>0) {
52		device_offset-=sizeof (struct ext2_inode)*mult;
53		entry_num-=mult;
54
55		sprintf (buffer,"setoffset %ld",device_offset);dispatch (buffer);
56		strcpy (buffer,"show");dispatch (buffer);
57	}
58
59	else {
60		wprintw (command_win,"Error - Entry out of limits\n");refresh_command_win ();
61	}
62
63	if (entry_num==0) {
64		wprintw (command_win,"Reached first inode in current group descriptor\n");
65		refresh_command_win ();
66	}
67}
68
69void type_ext2_inode___next (char *command_line)
70
71{
72
73	char *ptr,buffer [80];
74
75	long group_num,group_offset,entry_num,block_num,first_entry,last_entry;
76	long inode_num,mult=1;
77	struct ext2_group_desc desc;
78
79	ptr=parse_word (command_line,buffer);
80
81	if (*ptr!=0) {
82		ptr=parse_word (ptr,buffer);
83		mult=atol (buffer);
84	}
85
86
87	block_num=device_offset/file_system_info.block_size;
88
89	group_num=inode_offset_to_group_num (device_offset);
90	group_offset=file_system_info.first_group_desc_offset+group_num*sizeof (struct ext2_group_desc);
91
92	low_read ((char *) &desc,sizeof (struct ext2_group_desc),group_offset);
93
94	entry_num=(device_offset-desc.bg_inode_table*file_system_info.block_size)/sizeof (struct ext2_inode);
95
96	first_entry=0;last_entry=file_system_info.super_block.s_inodes_per_group-1;
97	inode_num=0;
98
99	if (entry_num+mult-1<last_entry) {
100		device_offset+=sizeof (struct ext2_inode)*mult;
101		entry_num+=mult;
102
103		sprintf (buffer,"setoffset %ld",device_offset);dispatch (buffer);
104		strcpy (buffer,"show");dispatch (buffer);
105	}
106
107	else {
108		wprintw (command_win,"Error - Entry out of limits\n");refresh_command_win ();
109	}
110
111	if (entry_num==last_entry) {
112		wprintw (command_win,"Reached last inode in current group descriptor\n");
113		refresh_command_win ();
114	}
115}
116
117
118void type_ext2_inode___show (char *command_line)
119
120{
121	struct ext2_inode *inode_ptr;
122
123	unsigned short temp;
124	int i;
125
126	long group_num,group_offset,entry_num,block_num,first_entry,last_entry,inode_num;
127	struct ext2_group_desc desc;
128
129	block_num=device_offset/file_system_info.block_size;
130
131	group_num=inode_offset_to_group_num (device_offset);
132	group_offset=file_system_info.first_group_desc_offset+group_num*sizeof (struct ext2_group_desc);
133
134	low_read ((char *) &desc,sizeof (struct ext2_group_desc),group_offset);
135
136	entry_num=(device_offset-desc.bg_inode_table*file_system_info.block_size)/sizeof (struct ext2_inode);
137	first_entry=0;last_entry=file_system_info.super_block.s_inodes_per_group-1;
138	inode_num=group_num*file_system_info.super_block.s_inodes_per_group+1;
139	inode_num+=entry_num;
140
141	inode_ptr=&type_data.u.t_ext2_inode;
142
143	show (command_line);
144
145	wmove (show_pad,0,40);wprintw (show_pad,"octal = %06o ",inode_ptr->i_mode);
146	for (i=6;i>=0;i-=3) {
147		temp=inode_ptr->i_mode & 0x1ff;
148		temp=temp >> i;
149		if (temp & 4)
150			wprintw (show_pad,"r");
151		else
152			wprintw (show_pad,"-");
153
154		if (temp & 2)
155			wprintw (show_pad,"w");
156		else
157			wprintw (show_pad,"-");
158
159		if (temp & 1)
160			wprintw (show_pad,"x");
161		else
162			wprintw (show_pad,"-");
163	}
164	wmove (show_pad,3,40);wprintw (show_pad,"%s",ctime ((time_t *) &type_data.u.t_ext2_inode.i_atime));
165	wmove (show_pad,4,40);wprintw (show_pad,"%s",ctime ((time_t *) &type_data.u.t_ext2_inode.i_ctime));
166	wmove (show_pad,5,40);wprintw (show_pad,"%s",ctime ((time_t *) &type_data.u.t_ext2_inode.i_mtime));
167	wmove (show_pad,6,40);wprintw (show_pad,"%s",ctime ((time_t *) &type_data.u.t_ext2_inode.i_dtime));
168
169	wmove (show_pad,10,40);
170	temp=inode_ptr->i_flags;
171
172	if (temp & EXT2_SECRM_FL)
173		wprintw (show_pad,"s");
174	else
175		wprintw (show_pad,"-");
176
177
178	if (temp & EXT2_UNRM_FL)
179		wprintw (show_pad,"u");
180	else
181		wprintw (show_pad,"-");
182
183	if (temp & EXT2_COMPR_FL)
184		wprintw (show_pad,"c");
185	else
186		wprintw (show_pad,"-");
187
188	if (temp & EXT2_SYNC_FL)
189		wprintw (show_pad,"S");
190	else
191		wprintw (show_pad,"-");
192
193	if (temp & EXT2_IMMUTABLE_FL)
194		wprintw (show_pad,"i");
195	else
196		wprintw (show_pad,"-");
197
198	if (temp & EXT2_APPEND_FL)
199		wprintw (show_pad,"a");
200	else
201		wprintw (show_pad,"-");
202
203	if (temp & EXT2_NODUMP_FL)
204		wprintw (show_pad,"d");
205	else
206		wprintw (show_pad,"-");
207
208	refresh_show_pad ();
209
210	wmove (show_win,1,0);
211
212	wprintw (show_win,"Inode %ld of %ld. Entry %ld of %ld in group descriptor %ld.\n"
213		,inode_num,file_system_info.super_block.s_inodes_count,entry_num,last_entry,group_num);
214
215	wprintw (show_win,"Inode type: ");
216
217	if (inode_num < EXT2_GOOD_OLD_FIRST_INO) {
218		switch (inode_num) {
219			case EXT2_BAD_INO:
220				wprintw (show_win,"Bad blocks inode - ");
221				break;
222			case EXT2_ROOT_INO:
223				wprintw (show_win,"Root inode - ");
224				break;
225			case EXT4_USR_QUOTA_INO:
226				wprintw (show_win,"User quota inode - ");
227				break;
228			case EXT4_GRP_QUOTA_INO:
229				wprintw (show_win,"Group quota inode - ");
230				break;
231			case EXT2_BOOT_LOADER_INO:
232				wprintw (show_win,"Boot loader inode - ");
233				break;
234			case EXT2_UNDEL_DIR_INO:
235				wprintw (show_win,"Undelete directory inode - ");
236				break;
237			default:
238				wprintw (show_win,"Reserved inode - ");
239				break;
240		}
241	}
242	if (type_data.u.t_ext2_inode.i_mode==0)
243		wprintw (show_win,"Free.            ");
244
245	if (S_ISREG (type_data.u.t_ext2_inode.i_mode))
246		wprintw (show_win,"File.            ");
247
248	if (S_ISDIR (type_data.u.t_ext2_inode.i_mode))
249		wprintw (show_win,"Directory.       ");
250
251	if (S_ISLNK (type_data.u.t_ext2_inode.i_mode)) {
252		wprintw (show_win,"Symbolic link.   ");
253		wmove (show_pad,12,40);
254
255		if (inode_ptr->i_size <= 60)
256			wprintw (show_pad,"-> %s",(char *) &type_data.u.t_ext2_inode.i_block [0]);
257		else
258			wprintw (show_pad,"Slow symbolic link\n");
259		refresh_show_pad ();
260	}
261
262	if (S_ISCHR (type_data.u.t_ext2_inode.i_mode))
263		wprintw (show_win,"Character device.");
264
265	if (S_ISBLK (type_data.u.t_ext2_inode.i_mode))
266		wprintw (show_win,"Block device.    ");
267
268	wprintw (show_win,"\n");refresh_show_win ();
269
270	if (entry_num==last_entry) {
271		wprintw (command_win,"Reached last inode in current group descriptor\n");
272		refresh_command_win ();
273	}
274
275	if (entry_num==first_entry) {
276		wprintw (command_win,"Reached first inode in current group descriptor\n");
277		refresh_command_win ();
278	}
279
280}
281
282void type_ext2_inode___entry (char *command_line)
283
284{
285	char *ptr,buffer [80];
286
287	long group_num,group_offset,entry_num,block_num,wanted_entry;
288	struct ext2_group_desc desc;
289
290	ptr=parse_word (command_line,buffer);
291	if (*ptr==0) return;
292	ptr=parse_word (ptr,buffer);
293	wanted_entry=atol (buffer);
294
295	block_num=device_offset/file_system_info.block_size;
296
297	group_num=inode_offset_to_group_num (device_offset);
298	group_offset=file_system_info.first_group_desc_offset+group_num*sizeof (struct ext2_group_desc);
299
300	low_read ((char *) &desc,sizeof (struct ext2_group_desc),group_offset);
301
302	entry_num=(device_offset-desc.bg_inode_table*file_system_info.block_size)/sizeof (struct ext2_inode);
303
304	if (wanted_entry > entry_num) {
305		sprintf (buffer,"next %ld",wanted_entry-entry_num);
306		dispatch (buffer);
307	}
308
309	else if (wanted_entry < entry_num) {
310		sprintf (buffer,"prev %ld",entry_num-wanted_entry);
311		dispatch (buffer);
312	}
313}
314
315void type_ext2_inode___group (char *command_line)
316
317{
318	char buffer [80];
319
320	long group_num,group_offset;
321
322	group_num=inode_offset_to_group_num (device_offset);
323	group_offset=file_system_info.first_group_desc_offset+group_num*sizeof (struct ext2_group_desc);
324
325	sprintf (buffer,"setoffset %ld",group_offset);dispatch (buffer);
326	sprintf (buffer,"settype ext2_group_desc");dispatch (buffer);
327}
328
329void type_ext2_inode___file (char *command_line)
330
331{
332	char buffer [80];
333
334	if (!S_ISREG (type_data.u.t_ext2_inode.i_mode)) {
335		wprintw (command_win,"Error - Inode type is not file\n");refresh_command_win ();
336		return;
337	}
338
339	if (!init_file_info ()) {
340		wprintw (command_win,"Error - Unable to show file\n");refresh_command_win ();
341		return;
342	}
343
344	sprintf (buffer,"settype file");dispatch (buffer);
345}
346
347void type_ext2_inode___dir (char *command_line)
348
349{
350	char buffer [80];
351
352	if (!S_ISDIR (type_data.u.t_ext2_inode.i_mode)) {
353		wprintw (command_win,"Error - Inode type is not directory\n");refresh_command_win ();
354		return;
355	}
356
357/* It is very important to init first_file_info first, as search_dir_entries relies on it */
358
359	if (!init_dir_info (&first_file_info)) {
360		wprintw (command_win,"Error - Unable to show directory\n");refresh_command_win ();
361		return;
362	}
363
364	file_info=first_file_info;
365
366	sprintf (buffer,"settype dir");dispatch (buffer);
367}
368
369long inode_offset_to_group_num (long inode_offset)
370
371{
372	int found=0;
373	struct ext2_group_desc desc;
374
375	long block_num,group_offset,group_num;
376
377	block_num=inode_offset/file_system_info.block_size;
378
379	group_offset=file_system_info.first_group_desc_offset;
380	group_num=(group_offset-file_system_info.first_group_desc_offset)/sizeof (struct ext2_group_desc);
381
382	while (!found && group_num>=0 && group_num<file_system_info.groups_count) {
383		low_read ((char *) &desc,sizeof (struct ext2_group_desc),group_offset);
384		if (block_num>=desc.bg_inode_table && block_num<desc.bg_inode_table+file_system_info.blocks_per_group)
385			found=1;
386		else
387			group_offset+=sizeof (struct ext2_group_desc);
388		group_num=(group_offset-file_system_info.first_group_desc_offset)/sizeof (struct ext2_group_desc);
389	}
390
391	if (!found)
392		return (-1);
393
394	return (group_num);
395}
396
397
398
399long int inode_offset_to_inode_num (long inode_offset)
400
401{
402	long group_num,group_offset,entry_num,block_num,first_entry,last_entry,inode_num;
403	struct ext2_group_desc desc;
404
405	block_num=inode_offset/file_system_info.block_size;
406
407	group_num=inode_offset_to_group_num (inode_offset);
408	group_offset=file_system_info.first_group_desc_offset+group_num*sizeof (struct ext2_group_desc);
409
410	low_read ((char *) &desc,sizeof (struct ext2_group_desc),group_offset);
411
412	entry_num=(inode_offset-desc.bg_inode_table*file_system_info.block_size)/sizeof (struct ext2_inode);
413	first_entry=0;last_entry=file_system_info.super_block.s_inodes_per_group-1;
414	inode_num=group_num*file_system_info.super_block.s_inodes_per_group+1;
415	inode_num+=entry_num;
416
417	return (inode_num);
418}
419
420long int inode_num_to_inode_offset (long inode_num)
421
422{
423	long group_num,group_offset,inode_offset,inode_entry;
424	struct ext2_group_desc desc;
425
426	inode_num--;
427
428	group_num=inode_num/file_system_info.super_block.s_inodes_per_group;
429	inode_entry=inode_num%file_system_info.super_block.s_inodes_per_group;
430	group_offset=file_system_info.first_group_desc_offset+group_num*sizeof (struct ext2_group_desc);
431	low_read ((char *) &desc,sizeof (struct ext2_group_desc),group_offset);
432
433	inode_offset=desc.bg_inode_table*file_system_info.block_size+inode_entry*sizeof (struct ext2_inode);
434
435	return (inode_offset);
436}
437