1 /* $Id: dosio.c,v 1.2 2003/12/05 18:07:15 nonaka Exp $ */
2
3 /*
4 * Copyright (c) 2003 NONAKA Kimihiro
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgment:
17 * This product includes software developed by NONAKA Kimihiro.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <sys/param.h>
34 #include <time.h>
35
36 #include "dosio.h"
37
38 #ifdef __LIBRETRO__
39 extern char slash;
40 #endif
41
42 static char curpath[MAX_PATH+32] = "";
43 static LPSTR curfilep = curpath;
44
45 void
dosio_init(void)46 dosio_init(void)
47 {
48
49 /* Nothing to do. */
50 }
51
52 void
dosio_term(void)53 dosio_term(void)
54 {
55
56 /* Nothing to do. */
57 }
58
59 /* �ե�������� */
60 FILEH
file_open(LPSTR filename)61 file_open(LPSTR filename)
62 {
63 FILEH ret;
64
65 ret = CreateFile(filename, GENERIC_READ | GENERIC_WRITE,
66 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
67 if (ret == (FILEH)INVALID_HANDLE_VALUE) {
68 ret = CreateFile(filename, GENERIC_READ,
69 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
70 if (ret == (FILEH)INVALID_HANDLE_VALUE)
71 return (FILEH)FALSE;
72 }
73 return ret;
74 }
75
76 FILEH
file_create(LPSTR filename,int ftype)77 file_create(LPSTR filename, int ftype)
78 {
79 FILEH ret;
80
81 (void)ftype;
82
83 ret = CreateFile(filename, GENERIC_READ | GENERIC_WRITE,
84 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
85 if (ret == (FILEH)INVALID_HANDLE_VALUE)
86 return (FILEH)FALSE;
87 return ret;
88 }
89
90 DWORD
file_seek(FILEH handle,long pointer,short mode)91 file_seek(FILEH handle, long pointer, short mode)
92 {
93
94 return SetFilePointer(handle, pointer, 0, mode);
95 }
96
97 DWORD
file_lread(FILEH handle,void * data,DWORD length)98 file_lread(FILEH handle, void *data, DWORD length)
99 {
100 DWORD readsize;
101
102 if (ReadFile(handle, data, length, &readsize, NULL) == 0)
103 return 0;
104 return readsize;
105 }
106
107 DWORD
file_lwrite(FILEH handle,void * data,DWORD length)108 file_lwrite(FILEH handle, void *data, DWORD length)
109 {
110 DWORD writesize;
111
112 if (WriteFile(handle, data, length, &writesize, NULL) == 0)
113 return 0;
114 return writesize;
115 }
116
117 WORD
file_read(FILEH handle,void * data,WORD length)118 file_read(FILEH handle, void *data, WORD length)
119 {
120 DWORD readsize;
121
122 if (ReadFile(handle, data, length, &readsize, NULL) == 0)
123 return 0;
124 return (WORD)readsize;
125 }
126
127 DWORD
file_zeroclr(FILEH handle,DWORD length)128 file_zeroclr(FILEH handle, DWORD length)
129 {
130 char buf[256];
131 DWORD size;
132 DWORD wsize;
133 DWORD ret = 0;
134
135 memset(buf, 0, sizeof(buf));
136 while (length > 0) {
137 wsize = (length >= sizeof(buf)) ? sizeof(buf) : length;
138
139 size = file_lwrite(handle, buf, wsize);
140 if (size == (DWORD)-1)
141 return -1;
142
143 ret += size;
144 if (size != wsize)
145 break;
146 length -= wsize;
147 }
148 return ret;
149 }
150
151
152 WORD
file_write(FILEH handle,void * data,WORD length)153 file_write(FILEH handle, void *data, WORD length)
154 {
155 DWORD writesize;
156
157 if (WriteFile(handle, data, length, &writesize, NULL) == 0)
158 return 0;
159 return (WORD)writesize;
160 }
161
162 WORD
file_lineread(FILEH handle,void * data,WORD length)163 file_lineread(FILEH handle, void *data, WORD length)
164 {
165 LPSTR p = (LPSTR)data;
166 DWORD readsize;
167 DWORD pos;
168 WORD ret = 0;
169
170 if ((length == 0) || ((pos = file_seek(handle, 0, 1)) == (DWORD)-1))
171 return 0;
172
173 ZeroMemory(data, length);
174 if (ReadFile(handle, data, length-1, &readsize, NULL) == 0)
175 return 0;
176
177 while (*p) {
178 ret++;
179 pos++;
180 if ((*p == 0x0d) || (*p == 0x0a)) {
181 break;
182 }
183 p++;
184 }
185 *p = '\0';
186
187 file_seek(handle, pos, 0);
188
189 return ret;
190 }
191
192 short
file_close(FILEH handle)193 file_close(FILEH handle)
194 {
195
196 FAKE_CloseHandle(handle);
197 return 0;
198 }
199
200 short
file_attr(LPSTR filename)201 file_attr(LPSTR filename)
202 {
203
204 return (short)GetFileAttributes(filename);
205 }
206
207
208 // �����ȥե��������
209 void
file_setcd(LPSTR exename)210 file_setcd(LPSTR exename)
211 {
212
213 strncpy(curpath, exename, sizeof(curpath));
214 plusyen(curpath, sizeof(curpath));
215 curfilep = curpath + strlen(exename) + 1;
216 *curfilep = '\0';
217 }
218
219 LPSTR
file_getcd(LPSTR filename)220 file_getcd(LPSTR filename)
221 {
222
223 strncpy(curfilep, filename, MAX_PATH - (curfilep - curpath));
224 return curpath;
225 }
226
227 FILEH
file_open_c(LPSTR filename)228 file_open_c(LPSTR filename)
229 {
230
231 strncpy(curfilep, filename, MAX_PATH - (curfilep - curpath));
232 return file_open(curpath);
233 }
234
235 FILEH
file_create_c(LPSTR filename,int ftype)236 file_create_c(LPSTR filename, int ftype)
237 {
238
239 strncpy(curfilep, filename, MAX_PATH - (curfilep - curpath));
240 return file_create(curpath, ftype);
241 }
242
243 short
file_attr_c(LPSTR filename)244 file_attr_c(LPSTR filename)
245 {
246
247 strncpy(curfilep, filename, MAX_PATH - (curfilep - curpath));
248 return file_attr(curpath);
249 }
250
251 int
file_getftype(LPSTR filename)252 file_getftype(LPSTR filename)
253 {
254
255 (void)filename;
256
257 return FTYPE_NONE;
258 }
259
260
261 LPSTR
getFileName(LPSTR filename)262 getFileName(LPSTR filename)
263 {
264 LPSTR p, q;
265
266 for (p = q = filename; *p != '\0'; p++)
267 if (*p == slash/*'/'*/)
268 q = p + 1;
269 return q;
270 }
271
272 void
cutFileName(LPSTR filename)273 cutFileName(LPSTR filename)
274 {
275 LPSTR p, q;
276
277 for (p = filename, q = NULL; *p != '\0'; p++)
278 if (*p == slash/*'/'*/)
279 q = p + 1;
280 if (q != NULL)
281 *q = '\0';
282 }
283
284 LPSTR
getExtName(LPSTR filename)285 getExtName(LPSTR filename)
286 {
287 LPSTR p;
288 LPSTR q;
289
290 p = getFileName(filename);
291 q = NULL;
292
293 while (*p != '\0') {
294 if (*p == '.')
295 q = p + 1;
296 p++;
297 }
298 if (q == NULL)
299 q = p;
300 return q;
301 }
302
303 void
cutExtName(LPSTR filename)304 cutExtName(LPSTR filename)
305 {
306 LPSTR p;
307 LPSTR q;
308
309 p = getFileName(filename);
310 q = NULL;
311
312 while (*p != '\0') {
313 if (*p == '.')
314 q = p;
315 p++;
316 }
317 if (q != NULL)
318 *q = '\0';
319 }
320
321 int
kanji1st(LPSTR str,int pos)322 kanji1st(LPSTR str, int pos)
323 {
324 int ret = 0;
325 BYTE c;
326
327 for (; pos > 0; pos--) {
328 c = (BYTE)str[pos];
329 if (!((0x81 <= c && c <= 0x9f) || (0xe0 <= c && c <= 0xfc)))
330 break;
331 ret ^= 1;
332 }
333 return ret;
334 }
335
336 int
kanji2nd(LPSTR str,int pos)337 kanji2nd(LPSTR str, int pos)
338 {
339 int ret = 0;
340 BYTE c;
341
342 while (pos-- > 0) {
343 c = (BYTE)str[pos];
344 if (!((0x81 <= c && c <= 0x9f) || (0xe0 <= c && c <= 0xfc)))
345 break;
346 ret ^= 1;
347 }
348 return ret;
349 }
350
351
352 int
ex_a2i(LPSTR str,int min,int max)353 ex_a2i(LPSTR str, int min, int max)
354 {
355 int ret = 0;
356 char c;
357
358 if (str == NULL)
359 return(min);
360
361 for (;;) {
362 c = *str++;
363 if (c == ' ')
364 continue;
365 if ((c < '0') || (c > '9'))
366 break;
367 ret = ret * 10 + (c - '0');
368 }
369
370 if (ret < min)
371 return min;
372 else if (ret > max)
373 return max;
374 return ret;
375 }
376
377 void
cutyen(LPSTR str)378 cutyen(LPSTR str)
379 {
380 int pos = strlen(str) - 1;
381
382 if ((pos > 0) && (str[pos] == slash/*'/'*/))
383 str[pos] = '\0';
384 }
385
386 void
plusyen(LPSTR str,int len)387 plusyen(LPSTR str, int len)
388 {
389 int pos = strlen(str);
390
391 if (pos) {
392 if (str[pos-1] == slash/*'/'*/)
393 return;
394 }
395 if ((pos + 2) >= len)
396 return;
397 str[pos++] = slash/*'/'*/;
398 str[pos] = '\0';
399 }
400
401
402 void
fname_mix(LPSTR str,LPSTR mix,int size)403 fname_mix(LPSTR str, LPSTR mix, int size)
404 {
405 LPSTR p;
406 int len;
407 char c;
408 char check;
409
410 cutFileName(str);
411 if (mix[0] == slash/*'/'*/)
412 str[0] = '\0';
413
414 len = strlen(str);
415 p = str + len;
416 check = '.';
417 while (len < size) {
418 c = *mix++;
419 if (c == '\0')
420 break;
421
422 if (c == check) {
423 /* current dir */
424 if (mix[0] == slash/*'/'*/) {
425 mix++;
426 continue;
427 }
428 /* parent dir */
429 if (mix[0] == '.' && mix[1] == slash/*'/'*/) {
430 mix += 2;
431 cutyen(str);
432 cutFileName(str);
433 len = strlen(str);
434 p = str + len;
435 continue;
436 }
437 }
438 if (c == slash/*'/'*/)
439 check = '.';
440 else
441 check = 0;
442 *p++ = c;
443 len++;
444 }
445 if (p < str + len)
446 *p = '\0';
447 else
448 str[len - 1] = '\0';
449 }
450
451 /*
452 * UNIX -> DOS �����Ѵ�
453 */
454 /* $NetBSD: msdosfs_conv.c,v 1.29 2001/01/18 20:28:27 jdolecek Exp $ */
455 /*-
456 * Copyright (C) 1995, 1997 Wolfgang Solfrank.
457 * Copyright (C) 1995, 1997 TooLs GmbH.
458 * All rights reserved.
459 * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below).
460 *
461 * Redistribution and use in source and binary forms, with or without
462 * modification, are permitted provided that the following conditions
463 * are met:
464 * 1. Redistributions of source code must retain the above copyright
465 * notice, this list of conditions and the following disclaimer.
466 * 2. Redistributions in binary form must reproduce the above copyright
467 * notice, this list of conditions and the following disclaimer in the
468 * documentation and/or other materials provided with the distribution.
469 * 3. All advertising materials mentioning features or use of this software
470 * must display the following acknowledgement:
471 * This product includes software developed by TooLs GmbH.
472 * 4. The name of TooLs GmbH may not be used to endorse or promote products
473 * derived from this software without specific prior written permission.
474 *
475 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
476 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
477 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
478 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
479 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
480 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
481 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
482 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
483 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
484 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
485 */
486 /*
487 * Written by Paul Popelka (paulp@uts.amdahl.com)
488 *
489 * You can do anything you want with this software, just don't say you wrote
490 * it, and don't remove this notice.
491 *
492 * This software is provided "as is".
493 *
494 * The author supplies this software to be publicly redistributed on the
495 * understanding that the author is not responsible for the correct
496 * functioning of this software in any circumstances and is not liable for
497 * any damages caused by this software.
498 *
499 * October 1992
500 */
501
502 /*
503 * Days in each month in a regular year.
504 */
505 unsigned short const regyear[] = {
506 31, 28, 31, 30, 31, 30,
507 31, 31, 30, 31, 30, 31
508 };
509
510 /*
511 * Days in each month in a leap year.
512 */
513 unsigned short const leapyear[] = {
514 31, 29, 31, 30, 31, 30,
515 31, 31, 30, 31, 30, 31
516 };
517
518 /*
519 * Variables used to remember parts of the last time conversion. Maybe we
520 * can avoid a full conversion.
521 */
522 static time_t lasttime;
523 static unsigned long lastday;
524 static unsigned short lastddate;
525 static unsigned short lastdtime;
526
527 /*
528 * Convert the unix version of time to dos's idea of time to be used in
529 * file timestamps. The passed in unix time is assumed to be in GMT.
530 */
531 void
unix2dostime(time_t t,unsigned short * ddp,unsigned short * dtp,unsigned char * dhp)532 unix2dostime(time_t t, unsigned short *ddp, unsigned short *dtp, unsigned char *dhp)
533 {
534 time_t tt;
535 unsigned long days;
536 unsigned long inc;
537 unsigned long year;
538 unsigned long month;
539 const unsigned short *months;
540
541 /*
542 * If the time from the last conversion is the same as now, then
543 * skip the computations and use the saved result.
544 */
545 tt = t;
546 t &= ~1;
547 if (lasttime != t) {
548 lasttime = t;
549 lastdtime = (((t / 2) % 30) << DT_2SECONDS_SHIFT)
550 + (((t / 60) % 60) << DT_MINUTES_SHIFT)
551 + (((t / 3600) % 24) << DT_HOURS_SHIFT);
552
553 /*
554 * If the number of days since 1970 is the same as the last
555 * time we did the computation then skip all this leap year
556 * and month stuff.
557 */
558 days = t / (24 * 60 * 60);
559 if (days != lastday) {
560 lastday = days;
561 for (year = 1970;; year++) {
562 inc = year & 0x03 ? 365 : 366;
563 if (days < inc)
564 break;
565 days -= inc;
566 }
567 months = year & 0x03 ? regyear : leapyear;
568 for (month = 0; month < 12; month++) {
569 if (days < months[month])
570 break;
571 days -= months[month];
572 }
573 lastddate = ((days + 1) << DD_DAY_SHIFT)
574 + ((month + 1) << DD_MONTH_SHIFT);
575 /*
576 * Remember dos's idea of time is relative to 1980.
577 * unix's is relative to 1970. If somehow we get a
578 * time before 1980 then don't give totally crazy
579 * results.
580 */
581 if (year > 1980)
582 lastddate += (year - 1980) << DD_YEAR_SHIFT;
583 }
584 }
585 if (dtp)
586 *dtp = lastdtime;
587 if (dhp)
588 *dhp = (tt & 1) * 100;
589
590 *ddp = lastddate;
591 }
592
593 /*
594 * The number of seconds between Jan 1, 1970 and Jan 1, 1980. In that
595 * interval there were 8 regular years and 2 leap years.
596 */
597 #define SECONDSTO1980 (((8 * 365) + (2 * 366)) * (24 * 60 * 60))
598
599 static unsigned short lastdosdate;
600 static unsigned long lastseconds;
601
602 /*
603 * Convert from dos' idea of time to unix'. This will probably only be
604 * called from the stat(), and fstat() system calls and so probably need
605 * not be too efficient.
606 */
607 void
dos2unixtime(unsigned int dd,unsigned int dt,unsigned int dh,time_t * tp)608 dos2unixtime(unsigned int dd, unsigned int dt, unsigned int dh, time_t *tp)
609 {
610 unsigned long seconds;
611 unsigned long m, month;
612 unsigned long y, year;
613 unsigned long days;
614 const unsigned short *months;
615
616 if (dd == 0) {
617 /*
618 * Uninitialized field, return the epoch.
619 */
620 tp = 0;
621 return;
622 }
623 seconds = ((dt & DT_2SECONDS_MASK) >> DT_2SECONDS_SHIFT) * 2
624 + ((dt & DT_MINUTES_MASK) >> DT_MINUTES_SHIFT) * 60
625 + ((dt & DT_HOURS_MASK) >> DT_HOURS_SHIFT) * 3600
626 + dh / 100;
627 /*
628 * If the year, month, and day from the last conversion are the
629 * same then use the saved value.
630 */
631 if (lastdosdate != dd) {
632 lastdosdate = dd;
633 days = 0;
634 year = (dd & DD_YEAR_MASK) >> DD_YEAR_SHIFT;
635 for (y = 0; y < year; y++)
636 days += y & 0x03 ? 365 : 366;
637 months = year & 0x03 ? regyear : leapyear;
638 /*
639 * Prevent going from 0 to 0xffffffff in the following
640 * loop.
641 */
642 month = (dd & DD_MONTH_MASK) >> DD_MONTH_SHIFT;
643 if (month == 0) {
644 printf("dos2unixtime(): month value out of range (%ld)\n",
645 month);
646 month = 1;
647 }
648 for (m = 0; m < month - 1; m++)
649 days += months[m];
650 days += ((dd & DD_DAY_MASK) >> DD_DAY_SHIFT) - 1;
651 lastseconds = (days * 24 * 60 * 60) + SECONDSTO1980;
652 }
653 *tp = seconds + lastseconds;
654 }
655