Line 0
Link Here
|
|
|
1 |
/* |
2 |
* $Id: mint_io.c,v 1.4 2003/11/18 21:05:42 standa Exp $ |
3 |
* |
4 |
* This file belongs to FreeMiNT. It's not in the original MiNT 1.12 |
5 |
* distribution. See the file CHANGES for a detailed log of changes. |
6 |
* |
7 |
* |
8 |
* Copyright 2000 Frank Naumann <fnaumann@freemint.de> |
9 |
* All rights reserved. |
10 |
* |
11 |
* This program is free software; you can redistribute it and/or modify |
12 |
* it under the terms of the GNU General Public License as published by |
13 |
* the Free Software Foundation; either version 2, or (at your option) |
14 |
* any later version. |
15 |
* |
16 |
* This file is distributed in the hope that it will be useful, |
17 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
19 |
* GNU General Public License for more details. |
20 |
* |
21 |
* You should have received a copy of the GNU General Public License |
22 |
* along with this program; if not, write to the Free Software |
23 |
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
24 |
* |
25 |
* |
26 |
* Author: Frank Naumann <fnaumann@freemint.de> |
27 |
* Started: 200-06-14 |
28 |
* |
29 |
* Please send suggestions, patches or bug reports to me or |
30 |
* the MiNT mailing list. |
31 |
* |
32 |
*/ |
33 |
|
34 |
# ifdef __MINT__ |
35 |
|
36 |
# include <assert.h> |
37 |
# include <ctype.h> |
38 |
# include <errno.h> |
39 |
# include <fcntl.h> |
40 |
# include <limits.h> |
41 |
# include <stdarg.h> |
42 |
# include <stdlib.h> |
43 |
# include <stdio.h> |
44 |
# include <string.h> |
45 |
# include <time.h> |
46 |
# include <unistd.h> |
47 |
|
48 |
# include "et/com_err.h" |
49 |
# include "ext2fs/ext2_io.h" |
50 |
# include <sys/ioctl.h> |
51 |
# include <sys/stat.h> |
52 |
# define loff_t ext2_loff_t |
53 |
# define llseek ext2fs_llseek |
54 |
|
55 |
# include <mintbind.h> |
56 |
# include "mint_io.h" |
57 |
# include "xhdi.h" |
58 |
|
59 |
|
60 |
# if 0 |
61 |
# define DEBUG(x) printf x |
62 |
# else |
63 |
# define DEBUG(x) |
64 |
# endif |
65 |
|
66 |
|
67 |
/* prototypes */ |
68 |
|
69 |
int __open_v(const char *_filename, int iomode, va_list argp); |
70 |
|
71 |
int open(__const char *__file, int __oflag, ...) __THROW; |
72 |
int __open(__const char *__file, int __oflag, ...) __THROW; |
73 |
|
74 |
int ioctl(int fd, int cmd, void *arg); |
75 |
int __ioctl(int fd, int cmd, void *arg); |
76 |
|
77 |
int fsync(int __fd) __THROW; |
78 |
int __fsync(int __fd) __THROW; |
79 |
|
80 |
__off_t lseek(int __fd, __off_t __offset, int __whence) __THROW; |
81 |
__off_t __lseek(int __fd, __off_t __offset, int __whence) __THROW; |
82 |
|
83 |
int close(int __fd) __THROW; |
84 |
int __close(int __fd) __THROW; |
85 |
|
86 |
ssize_t read(int __fd, void *__buf, size_t __nbytes) __THROW; |
87 |
ssize_t __read(int __fd, void *__buf, size_t __nbytes) __THROW; |
88 |
|
89 |
ssize_t write(int __fd, __const void *__buf, size_t __n) __THROW; |
90 |
ssize_t __write(int __fd, __const void *__buf, size_t __n) __THROW; |
91 |
|
92 |
int fstat(int __fd, struct stat *__buf) __THROW; |
93 |
int __fstat(int __fd, struct stat *__buf) __THROW; |
94 |
|
95 |
int stat(const char *filename, struct stat *st) __THROW; |
96 |
|
97 |
|
98 |
struct device |
99 |
{ |
100 |
int used; |
101 |
|
102 |
int drv; |
103 |
int open_flags; |
104 |
|
105 |
ushort xhdi_maj; |
106 |
ushort xhdi_min; |
107 |
ulong xhdi_start; |
108 |
ulong xhdi_blocks; |
109 |
ulong xhdi_blocksize; |
110 |
char xhdi_id[4]; |
111 |
|
112 |
loff_t pos; |
113 |
}; |
114 |
|
115 |
# define DEVS 16 |
116 |
static struct device devs[DEVS]; |
117 |
|
118 |
static void |
119 |
init_device(struct device *dev) |
120 |
{ |
121 |
dev->used = 0; |
122 |
|
123 |
dev->drv = -1; |
124 |
dev->open_flags = 0; |
125 |
dev->xhdi_maj = 0; |
126 |
dev->xhdi_min = 0; |
127 |
dev->xhdi_start = 0; |
128 |
dev->xhdi_blocks = 0; |
129 |
dev->xhdi_blocksize = 0; |
130 |
|
131 |
dev->pos = 0; |
132 |
} |
133 |
|
134 |
static inline void |
135 |
init(void) |
136 |
{ |
137 |
static int done = 0; |
138 |
int i; |
139 |
|
140 |
if (done) |
141 |
return; |
142 |
|
143 |
assert(sizeof(loff_t) == sizeof(long long)); |
144 |
|
145 |
for (i = 0; i < DEVS; i++) |
146 |
init_device (&devs[i]); |
147 |
|
148 |
init_XHDI(); |
149 |
|
150 |
/* we are now initialized */ |
151 |
done = 1; |
152 |
} |
153 |
|
154 |
static struct device * |
155 |
get_device(int fd) |
156 |
{ |
157 |
struct device *dev; |
158 |
|
159 |
if ((fd < 1024) || (fd >= (1024 + DEVS))) |
160 |
return NULL; |
161 |
|
162 |
fd -= 1024; |
163 |
dev = &devs[fd]; |
164 |
|
165 |
assert(dev->used); |
166 |
|
167 |
return dev; |
168 |
} |
169 |
|
170 |
static int |
171 |
alloc_device(void) |
172 |
{ |
173 |
int i; |
174 |
|
175 |
for (i = 0; i < DEVS; i++) |
176 |
{ |
177 |
struct device *dev = &devs[i]; |
178 |
|
179 |
if (!dev->used) |
180 |
{ |
181 |
dev->used = 1; |
182 |
return (i + 1024); |
183 |
} |
184 |
} |
185 |
|
186 |
__set_errno(ENOMEM); |
187 |
return -1; |
188 |
} |
189 |
|
190 |
static void |
191 |
free_device(struct device *dev) |
192 |
{ |
193 |
assert(dev->used); |
194 |
|
195 |
init_device (dev); |
196 |
} |
197 |
|
198 |
|
199 |
int |
200 |
open(const char *filename, int iomode, ...) |
201 |
{ |
202 |
const char *f = filename; |
203 |
struct device *mydev = NULL; |
204 |
int dev = -1; |
205 |
long ret; |
206 |
|
207 |
init(); |
208 |
|
209 |
if (!filename) |
210 |
{ |
211 |
__set_errno(EINVAL); |
212 |
return -1; |
213 |
} |
214 |
|
215 |
if ((f[1] == ':') && (f[2] == '\0')) |
216 |
{ |
217 |
int c = tolower(f[0]); |
218 |
|
219 |
if (c >= 'a' && c <= 'z') |
220 |
c = c - 'a'; |
221 |
else if (c >= '1' && c <= '6') |
222 |
c = 26 + (c - '1'); |
223 |
|
224 |
if ((c >= 0) && (c < 32)) |
225 |
{ |
226 |
dev = alloc_device(); |
227 |
if (dev != -1) |
228 |
{ |
229 |
mydev = get_device(dev); |
230 |
assert(mydev); |
231 |
|
232 |
mydev->drv = c; |
233 |
mydev->open_flags = iomode; |
234 |
} |
235 |
} |
236 |
} |
237 |
|
238 |
if (dev == -1) |
239 |
{ |
240 |
/* fall through */ |
241 |
|
242 |
va_list args; |
243 |
int retval; |
244 |
|
245 |
va_start(args, iomode); |
246 |
retval = __open_v(filename, iomode, args); |
247 |
va_end(args); |
248 |
|
249 |
return retval; |
250 |
} |
251 |
|
252 |
if (mydev->open_flags == O_RDONLY) |
253 |
{ |
254 |
DEBUG(("readonly mode!\n")); |
255 |
sync(); |
256 |
} |
257 |
else if (Dlock(1, mydev->drv)) |
258 |
{ |
259 |
printf("Can't lock partition %c:!\n", mydev->drv+'A'); |
260 |
|
261 |
if (mydev) |
262 |
free_device(mydev); |
263 |
|
264 |
__set_errno(EACCES); |
265 |
return -1; |
266 |
} |
267 |
|
268 |
__set_errno(EERROR); |
269 |
|
270 |
ret = XHGetVersion (); |
271 |
DEBUG(("XHDI version: %lx\n", ret)); |
272 |
|
273 |
ret = XHInqDev2(mydev->drv, |
274 |
&mydev->xhdi_maj, &mydev->xhdi_min, |
275 |
&mydev->xhdi_start, NULL, |
276 |
&mydev->xhdi_blocks, mydev->xhdi_id); |
277 |
if (ret) |
278 |
{ |
279 |
printf("XHInqDev2 [%c] fail (ret = %li, errno = %i)\n", |
280 |
mydev->drv+'A', ret, errno); |
281 |
ret = -1; |
282 |
} |
283 |
else |
284 |
{ |
285 |
ret = XHInqTarget(mydev->xhdi_maj, mydev->xhdi_min, |
286 |
&mydev->xhdi_blocksize, NULL, NULL); |
287 |
if (ret) |
288 |
{ |
289 |
printf("XHInqTarget [%i:%i] fail (ret = %li, errno = %i)\n", |
290 |
mydev->xhdi_maj, mydev->xhdi_min, ret, errno); |
291 |
ret = -1; |
292 |
} |
293 |
else |
294 |
{ |
295 |
char *xhdi_id = mydev->xhdi_id; |
296 |
|
297 |
if ( 0 |
298 |
|| ((xhdi_id[0] == 'G') && (xhdi_id[1] == 'E') && (xhdi_id[2] == 'M')) /* GEM */ |
299 |
|| ((xhdi_id[0] == 'B') && (xhdi_id[1] == 'G') && (xhdi_id[2] == 'M')) /* BGM */ |
300 |
|| ((xhdi_id[0] == 'F') && (xhdi_id[1] == '3') && (xhdi_id[2] == '2')) /* F32 */ |
301 |
|| ((xhdi_id[0] == 'M') && (xhdi_id[1] == 'I') && (xhdi_id[2] == 'X')) /* MIX */ |
302 |
|| ((xhdi_id[0] == 'R') && (xhdi_id[1] == 'A') && (xhdi_id[2] == 'W')) /* RAW */ |
303 |
|| ((xhdi_id[0] == 'L') && (xhdi_id[1] == 'N') && (xhdi_id[2] == 'X')) /* LNX */ |
304 |
|| ((xhdi_id[0] == '\0') && (xhdi_id[1] == 'D'))) /* any DOS */ |
305 |
{ |
306 |
DEBUG(("Partition ok and accepted!\n")); |
307 |
DEBUG(("start = %lu, blocks = %lu, blocksize = %lu\n", |
308 |
mydev->xhdi_start, mydev->xhdi_blocks, |
309 |
mydev->xhdi_blocksize)); |
310 |
} |
311 |
else |
312 |
{ |
313 |
xhdi_id [3] = '\0'; |
314 |
printf("Wrong partition ID [%s]!\n", xhdi_id); |
315 |
printf("Only 'RAW', 'LNX' and DOS partitions are supported.\n"); |
316 |
|
317 |
__set_errno(EPERM); |
318 |
ret = -1; |
319 |
} |
320 |
} |
321 |
} |
322 |
|
323 |
if (ret) |
324 |
{ |
325 |
if (mydev) |
326 |
free_device(mydev); |
327 |
|
328 |
dev = -1; |
329 |
} |
330 |
|
331 |
return dev; |
332 |
} |
333 |
|
334 |
int |
335 |
close(int fd) |
336 |
{ |
337 |
struct device *mydev = get_device(fd); |
338 |
int ret = 0; |
339 |
|
340 |
if (!mydev) |
341 |
/* fall through */ |
342 |
return __close(fd); |
343 |
|
344 |
if (mydev->open_flags == O_RDONLY) |
345 |
{ |
346 |
; |
347 |
} |
348 |
else if (Dlock(0, mydev->drv)) |
349 |
{ |
350 |
printf("Can't unlock partition %c:!\n", 'A'+mydev->drv); |
351 |
|
352 |
__set_errno(EACCES); |
353 |
ret = -1; |
354 |
} |
355 |
|
356 |
free_device(mydev); |
357 |
return ret; |
358 |
} |
359 |
|
360 |
/* simple buffer */ |
361 |
static char buffer[1024L * 128]; |
362 |
static ulong buf_recno = 0; |
363 |
static long buf_n = 0; |
364 |
|
365 |
static long |
366 |
rwabs_xhdi(struct device *mydev, ushort rw, void *buf, ulong size, ulong recno) |
367 |
{ |
368 |
ulong n = size / mydev->xhdi_blocksize; |
369 |
long r; |
370 |
|
371 |
assert((size % mydev->xhdi_blocksize) == 0); |
372 |
|
373 |
if (!n || (recno + n) > mydev->xhdi_blocks) |
374 |
{ |
375 |
printf("rwabs_xhdi: access outside partition (drv = %c:)\n", 'A'+mydev->drv); |
376 |
exit(2); |
377 |
} |
378 |
|
379 |
if (n > 65535UL) |
380 |
{ |
381 |
printf("rwabs_xhdi: n to large (drv = %c)\n", 'A'+mydev->drv); |
382 |
exit(2); |
383 |
} |
384 |
|
385 |
if (!rw && (buf_recno == recno) && (buf_n == n)) |
386 |
{ |
387 |
bcopy(buffer, buf, buf_n * mydev->xhdi_blocksize); |
388 |
return 0; |
389 |
} |
390 |
|
391 |
r = XHReadWrite (mydev->xhdi_maj, mydev->xhdi_min, rw, mydev->xhdi_start + recno, n, buf); |
392 |
|
393 |
if (!r && (n * mydev->xhdi_blocksize) <= sizeof(buffer)) |
394 |
{ |
395 |
bcopy(buf, buffer, n * mydev->xhdi_blocksize); |
396 |
|
397 |
buf_recno = recno; |
398 |
buf_n = n; |
399 |
} |
400 |
else |
401 |
buf_n = 0; |
402 |
|
403 |
return r; |
404 |
} |
405 |
|
406 |
# define max(a,b) (a > b ? a : b) |
407 |
# define min(a,b) (a > b ? b : a) |
408 |
|
409 |
int |
410 |
read(int fd, void *_buf, size_t size) |
411 |
{ |
412 |
struct device *mydev = get_device(fd); |
413 |
|
414 |
if (!mydev) |
415 |
/* fall through */ |
416 |
return __read(fd, _buf, size); |
417 |
|
418 |
{ |
419 |
char *buf = _buf; |
420 |
long todo; /* characters remaining */ |
421 |
long done; /* characters processed */ |
422 |
|
423 |
todo = size; |
424 |
done = 0; |
425 |
|
426 |
if (todo == 0) |
427 |
return 0; |
428 |
|
429 |
/* partial block copy |
430 |
*/ |
431 |
if (mydev->pos % mydev->xhdi_blocksize) |
432 |
{ |
433 |
char tmp[mydev->xhdi_blocksize]; |
434 |
|
435 |
ulong recno = mydev->pos / mydev->xhdi_blocksize; |
436 |
ulong offset = mydev->pos % mydev->xhdi_blocksize; |
437 |
ulong data; |
438 |
long ret; |
439 |
|
440 |
ret = rwabs_xhdi(mydev, 0, tmp, mydev->xhdi_blocksize, recno); |
441 |
if (ret) |
442 |
{ |
443 |
DEBUG(("read: partial part: read failure (r = %li, errno = %i)\n", ret, errno)); |
444 |
goto out; |
445 |
} |
446 |
|
447 |
data = mydev->xhdi_blocksize - offset; |
448 |
data = min (todo, data); |
449 |
|
450 |
memcpy(buf, tmp + offset, data); |
451 |
|
452 |
buf += data; |
453 |
todo -= data; |
454 |
done += data; |
455 |
mydev->pos += data; |
456 |
} |
457 |
|
458 |
if (todo) |
459 |
{ |
460 |
assert((todo > 0)); |
461 |
assert((mydev->pos % mydev->xhdi_blocksize) == 0); |
462 |
} |
463 |
|
464 |
|
465 |
/* full blocks |
466 |
*/ |
467 |
if (todo / mydev->xhdi_blocksize) |
468 |
{ |
469 |
ulong recno = mydev->pos / mydev->xhdi_blocksize; |
470 |
ulong data = (todo / mydev->xhdi_blocksize) * mydev->xhdi_blocksize; |
471 |
long ret; |
472 |
|
473 |
ret = rwabs_xhdi (mydev, 0, buf, data, recno); |
474 |
if (ret) |
475 |
{ |
476 |
DEBUG(("read: full blocks: read failure (r = %li, errno = %i)\n", ret, errno)); |
477 |
goto out; |
478 |
} |
479 |
|
480 |
buf += data; |
481 |
todo -= data; |
482 |
done += data; |
483 |
mydev->pos += data; |
484 |
} |
485 |
|
486 |
if (todo) |
487 |
{ |
488 |
assert((todo > 0) && (todo < mydev->xhdi_blocksize)); |
489 |
assert((mydev->pos % mydev->xhdi_blocksize) == 0); |
490 |
} |
491 |
|
492 |
/* anything left? |
493 |
*/ |
494 |
if (todo) |
495 |
{ |
496 |
char tmp[mydev->xhdi_blocksize]; |
497 |
|
498 |
ulong recno = mydev->pos / mydev->xhdi_blocksize; |
499 |
long ret; |
500 |
|
501 |
ret = rwabs_xhdi (mydev, 0, tmp, mydev->xhdi_blocksize, recno); |
502 |
if (ret) |
503 |
{ |
504 |
DEBUG(("read: left part: read failure (r = %li, errno = %i)]\n", ret, errno)); |
505 |
goto out; |
506 |
} |
507 |
|
508 |
memcpy(buf, tmp, todo); |
509 |
|
510 |
done += todo; |
511 |
mydev->pos += todo; |
512 |
} |
513 |
|
514 |
assert(done == size); |
515 |
|
516 |
out: |
517 |
return done; |
518 |
} |
519 |
} |
520 |
|
521 |
int |
522 |
write(int fd, const void *_buf, size_t size) |
523 |
{ |
524 |
struct device *mydev = get_device(fd); |
525 |
|
526 |
if (!mydev) |
527 |
/* fall through */ |
528 |
return __write(fd, _buf, size); |
529 |
|
530 |
if (mydev->open_flags == O_RDONLY) |
531 |
{ |
532 |
__set_errno(EPERM); |
533 |
return -1; |
534 |
} |
535 |
{ |
536 |
const char *buf = _buf; |
537 |
long todo; /* characters remaining */ |
538 |
long done; /* characters processed */ |
539 |
|
540 |
todo = size; |
541 |
done = 0; |
542 |
|
543 |
if (todo == 0) |
544 |
return 0; |
545 |
|
546 |
/* partial block copy |
547 |
*/ |
548 |
if (mydev->pos % mydev->xhdi_blocksize) |
549 |
{ |
550 |
char tmp[mydev->xhdi_blocksize]; |
551 |
|
552 |
ulong recno = mydev->pos / mydev->xhdi_blocksize; |
553 |
ulong offset = mydev->pos % mydev->xhdi_blocksize; |
554 |
ulong data; |
555 |
long ret; |
556 |
|
557 |
ret = rwabs_xhdi(mydev, 0, tmp, mydev->xhdi_blocksize, recno); |
558 |
if (ret) |
559 |
{ |
560 |
DEBUG(("write: partial part: read failure (r = %li, errno = %i)\n", ret, errno)); |
561 |
goto out; |
562 |
} |
563 |
|
564 |
data = mydev->xhdi_blocksize - offset; |
565 |
data = min (todo, data); |
566 |
|
567 |
memcpy(tmp + offset, buf, data); |
568 |
|
569 |
ret = rwabs_xhdi(mydev, 1, tmp, mydev->xhdi_blocksize, recno); |
570 |
if (ret) |
571 |
{ |
572 |
DEBUG(("write: partial part: write failure (r = %li, errno = %i)\n", ret, errno)); |
573 |
goto out; |
574 |
} |
575 |
|
576 |
buf += data; |
577 |
todo -= data; |
578 |
done += data; |
579 |
mydev->pos += data; |
580 |
} |
581 |
|
582 |
if (todo) |
583 |
{ |
584 |
assert((todo > 0)); |
585 |
assert((mydev->pos % mydev->xhdi_blocksize) == 0); |
586 |
} |
587 |
|
588 |
/* full blocks |
589 |
*/ |
590 |
if (todo / mydev->xhdi_blocksize) |
591 |
{ |
592 |
ulong recno = mydev->pos / mydev->xhdi_blocksize; |
593 |
ulong data = (todo / mydev->xhdi_blocksize) * mydev->xhdi_blocksize; |
594 |
long ret; |
595 |
|
596 |
ret = rwabs_xhdi(mydev, 1, (void *)buf, data, recno); |
597 |
if (ret) |
598 |
{ |
599 |
DEBUG(("write: full blocks: write failure (r = %li, errno = %i)\n", ret, errno)); |
600 |
goto out; |
601 |
} |
602 |
|
603 |
buf += data; |
604 |
todo -= data; |
605 |
done += data; |
606 |
mydev->pos += data; |
607 |
} |
608 |
|
609 |
if (todo) |
610 |
{ |
611 |
assert((todo > 0) && (todo < mydev->xhdi_blocksize)); |
612 |
assert((mydev->pos % mydev->xhdi_blocksize) == 0); |
613 |
} |
614 |
|
615 |
/* anything left? |
616 |
*/ |
617 |
if (todo) |
618 |
{ |
619 |
char tmp[mydev->xhdi_blocksize]; |
620 |
|
621 |
ulong recno = mydev->pos / mydev->xhdi_blocksize; |
622 |
long ret; |
623 |
|
624 |
ret = rwabs_xhdi(mydev, 0, tmp, mydev->xhdi_blocksize, recno); |
625 |
if (ret) |
626 |
{ |
627 |
DEBUG(("write: left part: read failure (r = %li, errno = %i)]\n", ret, errno)); |
628 |
goto out; |
629 |
} |
630 |
|
631 |
memcpy(tmp, buf, todo); |
632 |
|
633 |
ret = rwabs_xhdi(mydev, 1, tmp, mydev->xhdi_blocksize, recno); |
634 |
if (ret) |
635 |
{ |
636 |
DEBUG(("write: partial part: write failure (r = %li, errno = %i)\n", ret, errno)); |
637 |
goto out; |
638 |
} |
639 |
|
640 |
done += todo; |
641 |
mydev->pos += todo; |
642 |
} |
643 |
|
644 |
assert(done == size); |
645 |
|
646 |
out: |
647 |
return done; |
648 |
} |
649 |
} |
650 |
|
651 |
int |
652 |
ioctl(int fd, int cmd, void *arg) |
653 |
{ |
654 |
struct device *mydev = get_device(fd); |
655 |
|
656 |
if (!mydev) |
657 |
/* fall through */ |
658 |
return __ioctl(fd, cmd, arg); |
659 |
|
660 |
DEBUG(("ioctl: cmd = %i\n", cmd)); |
661 |
|
662 |
switch (cmd) |
663 |
{ |
664 |
case BLKGETSIZE: |
665 |
{ |
666 |
ulong *size = arg; |
667 |
*size = mydev->xhdi_blocks * (mydev->xhdi_blocksize / 512); |
668 |
break; |
669 |
} |
670 |
case BLOCKSIZE: |
671 |
{ |
672 |
ulong *block_size = arg; |
673 |
*block_size = mydev->xhdi_blocksize; |
674 |
break; |
675 |
} |
676 |
default: |
677 |
__set_errno(EINVAL); |
678 |
return -1; |
679 |
} |
680 |
|
681 |
return 0; |
682 |
} |
683 |
|
684 |
int |
685 |
fstat(int fd, struct stat *st) |
686 |
{ |
687 |
struct device *mydev = get_device(fd); |
688 |
|
689 |
if (!mydev) |
690 |
/* fall through */ |
691 |
return __fstat(fd, st); |
692 |
|
693 |
bzero(st, sizeof(*st)); |
694 |
|
695 |
st->st_dev = mydev->xhdi_maj; |
696 |
st->st_ino = mydev->drv; |
697 |
st->st_mode = S_IFBLK | S_IRUSR | S_IWUSR; |
698 |
st->st_nlink = 1; |
699 |
st->st_uid = 0; |
700 |
st->st_gid = 0; |
701 |
st->st_rdev = mydev->xhdi_min; |
702 |
st->st_atime = time (NULL); |
703 |
st->st_mtime = time (NULL); |
704 |
st->st_ctime = time (NULL); |
705 |
st->st_size = (int64_t) mydev->xhdi_blocks * mydev->xhdi_blocksize; |
706 |
st->st_blocks = (int64_t) mydev->xhdi_blocks * mydev->xhdi_blocksize / 512; |
707 |
st->st_blksize = mydev->xhdi_blocksize; |
708 |
st->st_flags = 0; |
709 |
st->st_gen = 0; |
710 |
|
711 |
return 0; |
712 |
} |
713 |
|
714 |
int |
715 |
stat(const char *filename, struct stat *st) |
716 |
{ |
717 |
struct device *mydev; |
718 |
int fd, res; |
719 |
|
720 |
fd = open(filename, O_RDONLY); |
721 |
if (fd == -1) |
722 |
return -1; |
723 |
|
724 |
mydev = get_device(fd); |
725 |
if (!mydev) |
726 |
{ |
727 |
close(fd); |
728 |
|
729 |
/* fall through */ |
730 |
return __stat(filename, st); |
731 |
} |
732 |
|
733 |
res = fstat(fd, st); |
734 |
close(fd); |
735 |
|
736 |
return res; |
737 |
} |
738 |
|
739 |
int |
740 |
fsync(int fd) |
741 |
{ |
742 |
struct device *mydev = get_device(fd); |
743 |
|
744 |
if (!mydev) |
745 |
/* fall through */ |
746 |
return __fsync(fd); |
747 |
|
748 |
/* nothing todo */ |
749 |
return 0; |
750 |
} |
751 |
|
752 |
loff_t llseek(int fd, loff_t offset, int origin); |
753 |
|
754 |
loff_t |
755 |
llseek(int fd, loff_t offset, int origin) |
756 |
{ |
757 |
struct device *mydev = get_device(fd); |
758 |
|
759 |
if (!mydev) |
760 |
/* fall through */ |
761 |
return __lseek(fd, (off_t) offset, origin); |
762 |
|
763 |
|
764 |
switch (origin) |
765 |
{ |
766 |
case SEEK_SET: |
767 |
break; |
768 |
case SEEK_CUR: |
769 |
offset += mydev->pos; |
770 |
break; |
771 |
case SEEK_END: |
772 |
offset += (int64_t) mydev->xhdi_blocks * mydev->xhdi_blocksize; |
773 |
break; |
774 |
default: |
775 |
return -1; |
776 |
} |
777 |
|
778 |
if (offset > (loff_t) mydev->xhdi_blocks * mydev->xhdi_blocksize) |
779 |
{ |
780 |
__set_errno(EINVAL); |
781 |
return -1; |
782 |
} |
783 |
|
784 |
mydev->pos = offset; |
785 |
return mydev->pos; |
786 |
} |
787 |
|
788 |
loff_t lseek64(int fd, loff_t offset, int origin); |
789 |
|
790 |
loff_t |
791 |
lseek64(int fd, loff_t offset, int origin) |
792 |
{ |
793 |
return llseek(fd, offset, origin); |
794 |
} |
795 |
|
796 |
__off_t |
797 |
lseek(int fd, __off_t offset, int mode) |
798 |
{ |
799 |
struct device *mydev = get_device(fd); |
800 |
|
801 |
if (!mydev) |
802 |
/* fall through */ |
803 |
return __lseek(fd, offset, mode); |
804 |
|
805 |
{ |
806 |
loff_t _offset = offset; |
807 |
|
808 |
switch (mode) |
809 |
{ |
810 |
case SEEK_SET: |
811 |
break; |
812 |
case SEEK_CUR: |
813 |
_offset += mydev->pos; |
814 |
break; |
815 |
case SEEK_END: |
816 |
_offset += (loff_t) mydev->xhdi_blocks * mydev->xhdi_blocksize; |
817 |
break; |
818 |
default: |
819 |
return -1; |
820 |
} |
821 |
|
822 |
if (_offset > LONG_MAX) |
823 |
{ |
824 |
__set_errno(EINVAL); |
825 |
return -1; |
826 |
} |
827 |
|
828 |
if (_offset > (loff_t) mydev->xhdi_blocks * mydev->xhdi_blocksize) |
829 |
{ |
830 |
__set_errno(EINVAL); |
831 |
return -1; |
832 |
} |
833 |
|
834 |
mydev->pos = _offset; |
835 |
return (off_t) mydev->pos; |
836 |
} |
837 |
} |
838 |
|
839 |
int gettype(int fd); |
840 |
|
841 |
int |
842 |
gettype(int fd) |
843 |
{ |
844 |
struct device *mydev = get_device(fd); |
845 |
char *xhdi_id; |
846 |
|
847 |
if (!mydev) |
848 |
return -1; |
849 |
|
850 |
/* Get filesystem type by XHDI ID */ |
851 |
xhdi_id = mydev->xhdi_id; |
852 |
if ((xhdi_id[0] == '\0') && (xhdi_id[1] == 'D')) |
853 |
return 0; /* DOS (\0D*) */ |
854 |
else |
855 |
return 1; /* Atari (GEM/GBM) */ |
856 |
} |
857 |
|
858 |
# endif /* __MINT__ */ |