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
20 #if defined(__linux__) || defined(sun)
23 #if defined(__NetBSD__) || defined(__FreeBSD__)
24 #include <sys/param.h>
25 #include <sys/mount.h>
37 #define WINE_INI_USER "~/.winerc"
38 #define MAX_OPEN_DIRS 16
39 #define MAX_DOS_DRIVES 26
41 extern char WindowsDirectory
[256], SystemDirectory
[256],TempDirectory
[256];
43 char WindowsPath
[256];
45 static int CurrentDrive
= 2;
47 struct DosDriveStruct
{ /* eg: */
48 char *rootdir
; /* /usr/windows */
49 char cwd
[256]; /* / */
50 char label
[13]; /* DRIVE-A */
51 unsigned int serialnumber
; /* ABCD5678 */
55 static struct DosDriveStruct DosDrives
[MAX_DOS_DRIVES
];
56 static struct dosdirent DosDirs
[MAX_OPEN_DIRS
];
58 static void ExpandTildeString(char *s
)
61 char temp
[1024], *ptr
= temp
;
75 if ( (entry
= getpwuid(getuid())) == NULL
)
80 strcpy(s
, entry
->pw_dir
);
81 s
+= strlen(entry
->pw_dir
);
86 void ChopOffSlash(char *path
)
88 if (path
[strlen(path
)-1] == '/' || path
[strlen(path
)-1] == '\\')
89 path
[strlen(path
)-1] = '\0';
94 /* \WINDOWS\\SYSTEM => /windows/system */
104 if (*(p
+1) == '/' || *(p
+1) == '\\')
113 /* /windows//system => \WINDOWS\SYSTEM */
122 if (*(p
+1) == '/' || *(p
+1) == '\\')
129 void DOS_InitFS(void)
132 char drive
[2], temp
[256];
134 GetPrivateProfileString("wine", "windows", "c:\\windows",
135 WindowsDirectory
, sizeof(WindowsDirectory
), WINE_INI
);
137 GetPrivateProfileString("wine", "system", "c:\\windows\\system",
138 SystemDirectory
, sizeof(SystemDirectory
), WINE_INI
);
140 GetPrivateProfileString("wine", "temp", "c:\\windows",
141 TempDirectory
, sizeof(TempDirectory
), WINE_INI
);
143 GetPrivateProfileString("wine", "path", "c:\\windows;c:\\windows\\system",
144 WindowsPath
, sizeof(WindowsPath
), WINE_INI
);
146 ChopOffSlash(WindowsDirectory
);
147 ToDos(WindowsDirectory
);
149 ChopOffSlash(SystemDirectory
);
150 ToDos(SystemDirectory
);
152 ChopOffSlash(TempDirectory
);
153 ToDos(TempDirectory
);
156 ExpandTildeString(WindowsPath
);
158 for (x
=0; x
!=MAX_DOS_DRIVES
; x
++) {
159 DosDrives
[x
].serialnumber
= (0xEB0500L
| x
);
163 GetPrivateProfileString("drives", drive
, "*", temp
, sizeof(temp
), WINE_INI
);
164 if (!strcmp(temp
, "*") || *temp
== '\0') {
165 DosDrives
[x
].rootdir
= NULL
;
166 DosDrives
[x
].cwd
[0] = '\0';
167 DosDrives
[x
].label
[0] = '\0';
168 DosDrives
[x
].disabled
= 1;
171 ExpandTildeString(temp
);
173 DosDrives
[x
].rootdir
= strdup(temp
);
174 strcpy(DosDrives
[x
].rootdir
, temp
);
175 strcpy(DosDrives
[x
].cwd
, "/windows/");
176 strcpy(DosDrives
[x
].label
, "DRIVE-");
177 strcat(DosDrives
[x
].label
, drive
);
178 DosDrives
[x
].disabled
= 0;
180 DosDrives
[25].rootdir
= "/";
181 strcpy(DosDrives
[25].cwd
, "/");
182 strcpy(DosDrives
[25].label
, "UNIX-FS");
183 DosDrives
[25].serialnumber
= 0x12345678;
184 DosDrives
[25].disabled
= 0;
186 /* Get the startup directory and try to map it to a DOS drive
187 * and directory. (i.e., if we start in /dos/windows/word and
188 * drive C is defined as /dos, the starting wd for C will be
189 * /windows/word) Also set the default drive to whatever drive
190 * corresponds to the directory we started in.
193 for (x
=0; x
!=MAX_DOS_DRIVES
; x
++)
194 if (DosDrives
[x
].rootdir
!= NULL
)
195 strcpy( DosDrives
[x
].cwd
, "\\" );
198 strcat(temp
, "/"); /* For DOS_GetDosFileName */
199 strcpy(temp
, DOS_GetDosFileName(temp
));
203 strcpy(DosDrives
[temp
[0] - 'A'].cwd
, &temp
[2]);
204 DOS_SetDefaultDrive(temp
[0] - 'A');
208 DOS_SetDefaultDrive(2);
211 for (x
=0; x
!=MAX_DOS_DRIVES
; x
++) {
212 if (DosDrives
[x
].rootdir
!= NULL
) {
213 dprintf_dosfs(stddeb
, "DOSFS: %c: => %-40s %s %s %X %d\n",
215 DosDrives
[x
].rootdir
,
218 DosDrives
[x
].serialnumber
,
219 DosDrives
[x
].disabled
224 for (x
=0; x
!=MAX_OPEN_DIRS
; x
++)
225 DosDirs
[x
].inuse
= 0;
227 dprintf_dosfs(stddeb
,"wine.ini = %s\n",WINE_INI
);
228 dprintf_dosfs(stddeb
,"win.ini = %s\n",WIN_INI
);
229 dprintf_dosfs(stddeb
,"windir = %s\n",WindowsDirectory
);
230 dprintf_dosfs(stddeb
,"sysdir = %s\n",SystemDirectory
);
231 dprintf_dosfs(stddeb
,"tempdir = %s\n",TempDirectory
);
232 dprintf_dosfs(stddeb
,"path = %s\n",WindowsPath
);
235 WORD
DOS_GetEquipment(void)
239 int parallelports
= 0;
243 /* borrowed from Ralph Brown's interrupt lists
245 bits 15-14: number of parallel devices
246 bit 13: [Conv] Internal modem
248 bits 11- 9: number of serial devices
250 bits 7- 6: number of diskette drives minus one
251 bits 5- 4: Initial video mode:
257 bit 2: [PS] =1 if pointing device
259 bit 1: =1 if math co-processor
260 bit 0: =1 if diskette available for boot
262 /* Currently the only of these bits correctly set are:
263 bits 15-14 } Added by William Owen Smith,
264 bits 11-9 } wos@dcs.warwick.ac.uk
269 if (DosDrives
[0].rootdir
!= NULL
)
271 if (DosDrives
[1].rootdir
!= NULL
)
276 for (x
=0; x
!=MAX_PORTS
; x
++) {
277 if (COM
[x
].devicename
)
279 if (LPT
[x
].devicename
)
282 if (serialports
> 7) /* 3 bits -- maximum value = 7 */
284 if (parallelports
> 3) /* 2 bits -- maximum value = 3 */
287 equipment
= (diskdrives
<< 6) | (serialports
<< 9) |
288 (parallelports
<< 14) | 0x02;
290 dprintf_dosfs(stddeb
, "DOS_GetEquipment : diskdrives = %d serialports = %d "
291 "parallelports = %d\n"
292 "DOS_GetEquipment : equipment = %d\n",
293 diskdrives
, serialports
, parallelports
, equipment
);
298 int DOS_ValidDrive(int drive
)
302 dprintf_dosfs(stddeb
,"ValidDrive %c (%d) -- ",'A'+drive
,drive
);
304 if (drive
>= MAX_DOS_DRIVES
)
306 if (DosDrives
[drive
].rootdir
== NULL
)
308 if (DosDrives
[drive
].disabled
)
311 dprintf_dosfs(stddeb
, "%s\n", valid
? "Valid" : "Invalid");
316 int DOS_ValidDirectory(char *name
)
320 dprintf_dosfs(stddeb
, "DOS_ValidDirectory: '%s'\n", name
);
321 if ((dirname
= DOS_GetUnixFileName(name
)) == NULL
)
323 if (stat(dirname
,&s
))
325 if (!S_ISDIR(s
.st_mode
))
327 dprintf_dosfs(stddeb
, "==> OK\n");
333 /* Simplify the path in "name" by removing "//"'s and
334 ".."'s in names like "/usr/bin/../lib/test" */
335 void DOS_SimplifyPath(char *name
)
340 dprintf_dosfs(stddeb
,"SimplifyPath: Before %s\n",name
);
343 while ((l
= strstr(name
,"//"))) {
344 strcpy(l
,l
+1); changed
= TRUE
;
346 while ((l
= strstr(name
,"/../"))) {
348 p
= strrchr(name
,'/');
349 if (p
== NULL
) p
= name
;
354 dprintf_dosfs(stddeb
,"SimplifyPath: After %s\n",name
);
358 int DOS_GetDefaultDrive(void)
360 dprintf_dosfs(stddeb
,"GetDefaultDrive (%c)\n",'A'+CurrentDrive
);
361 return( CurrentDrive
);
364 void DOS_SetDefaultDrive(int drive
)
366 dprintf_dosfs(stddeb
,"SetDefaultDrive to %c:\n",'A'+drive
);
367 if (DOS_ValidDrive(drive
))
368 CurrentDrive
= drive
;
371 int DOS_DisableDrive(int drive
)
373 if (drive
>= MAX_DOS_DRIVES
)
375 if (DosDrives
[drive
].rootdir
== NULL
)
378 DosDrives
[drive
].disabled
= 1;
382 int DOS_EnableDrive(int drive
)
384 if (drive
>= MAX_DOS_DRIVES
)
386 if (DosDrives
[drive
].rootdir
== NULL
)
389 DosDrives
[drive
].disabled
= 0;
393 static void GetUnixDirName(char *rootdir
, char *name
)
396 char *nameptr
, *cwdptr
;
398 cwdptr
= rootdir
+ strlen(rootdir
);
401 dprintf_dosfs(stddeb
,"GetUnixDirName: %s <=> %s => ",rootdir
, name
);
404 if (*nameptr
== '.' & !filename
) {
406 if (*nameptr
== '\0') {
410 if (*nameptr
== '.') {
412 while (cwdptr
!= rootdir
) {
414 if (*cwdptr
== '/') {
421 if (*nameptr
== '\\' || *nameptr
== '/') {
427 if (*nameptr
== '\\' || *nameptr
== '/') {
436 *cwdptr
++ = *nameptr
++;
442 dprintf_dosfs(stddeb
,"%s\n", rootdir
);
446 char *DOS_GetUnixFileName(char *dosfilename
)
448 /* a:\windows\system.ini => /dos/windows/system.ini */
450 static char temp
[256];
451 static char dostemp
[256];
454 if (dosfilename
[1] == ':')
456 drive
= (islower(*dosfilename
) ? toupper(*dosfilename
) : *dosfilename
) - 'A';
458 if (!DOS_ValidDrive(drive
))
463 drive
= CurrentDrive
;
465 /* Consider dosfilename const */
466 strcpy(dostemp
,dosfilename
);
468 /* Expand the filename to it's full path if it doesn't
469 * start from the root.
471 DOS_ExpandToFullPath(dostemp
, drive
);
473 strcpy(temp
, DosDrives
[drive
].rootdir
);
474 strcat(temp
, DosDrives
[drive
].cwd
);
475 GetUnixDirName(temp
+ strlen(DosDrives
[drive
].rootdir
), dostemp
);
477 dprintf_dosfs(stddeb
,"GetUnixFileName: %s => %s\n", dosfilename
, temp
);
481 /* Note: This function works on directories as well as long as
482 * the directory ends in a slash.
484 char *DOS_GetDosFileName(char *unixfilename
)
487 static char temp
[256], rootdir
[256];
488 /* /dos/windows/system.ini => c:\windows\system.ini */
490 /* Expand it if it's a relative name.
492 DOS_ExpandToFullUnixPath(unixfilename
);
494 for (i
= 0 ; i
!= MAX_DOS_DRIVES
; i
++) {
495 if (DosDrives
[i
].rootdir
!= NULL
) {
496 strcpy(rootdir
, DosDrives
[i
].rootdir
);
497 strcat(rootdir
, "/");
498 if (strncmp(rootdir
, unixfilename
, strlen(rootdir
)) == 0) {
499 sprintf(temp
, "%c:\\%s", 'A' + i
, unixfilename
+ strlen(rootdir
));
505 sprintf(temp
, "Z:%s", unixfilename
);
510 char *DOS_GetCurrentDir(int drive
)
512 static char temp
[256];
514 if (!DOS_ValidDrive(drive
))
517 strcpy(temp
, DosDrives
[drive
].cwd
);
518 DOS_SimplifyPath( temp
);
522 dprintf_dosfs(stddeb
,"DOS_GetCWD: %c:%s\n", 'A'+drive
, temp
);
526 int DOS_ChangeDir(int drive
, char *dirname
)
528 char temp
[256],old
[256];
530 if (!DOS_ValidDrive(drive
))
533 strcpy(temp
, dirname
);
535 strcpy(old
, DosDrives
[drive
].cwd
);
537 GetUnixDirName(DosDrives
[drive
].cwd
, temp
);
538 strcat(DosDrives
[drive
].cwd
,"/");
540 dprintf_dosfs(stddeb
,"DOS_SetCWD: %c: %s\n",'A'+drive
,
541 DosDrives
[drive
].cwd
);
543 if (!DOS_ValidDirectory(DosDrives
[drive
].cwd
))
545 strcpy(DosDrives
[drive
].cwd
, old
);
548 DOS_SimplifyPath(DosDrives
[drive
].cwd
);
552 int DOS_MakeDir(int drive
, char *dirname
)
556 if (!DOS_ValidDrive(drive
))
559 strcpy(temp
, DosDrives
[drive
].cwd
);
560 GetUnixDirName(temp
, dirname
);
561 strcat(DosDrives
[drive
].cwd
,"/");
563 ToUnix(temp
+ strlen(DosDrives
[drive
].cwd
));
566 dprintf_dosfs(stddeb
,
567 "DOS_MakeDir: %c:\%s => %s",'A'+drive
, dirname
, temp
);
571 /* DOS_ExpandToFullPath takes a dos-style filename and converts it
572 * into a full path based on the current working directory.
573 * (e.g., "foo.bar" => "d:\\moo\\foo.bar")
575 void DOS_ExpandToFullPath(char *filename
, int drive
)
579 dprintf_dosfs(stddeb
, "DOS_ExpandToFullPath: Original = %s\n", filename
);
581 /* If the filename starts with '/' or '\',
582 * don't bother -- we're already at the root.
584 if(filename
[0] == '/' || filename
[0] == '\\')
587 strcpy(temp
, DosDrives
[drive
].cwd
);
588 strcat(temp
, filename
);
589 strcpy(filename
, temp
);
591 dprintf_dosfs(stddeb
, " Expanded = %s\n", temp
);
594 /* DOS_ExpandToFullUnixPath takes a unix filename and converts it
595 * into a full path based on the current working directory. Thus,
596 * it's probably not a good idea to get a relative name, change the
597 * working directory, and then convert it...
599 void DOS_ExpandToFullUnixPath(char *filename
)
603 if(filename
[0] == '/')
607 if(!strncmp(filename
, "./", 2))
608 strcat(temp
, filename
+ 1);
612 strcat(temp
, filename
);
614 dprintf_dosfs(stddeb
, "DOS_ExpandToFullUnixPath: %s => %s\n", filename
, temp
);
615 strcpy(filename
, temp
);
618 int DOS_GetSerialNumber(int drive
, unsigned long *serialnumber
)
620 if (!DOS_ValidDrive(drive
))
623 *serialnumber
= DosDrives
[drive
].serialnumber
;
627 int DOS_SetSerialNumber(int drive
, unsigned long serialnumber
)
629 if (!DOS_ValidDrive(drive
))
632 DosDrives
[drive
].serialnumber
= serialnumber
;
636 char *DOS_GetVolumeLabel(int drive
)
638 if (!DOS_ValidDrive(drive
))
641 return (DosDrives
[drive
].label
);
644 int DOS_SetVolumeLabel(int drive
, char *label
)
646 if (!DOS_ValidDrive(drive
))
649 strncpy(DosDrives
[drive
].label
, label
, 8);
653 int DOS_GetFreeSpace(int drive
, long *size
, long *available
)
657 if (!DOS_ValidDrive(drive
))
660 if (statfs(DosDrives
[drive
].rootdir
, &info
) < 0) {
661 fprintf(stderr
,"dosfs: cannot do statfs(%s)\n",
662 DosDrives
[drive
].rootdir
);
666 *size
= info
.f_bsize
* info
.f_blocks
;
667 *available
= info
.f_bavail
* info
.f_bsize
;
672 char *DOS_FindFile(char *buffer
, int buflen
, char *filename
, char **extensions
,
675 char *workingpath
, *dirname
, *rootname
, **e
;
678 int rootnamelen
, found
= 0;
679 struct stat filestat
;
681 if (strchr(filename
, '\\') != NULL
)
683 strncpy(buffer
, DOS_GetUnixFileName(filename
), buflen
);
684 stat( buffer
, &filestat
);
685 if (S_ISREG(filestat
.st_mode
))
691 if (strchr(filename
, '/') != NULL
)
693 strncpy(buffer
, filename
, buflen
);
697 dprintf_dosfs(stddeb
,"DOS_FindFile: looking for %s\n", filename
);
698 rootnamelen
= strlen(filename
);
699 rootname
= strdup(filename
);
701 workingpath
= strdup(path
);
703 for(dirname
= strtok(workingpath
, ";");
705 dirname
= strtok(NULL
, ";"))
707 if (strchr(dirname
, '\\') != NULL
)
708 d
= opendir( DOS_GetUnixFileName(dirname
) );
710 d
= opendir( dirname
);
712 dprintf_dosfs(stddeb
,"in %s\n",dirname
);
715 while ((f
= readdir(d
)) != NULL
)
717 if (strncasecmp(rootname
, f
->d_name
, rootnamelen
) == 0)
719 if (extensions
== NULL
||
720 strcasecmp(rootname
, f
->d_name
) == 0)
723 if (f
->d_name
[rootnamelen
] == '.')
724 for (e
= extensions
; *e
!= NULL
; e
++)
725 if (strcasecmp(*e
, f
->d_name
+ rootnamelen
+ 1)
734 if (strchr(dirname
, '\\') != NULL
)
735 strncpy(buffer
, DOS_GetUnixFileName(dirname
), buflen
);
737 strncpy(buffer
, dirname
, buflen
);
739 strncat(buffer
, "/", buflen
- strlen(buffer
));
740 strncat(buffer
, f
->d_name
, buflen
- strlen(buffer
));
742 stat(buffer
, &filestat
);
743 if (S_ISREG(filestat
.st_mode
)) {
758 /**********************************************************************
761 char *WineIniFileName(void)
764 static char *filename
= NULL
;
765 static char name
[256];
770 strcpy(name
, WINE_INI_USER
);
771 ExpandTildeString(name
);
772 if ((fd
= open(name
, O_RDONLY
)) != -1) {
777 if ((fd
= open(WINE_INI_GLOBAL
, O_RDONLY
)) != -1) {
779 filename
= WINE_INI_GLOBAL
;
782 fprintf(stderr
,"wine: can't open configuration file %s or %s !\n",
783 WINE_INI_GLOBAL
, WINE_INI_USER
);
787 char *WinIniFileName(void)
789 static char *name
= NULL
;
796 strcpy(name
, DOS_GetUnixFileName(WindowsDirectory
));
798 strcat(name
, "win.ini");
800 name
= realloc(name
, strlen(name
) + 1);
805 static int match(char *filename
, char *filemask
)
807 char name
[12], mask
[12];
810 dprintf_dosfs(stddeb
, "match: %s, %s\n", filename
, filemask
);
812 for( i
=0; i
<11; i
++ ) {
820 if( !(*filename
) || *filename
== '.' )
823 name
[i
] = toupper( *filename
++ );
824 while( *filename
&& *filename
!= '.' )
828 for( i
=8; i
<11; i
++ )
832 name
[i
] = toupper( *filename
++ );
835 if( !(*filemask
) || *filemask
== '.' )
837 else if( *filemask
== '*' ) {
844 mask
[i
] = toupper( *filemask
++ );
845 while( *filemask
&& *filemask
!= '.' )
849 for( i
=8; i
<11; i
++ )
852 else if (*filemask
== '*' ) {
854 for( j
=i
; j
<11; j
++ )
859 mask
[i
] = toupper( *filemask
++ );
861 dprintf_dosfs(stddeb
, "changed to: %s, %s\n", name
, mask
);
863 for( i
=0; i
<11; i
++ )
864 if( ( name
[i
] != mask
[i
] ) && ( mask
[i
] != '?' ) )
870 struct dosdirent
*DOS_opendir(char *dosdirname
)
876 if ((unixdirname
= DOS_GetUnixFileName(dosdirname
)) == NULL
)
879 strcpy(temp
, unixdirname
);
891 for (x
=0; x
<= MAX_OPEN_DIRS
; x
++) {
892 if (x
== MAX_OPEN_DIRS
) {
893 fprintf( stderr
, "DOS_opendir(): Too many open directories\n");
896 if (!DosDirs
[x
].inuse
) break;
897 if (strcmp(DosDirs
[x
].unixpath
,temp
) == 0) break;
900 strcpy(DosDirs
[x
].filemask
, unixdirname
);
901 ToDos(DosDirs
[x
].filemask
);
902 dprintf_dosfs(stddeb
,"DOS_opendir: %s / %s\n", unixdirname
, temp
);
904 DosDirs
[x
].inuse
= 1;
905 strcpy(DosDirs
[x
].unixpath
, temp
);
906 DosDirs
[x
].entnum
= 0;
908 if ((DosDirs
[x
].ds
= opendir(temp
)) == NULL
)
915 struct dosdirent
*DOS_readdir(struct dosdirent
*de
)
925 if ((d
= readdir(de
->ds
)) == NULL
)
928 de
->entnum
++; /* Increment the directory entry number */
929 strcpy(de
->filename
, d
->d_name
);
930 if (d
->d_reclen
> 12)
931 de
->filename
[12] = '\0';
934 } while ( !match(de
->filename
, de
->filemask
) );
936 strcpy(temp
,de
->unixpath
);
938 strcat(temp
,de
->filename
);
939 ToUnix(temp
+ strlen(de
->unixpath
));
943 if S_ISDIR(st
.st_mode
)
944 de
->attribute
|= FA_DIREC
;
946 de
->filesize
= st
.st_size
;
947 de
->filetime
= st
.st_mtime
;
952 void DOS_closedir(struct dosdirent
*de
)