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 strcat(temp, "/"); /* For DOS_GetDosFileName */
194 strcpy(temp, DOS_GetDosFileName(temp));
198 strcpy(DosDrives[temp[0] - 'A'].cwd, &temp[2]);
199 DOS_SetDefaultDrive(temp[0] - 'A');
203 DOS_SetDefaultDrive(2);
206 for (x=0; x!=MAX_DOS_DRIVES; x++) {
207 if (DosDrives[x].rootdir != NULL) {
208 dprintf_dosfs(stddeb, "DOSFS: %c: => %-40s %s %s %X %d\n",
210 DosDrives[x].rootdir,
213 DosDrives[x].serialnumber,
214 DosDrives[x].disabled
219 for (x=0; x!=MAX_OPEN_DIRS ; x++)
220 DosDirs[x].inuse = 0;
222 dprintf_dosfs(stddeb,"wine.ini = %s\n",WINE_INI);
223 dprintf_dosfs(stddeb,"win.ini = %s\n",WIN_INI);
224 dprintf_dosfs(stddeb,"windir = %s\n",WindowsDirectory);
225 dprintf_dosfs(stddeb,"sysdir = %s\n",SystemDirectory);
226 dprintf_dosfs(stddeb,"tempdir = %s\n",TempDirectory);
227 dprintf_dosfs(stddeb,"path = %s\n",WindowsPath);
230 WORD DOS_GetEquipment(void)
234 int parallelports = 0;
238 /* borrowed from Ralph Brown's interrupt lists
240 bits 15-14: number of parallel devices
241 bit 13: [Conv] Internal modem
243 bits 11- 9: number of serial devices
245 bits 7- 6: number of diskette drives minus one
246 bits 5- 4: Initial video mode:
252 bit 2: [PS] =1 if pointing device
254 bit 1: =1 if math co-processor
255 bit 0: =1 if diskette available for boot
257 /* Currently the only of these bits correctly set are:
258 bits 15-14 } Added by William Owen Smith,
259 bits 11-9 } wos@dcs.warwick.ac.uk
264 if (DosDrives[0].rootdir != NULL)
266 if (DosDrives[1].rootdir != NULL)
271 for (x=0; x!=MAX_PORTS; x++) {
272 if (COM[x].devicename)
274 if (LPT[x].devicename)
277 if (serialports > 7) /* 3 bits -- maximum value = 7 */
279 if (parallelports > 3) /* 2 bits -- maximum value = 3 */
282 equipment = (diskdrives << 6) | (serialports << 9) |
283 (parallelports << 14) | 0x02;
285 dprintf_dosfs(stddeb, "DOS_GetEquipment : diskdrives = %d serialports = %d "
286 "parallelports = %d\n"
287 "DOS_GetEquipment : equipment = %d\n",
288 diskdrives, serialports, parallelports, equipment);
293 int DOS_ValidDrive(int drive)
295 dprintf_dosfs(stddeb,"ValidDrive %c (%d)\n",'A'+drive,drive);
296 if (drive >= MAX_DOS_DRIVES)
298 if (DosDrives[drive].rootdir == NULL)
300 if (DosDrives[drive].disabled)
307 int DOS_ValidDirectory(char *name)
311 dprintf_dosfs(stddeb, "DOS_ValidDirectory: '%s'\n", name);
312 if ((dirname = DOS_GetUnixFileName(name)) == NULL)
314 if (stat(dirname,&s))
316 if (!S_ISDIR(s.st_mode))
318 dprintf_dosfs(stddeb, "==> OK\n");
324 int DOS_GetDefaultDrive(void)
326 dprintf_dosfs(stddeb,"GetDefaultDrive (%c)\n",'A'+CurrentDrive);
327 return( CurrentDrive);
330 void DOS_SetDefaultDrive(int drive)
332 dprintf_dosfs(stddeb,"SetDefaultDrive to %c:\n",'A'+drive);
333 if (DOS_ValidDrive(drive))
334 CurrentDrive = drive;
337 int DOS_DisableDrive(int drive)
339 if (drive >= MAX_DOS_DRIVES)
341 if (DosDrives[drive].rootdir == NULL)
344 DosDrives[drive].disabled = 1;
348 int DOS_EnableDrive(int drive)
350 if (drive >= MAX_DOS_DRIVES)
352 if (DosDrives[drive].rootdir == NULL)
355 DosDrives[drive].disabled = 0;
359 static void GetUnixDirName(char *rootdir, char *name)
362 char *nameptr, *cwdptr;
364 cwdptr = rootdir + strlen(rootdir);
367 dprintf_dosfs(stddeb,"GetUnixDirName: %s <=> %s => ",rootdir, name);
370 if (*nameptr == '.' & !filename) {
372 if (*nameptr == '\0') {
376 if (*nameptr == '.') {
378 while (cwdptr != rootdir) {
380 if (*cwdptr == '/') {
387 if (*nameptr == '\\' || *nameptr == '/') {
393 if (*nameptr == '\\' || *nameptr == '/') {
402 *cwdptr++ = *nameptr++;
408 dprintf_dosfs(stddeb,"%s\n", rootdir);
412 char *DOS_GetUnixFileName(char *dosfilename)
414 /* a:\windows\system.ini => /dos/windows/system.ini */
416 static char temp[256];
419 if (dosfilename[1] == ':')
421 drive = (islower(*dosfilename) ? toupper(*dosfilename) : *dosfilename) - 'A';
423 if (!DOS_ValidDrive(drive))
428 drive = CurrentDrive;
430 /* Expand the filename to it's full path if it doesn't
431 * start from the root.
433 DOS_ExpandToFullPath(dosfilename, drive);
435 strcpy(temp, DosDrives[drive].rootdir);
436 strcat(temp, DosDrives[drive].cwd);
437 GetUnixDirName(temp + strlen(DosDrives[drive].rootdir), dosfilename);
439 dprintf_dosfs(stddeb,"GetUnixFileName: %s => %s\n", dosfilename, temp);
443 /* Note: This function works on directories as well as long as
444 * the directory ends in a slash.
446 char *DOS_GetDosFileName(char *unixfilename)
449 static char temp[256], rootdir[256];
450 /* /dos/windows/system.ini => c:\windows\system.ini */
452 /* Expand it if it's a relative name.
454 DOS_ExpandToFullUnixPath(unixfilename);
456 for (i = 0 ; i != MAX_DOS_DRIVES; i++) {
457 if (DosDrives[i].rootdir != NULL) {
458 strcpy(rootdir, DosDrives[i].rootdir);
459 strcat(rootdir, "/");
460 if (strncmp(rootdir, unixfilename, strlen(rootdir)) == 0) {
461 sprintf(temp, "%c:\\%s", 'A' + i, unixfilename + strlen(rootdir));
467 sprintf(temp, "Z:%s", unixfilename);
472 char *DOS_GetCurrentDir(int drive)
474 /* should return 'WINDOWS\SYSTEM' */
476 static char temp[256];
478 if (!DOS_ValidDrive(drive))
481 strcpy(temp, DosDrives[drive].cwd);
485 dprintf_dosfs(stddeb,"DOS_GetCWD: %c: %s\n",'A'+drive, temp + 1);
489 int DOS_ChangeDir(int drive, char *dirname)
491 char temp[256],old[256];
493 if (!DOS_ValidDrive(drive))
496 strcpy(temp, dirname);
498 strcpy(old, DosDrives[drive].cwd);
500 GetUnixDirName(DosDrives[drive].cwd, temp);
501 strcat(DosDrives[drive].cwd,"/");
503 dprintf_dosfs(stddeb,"DOS_SetCWD: %c: %s\n",'A'+drive,
504 DosDrives[drive].cwd);
506 if (!DOS_ValidDirectory(DosDrives[drive].cwd))
508 strcpy(DosDrives[drive].cwd, old);
514 int DOS_MakeDir(int drive, char *dirname)
518 if (!DOS_ValidDrive(drive))
521 strcpy(temp, DosDrives[drive].cwd);
522 GetUnixDirName(temp, dirname);
523 strcat(DosDrives[drive].cwd,"/");
525 ToUnix(temp + strlen(DosDrives[drive].cwd));
528 dprintf_dosfs(stddeb,
529 "DOS_MakeDir: %c:\%s => %s",'A'+drive, dirname, temp);
533 /* DOS_ExpandToFullPath takes a dos-style filename and converts it
534 * into a full path based on the current working directory.
535 * (e.g., "foo.bar" => "d:\\moo\\foo.bar")
537 void DOS_ExpandToFullPath(char *filename, int drive)
541 dprintf_dosfs(stddeb, "DOS_ExpandToFullPath: Original = %s\n", filename);
543 /* If the filename starts with '/' or '\',
544 * don't bother -- we're already at the root.
546 if(filename[0] == '/' || filename[0] == '\\')
549 strcpy(temp, DosDrives[drive].cwd);
550 strcat(temp, filename);
551 strcpy(filename, temp);
553 dprintf_dosfs(stddeb, " Expanded = %s\n", temp);
556 /* DOS_ExpandToFullUnixPath takes a unix filename and converts it
557 * into a full path based on the current working directory. Thus,
558 * it's probably not a good idea to get a relative name, change the
559 * working directory, and then convert it...
561 void DOS_ExpandToFullUnixPath(char *filename)
565 if(filename[0] == '/')
569 if(strncmp(filename, "./", 2))
570 strcat(temp, filename + 1);
574 strcat(temp, filename);
576 dprintf_dosfs(stddeb, "DOS_ExpandToFullUnixPath: %s => %s\n", filename, temp);
577 strcpy(filename, temp);
580 int DOS_GetSerialNumber(int drive, unsigned long *serialnumber)
582 if (!DOS_ValidDrive(drive))
585 *serialnumber = DosDrives[drive].serialnumber;
589 int DOS_SetSerialNumber(int drive, unsigned long serialnumber)
591 if (!DOS_ValidDrive(drive))
594 DosDrives[drive].serialnumber = serialnumber;
598 char *DOS_GetVolumeLabel(int drive)
600 if (!DOS_ValidDrive(drive))
603 return (DosDrives[drive].label);
606 int DOS_SetVolumeLabel(int drive, char *label)
608 if (!DOS_ValidDrive(drive))
611 strncpy(DosDrives[drive].label, label, 8);
615 int DOS_GetFreeSpace(int drive, long *size, long *available)
619 if (!DOS_ValidDrive(drive))
622 if (statfs(DosDrives[drive].rootdir, &info) < 0) {
623 fprintf(stderr,"dosfs: cannot do statfs(%s)\n",
624 DosDrives[drive].rootdir);
628 *size = info.f_bsize * info.f_blocks;
629 *available = info.f_bavail * info.f_bsize;
634 char *DOS_FindFile(char *buffer, int buflen, char *filename, char **extensions,
637 char *workingpath, *dirname, *rootname, **e;
640 int rootnamelen, found = 0;
641 struct stat filestat;
643 if (strchr(filename, '\\') != NULL)
645 strncpy(buffer, DOS_GetUnixFileName(filename), buflen);
646 stat( buffer, &filestat);
647 if (S_ISREG(filestat.st_mode))
653 if (strchr(filename, '/') != NULL)
655 strncpy(buffer, filename, buflen);
659 dprintf_dosfs(stddeb,"DOS_FindFile: looking for %s\n", filename);
660 rootnamelen = strlen(filename);
661 rootname = strdup(filename);
663 workingpath = strdup(path);
665 for(dirname = strtok(workingpath, ";");
667 dirname = strtok(NULL, ";"))
669 if (strchr(dirname, '\\') != NULL)
670 d = opendir( DOS_GetUnixFileName(dirname) );
672 d = opendir( dirname );
674 dprintf_dosfs(stddeb,"in %s\n",dirname);
677 while ((f = readdir(d)) != NULL)
679 if (strncasecmp(rootname, f->d_name, rootnamelen) == 0)
681 if (extensions == NULL ||
682 strcasecmp(rootname, f->d_name) == 0)
685 if (f->d_name[rootnamelen] == '.')
686 for (e = extensions; *e != NULL; e++)
687 if (strcasecmp(*e, f->d_name + rootnamelen + 1)
696 if (strchr(dirname, '\\') != NULL)
697 strncpy(buffer, DOS_GetUnixFileName(dirname), buflen);
699 strncpy(buffer, dirname, buflen);
701 strncat(buffer, "/", buflen - strlen(buffer));
702 strncat(buffer, f->d_name, buflen - strlen(buffer));
704 stat(buffer, &filestat);
705 if (S_ISREG(filestat.st_mode)) {
720 /**********************************************************************
723 char *WineIniFileName(void)
726 static char *filename = NULL;
727 static char name[256];
732 strcpy(name, WINE_INI_USER);
733 ExpandTildeString(name);
734 if ((fd = open(name, O_RDONLY)) != -1) {
739 if ((fd = open(WINE_INI_GLOBAL, O_RDONLY)) != -1) {
741 filename = WINE_INI_GLOBAL;
744 fprintf(stderr,"wine: can't open configuration file %s or %s !\n",
745 WINE_INI_GLOBAL, WINE_INI_USER);
749 char *WinIniFileName(void)
751 static char *name = NULL;
758 strcpy(name, DOS_GetUnixFileName(WindowsDirectory));
760 strcat(name, "win.ini");
762 name = realloc(name, strlen(name) + 1);
767 static int match(char *filename, char *filemask)
769 int x, masklength = strlen(filemask);
771 dprintf_dosfs(stddeb, "match: %s, %s\n", filename, filemask);
772 for (x = 0; x != masklength ; x++) {
773 /* printf("(%c%c) ", *filename, filemask[x]);
776 /* stop if EOFname */
779 if (filemask[x] == '?') {
780 /* skip the next char */
785 if (filemask[x] == '*') {
786 /* skip each char until '.' or EOFname */
787 while (*filename && *filename !='.')
791 if (filemask[x] != *filename)
799 struct dosdirent *DOS_opendir(char *dosdirname)
805 for (x=0; x != MAX_OPEN_DIRS && DosDirs[x].inuse; x++)
808 if (x == MAX_OPEN_DIRS)
811 if ((unixdirname = DOS_GetUnixFileName(dosdirname)) == NULL)
814 strcpy(temp, unixdirname);
821 strcpy(DosDirs[x].filemask, temp +y);
822 ToDos(DosDirs[x].filemask);
827 dprintf_dosfs(stddeb,"DOS_opendir: %s -> %s\n", unixdirname, temp);
829 DosDirs[x].inuse = 1;
830 strcpy(DosDirs[x].unixpath, temp);
832 if ((DosDirs[x].ds = opendir(temp)) == NULL)
839 struct dosdirent *DOS_readdir(struct dosdirent *de)
849 if ((d = readdir(de->ds)) == NULL)
852 strcpy(de->filename, d->d_name);
853 if (d->d_reclen > 12)
854 de->filename[12] = '\0';
857 } while ( !match(de->filename, de->filemask) );
859 strcpy(temp,de->unixpath);
861 strcat(temp,de->filename);
862 ToUnix(temp + strlen(de->unixpath));
866 if S_ISDIR(st.st_mode)
867 de->attribute |= FA_DIREC;
869 de->filesize = st.st_size;
870 de->filetime = st.st_mtime;
875 void DOS_closedir(struct dosdirent *de)