Release 951105
[wine/multimedia.git] / misc / dos_fs.c
blob13f52bf7b324ceab3b9d10014dc2ad3403c93dc6
1 /*
2 * DOS-FS
3 * NOV 1993 Erik Bos <erik@xs4all.nl>
5 * FindFile by Bob, hacked for dos & unixpaths by Erik.
7 * Bugfix by dash@ifi.uio.no: ToUnix() was called to often
8 */
10 #include <ctype.h>
11 #include <errno.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <sys/stat.h>
16 #include <pwd.h>
17 #include <dirent.h>
18 #include <unistd.h>
19 #include <fcntl.h>
21 #if defined(__linux__) || defined(sun)
22 #include <sys/vfs.h>
23 #endif
24 #if defined(__NetBSD__) || defined(__FreeBSD__)
25 #include <sys/param.h>
26 #include <sys/mount.h>
27 #endif
28 #ifdef __svr4__
29 #include <sys/statfs.h>
30 #endif
31 #include "wine.h"
32 #include "windows.h"
33 #include "msdos.h"
34 #include "dos_fs.h"
35 #include "comm.h"
36 #include "task.h"
37 #include "stddebug.h"
38 #include "debug.h"
39 #include "xmalloc.h"
41 #ifndef WINE_INI_GLOBAL
42 /* Get the WINE_INI_GLOBAL definition from autoconf.h */
43 #include "autoconf.h"
44 #endif
46 #define WINE_INI_USER "~/.winerc"
47 #define MAX_DOS_DRIVES 26
49 extern char WindowsDirectory[256], SystemDirectory[256],TempDirectory[256];
51 char WindowsPath[256];
53 static int max_open_dirs = 0;
54 static int CurrentDrive = 2;
56 struct DosDriveStruct { /* eg: */
57 char *rootdir; /* /usr/windows */
58 char cwd[256]; /* / */
59 char label[13]; /* DRIVE-A */
60 unsigned int serialnumber; /* ABCD5678 */
61 int disabled; /* 0 */
64 static struct DosDriveStruct DosDrives[MAX_DOS_DRIVES];
65 static struct dosdirent *DosDirs=NULL;
67 WORD ExtendedError;
68 BYTE ErrorClass, Action, ErrorLocus;
70 int DOS_Error(int e, int class, int el)
72 ErrorClass = class;
73 Action = SA_Ask4Retry;
74 ErrorLocus = el;
75 ExtendedError = e;
77 return e;
80 void errno_to_doserr(void)
82 switch (errno) {
83 case EAGAIN:
84 DOS_Error (ShareViolation, EC_Temporary, EL_Unknown);
85 break;
86 case EBADF:
87 DOS_Error (InvalidHandle, EC_AppError, EL_Unknown);
88 break;
89 case ENOSPC:
90 DOS_Error (DiskFull, EC_MediaError, EL_Disk);
91 break;
92 case EACCES:
93 case EPERM:
94 case EROFS:
95 DOS_Error (WriteProtected, EC_AccessDenied, EL_Unknown);
96 break;
97 case EBUSY:
98 DOS_Error (LockViolation, EC_AccessDenied, EL_Unknown);
99 break;
100 case ENOENT:
101 DOS_Error (FileNotFound, EC_NotFound, EL_Unknown);
102 break;
103 case EISDIR:
104 DOS_Error (CanNotMakeDir, EC_AccessDenied, EL_Unknown);
105 break;
106 case ENFILE:
107 case EMFILE:
108 DOS_Error (NoMoreFiles, EC_MediaError, EL_Unknown);
109 break;
110 case EEXIST:
111 DOS_Error (FileExists, EC_Exists, EL_Disk);
112 break;
113 default:
114 dprintf_int(stddeb, "int21: unknown errno %d!\n", errno);
115 DOS_Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
116 break;
121 static void ExpandTildeString(char *s)
123 struct passwd *entry;
124 char temp[1024], *ptr = temp;
126 strcpy(temp, s);
128 while (*ptr)
130 if (*ptr != '~')
132 *s++ = *ptr++;
133 continue;
136 ptr++;
138 if ( (entry = getpwuid(getuid())) == NULL)
140 continue;
143 strcpy(s, entry->pw_dir);
144 s += strlen(entry->pw_dir);
146 *s = 0;
149 /* Simplify the path in "name" by removing "//"'s, "/./"'s, and
150 ".."'s in names like "/usr/bin/../lib/test" */
151 static void DOS_SimplifyPath(char *name)
153 char *l,*p;
154 BOOL changed;
156 dprintf_dosfs(stddeb,"SimplifyPath: Before %s\n",name);
157 do {
158 changed = FALSE;
159 while ((l = strstr(name,"//"))) {
160 strcpy(l,l+1); changed = TRUE;
162 while ((l = strstr(name,"/../"))) {
163 *l = 0;
164 p = strrchr(name,'/');
165 if (p == NULL) p = name;
166 strcpy(p,l+3);
167 changed = TRUE;
169 while ((l = strstr(name, "/./"))) {
170 strcpy(l, l+2); changed = TRUE;
172 } while (changed);
173 dprintf_dosfs(stddeb,"SimplifyPath: After %s\n",name);
177 /* ChopOffSlash takes care to strip directory slashes from the
178 * end off the path name, but leaves a single slash. Multiple
179 * slashes at the end of a path are all removed.
182 void ChopOffSlash(char *path)
184 char *p = path + strlen(path) - 1;
185 while ((*p == '\\') && (p > path)) *p-- = '\0';
188 void ToUnix(char *s)
190 while(*s){
191 if (*s == '\\') *s = '/';
192 *s=tolower(*s); /* umsdos fs can't read files without :( */
193 s++;
197 void ToDos(char *s)
199 while(*s){
200 if (*s == '/') *s = '\\';
201 s++;
205 void DOS_InitFS(void)
207 int x;
208 char drive[2], temp[256];
210 GetPrivateProfileString("wine", "windows", "c:\\windows",
211 WindowsDirectory, sizeof(WindowsDirectory), WINE_INI);
213 GetPrivateProfileString("wine", "system", "c:\\windows\\system",
214 SystemDirectory, sizeof(SystemDirectory), WINE_INI);
216 GetPrivateProfileString("wine", "temp", "c:\\windows",
217 TempDirectory, sizeof(TempDirectory), WINE_INI);
219 GetPrivateProfileString("wine", "path", "c:\\windows;c:\\windows\\system",
220 WindowsPath, sizeof(WindowsPath), WINE_INI);
222 ChopOffSlash(WindowsDirectory);
223 ToDos(WindowsDirectory);
225 ChopOffSlash(SystemDirectory);
226 ToDos(SystemDirectory);
228 ChopOffSlash(TempDirectory);
229 ToDos(TempDirectory);
231 ToDos(WindowsPath);
232 ExpandTildeString(WindowsPath);
234 for (x=0; x!=MAX_DOS_DRIVES; x++) {
235 DosDrives[x].serialnumber = (0xEB0500L | x);
237 drive[0] = 'A' + x;
238 drive[1] = '\0';
239 GetPrivateProfileString("drives", drive, "*", temp, sizeof(temp), WINE_INI);
240 if (!strcmp(temp, "*") || *temp == '\0') {
241 DosDrives[x].rootdir = NULL;
242 DosDrives[x].cwd[0] = '\0';
243 DosDrives[x].label[0] = '\0';
244 DosDrives[x].disabled = 1;
245 continue;
247 ExpandTildeString(temp);
248 ChopOffSlash(temp);
249 DosDrives[x].rootdir = strdup(temp);
250 strcpy(DosDrives[x].rootdir, temp);
251 strcpy(DosDrives[x].cwd, "/windows/");
252 strcpy(DosDrives[x].label, "DRIVE-");
253 strcat(DosDrives[x].label, drive);
254 DosDrives[x].disabled = 0;
256 DosDrives[25].rootdir = "/";
257 strcpy(DosDrives[25].label, "UNIX-FS");
258 DosDrives[25].serialnumber = 0x12345678;
259 DosDrives[25].disabled = 0;
261 /* Get the startup directory and try to map it to a DOS drive
262 * and directory. (i.e., if we start in /dos/windows/word and
263 * drive C is defined as /dos, the starting wd for C will be
264 * /windows/word) Also set the default drive to whatever drive
265 * corresponds to the directory we started in.
268 for (x=0; x!=MAX_DOS_DRIVES; x++)
269 if (DosDrives[x].rootdir != NULL)
270 strcpy( DosDrives[x].cwd, "/" );
272 getcwd(temp, 254);
273 strcat(temp, "/"); /* For DOS_GetDosFileName */
274 strcpy(DosDrives[25].cwd, temp );
275 strcpy(temp, DOS_GetDosFileName(temp));
276 if(temp[0] != 'Z')
278 ToUnix(temp + 2);
279 strcpy(DosDrives[temp[0] - 'A'].cwd, &temp[2]);
280 DOS_SetDefaultDrive(temp[0] - 'A');
282 else
284 DOS_SetDefaultDrive(2);
287 for (x=0; x!=MAX_DOS_DRIVES; x++) {
288 if (DosDrives[x].rootdir != NULL) {
289 dprintf_dosfs(stddeb, "DOSFS: %c: => %-40s %s %s %X %d\n",
290 'A'+x,
291 DosDrives[x].rootdir,
292 DosDrives[x].cwd,
293 DosDrives[x].label,
294 DosDrives[x].serialnumber,
295 DosDrives[x].disabled);
299 for (x=0; x!=max_open_dirs ; x++)
300 DosDirs[x].inuse = 0;
302 dprintf_dosfs(stddeb,"wine.ini = %s\n",WINE_INI);
303 dprintf_dosfs(stddeb,"win.ini = %s\n",WIN_INI);
304 dprintf_dosfs(stddeb,"windir = %s\n",WindowsDirectory);
305 dprintf_dosfs(stddeb,"sysdir = %s\n",SystemDirectory);
306 dprintf_dosfs(stddeb,"tempdir = %s\n",TempDirectory);
307 dprintf_dosfs(stddeb,"path = %s\n",WindowsPath);
310 WORD DOS_GetEquipment(void)
312 WORD equipment;
313 int diskdrives = 0;
314 int parallelports = 0;
315 int serialports = 0;
316 int x;
318 /* borrowed from Ralph Brown's interrupt lists
320 bits 15-14: number of parallel devices
321 bit 13: [Conv] Internal modem
322 bit 12: reserved
323 bits 11- 9: number of serial devices
324 bit 8: reserved
325 bits 7- 6: number of diskette drives minus one
326 bits 5- 4: Initial video mode:
327 00b = EGA,VGA,PGA
328 01b = 40 x 25 color
329 10b = 80 x 25 color
330 11b = 80 x 25 mono
331 bit 3: reserved
332 bit 2: [PS] =1 if pointing device
333 [non-PS] reserved
334 bit 1: =1 if math co-processor
335 bit 0: =1 if diskette available for boot
337 /* Currently the only of these bits correctly set are:
338 bits 15-14 } Added by William Owen Smith,
339 bits 11-9 } wos@dcs.warwick.ac.uk
340 bits 7-6
341 bit 2 (always set)
344 if (DosDrives[0].rootdir != NULL)
345 diskdrives++;
346 if (DosDrives[1].rootdir != NULL)
347 diskdrives++;
348 if (diskdrives)
349 diskdrives--;
351 for (x=0; x!=MAX_PORTS; x++) {
352 if (COM[x].devicename)
353 serialports++;
354 if (LPT[x].devicename)
355 parallelports++;
357 if (serialports > 7) /* 3 bits -- maximum value = 7 */
358 serialports=7;
359 if (parallelports > 3) /* 2 bits -- maximum value = 3 */
360 parallelports=3;
362 equipment = (diskdrives << 6) | (serialports << 9) |
363 (parallelports << 14) | 0x02;
365 dprintf_dosfs(stddeb, "DOS_GetEquipment : diskdrives = %d serialports = %d "
366 "parallelports = %d\n"
367 "DOS_GetEquipment : equipment = %d\n",
368 diskdrives, serialports, parallelports, equipment);
370 return equipment;
373 int DOS_ValidDrive(int drive)
375 dprintf_dosfs(stddeb,"ValidDrive %c (%d)\n",'A'+drive,drive);
377 if (drive < 0 || drive >= MAX_DOS_DRIVES) return 0;
378 if (DosDrives[drive].rootdir == NULL) return 0;
379 if (DosDrives[drive].disabled) return 0;
381 dprintf_dosfs(stddeb, " -- valid\n");
382 return 1;
385 static void DOS_GetCurrDir_Unix(char *buffer, int drive)
387 TDB *pTask = (TDB *)GlobalLock(GetCurrentTask());
389 if (pTask != NULL && (pTask->curdrive & ~0x80) == drive) {
390 strcpy(buffer, pTask->curdir);
391 ToUnix(buffer);
392 } else {
393 strcpy(buffer, DosDrives[drive].cwd);
397 char *DOS_GetCurrentDir(int drive)
399 static char temp[256];
401 if (!DOS_ValidDrive(drive)) return 0;
403 DOS_GetCurrDir_Unix(temp, drive);
404 DOS_SimplifyPath( temp );
405 ToDos(temp);
406 ChopOffSlash(temp);
408 dprintf_dosfs(stddeb,"DOS_GetCWD: %c:%s\n", 'A'+drive, temp);
409 return temp + 1;
412 char *DOS_GetUnixFileName(const char *dosfilename)
414 /* a:\windows\system.ini => /dos/windows/system.ini */
416 /* FIXME: should handle devices here (like LPT: or NUL:) */
418 static char dostemp[256], temp[256];
419 int drive = DOS_GetDefaultDrive();
421 if (dosfilename[0] && dosfilename[1] == ':')
423 drive = toupper(*dosfilename) - 'A';
424 dosfilename += 2;
426 if (!DOS_ValidDrive(drive)) return NULL;
428 strncpy( dostemp, dosfilename, 255 );
429 dostemp[255] = 0;
430 ToUnix(dostemp);
431 strcpy(temp, DosDrives[drive].rootdir);
432 if (dostemp[0] != '/') {
433 DOS_GetCurrDir_Unix(temp+strlen(temp), drive);
435 strcat(temp, dostemp);
436 DOS_SimplifyPath(temp);
438 dprintf_dosfs(stddeb,"GetUnixFileName: %s => %s\n", dosfilename, temp);
439 return temp;
442 /* Note: This function works on directories as well as long as
443 * the directory ends in a slash.
445 char *DOS_GetDosFileName(char *unixfilename)
447 int i;
448 static char temp[256], temp2[256];
449 /* /dos/windows/system.ini => c:\windows\system.ini */
451 dprintf_dosfs(stddeb,"DOS_GetDosFileName: %s\n", unixfilename);
452 if (unixfilename[0] == '/') {
453 strncpy(temp, unixfilename, 255);
454 temp[255] = 0;
455 } else {
456 /* Expand it if it's a relative name. */
457 getcwd(temp, 255);
458 if(strncmp(unixfilename, "./", 2) != 0) {
459 strcat(temp, unixfilename + 1);
460 } else {
461 strcat(temp, "/");
462 strcat(temp, unixfilename);
465 for (i = 0 ; i < MAX_DOS_DRIVES; i++) {
466 if (DosDrives[i].rootdir != NULL) {
467 int len = strlen(DosDrives[i].rootdir);
468 dprintf_dosfs(stddeb, " check %c:%s\n", i+'A', DosDrives[i].rootdir);
469 if (strncmp(DosDrives[i].rootdir, temp, len) == 0 && temp[len] == '/')
471 sprintf(temp2, "%c:%s", 'A' + i, temp+len);
472 ToDos(temp2+2);
473 return temp2;
477 sprintf(temp, "Z:%s", unixfilename);
478 ToDos(temp+2);
479 return temp;
482 int DOS_ValidDirectory(int drive, char *name)
484 char temp[256];
485 struct stat s;
487 strcpy(temp, DosDrives[drive].rootdir);
488 strcat(temp, name);
489 if (stat(temp, &s)) return 0;
490 if (!S_ISDIR(s.st_mode)) return 0;
491 dprintf_dosfs(stddeb, "==> OK\n");
492 return 1;
495 int DOS_GetDefaultDrive(void)
497 TDB *pTask = (TDB *)GlobalLock(GetCurrentTask());
498 int drive = pTask == NULL ? CurrentDrive : pTask->curdrive & ~0x80;
500 dprintf_dosfs(stddeb,"GetDefaultDrive (%c)\n",'A'+drive);
501 return drive;
504 void DOS_SetDefaultDrive(int drive)
506 TDB *pTask = (TDB *)GlobalLock(GetCurrentTask());
508 dprintf_dosfs(stddeb,"SetDefaultDrive to %c:\n",'A'+drive);
509 if (DOS_ValidDrive(drive) && drive != DOS_GetDefaultDrive()) {
510 if (pTask == NULL) CurrentDrive = drive;
511 else {
512 char temp[256];
513 pTask->curdrive = drive | 0x80;
514 strcpy(temp, DosDrives[drive].rootdir);
515 strcat(temp, DosDrives[drive].cwd);
516 strcpy(temp, DOS_GetDosFileName(temp));
517 dprintf_dosfs(stddeb, " curdir = %s\n", temp);
518 if (strlen(temp)-2 < sizeof(pTask->curdir)) strcpy(pTask->curdir, temp+2);
519 else fprintf(stderr, "dosfs: curdir too long\n");
524 int DOS_DisableDrive(int drive)
526 if (drive >= MAX_DOS_DRIVES) return 0;
527 if (DosDrives[drive].rootdir == NULL) return 0;
529 DosDrives[drive].disabled = 1;
530 return 1;
533 int DOS_EnableDrive(int drive)
535 if (drive >= MAX_DOS_DRIVES) return 0;
536 if (DosDrives[drive].rootdir == NULL) return 0;
538 DosDrives[drive].disabled = 0;
539 return 1;
542 int DOS_ChangeDir(int drive, char *dirname)
544 TDB *pTask = (TDB *)GlobalLock(GetCurrentTask());
545 char temp[256];
547 if (!DOS_ValidDrive(drive)) return 0;
549 if (dirname[0] == '\\') {
550 strcpy(temp, dirname);
551 } else {
552 DOS_GetCurrDir_Unix(temp, drive);
553 strcat(temp, dirname);
555 ToUnix(temp);
556 strcat(temp, "/");
557 DOS_SimplifyPath(temp);
558 dprintf_dosfs(stddeb,"DOS_SetCWD: %c: %s ==> %s\n", 'A'+drive, dirname, temp);
560 if (!DOS_ValidDirectory(drive, temp)) return 0;
561 strcpy(DosDrives[drive].cwd, temp);
562 if (pTask != NULL && DOS_GetDefaultDrive() == drive) {
563 strcpy(temp, DosDrives[drive].rootdir);
564 strcat(temp, DosDrives[drive].cwd);
565 strcpy(temp, DOS_GetDosFileName(temp));
566 dprintf_dosfs(stddeb, " curdir = %s\n", temp);
567 if (strlen(temp)-2 < sizeof(pTask->curdir)) strcpy(pTask->curdir, temp+2);
568 else fprintf(stderr, "dosfs: curdir too long\n");
570 return 1;
573 int DOS_MakeDir(int drive, char *dirname)
575 char temp[256], currdir[256];
577 if (!DOS_ValidDrive(drive)) return 0;
579 strcpy(temp, DosDrives[drive].rootdir);
580 DOS_GetCurrDir_Unix(currdir, drive);
581 strcat(temp, currdir);
582 strcat(temp, dirname);
583 ToUnix(temp);
584 DOS_SimplifyPath(temp);
585 mkdir(temp,0);
587 dprintf_dosfs(stddeb, "DOS_MakeDir: %c:\%s => %s",'A'+drive, dirname, temp);
588 return 1;
591 int DOS_GetSerialNumber(int drive, unsigned long *serialnumber)
593 if (!DOS_ValidDrive(drive))
594 return 0;
596 *serialnumber = DosDrives[drive].serialnumber;
597 return 1;
600 int DOS_SetSerialNumber(int drive, unsigned long serialnumber)
602 if (!DOS_ValidDrive(drive))
603 return 0;
605 DosDrives[drive].serialnumber = serialnumber;
606 return 1;
609 char *DOS_GetVolumeLabel(int drive)
611 if (!DOS_ValidDrive(drive))
612 return NULL;
614 return DosDrives[drive].label;
617 int DOS_SetVolumeLabel(int drive, char *label)
619 if (!DOS_ValidDrive(drive))
620 return 0;
622 strncpy(DosDrives[drive].label, label, 8);
623 return 1;
626 int DOS_GetFreeSpace(int drive, long *size, long *available)
628 struct statfs info;
630 if (!DOS_ValidDrive(drive))
631 return 0;
633 #ifdef __svr4__
634 if (statfs(DosDrives[drive].rootdir, &info, 0, 0) < 0) {
635 #else
636 if (statfs(DosDrives[drive].rootdir, &info) < 0) {
637 #endif
638 fprintf(stderr,"dosfs: cannot do statfs(%s)\n",
639 DosDrives[drive].rootdir);
640 return 0;
643 *size = info.f_bsize * info.f_blocks;
644 #ifdef __svr4__
645 *available = info.f_bfree * info.f_bsize;
646 #else
647 *available = info.f_bavail * info.f_bsize;
648 #endif
650 return 1;
653 char *DOS_FindFile(char *buffer, int buflen, const char *filename, char **extensions,
654 char *path)
656 char *workingpath, *dirname, *rootname, **e;
657 DIR *d;
658 struct dirent *f;
659 int rootnamelen;
660 struct stat filestat;
662 if (strchr(filename, '\\') != NULL)
664 strncpy(buffer, DOS_GetUnixFileName(filename), buflen);
665 stat( buffer, &filestat);
666 if (S_ISREG(filestat.st_mode))
667 return buffer;
668 else
669 return NULL;
672 if (strchr(filename, '/') != NULL)
674 strncpy(buffer, filename, buflen);
675 return buffer;
678 dprintf_dosfs(stddeb,"DOS_FindFile: looking for %s\n", filename);
679 rootnamelen = strlen(filename);
680 rootname = strdup(filename);
681 ToUnix(rootname);
682 workingpath = strdup(path);
684 for(dirname = strtok(workingpath, ";");
685 dirname != NULL;
686 dirname = strtok(NULL, ";"))
688 if (strchr(dirname, '\\') != NULL)
689 d = opendir( DOS_GetUnixFileName(dirname) );
690 else
691 d = opendir( dirname );
693 dprintf_dosfs(stddeb,"in %s\n",dirname);
694 if (d != NULL)
696 while ((f = readdir(d)) != NULL)
698 if (strcasecmp(rootname, f->d_name) != 0) {
699 if (strncasecmp(rootname, f->d_name, rootnamelen) != 0
700 || extensions == NULL
701 || f->d_name[rootnamelen] != '.')
702 continue;
704 for (e = extensions; *e != NULL; e++) {
705 if (strcasecmp(*e, f->d_name + rootnamelen + 1) == 0)
706 break;
708 if (*e == NULL) continue;
711 if (strchr(dirname, '\\') != NULL) {
712 strncpy(buffer, DOS_GetUnixFileName(dirname), buflen);
713 } else {
714 strncpy(buffer, dirname, buflen);
717 strncat(buffer, "/", buflen - strlen(buffer));
718 strncat(buffer, f->d_name, buflen - strlen(buffer));
720 stat(buffer, &filestat);
721 if (S_ISREG(filestat.st_mode)) {
722 closedir(d);
723 free(rootname);
724 DOS_SimplifyPath(buffer);
725 return buffer;
728 closedir(d);
731 return NULL;
734 /**********************************************************************
735 * WineIniFileName
737 char *WineIniFileName(void)
739 int fd;
740 static char *filename = NULL;
741 static char name[256];
743 if (filename)
744 return filename;
746 strcpy(name, WINE_INI_USER);
747 ExpandTildeString(name);
748 if ((fd = open(name, O_RDONLY)) != -1) {
749 close(fd);
750 filename = name;
751 return filename;
753 if ((fd = open(WINE_INI_GLOBAL, O_RDONLY)) != -1) {
754 close(fd);
755 filename = WINE_INI_GLOBAL;
756 return filename;
758 fprintf(stderr,"wine: can't open configuration file %s or %s !\n",
759 WINE_INI_GLOBAL, WINE_INI_USER);
760 exit(1);
763 char *WinIniFileName(void)
765 static char *name = NULL;
767 if (name)
768 return name;
770 name = xmalloc(1024);
772 strcpy(name, DOS_GetUnixFileName(WindowsDirectory));
773 strcat(name, "/");
774 strcat(name, "win.ini");
776 name = xrealloc(name, strlen(name) + 1);
778 return name;
781 static int match(char *filename, char *filemask)
783 char name[12], mask[12];
784 int i;
786 dprintf_dosfs(stddeb, "match: %s, %s\n", filename, filemask);
788 for( i=0; i<11; i++ ) {
789 name[i] = ' ';
790 mask[i] = ' ';
792 name[11] = 0;
793 mask[11] = 0;
795 for( i=0; i<8; i++ )
796 if( !(*filename) || *filename == '.' )
797 break;
798 else
799 name[i] = toupper( *filename++ );
800 while( *filename && *filename != '.' )
801 filename++;
802 if( *filename )
803 filename++;
804 for( i=8; i<11; i++ )
805 if( !(*filename) )
806 break;
807 else
808 name[i] = toupper( *filename++ );
810 for( i=0; i<8; i++ )
811 if( !(*filemask) || *filemask == '.' )
812 break;
813 else if( *filemask == '*' ) {
814 int j;
815 for( j=i; j<8; j++ )
816 mask[j] = '?';
817 break;
819 else
820 mask[i] = toupper( *filemask++ );
821 while( *filemask && *filemask != '.' )
822 filemask++;
823 if( *filemask )
824 filemask++;
825 for( i=8; i<11; i++ )
826 if( !(*filemask) )
827 break;
828 else if (*filemask == '*' ) {
829 int j;
830 for( j=i; j<11; j++ )
831 mask[j] = '?';
832 break;
834 else
835 mask[i] = toupper( *filemask++ );
837 dprintf_dosfs(stddeb, "changed to: %s, %s\n", name, mask);
839 for( i=0; i<11; i++ )
840 if( ( name[i] != mask[i] ) && ( mask[i] != '?' ) )
841 return 0;
843 return 1;
846 struct dosdirent *DOS_opendir(char *dosdirname)
848 int x, len;
849 char *unixdirname;
850 char dirname[256];
851 DIR *ds;
853 if ((unixdirname = DOS_GetUnixFileName(dosdirname)) == NULL) return NULL;
855 len = strrchr(unixdirname, '/') - unixdirname + 1;
856 strncpy(dirname, unixdirname, len);
857 dirname[len] = 0;
858 unixdirname = strrchr(unixdirname, '/') + 1;
860 for (x=0; x <= max_open_dirs; x++) {
861 if (x == max_open_dirs) {
862 if (DosDirs) {
863 DosDirs=(struct dosdirent*)xrealloc(DosDirs,(++max_open_dirs)*sizeof(DosDirs[0]));
864 } else {
865 DosDirs=(struct dosdirent*)xmalloc(sizeof(DosDirs[0]));
866 max_open_dirs=1;
868 break; /* this one is definitely not in use */
870 if (!DosDirs[x].inuse) break;
871 if (strcmp(DosDirs[x].unixpath, dirname) == 0) break;
874 strncpy(DosDirs[x].filemask, unixdirname, 12);
875 DosDirs[x].filemask[12] = 0;
876 dprintf_dosfs(stddeb,"DOS_opendir: %s / %s\n", unixdirname, dirname);
878 DosDirs[x].inuse = 1;
879 strcpy(DosDirs[x].unixpath, dirname);
880 DosDirs[x].entnum = 0;
882 if ((ds = opendir(dirname)) == NULL) return NULL;
883 if (-1==(DosDirs[x].telldirnum=telldir(ds))) {
884 closedir(ds);
885 return NULL;
887 if (-1==closedir(ds)) return NULL;
889 return &DosDirs[x];
893 struct dosdirent *DOS_readdir(struct dosdirent *de)
895 char temp[256];
896 struct dirent *d;
897 struct stat st;
898 DIR *ds;
900 if (!de->inuse)
901 return NULL;
902 if (!(ds=opendir(de->unixpath))) return NULL;
903 seekdir(ds,de->telldirnum); /* returns no error value. strange */
905 if (de->search_attribute & FA_LABEL) {
906 int drive;
907 de->search_attribute &= ~FA_LABEL; /* don't find it again */
908 for(drive = 0; drive < MAX_DOS_DRIVES; drive++) {
909 if (DosDrives[drive].rootdir != NULL &&
910 strcmp(DosDrives[drive].rootdir, de->unixpath) == 0)
912 strcpy(de->filename, DOS_GetVolumeLabel(drive));
913 de->attribute = FA_LABEL;
914 return de;
919 do {
920 if ((d = readdir(ds)) == NULL) {
921 de->telldirnum=telldir(ds);
922 closedir(ds);
923 return NULL;
926 de->entnum++; /* Increment the directory entry number */
927 strcpy(de->filename, d->d_name);
928 if (d->d_reclen > 12)
929 de->filename[12] = '\0';
931 ToDos(de->filename);
932 } while ( !match(de->filename, de->filemask) );
934 strcpy(temp,de->unixpath);
935 strcat(temp,"/");
936 strcat(temp,de->filename);
937 ToUnix(temp + strlen(de->unixpath));
939 stat (temp, &st);
940 de->attribute = 0x0;
941 if S_ISDIR(st.st_mode)
942 de->attribute |= FA_DIREC;
944 de->filesize = st.st_size;
945 de->filetime = st.st_mtime;
947 de->telldirnum = telldir(ds);
948 closedir(ds);
949 return de;
952 void DOS_closedir(struct dosdirent *de)
954 if (de && de->inuse)
955 de->inuse = 0;
958 char *DOS_GetRedirectedDir(int drive)
960 if(DOS_ValidDrive(drive))
961 return (DosDrives[drive].rootdir);
962 else
963 return ("/");