c751217ab3f63a98dad4b69f17d1d488d38fd440
[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 static int WIN32open(const char *path, int oflag, ...);
57 #define open WIN32open
58 static int WIN32close(int fd);
59 #define close WIN32close
60 static int WIN32read(int fd, void *buf, unsigned int len);
61 #define read WIN32read
62 static int WIN32write(int fd, void *buf, unsigned int len);
63 #define write WIN32write
64 static loff_t WIN32llseek(int fd, loff_t offset, int whence);
65 #define llseek WIN32llseek
66
67 static int is_device = 0;
68
69 void fs_open(char *path,int rw)
70 {
71 #ifdef _WIN32
72 static char dev_buf[] = "\\\\.\\X:";
73 #else
74 struct stat stbuf;
75 #endif
76
77 if (path[1] == ':' && path[2] == '\0') {
78 dev_buf[4] = path[0];
79 path = dev_buf;
80 // is_device = 1;
81 }
82
83 if ((fd = open(path,rw ? O_RDWR : O_RDONLY)) < 0)
84 pdie("open %s",path);
85 changes = last = NULL;
86 did_change = 0;
87
88 #if 0
89 if (fstat(fd,&stbuf) < 0)
90 pdie("fstat %s",path);
91 device_no = S_ISBLK(stbuf.st_mode) ? (stbuf.st_rdev >> 8) & 0xff : 0;
92 #endif
93 }
94
95
96 void fs_read(loff_t pos,int size,void *data)
97 {
98 CHANGE *walk;
99 int got;
100
101 if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos);
102 if ((got = read(fd,data,size)) < 0) pdie("Read %d bytes at %lld",size,pos);
103 if (got != size) die("Got %d bytes instead of %d at %lld",got,size,pos);
104 for (walk = changes; walk; walk = walk->next) {
105 if (walk->pos < pos+size && walk->pos+walk->size > pos) {
106 if (walk->pos < pos)
107 memcpy(data,(char *) walk->data+pos-walk->pos,min(size,
108 walk->size-pos+walk->pos));
109 else memcpy((char *) data+walk->pos-pos,walk->data,min(walk->size,
110 size+pos-walk->pos));
111 }
112 }
113 }
114
115
116 int fs_test(loff_t pos,int size)
117 {
118 void *scratch;
119 int okay;
120
121 if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos);
122 scratch = alloc(size);
123 okay = read(fd,scratch,size) == size;
124 free(scratch);
125 return okay;
126 }
127
128
129 void fs_write(loff_t pos,int size,void *data)
130 {
131 CHANGE *new;
132 int did;
133
134 if (write_immed) {
135 did_change = 1;
136 if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos);
137 if ((did = write(fd,data,size)) == size) return;
138 if (did < 0) pdie("Write %d bytes at %lld",size,pos);
139 die("Wrote %d bytes instead of %d at %lld",did,size,pos);
140 }
141 new = alloc(sizeof(CHANGE));
142 new->pos = pos;
143 memcpy(new->data = alloc(new->size = size),data,size);
144 new->next = NULL;
145 if (last) last->next = new;
146 else changes = new;
147 last = new;
148 }
149
150
151 static void fs_flush(void)
152 {
153 CHANGE *this;
154 int size;
155
156 while (changes) {
157 this = changes;
158 changes = changes->next;
159 if (llseek(fd,this->pos,0) != this->pos)
160 fprintf(stderr,"Seek to %lld failed: %s\n Did not write %d bytes.\n",
161 (long long)this->pos,strerror(errno),this->size);
162 else if ((size = write(fd,this->data,this->size)) < 0)
163 fprintf(stderr,"Writing %d bytes at %lld failed: %s\n",this->size,
164 (long long)this->pos,strerror(errno));
165 else if (size != this->size)
166 fprintf(stderr,"Wrote %d bytes instead of %d bytes at %lld."
167 "\n",size,this->size,(long long)this->pos);
168 free(this->data);
169 free(this);
170 }
171 }
172
173
174 int fs_close(int write)
175 {
176 CHANGE *next;
177 int changed;
178
179 changed = !!changes;
180 if (write) fs_flush();
181 else while (changes) {
182 next = changes->next;
183 free(changes->data);
184 free(changes);
185 changes = next;
186 }
187 if (close(fd) < 0) pdie("closing file system");
188 return changed || did_change;
189 }
190
191
192 int fs_changed(void)
193 {
194 return !!changes || did_change;
195 }
196
197 /* Local Variables: */
198 /* tab-width: 8 */
199 /* End: */
200
201
202 #define O_SHORT_LIVED _O_SHORT_LIVED
203 #define O_ACCMODE 3
204 #define O_NONE 3
205 #define O_BACKUP 0x10000
206 #define O_SHARED 0x20000
207
208 static int WIN32open(const char *path, int oflag, ...)
209 {
210 HANDLE fh;
211 DWORD desiredAccess;
212 DWORD shareMode;
213 DWORD creationDisposition;
214 DWORD flagsAttributes = FILE_ATTRIBUTE_NORMAL;
215 SECURITY_ATTRIBUTES securityAttributes;
216 va_list ap;
217 int pmode;
218 int trunc = FALSE;
219
220 securityAttributes.nLength = sizeof(securityAttributes);
221 securityAttributes.lpSecurityDescriptor = NULL;
222 securityAttributes.bInheritHandle = oflag & O_NOINHERIT ? FALSE : TRUE;
223 switch (oflag & O_ACCMODE) {
224 case O_RDONLY:
225 desiredAccess = GENERIC_READ;
226 shareMode = FILE_SHARE_READ;
227 break;
228 case O_WRONLY:
229 desiredAccess = GENERIC_WRITE;
230 shareMode = 0;
231 break;
232 case O_RDWR:
233 desiredAccess = GENERIC_READ|GENERIC_WRITE;
234 shareMode = 0;
235 break;
236 case O_NONE:
237 desiredAccess = 0;
238 shareMode = FILE_SHARE_READ|FILE_SHARE_WRITE;
239 }
240 if (oflag & O_APPEND) {
241 desiredAccess |= FILE_APPEND_DATA|SYNCHRONIZE;
242 shareMode = FILE_SHARE_READ|FILE_SHARE_WRITE;
243 }
244 if (oflag & O_SHARED)
245 shareMode |= FILE_SHARE_READ|FILE_SHARE_WRITE;
246 switch (oflag & (O_CREAT|O_EXCL|O_TRUNC)) {
247 case 0:
248 case O_EXCL:
249 creationDisposition = OPEN_EXISTING;
250 break;
251 case O_CREAT:
252 creationDisposition = OPEN_ALWAYS;
253 break;
254 case O_CREAT|O_EXCL:
255 case O_CREAT|O_TRUNC|O_EXCL:
256 creationDisposition = CREATE_NEW;
257 break;
258 case O_TRUNC:
259 case O_TRUNC|O_EXCL:
260 creationDisposition = TRUNCATE_EXISTING;
261 break;
262 case O_CREAT|O_TRUNC:
263 creationDisposition = OPEN_ALWAYS;
264 trunc = TRUE;
265 break;
266 }
267 if (oflag & O_CREAT) {
268 va_start(ap, oflag);
269 pmode = va_arg(ap, int);
270 va_end(ap);
271 if ((pmode & 0222) == 0)
272 flagsAttributes |= FILE_ATTRIBUTE_READONLY;
273 }
274 if (oflag & O_TEMPORARY) {
275 flagsAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
276 desiredAccess |= DELETE;
277 }
278 if (oflag & O_SHORT_LIVED)
279 flagsAttributes |= FILE_ATTRIBUTE_TEMPORARY;
280 if (oflag & O_SEQUENTIAL)
281 flagsAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
282 else if (oflag & O_RANDOM)
283 flagsAttributes |= FILE_FLAG_RANDOM_ACCESS;
284 if (oflag & O_BACKUP)
285 flagsAttributes |= FILE_FLAG_BACKUP_SEMANTICS;
286 if ((fh = CreateFile(path, desiredAccess, shareMode, &securityAttributes,
287 creationDisposition, flagsAttributes, NULL)) == INVALID_HANDLE_VALUE) {
288 errno = GetLastError();
289 return -1;
290 }
291 if (trunc) {
292 if (!SetEndOfFile(fh)) {
293 errno = GetLastError();
294 CloseHandle(fh);
295 DeleteFile(path);
296 return -1;
297 }
298 }
299 return (int)fh;
300 }
301
302 static int WIN32close(int fd)
303 {
304 if (!CloseHandle((HANDLE)fd)) {
305 errno = GetLastError();
306 return -1;
307 }
308 return 0;
309 }
310
311 static int WIN32read(int fd, void *buf, unsigned int len)
312 {
313 DWORD actualLen;
314
315 if (!ReadFile((HANDLE)fd, buf, (DWORD)len, &actualLen, NULL)) {
316 errno = GetLastError();
317 if (errno == ERROR_BROKEN_PIPE)
318 return 0;
319 else
320 return -1;
321 }
322 return (int)actualLen;
323 }
324
325 static int WIN32write(int fd, void *buf, unsigned int len)
326 {
327 DWORD actualLen;
328
329 if (!WriteFile((HANDLE)fd, buf, (DWORD)len, &actualLen, NULL)) {
330 errno = GetLastError();
331 return -1;
332 }
333 return (int)actualLen;
334 }
335
336 static loff_t WIN32llseek(int fd, loff_t offset, int whence)
337 {
338 long lo, hi;
339 DWORD err;
340
341 lo = offset & 0xffffffff;
342 hi = offset >> 32;
343 lo = SetFilePointer((HANDLE)fd, lo, &hi, whence);
344 if (lo == 0xFFFFFFFF && (err = GetLastError()) != NO_ERROR) {
345 errno = err;
346 return -1;
347 }
348 return ((loff_t)hi << 32) | (off_t)lo;
349 }
350
351 int fsctl(int fd, int code)
352 {
353 DWORD ret;
354 if (!DeviceIoControl((HANDLE)fd, code, NULL, 0, NULL, 0, &ret, NULL)) {
355 errno = GetLastError();
356 return -1;
357 }
358 return 0;
359 }