Release 940510
[wine/multimedia.git] / misc / dos_fs.c
blob6d342224a8462dcb7a1172bbbaebbe6db5915724
1 /*
2 * DOS-FS
3 * NOV 1993 Erik Bos (erik@(trashcan.)hacktic.nl)
5 * FindFile by Bob, hacked for dos & unixpaths by Erik.
6 */
8 #include <ctype.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sys/stat.h>
13 #include <pwd.h>
14 #include <dirent.h>
15 #include <unistd.h>
16 #include <fcntl.h>
18 #if defined(__linux__) || defined(sun)
19 #include <sys/vfs.h>
20 #endif
21 #if defined(__NetBSD__) || defined(__FreeBSD__)
22 #include <sys/types.h>
23 #include <sys/mount.h>
24 #endif
26 #include "windows.h"
27 #include "msdos.h"
28 #include "prototypes.h"
29 #include "autoconf.h"
31 /* #define DEBUG */
33 #define WINE_INI_USER "~/.winerc"
34 #define MAX_OPEN_DIRS 16
35 #define MAX_DOS_DRIVES 26
37 extern char WindowsDirectory[256], SystemDirectory[256],TempDirectory[256];
39 char WindowsPath[256];
41 static int CurrentDrive = 2;
43 struct DosDriveStruct { /* eg: */
44 char *rootdir; /* /usr/windows */
45 char cwd[256]; /* / */
46 char label[13]; /* DRIVE-A */
47 unsigned int serialnumber; /* ABCD5678 */
48 int disabled; /* 0 */
51 static struct DosDriveStruct DosDrives[MAX_DOS_DRIVES];
52 static struct dosdirent DosDirs[MAX_OPEN_DIRS];
54 static void ExpandTildeString(char *s)
56 struct passwd *entry;
57 char temp[1024], *ptr = temp;
59 strcpy(temp, s);
61 while (*ptr)
63 if (*ptr != '~')
65 *s++ = *ptr++;
66 continue;
69 ptr++;
71 if ( (entry = getpwuid(getuid())) == NULL)
73 continue;
76 strcpy(s, entry->pw_dir);
77 s += strlen(entry->pw_dir);
79 *s = 0;
82 void ChopOffSlash(char *path)
84 if (path[strlen(path)-1] == '/' || path[strlen(path)-1] == '\\')
85 path[strlen(path)-1] = '\0';
88 void DOS_InitFS(void)
90 int x;
91 char drive[2], temp[256], *ptr;
93 GetPrivateProfileString("wine", "windows", "c:\\windows",
94 WindowsDirectory, sizeof(WindowsDirectory), WINE_INI);
96 GetPrivateProfileString("wine", "system", "c:\\windows\\system",
97 SystemDirectory, sizeof(SystemDirectory), WINE_INI);
99 GetPrivateProfileString("wine", "temp", "c:\\windows",
100 TempDirectory, sizeof(TempDirectory), WINE_INI);
102 GetPrivateProfileString("wine", "path", "c:\\windows;c:\\windows\\system",
103 WindowsPath, sizeof(WindowsPath), WINE_INI);
105 ChopOffSlash(WindowsDirectory);
106 ToDos(WindowsDirectory);
108 ChopOffSlash(SystemDirectory);
109 ToDos(SystemDirectory);
111 ChopOffSlash(TempDirectory);
112 ToDos(TempDirectory);
114 ToDos(WindowsPath);
115 ExpandTildeString(WindowsPath);
117 for (x=0; x!=MAX_DOS_DRIVES; x++) {
118 DosDrives[x].serialnumber = (0xEB0500L | x);
120 drive[0] = 'A' + x;
121 drive[1] = '\0';
122 GetPrivateProfileString("drives", drive, "*", temp, sizeof(temp), WINE_INI);
123 if (!strcmp(temp, "*") || *temp == '\0') {
124 DosDrives[x].rootdir = NULL;
125 DosDrives[x].cwd[0] = '\0';
126 DosDrives[x].label[0] = '\0';
127 DosDrives[x].disabled = 1;
128 continue;
130 ExpandTildeString(temp);
131 if ((ptr = (char *) malloc(strlen(temp)+1)) == NULL) {
132 fprintf(stderr,"DOSFS: can't malloc for drive info!");
133 continue;
135 ChopOffSlash(temp);
136 DosDrives[x].rootdir = ptr;
137 strcpy(DosDrives[x].rootdir, temp);
138 strcpy(DosDrives[x].cwd, "/windows/");
139 strcpy(DosDrives[x].label, "DRIVE-");
140 strcat(DosDrives[x].label, drive);
141 DosDrives[x].disabled = 0;
143 DOS_SetDefaultDrive(2);
145 for (x=0; x!=MAX_DOS_DRIVES; x++) {
146 if (DosDrives[x].rootdir != NULL) {
147 #ifdef DEBUG
148 fprintf(stderr, "DOSFS: %c: => %-40s %s %s %X %d\n",
149 'A'+x,
150 DosDrives[x].rootdir,
151 DosDrives[x].cwd,
152 DosDrives[x].label,
153 DosDrives[x].serialnumber,
154 DosDrives[x].disabled
156 #endif
160 for (x=0; x!=MAX_OPEN_DIRS ; x++)
161 DosDirs[x].inuse = 0;
163 #ifdef DEBUG
164 fprintf(stderr,"wine.ini = %s\n",WINE_INI);
165 fprintf(stderr,"win.ini = %s\n",WIN_INI);
166 fprintf(stderr,"windir = %s\n",WindowsDirectory);
167 fprintf(stderr,"sysdir = %s\n",SystemDirectory);
168 fprintf(stderr,"tempdir = %s\n",TempDirectory);
169 fprintf(stderr,"path = %s\n",WindowsPath);
170 #endif
173 WORD DOS_GetEquipment(void)
175 WORD equipment;
176 int diskdrives = 0;
178 /* borrowed from Ralph Brown's interrupt lists
180 bits 15-14: number of parallel devices
181 bit 13: [Conv] Internal modem
182 bit 12: reserved
183 bits 11- 9: number of serial devices
184 bit 8: reserved
185 bits 7- 6: number of diskette drives minus one
186 bits 5- 4: Initial video mode:
187 00b = EGA,VGA,PGA
188 01b = 40 x 25 color
189 10b = 80 x 25 color
190 11b = 80 x 25 mono
191 bit 3: reserved
192 bit 2: [PS] =1 if pointing device
193 [non-PS] reserved
194 bit 1: =1 if math co-processor
195 bit 0: =1 if diskette available for boot
198 if (DosDrives[0].rootdir != NULL)
199 diskdrives++;
200 if (DosDrives[1].rootdir != NULL)
201 diskdrives++;
202 if (diskdrives)
203 diskdrives--;
205 equipment = (diskdrives << 6) || 0x02;
207 return (equipment);
210 int DOS_ValidDrive(int drive)
213 #ifdef DEBUG
214 fprintf(stderr,"ValidDrive %c (%d)\n",'A'+drive,drive);
215 #endif
217 if (drive >= MAX_DOS_DRIVES)
218 return 0;
219 if (DosDrives[drive].rootdir == NULL)
220 return 0;
221 if (DosDrives[drive].disabled)
222 return 0;
224 return 1;
227 int DOS_GetDefaultDrive(void)
229 #ifdef DEBUG
230 fprintf(stderr,"GetDefaultDrive (%c)\n",'A'+CurrentDrive);
231 #endif
233 return( CurrentDrive);
236 void DOS_SetDefaultDrive(int drive)
238 #ifdef DEBUG
239 fprintf(stderr,"SetDefaultDrive to %c:\n",'A'+drive);
240 #endif
242 if (DOS_ValidDrive(drive))
243 CurrentDrive = drive;
246 void ToUnix(char *s)
248 /* \WINDOWS\\SYSTEM => /windows/system */
250 char *p;
252 for (p = s; *p; p++)
254 if (*p != '\\')
255 *s++ = tolower(*p);
256 else {
257 *s++ = '/';
258 if (*(p+1) == '/' || *(p+1) == '\\')
259 p++;
262 *s = '\0';
265 void ToDos(char *s)
267 /* /windows//system => \WINDOWS\SYSTEM */
269 char *p;
270 for (p = s; *p; p++)
272 if (*p != '/')
273 *s++ = toupper(*p);
274 else {
275 *s++ = '\\';
276 if (*s == '/' || *s == '\\')
277 p++;
280 *s = '\0';
283 int DOS_DisableDrive(int drive)
285 if (drive >= MAX_DOS_DRIVES)
286 return 0;
287 if (DosDrives[drive].rootdir == NULL)
288 return 0;
290 DosDrives[drive].disabled = 1;
291 return 1;
294 int DOS_EnableDrive(int drive)
296 if (drive >= MAX_DOS_DRIVES)
297 return 0;
298 if (DosDrives[drive].rootdir == NULL)
299 return 0;
301 DosDrives[drive].disabled = 0;
302 return 1;
305 static void GetUnixDirName(char *rootdir, char *name)
307 int filename = 1;
308 char *nameptr, *cwdptr;
310 cwdptr = rootdir + strlen(rootdir);
311 nameptr = name;
313 #ifdef DEBUG
314 fprintf(stderr,"GetUnixDirName: %s <=> %s => ",rootdir, name);
315 #endif
317 while (*nameptr) {
318 if (*nameptr == '.' & !filename) {
319 nameptr++;
320 if (*nameptr == '\0') {
321 cwdptr--;
322 break;
324 if (*nameptr == '.') {
325 cwdptr--;
326 while (cwdptr != rootdir) {
327 cwdptr--;
328 if (*cwdptr == '/') {
329 *(cwdptr+1) = '\0';
330 goto next;
333 goto next;
335 if (*nameptr == '\\' || *nameptr == '/') {
336 next: nameptr++;
337 filename = 0;
338 continue;
341 if (*nameptr == '\\' || *nameptr == '/') {
342 filename = 0;
343 if (nameptr == name)
344 cwdptr = rootdir;
345 *cwdptr++='/';
346 nameptr++;
347 continue;
349 filename = 1;
350 *cwdptr++ = *nameptr++;
352 *cwdptr = '\0';
354 ToUnix(rootdir);
356 #ifdef DEBUG
357 fprintf(stderr,"%s\n", rootdir);
358 #endif
362 char *GetUnixFileName(char *dosfilename)
364 /* a:\windows\system.ini => /dos/windows/system.ini */
366 char temp[256];
367 int drive;
369 if (dosfilename[1] == ':')
371 drive = (islower(*dosfilename) ? toupper(*dosfilename) : *dosfilename) - 'A';
373 if (!DOS_ValidDrive(drive))
374 return NULL;
375 else
376 dosfilename+=2;
377 } else
378 drive = CurrentDrive;
380 strcpy(temp, DosDrives[drive].rootdir);
381 strcat(temp, DosDrives[drive].cwd);
382 GetUnixDirName(temp + strlen(DosDrives[drive].rootdir), dosfilename);
384 ToUnix(temp);
386 #ifdef DEBUG
387 fprintf(stderr,"GetUnixFileName: %s => %s\n", dosfilename, temp);
388 #endif
390 return(temp);
393 char *DOS_GetCurrentDir(int drive)
395 /* should return 'WINDOWS\SYSTEM' */
397 char temp[256];
399 if (!DOS_ValidDrive(drive))
400 return 0;
402 strcpy(temp, DosDrives[drive].cwd);
403 ToDos(temp);
404 fprintf(stderr, "2 %s\n", temp);
405 ChopOffSlash(temp);
407 #ifdef DEBUG
408 fprintf(stderr,"DOS_GetCWD: %c: %s\n",'A'+drive, temp + 1);
409 #endif
410 return (temp + 1);
413 int DOS_ChangeDir(int drive, char *dirname)
415 char temp[256];
417 if (!DOS_ValidDrive(drive))
418 return 0;
420 strcpy(temp, dirname);
421 ToUnix(temp);
423 GetUnixDirName(DosDrives[drive].cwd, temp);
424 strcat(DosDrives[drive].cwd,"/");
425 #ifdef DEBUG
426 fprintf(stderr,"DOS_SetCWD: %c: %s\n",'A'+drive, DosDrives[drive].cwd);
427 #endif
428 return 1;
431 int DOS_MakeDir(int drive, char *dirname)
433 char temp[256];
435 if (!DOS_ValidDrive(drive))
436 return 0;
438 strcpy(temp, DosDrives[drive].cwd);
439 GetUnixDirName(temp, dirname);
440 strcat(DosDrives[drive].cwd,"/");
442 ToUnix(temp);
443 mkdir(temp,0);
445 #ifdef DEBUG
446 fprintf(stderr,"DOS_MakeDir: %c:\%s => %s",'A'+drive, dirname, temp);
447 #endif
448 return 1;
451 int DOS_GetSerialNumber(int drive, unsigned long *serialnumber)
453 if (!DOS_ValidDrive(drive))
454 return 0;
456 *serialnumber = DosDrives[drive].serialnumber;
457 return 1;
460 int DOS_SetSerialNumber(int drive, unsigned long serialnumber)
462 if (!DOS_ValidDrive(drive))
463 return 0;
465 DosDrives[drive].serialnumber = serialnumber;
466 return 1;
469 char *DOS_GetVolumeLabel(int drive)
471 if (!DOS_ValidDrive(drive))
472 return NULL;
474 return (DosDrives[drive].label);
477 int DOS_SetVolumeLabel(int drive, char *label)
479 if (!DOS_ValidDrive(drive))
480 return 0;
482 strncpy(DosDrives[drive].label, label, 8);
483 return 1;
486 int DOS_GetFreeSpace(int drive, long *size, long *available)
488 struct statfs info;
490 if (!DOS_ValidDrive(drive))
491 return 0;
493 if (statfs(DosDrives[drive].rootdir, &info) < 0) {
494 fprintf(stderr,"dosfs: cannot do statfs(%s)\n",DosDrives[drive].rootdir);
495 return 0;
498 *size = info.f_bsize * info.f_blocks / 1024;
499 *available = info.f_bavail * info.f_bsize / 1024;
501 return 1;
504 char *FindFile(char *buffer, int buflen, char *filename, char **extensions,
505 char *path)
507 char *workingpath, *dirname, *rootname, **e;
508 DIR *d;
509 struct dirent *f;
510 int rootnamelen, found = 0;
511 struct stat filestat;
513 if (strchr(filename, '\\') != NULL)
515 strncpy(buffer, GetUnixFileName(filename), buflen);
516 ToUnix(buffer);
517 return buffer;
520 if (strchr(filename, '/') != NULL)
522 strncpy(buffer, filename, buflen);
523 return buffer;
526 #ifdef DEBUG
527 fprintf(stderr,"FindFile: looking for %s\n", filename);
528 #endif
530 rootnamelen = strlen(filename);
531 if ((rootname = malloc(rootnamelen + 1)) == NULL)
532 return NULL;
533 strcpy(rootname, filename);
534 ToUnix(rootname);
536 if ((workingpath = malloc(strlen(path) + 1)) == NULL)
537 return NULL;
538 strcpy(workingpath, path);
540 for(dirname = strtok(workingpath, ";");
541 dirname != NULL;
542 dirname = strtok(NULL, ";"))
544 if (strchr(dirname, '\\') != NULL)
545 d = opendir( GetUnixFileName(dirname) );
546 else
547 d = opendir( dirname );
549 #ifdef DEBUG
550 fprintf(stderr,"in %s\n",dirname);
551 #endif
553 if (d != NULL)
555 while ((f = readdir(d)) != NULL)
557 if (strncasecmp(rootname, f->d_name, rootnamelen) == 0)
559 if (extensions == NULL ||
560 strcasecmp(rootname, f->d_name) == 0)
561 found = 1;
562 else
563 if (f->d_name[rootnamelen] == '.')
564 for (e = extensions; *e != NULL; e++)
565 if (strcasecmp(*e, f->d_name + rootnamelen + 1)
566 == 0)
568 found = 1;
569 break;
572 if (found)
574 if (strchr(dirname, '\\') != NULL)
575 strncpy(buffer, GetUnixFileName(dirname), buflen);
576 else
577 strncpy(buffer, dirname, buflen);
579 strncat(buffer, "/", buflen - strlen(buffer));
580 strncat(buffer, f->d_name, buflen - strlen(buffer));
582 stat(buffer, &filestat);
583 if (S_ISREG(filestat.st_mode)) {
584 closedir(d);
585 free(rootname);
586 ToUnix(buffer);
587 return buffer;
588 } else
589 found = 0;
593 closedir(d);
596 return NULL;
599 /**********************************************************************
600 * WineIniFileName
602 char *WineIniFileName(void)
604 int fd;
605 static char *filename = NULL;
606 char name[256];
608 if (filename)
609 return filename;
611 strcpy(name, WINE_INI_USER);
612 ExpandTildeString(name);
613 if ((fd = open(name, O_RDONLY)) != -1) {
614 close(fd);
615 filename = malloc(strlen(name) + 1);
616 strcpy(filename, name);
617 return(filename);
619 if ((fd = open(WINE_INI_GLOBAL, O_RDONLY)) != -1) {
620 close(fd);
621 filename = malloc(strlen(WINE_INI_GLOBAL) + 1);
622 strcpy(filename, WINE_INI_GLOBAL);
623 return(filename);
625 fprintf(stderr,"wine: can't open configuration file %s or %s !\n",
626 WINE_INI_GLOBAL, WINE_INI_USER);
627 exit(1);
630 char *WinIniFileName(void)
632 static char *name = NULL;
634 if (name)
635 return name;
637 name = malloc(1024);
639 strcpy(name, GetUnixFileName(WindowsDirectory));
640 strcat(name, "/");
641 strcat(name, "win.ini");
642 ToUnix(name);
644 name = realloc(name, strlen(name) + 1);
646 return name;
649 static int match(char *filename, char *filemask)
651 int x, masklength = strlen(filemask);
653 #ifdef DEBUG
654 fprintf(stderr, "match: %s, %s\n", filename, filemask);
655 #endif
657 for (x = 0; x != masklength ; x++) {
658 /* printf("(%c%c) ", *filename, filemask[x]);
660 if (!*filename)
661 /* stop if EOFname */
662 return 1;
664 if (filemask[x] == '?') {
665 /* skip the next char */
666 filename++;
667 continue;
670 if (filemask[x] == '*') {
671 /* skip each char until '.' or EOFname */
672 while (*filename && *filename !='.')
673 filename++;
674 continue;
676 if (filemask[x] != *filename)
677 return 0;
679 filename++;
681 return 1;
684 struct dosdirent *DOS_opendir(char *dosdirname)
686 int x,y;
687 char *unixdirname;
688 char temp[256];
690 for (x=0; x != MAX_OPEN_DIRS && DosDirs[x].inuse; x++)
693 if (x == MAX_OPEN_DIRS)
694 return NULL;
696 if ((unixdirname = GetUnixFileName(dosdirname)) == NULL)
697 return NULL;
699 strcpy(temp, unixdirname);
700 y = strlen(temp);
701 while (y--)
703 if (temp[y] == '/')
705 temp[y++] = '\0';
706 strcpy(DosDirs[x].filemask, temp +y);
707 ToDos(DosDirs[x].filemask);
708 break;
712 #ifdef DEBUG
713 fprintf(stderr,"DOS_opendir: %s -> %s\n", unixdirname, temp);
714 #endif
716 DosDirs[x].inuse = 1;
717 strcpy(DosDirs[x].unixpath, temp);
719 if ((DosDirs[x].ds = opendir(temp)) == NULL)
720 return NULL;
722 return &DosDirs[x];
726 struct dosdirent *DOS_readdir(struct dosdirent *de)
728 char temp[256];
729 struct dirent *d;
730 struct stat st;
732 if (!de->inuse)
733 return NULL;
735 do {
736 if ((d = readdir(de->ds)) == NULL)
738 closedir(de->ds);
739 de->inuse = 0;
740 return de;
743 strcpy(de->filename, d->d_name);
744 if (d->d_reclen > 12)
745 de->filename[12] = '\0';
747 ToDos(de->filename);
748 } while ( !match(de->filename, de->filemask) );
750 strcpy(temp,de->unixpath);
751 strcat(temp,"/");
752 strcat(temp,de->filename);
753 ToUnix(temp);
755 stat (temp, &st);
756 de->attribute = 0x0;
757 if S_ISDIR(st.st_mode)
758 de->attribute |= FA_DIREC;
760 de->filesize = st.st_size;
761 de->filetime = st.st_mtime;
763 return de;
766 void DOS_closedir(struct dosdirent *de)
768 if (de->inuse)
770 closedir(de->ds);
771 de->inuse = 0;