added port of dosfsck. Does not work yet as I cannot figure how to open the device...
[reactos.git] / rosapps / sysutils / dosfsck / io.c
1 /* io.c - Virtual disk input/output */
2
3 /* Written 1993 by Werner Almesberger */
4
5 /*
6 * Thu Feb 26 01:15:36 CET 1998: Martin Schulze <joey@infodrom.north.de>
7 * Fixed nasty bug that caused every file with a name like
8 * xxxxxxxx.xxx to be treated as bad name that needed to be fixed.
9 */
10
11 /* FAT32, VFAT, Atari format support, and various fixes additions May 1998
12 * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
13
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <unistd.h>
18 #include <sys/stat.h>
19 //#include <sys/ioctl.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 //#include <linux/fd.h>
23
24
25 #ifdef _WIN32
26 #define _WIN32_WINNT 0x0400
27 #include <windows.h>
28 #include <winioctl.h>
29 #define __LITTLE_ENDIAN 1234
30 #define __BIG_ENDIAN 4321
31 #define __BYTE_ORDER __LITTLE_ENDIAN
32 #define inline
33 #define __attribute__(x)
34 #define BLOCK_SIZE 512
35 #endif
36
37
38 #include "dosfsck.h"
39 #include "common.h"
40 #include "io.h"
41
42
43 typedef struct _change {
44 void *data;
45 loff_t pos;
46 int size;
47 struct _change *next;
48 } CHANGE;
49
50
51 static CHANGE *changes,*last;
52 static int fd,did_change = 0;
53
54 unsigned device_no;
55
56 void fs_open(char *path,int rw)
57 {
58 //#ifdef _WIN32
59 // static char dev_buf[] = "\\\\.\\X:";
60 //#else
61 struct stat stbuf;
62 //#endif
63 if ((fd = open(path,rw ? O_RDWR : O_RDONLY)) < 0)
64 pdie("open %s",path);
65 changes = last = NULL;
66 did_change = 0;
67
68 if (fstat(fd,&stbuf) < 0)
69 pdie("fstat %s",path);
70 device_no = S_ISBLK(stbuf.st_mode) ? (stbuf.st_rdev >> 8) & 0xff : 0;
71 }
72
73
74 void fs_read(loff_t pos,int size,void *data)
75 {
76 CHANGE *walk;
77 int got;
78
79 if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos);
80 if ((got = read(fd,data,size)) < 0) pdie("Read %d bytes at %lld",size,pos);
81 if (got != size) die("Got %d bytes instead of %d at %lld",got,size,pos);
82 for (walk = changes; walk; walk = walk->next) {
83 if (walk->pos < pos+size && walk->pos+walk->size > pos) {
84 if (walk->pos < pos)
85 memcpy(data,(char *) walk->data+pos-walk->pos,min(size,
86 walk->size-pos+walk->pos));
87 else memcpy((char *) data+walk->pos-pos,walk->data,min(walk->size,
88 size+pos-walk->pos));
89 }
90 }
91 }
92
93
94 int fs_test(loff_t pos,int size)
95 {
96 void *scratch;
97 int okay;
98
99 if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos);
100 scratch = alloc(size);
101 okay = read(fd,scratch,size) == size;
102 free(scratch);
103 return okay;
104 }
105
106
107 void fs_write(loff_t pos,int size,void *data)
108 {
109 CHANGE *new;
110 int did;
111
112 if (write_immed) {
113 did_change = 1;
114 if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos);
115 if ((did = write(fd,data,size)) == size) return;
116 if (did < 0) pdie("Write %d bytes at %lld",size,pos);
117 die("Wrote %d bytes instead of %d at %lld",did,size,pos);
118 }
119 new = alloc(sizeof(CHANGE));
120 new->pos = pos;
121 memcpy(new->data = alloc(new->size = size),data,size);
122 new->next = NULL;
123 if (last) last->next = new;
124 else changes = new;
125 last = new;
126 }
127
128
129 static void fs_flush(void)
130 {
131 CHANGE *this;
132 int size;
133
134 while (changes) {
135 this = changes;
136 changes = changes->next;
137 if (llseek(fd,this->pos,0) != this->pos)
138 fprintf(stderr,"Seek to %lld failed: %s\n Did not write %d bytes.\n",
139 (long long)this->pos,strerror(errno),this->size);
140 else if ((size = write(fd,this->data,this->size)) < 0)
141 fprintf(stderr,"Writing %d bytes at %lld failed: %s\n",this->size,
142 (long long)this->pos,strerror(errno));
143 else if (size != this->size)
144 fprintf(stderr,"Wrote %d bytes instead of %d bytes at %lld."
145 "\n",size,this->size,(long long)this->pos);
146 free(this->data);
147 free(this);
148 }
149 }
150
151
152 int fs_close(int write)
153 {
154 CHANGE *next;
155 int changed;
156
157 changed = !!changes;
158 if (write) fs_flush();
159 else while (changes) {
160 next = changes->next;
161 free(changes->data);
162 free(changes);
163 changes = next;
164 }
165 if (close(fd) < 0) pdie("closing file system");
166 return changed || did_change;
167 }
168
169
170 int fs_changed(void)
171 {
172 return !!changes || did_change;
173 }
174
175 /* Local Variables: */
176 /* tab-width: 8 */
177 /* End: */
178
179
180 #define open WIN32open
181 #define close WIN32close
182 #define read WIN32read
183 #define write WIN32write
184 #define llseek WIN32llseek
185
186 #define O_SHORT_LIVED _O_SHORT_LIVED
187 #define O_ACCMODE 3
188 #define O_NONE 3
189 #define O_BACKUP 0x10000
190 #define O_SHARED 0x20000
191
192 static int WIN32open(const char *path, int oflag, ...)
193 {
194 HANDLE fh;
195 DWORD desiredAccess;
196 DWORD shareMode;
197 DWORD creationDisposition;
198 DWORD flagsAttributes = FILE_ATTRIBUTE_NORMAL;
199 SECURITY_ATTRIBUTES securityAttributes;
200 va_list ap;
201 int pmode;
202 int trunc = FALSE;
203
204 securityAttributes.nLength = sizeof(securityAttributes);
205 securityAttributes.lpSecurityDescriptor = NULL;
206 securityAttributes.bInheritHandle = oflag & O_NOINHERIT ? FALSE : TRUE;
207 switch (oflag & O_ACCMODE) {
208 case O_RDONLY:
209 desiredAccess = GENERIC_READ;
210 shareMode = FILE_SHARE_READ;
211 break;
212 case O_WRONLY:
213 desiredAccess = GENERIC_WRITE;
214 shareMode = 0;
215 break;
216 case O_RDWR:
217 desiredAccess = GENERIC_READ|GENERIC_WRITE;
218 shareMode = 0;
219 break;
220 case O_NONE:
221 desiredAccess = 0;
222 shareMode = FILE_SHARE_READ|FILE_SHARE_WRITE;
223 }
224 if (oflag & O_APPEND) {
225 desiredAccess |= FILE_APPEND_DATA|SYNCHRONIZE;
226 shareMode = FILE_SHARE_READ|FILE_SHARE_WRITE;
227 }
228 if (oflag & O_SHARED)
229 shareMode |= FILE_SHARE_READ|FILE_SHARE_WRITE;
230 switch (oflag & (O_CREAT|O_EXCL|O_TRUNC)) {
231 case 0:
232 case O_EXCL:
233 creationDisposition = OPEN_EXISTING;
234 break;
235 case O_CREAT:
236 creationDisposition = OPEN_ALWAYS;
237 break;
238 case O_CREAT|O_EXCL:
239 case O_CREAT|O_TRUNC|O_EXCL:
240 creationDisposition = CREATE_NEW;
241 break;
242 case O_TRUNC:
243 case O_TRUNC|O_EXCL:
244 creationDisposition = TRUNCATE_EXISTING;
245 break;
246 case O_CREAT|O_TRUNC:
247 creationDisposition = OPEN_ALWAYS;
248 trunc = TRUE;
249 break;
250 }
251 if (oflag & O_CREAT) {
252 va_start(ap, oflag);
253 pmode = va_arg(ap, int);
254 va_end(ap);
255 if ((pmode & 0222) == 0)
256 flagsAttributes |= FILE_ATTRIBUTE_READONLY;
257 }
258 if (oflag & O_TEMPORARY) {
259 flagsAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
260 desiredAccess |= DELETE;
261 }
262 if (oflag & O_SHORT_LIVED)
263 flagsAttributes |= FILE_ATTRIBUTE_TEMPORARY;
264 if (oflag & O_SEQUENTIAL)
265 flagsAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
266 else if (oflag & O_RANDOM)
267 flagsAttributes |= FILE_FLAG_RANDOM_ACCESS;
268 if (oflag & O_BACKUP)
269 flagsAttributes |= FILE_FLAG_BACKUP_SEMANTICS;
270 if ((fh = CreateFile(path, desiredAccess, shareMode, &securityAttributes,
271 creationDisposition, flagsAttributes, NULL)) == INVALID_HANDLE_VALUE) {
272 errno = GetLastError();
273 return -1;
274 }
275 if (trunc) {
276 if (!SetEndOfFile(fh)) {
277 errno = GetLastError();
278 CloseHandle(fh);
279 DeleteFile(path);
280 return -1;
281 }
282 }
283 return (int)fh;
284 }
285
286 static int WIN32close(int fd)
287 {
288 if (!CloseHandle((HANDLE)fd)) {
289 errno = GetLastError();
290 return -1;
291 }
292 return 0;
293 }
294
295 static int WIN32read(int fd, void *buf, unsigned int len)
296 {
297 DWORD actualLen;
298
299 if (!ReadFile((HANDLE)fd, buf, (DWORD)len, &actualLen, NULL)) {
300 errno = GetLastError();
301 if (errno == ERROR_BROKEN_PIPE)
302 return 0;
303 else
304 return -1;
305 }
306 return (int)actualLen;
307 }
308
309 static int WIN32write(int fd, void *buf, unsigned int len)
310 {
311 DWORD actualLen;
312
313 if (!WriteFile((HANDLE)fd, buf, (DWORD)len, &actualLen, NULL)) {
314 errno = GetLastError();
315 return -1;
316 }
317 return (int)actualLen;
318 }
319
320 static loff_t WIN32llseek(int fd, loff_t offset, int whence)
321 {
322 long lo, hi;
323 DWORD err;
324
325 lo = offset & 0xffffffff;
326 hi = offset >> 32;
327 lo = SetFilePointer((HANDLE)fd, lo, &hi, whence);
328 if (lo == 0xFFFFFFFF && (err = GetLastError()) != NO_ERROR) {
329 errno = err;
330 return -1;
331 }
332 return ((loff_t)hi << 32) | (off_t)lo;
333 }
334
335 int fsctl(int fd, int code)
336 {
337 DWORD ret;
338 if (!DeviceIoControl((HANDLE)fd, code, NULL, 0, NULL, 0, &ret, NULL)) {
339 errno = GetLastError();
340 return -1;
341 }
342 return 0;
343 }