1/*
2
3/usr/src/ext2ed/disk.c
4
5A part of the extended file system 2 disk editor.
6
7-------------------------------------------------
8The filesystem's disk activity pass through here.
9-------------------------------------------------
10
11This file is acting as a filter - Before we pass an actual read or write request to the operating system, we
12double check the various permissions and possible errors here.
13
14The major update which needs to be done here is switching to the use of the llseek system call, so that we will
15be able to support ext2 filesystems up to 4 TB. Currently, due to the standard fseek usage, we can't handle
16filesystems bigger than 4 GB. The limit is actually 2 GB because I used long rather than unsigned long long at too
17many places in the program. To conclude - This upgrade needs to be done carefuly; There are many places to change.
18
19First written on: April 9 1995
20
21Copyright (C) 1995 Gadi Oxman
22
23*/
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <time.h>
29
30#include "ext2ed.h"
31
32int write_access;
33
34int low_read (unsigned char *buffer,unsigned long length,unsigned long offset)
35
36/*
37
38This function is used when we need to read something from the filesystem.
39
40*/
41
42{
43
44#ifdef DEBUG
45
46	char temp [80];
47
48	if (device_handle==NULL) {					/* Check that a device is indeed open */
49		internal_error ("No device opened yet read requested","disk","low_read");
50		return (0);
51	}
52	if (offset > file_system_info.file_system_size) {		/* Check that the offset is within limits */
53		sprintf (temp,"Seek offset %ld is out of range",offset);
54		internal_error (temp,"disk","low_read");
55		return (0);
56	}
57
58#endif
59
60	if ( (fseek (device_handle,offset,SEEK_SET))==-1) {		/* Seek to the required offset */
61		wprintw (command_win,"Error - Failed to seek to offset %ld in device %s\n",offset,device_name);
62		refresh_command_win ();
63		return (0);
64	};
65
66	if ( (fread (buffer,1,length,device_handle))==-1) {		/* And do the actual reading */
67		wprintw (command_win,"Error - Failed to read from offset %ld in device %s\n",offset,device_name);
68		refresh_command_win ();return (0);
69	};
70
71	return (1);
72}
73
74int low_write (unsigned char *buffer,unsigned long length,unsigned long offset)
75
76/*
77
78This is used to change something in the filesystem.
79write_access is checked to see if we are allowed to do the actual writing.
80As a double safety measure, AllowChanges is rechecked here.
81If logging is enabled, we log the change before writing it to the device.
82
83*/
84{
85	char temp [80];
86
87	if (!write_access) {
88		wprintw (command_win,"Error - Write access not aviable (use enablewrite)\n");
89		return (0);
90	}
91
92#ifdef DEBUG
93
94	if (!AllowChanges) {
95		internal_error ("AllowChanges=0 yet enablewrite succeeded","disk","low_write");
96		return (0);
97	}
98
99	if (device_handle==NULL) {
100		internal_error ("No device opened yet read requested","disk","low_write");
101		return (0);
102	}
103
104	if (offset > file_system_info.file_system_size) {
105		sprintf (temp,"Seek offset %ld is out of range",offset);
106		internal_error (temp,"disk","low_write");
107		return (0);
108	}
109
110#endif
111
112	if (LogChanges)
113		if (!log_changes (buffer,length,offset))
114			return (0);
115
116	if ( (fseek (device_handle,offset,SEEK_SET))==-1) {
117		wprintw (command_win,"Error - Failed to seek to offset %ld in device %s\n",offset,device_name);
118		refresh_command_win ();return (0);
119	};
120
121
122	if ( (fwrite (buffer,1,length,device_handle))==-1) {
123		wprintw (command_win,"Error - Failed to write to offset %ld in device %s\n",offset,device_name);
124		refresh_command_win ();return (0);
125	};
126
127	wprintw (command_win,"Data written");refresh_command_win ();
128	return (1);
129}
130
131int log_changes (unsigned char *buffer,unsigned long length,unsigned long offset)
132
133/*
134
135Log the change in a primitive form - An hex dump of the data before the change and after the change.
136The hex bytes are converted to text, so that they will be readable with a standard text editor.
137
138*/
139
140{
141	unsigned char *original;
142
143	int i;
144	time_t current_time;
145	FILE *fp;
146
147	if ((fp=fopen (LogFile,"a+"))==NULL) {
148		wprintw (command_win,"Error - Unable to open log file %s\n",LogFile);
149		refresh_command_win ();return (0);
150	};
151
152	current_time=time (NULL);
153
154	fprintf (fp,"\n----- EXT2ED log begin -----\n\n");
155	fprintf (fp,"Time: %s\nDevice: %s\n",ctime ((time_t *) &current_time),device_name);
156	fprintf (fp,"Offset: %lu\nLength: %lu\n",offset,length);
157
158	original=(unsigned char *) malloc (length*sizeof (unsigned char));
159
160	if (original==NULL) {
161		wprintw (command_win,"Fatal error - Can\'t allocate %lu bytes!");
162		refresh_command_win ();fclose (fp);return (0);
163	}
164
165	if (!low_read (original,length,offset)) {
166		fclose (fp);return (0);
167	}
168
169	fprintf (fp,"\nOriginal data:\n\n");
170
171	for (i=0;i<length;i++) {
172		if (i%16==0 && i!=0) fprintf (fp,"\n");
173		fprintf (fp,"%02x ",original [i]);
174	}
175
176	fprintf (fp,"\n\nNew data:\n\n");
177
178	for (i=0;i<length;i++) {
179		if (i%16==0 && i!=0) fprintf (fp,"\n");
180		fprintf (fp,"%02x ",buffer [i]);
181	}
182
183	fprintf (fp,"\n----- EXT2ED log end  -----\n");
184
185	fclose (fp);
186	return (1);
187}
188
189int load_type_data (void)
190
191/*
192
193Just read from the current position into type data.
194
195*/
196
197{
198	if (device_handle==NULL) {
199		printf ("Error - No device opened\n");
200		return (0);
201	}
202
203	if (device_offset==-1) {
204		printf ("Error - No offset set\n");
205		return (0);
206	}
207
208	if (low_read (type_data.u.buffer,EXT2_MAX_BLOCK_SIZE,device_offset)==0)
209		return (0);
210
211	if (current_type!=NULL)
212		if (strcmp (current_type->name,"ext2_dir_entry")==0)
213			current_type->length=type_data.u.t_ext2_dir_entry.rec_len;
214
215	return (1);
216}
217
218int write_type_data (void)
219
220{
221	if (device_handle==NULL) {
222		wprintw (command_win,"Error - No device opened\n");
223		refresh_command_win ();
224		return (0);
225	}
226
227	if (device_offset==-1) {
228		wprintw (command_win,"Error - No offset set\n");
229		refresh_command_win ();
230		return (0);
231	}
232
233	if (low_write (type_data.u.buffer,file_system_info.block_size,device_offset)==0)
234		return (0);
235
236	return (1);
237}
238
239