Release 940804
[wine/gsoc-2012-control.git] / misc / dos_fs.c
blobbb1d3e58f7ca27337e9ada5a2b47159961f0066b
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"
30 #include "comm.h"
32 /* #define DEBUG /* */
34 #define WINE_INI_USER "~/.winerc"
35 #define MAX_OPEN_DIRS 16
36 #define MAX_DOS_DRIVES 26
38 extern char WindowsDirectory[256], SystemDirectory[256],TempDirectory[256];
40 char WindowsPath[256];
42 static int CurrentDrive = 2;
44 struct DosDriveStruct { /* eg: */
45 char *rootdir; /* /usr/windows */
46 char cwd[256]; /* / */
47 char label[13]; /* DRIVE-A */
48 unsigned int serialnumber; /* ABCD5678 */
49 int disabled; /* 0 */
52 static struct DosDriveStruct DosDrives[MAX_DOS_DRIVES];
53 static struct dosdirent DosDirs[MAX_OPEN_DIRS];
55 static void ExpandTildeString(char *s)
57 struct passwd *entry;
58 char temp[1024], *ptr = temp;
60 strcpy(temp, s);
62 while (*ptr)
64 if (*ptr != '~')
66 *s++ = *ptr++;
67 continue;
70 ptr++;
72 if ( (entry = getpwuid(getuid())) == NULL)
74 continue;
77 strcpy(s, entry->pw_dir);
78 s += strlen(entry->pw_dir);
80 *s = 0;
83 void ChopOffSlash(char *path)
85 if (path[strlen(path)-1] == '/' || path[strlen(path)-1] == '\\')
86 path[strlen(path)-1] = '\0';
89 void DOS_InitFS(void)
91 int x;
92 char drive[2], temp[256], *ptr;
94 GetPrivateProfileString("wine", "windows", "c:\\windows",
95 WindowsDirectory, sizeof(WindowsDirectory), WINE_INI);
97 GetPrivateProfileString("wine", "system", "c:\\windows\\system",
98 SystemDirectory, sizeof(SystemDirectory), WINE_INI);
100 GetPrivateProfileString("wine", "temp", "c:\\windows",
101 TempDirectory, sizeof(TempDirectory), WINE_INI);
103 GetPrivateProfileString("wine", "path", "c:\\windows;c:\\windows\\system",
104 WindowsPath, sizeof(WindowsPath), WINE_INI);
106 ChopOffSlash(WindowsDirectory);
107 ToDos(WindowsDirectory);
109 ChopOffSlash(SystemDirectory);
110 ToDos(SystemDirectory);
112 ChopOffSlash(TempDirectory);
113 ToDos(TempDirectory);
115 ToDos(WindowsPath);
116 ExpandTildeString(WindowsPath);
118 for (x=0; x!=MAX_DOS_DRIVES; x++) {
119 DosDrives[x].serialnumber = (0xEB0500L | x);
121 drive[0] = 'A' + x;
122 drive[1] = '\0';
123 GetPrivateProfileString("drives", drive, "*", temp, sizeof(temp), WINE_INI);
124 if (!strcmp(temp, "*") || *temp == '\0') {
125 DosDrives[x].rootdir = NULL;
126 DosDrives[x].cwd[0] = '\0';
127 DosDrives[x].label[0] = '\0';
128 DosDrives[x].disabled = 1;
129 continue;
131 ExpandTildeString(temp);
132 ChopOffSlash(temp);
133 DosDrives[x].rootdir = strdup(temp);
134 strcpy(DosDrives[x].rootdir, temp);
135 strcpy(DosDrives[x].cwd, "/windows/");
136 strcpy(DosDrives[x].label, "DRIVE-");
137 strcat(DosDrives[x].label, drive);
138 DosDrives[x].disabled = 0;
140 DOS_SetDefaultDrive(2);
142 for (x=0; x!=MAX_DOS_DRIVES; x++) {
143 if (DosDrives[x].rootdir != NULL) {
144 #ifdef DEBUG
145 fprintf(stderr, "DOSFS: %c: => %-40s %s %s %X %d\n",
146 'A'+x,
147 DosDrives[x].rootdir,
148 DosDrives[x].cwd,
149 DosDrives[x].label,
150 DosDrives[x].serialnumber,
151 DosDrives[x].disabled
153 #endif
157 for (x=0; x!=MAX_OPEN_DIRS ; x++)
158 DosDirs[x].inuse = 0;
160 #ifdef DEBUG
161 fprintf(stderr,"wine.ini = %s\n",WINE_INI);
162 fprintf(stderr,"win.ini = %s\n",WIN_INI);
163 fprintf(stderr,"windir = %s\n",WindowsDirectory);
164 fprintf(stderr,"sysdir = %s\n",SystemDirectory);
165 fprintf(stderr,"tempdir = %s\n",TempDirectory);
166 fprintf(stderr,"path = %s\n",WindowsPath);
167 #endif
170 WORD DOS_GetEquipment(void)
172 WORD equipment;
173 int diskdrives = 0;
174 int parallelports = 0;
175 int serialports = 0;
176 int x;
177 extern struct DosDeviceStruct COM[MAX_PORTS];
178 extern struct DosDeviceStruct LPT[MAX_PORTS];
180 /* borrowed from Ralph Brown's interrupt lists
182 bits 15-14: number of parallel devices
183 bit 13: [Conv] Internal modem
184 bit 12: reserved
185 bits 11- 9: number of serial devices
186 bit 8: reserved
187 bits 7- 6: number of diskette drives minus one
188 bits 5- 4: Initial video mode:
189 00b = EGA,VGA,PGA
190 01b = 40 x 25 color
191 10b = 80 x 25 color
192 11b = 80 x 25 mono
193 bit 3: reserved
194 bit 2: [PS] =1 if pointing device
195 [non-PS] reserved
196 bit 1: =1 if math co-processor
197 bit 0: =1 if diskette available for boot
199 /* Currently the only of these bits correctly set are:
200 bits 15-14 } Added by William Owen Smith,
201 bits 11-9 } wos@dcs.warwick.ac.uk
202 bits 7-6
203 bit 2 (always set)
206 if (DosDrives[0].rootdir != NULL)
207 diskdrives++;
208 if (DosDrives[1].rootdir != NULL)
209 diskdrives++;
210 if (diskdrives)
211 diskdrives--;
213 for (x=0; x!=MAX_PORTS; x++) {
214 if (COM[x].devicename)
215 serialports++;
216 if (LPT[x].devicename)
217 parallelports++;
219 if (serialports > 7) /* 3 bits -- maximum value = 7 */
220 serialports=7;
221 if (parallelports > 3) /* 2 bits -- maximum value = 3 */
222 parallelports=3;
224 equipment = (diskdrives << 6) | (serialports << 9) |
225 (parallelports << 14) | 0x02;
227 #ifdef DEBUG
228 fprintf(stderr, "DOS_GetEquipment : diskdrives = %d serialports = %d "
229 "parallelports = %d\n"
230 "DOS_GetEquipment : equipment = %d\n",
231 diskdrives, serialports, parallelports, equipment);
232 #endif
234 return (equipment);
237 int DOS_ValidDrive(int drive)
240 #ifdef DEBUG
241 fprintf(stderr,"ValidDrive %c (%d)\n",'A'+drive,drive);
242 #endif
244 if (drive >= MAX_DOS_DRIVES)
245 return 0;
246 if (DosDrives[drive].rootdir == NULL)
247 return 0;
248 if (DosDrives[drive].disabled)
249 return 0;
251 return 1;
254 int DOS_GetDefaultDrive(void)
256 #ifdef DEBUG
257 fprintf(stderr,"GetDefaultDrive (%c)\n",'A'+CurrentDrive);
258 #endif
260 return( CurrentDrive);
263 void DOS_SetDefaultDrive(int drive)
265 #ifdef DEBUG
266 fprintf(stderr,"SetDefaultDrive to %c:\n",'A'+drive);
267 #endif
269 if (DOS_ValidDrive(drive))
270 CurrentDrive = drive;
273 void ToUnix(char *s)
275 /* \WINDOWS\\SYSTEM => /windows/system */
277 char *p;
279 for (p = s; *p; p++)
281 if (*p != '\\')
282 *s++ = tolower(*p);
283 else {
284 *s++ = '/';
285 if (*(p+1) == '/' || *(p+1) == '\\')
286 p++;
289 *s = '\0';
292 void ToDos(char *s)
294 /* /windows//system => \WINDOWS\SYSTEM */
296 char *p;
297 for (p = s; *p; p++)
299 if (*p != '/')
300 *s++ = toupper(*p);
301 else {
302 *s++ = '\\';
303 if (*(p+1) == '/' || *(p+1) == '\\')
304 p++;
307 *s = '\0';
310 int DOS_DisableDrive(int drive)
312 if (drive >= MAX_DOS_DRIVES)
313 return 0;
314 if (DosDrives[drive].rootdir == NULL)
315 return 0;
317 DosDrives[drive].disabled = 1;
318 return 1;
321 int DOS_EnableDrive(int drive)
323 if (drive >= MAX_DOS_DRIVES)
324 return 0;
325 if (DosDrives[drive].rootdir == NULL)
326 return 0;
328 DosDrives[drive].disabled = 0;
329 return 1;
332 static void GetUnixDirName(char *rootdir, char *name)
334 int filename = 1;
335 char *nameptr, *cwdptr;
337 cwdptr = rootdir + strlen(rootdir);
338 nameptr = name;
340 #ifdef DEBUG
341 fprintf(stderr,"GetUnixDirName: %s <=> %s => ",rootdir, name);
342 #endif
344 while (*nameptr) {
345 if (*nameptr == '.' & !filename) {
346 nameptr++;
347 if (*nameptr == '\0') {
348 cwdptr--;
349 break;
351 if (*nameptr == '.') {
352 cwdptr--;
353 while (cwdptr != rootdir) {
354 cwdptr--;
355 if (*cwdptr == '/') {
356 *(cwdptr+1) = '\0';
357 goto next;
360 goto next;
362 if (*nameptr == '\\' || *nameptr == '/') {
363 next: nameptr++;
364 filename = 0;
365 continue;
368 if (*nameptr == '\\' || *nameptr == '/') {
369 filename = 0;
370 if (nameptr == name)
371 cwdptr = rootdir;
372 *cwdptr++='/';
373 nameptr++;
374 continue;
376 filename = 1;
377 *cwdptr++ = *nameptr++;
379 *cwdptr = '\0';
381 ToUnix(rootdir);
383 #ifdef DEBUG
384 fprintf(stderr,"%s\n", rootdir);
385 #endif
389 char *GetUnixFileName(char *dosfilename)
391 /* a:\windows\system.ini => /dos/windows/system.ini */
393 static char temp[256];
394 int drive;
396 if (dosfilename[1] == ':')
398 drive = (islower(*dosfilename) ? toupper(*dosfilename) : *dosfilename) - 'A';
400 if (!DOS_ValidDrive(drive))
401 return NULL;
402 else
403 dosfilename+=2;
404 } else
405 drive = CurrentDrive;
407 strcpy(temp, DosDrives[drive].rootdir);
408 strcat(temp, DosDrives[drive].cwd);
409 GetUnixDirName(temp + strlen(DosDrives[drive].rootdir), dosfilename);
411 ToUnix(temp);
413 #ifdef DEBUG
414 fprintf(stderr,"GetUnixFileName: %s => %s\n", dosfilename, temp);
415 #endif
417 return(temp);
420 char *GetDosFileName(char *unixfilename)
422 int i;
423 static char temp[256], rootdir[256];
424 /* /dos/windows/system.ini => c:\windows\system.ini */
426 for (i = 0 ; i != MAX_DOS_DRIVES; i++) {
427 if (DosDrives[i].rootdir != NULL) {
428 strcpy(rootdir, DosDrives[i].rootdir);
429 strcat(rootdir, "/");
430 ToUnix(rootdir);
431 if (strncmp(rootdir, unixfilename, strlen(rootdir)) == 0) {
432 sprintf(temp, "%c:\\%s", 'A' + i, unixfilename + strlen(rootdir));
433 ToDos(temp);
434 return temp;
438 sprintf(temp, "UNIX:%s", unixfilename);
439 ToDos(temp);
440 return(temp);
443 char *DOS_GetCurrentDir(int drive)
445 /* should return 'WINDOWS\SYSTEM' */
447 char temp[256];
449 if (!DOS_ValidDrive(drive))
450 return 0;
452 strcpy(temp, DosDrives[drive].cwd);
453 ToDos(temp);
454 fprintf(stderr, "2 %s\n", temp);
455 ChopOffSlash(temp);
457 #ifdef DEBUG
458 fprintf(stderr,"DOS_GetCWD: %c: %s\n",'A'+drive, temp + 1);
459 #endif
460 return (temp + 1);
463 int DOS_ChangeDir(int drive, char *dirname)
465 char temp[256];
467 if (!DOS_ValidDrive(drive))
468 return 0;
470 strcpy(temp, dirname);
471 ToUnix(temp);
473 GetUnixDirName(DosDrives[drive].cwd, temp);
474 strcat(DosDrives[drive].cwd,"/");
475 #ifdef DEBUG
476 fprintf(stderr,"DOS_SetCWD: %c: %s\n",'A'+drive, DosDrives[drive].cwd);
477 #endif
478 return 1;
481 int DOS_MakeDir(int drive, char *dirname)
483 char temp[256];
485 if (!DOS_ValidDrive(drive))
486 return 0;
488 strcpy(temp, DosDrives[drive].cwd);
489 GetUnixDirName(temp, dirname);
490 strcat(DosDrives[drive].cwd,"/");
492 ToUnix(temp);
493 mkdir(temp,0);
495 #ifdef DEBUG
496 fprintf(stderr,"DOS_MakeDir: %c:\%s => %s",'A'+drive, dirname, temp);
497 #endif
498 return 1;
501 int DOS_GetSerialNumber(int drive, unsigned long *serialnumber)
503 if (!DOS_ValidDrive(drive))
504 return 0;
506 *serialnumber = DosDrives[drive].serialnumber;
507 return 1;
510 int DOS_SetSerialNumber(int drive, unsigned long serialnumber)
512 if (!DOS_ValidDrive(drive))
513 return 0;
515 DosDrives[drive].serialnumber = serialnumber;
516 return 1;
519 char *DOS_GetVolumeLabel(int drive)
521 if (!DOS_ValidDrive(drive))
522 return NULL;
524 return (DosDrives[drive].label);
527 int DOS_SetVolumeLabel(int drive, char *label)
529 if (!DOS_ValidDrive(drive))
530 return 0;
532 strncpy(DosDrives[drive].label, label, 8);
533 return 1;
536 int DOS_GetFreeSpace(int drive, long *size, long *available)
538 struct statfs info;
540 if (!DOS_ValidDrive(drive))
541 return 0;
543 if (statfs(DosDrives[drive].rootdir, &info) < 0) {
544 fprintf(stderr,"dosfs: cannot do statfs(%s)\n",DosDrives[drive].rootdir);
545 return 0;
548 *size = info.f_bsize * info.f_blocks / 1024;
549 *available = info.f_bavail * info.f_bsize / 1024;
551 return 1;
554 char *FindFile(char *buffer, int buflen, char *filename, char **extensions,
555 char *path)
557 char *workingpath, *dirname, *rootname, **e;
558 DIR *d;
559 struct dirent *f;
560 int rootnamelen, found = 0;
561 struct stat filestat;
563 if (strchr(filename, '\\') != NULL)
565 strncpy(buffer, GetUnixFileName(filename), buflen);
566 ToUnix(buffer);
567 stat( buffer, &filestat);
568 if (S_ISREG(filestat.st_mode))
569 return buffer;
570 else
571 return NULL;
574 if (strchr(filename, '/') != NULL)
576 strncpy(buffer, filename, buflen);
577 return buffer;
580 #ifdef DEBUG
581 fprintf(stderr,"FindFile: looking for %s\n", filename);
582 #endif
584 rootnamelen = strlen(filename);
585 if ((rootname = malloc(rootnamelen + 1)) == NULL)
586 return NULL;
587 strcpy(rootname, filename);
588 ToUnix(rootname);
590 if ((workingpath = malloc(strlen(path) + 1)) == NULL)
591 return NULL;
592 strcpy(workingpath, path);
594 for(dirname = strtok(workingpath, ";");
595 dirname != NULL;
596 dirname = strtok(NULL, ";"))
598 if (strchr(dirname, '\\') != NULL)
599 d = opendir( GetUnixFileName(dirname) );
600 else
601 d = opendir( dirname );
603 #ifdef DEBUG
604 fprintf(stderr,"in %s\n",dirname);
605 #endif
607 if (d != NULL)
609 while ((f = readdir(d)) != NULL)
611 if (strncasecmp(rootname, f->d_name, rootnamelen) == 0)
613 if (extensions == NULL ||
614 strcasecmp(rootname, f->d_name) == 0)
615 found = 1;
616 else
617 if (f->d_name[rootnamelen] == '.')
618 for (e = extensions; *e != NULL; e++)
619 if (strcasecmp(*e, f->d_name + rootnamelen + 1)
620 == 0)
622 found = 1;
623 break;
626 if (found)
628 if (strchr(dirname, '\\') != NULL)
629 strncpy(buffer, GetUnixFileName(dirname), buflen);
630 else
631 strncpy(buffer, dirname, buflen);
633 strncat(buffer, "/", buflen - strlen(buffer));
634 strncat(buffer, f->d_name, buflen - strlen(buffer));
636 stat(buffer, &filestat);
637 if (S_ISREG(filestat.st_mode)) {
638 closedir(d);
639 free(rootname);
640 ToUnix(buffer);
641 return buffer;
642 } else
643 found = 0;
647 closedir(d);
650 return NULL;
653 /**********************************************************************
654 * WineIniFileName
656 char *WineIniFileName(void)
658 int fd;
659 static char *filename = NULL;
660 char name[256];
662 if (filename)
663 return filename;
665 strcpy(name, WINE_INI_USER);
666 ExpandTildeString(name);
667 if ((fd = open(name, O_RDONLY)) != -1) {
668 close(fd);
669 filename = malloc(strlen(name) + 1);
670 strcpy(filename, name);
671 return(filename);
673 if ((fd = open(WINE_INI_GLOBAL, O_RDONLY)) != -1) {
674 close(fd);
675 filename = malloc(strlen(WINE_INI_GLOBAL) + 1);
676 strcpy(filename, WINE_INI_GLOBAL);
677 return(filename);
679 fprintf(stderr,"wine: can't open configuration file %s or %s !\n",
680 WINE_INI_GLOBAL, WINE_INI_USER);
681 exit(1);
684 char *WinIniFileName(void)
686 static char *name = NULL;
688 if (name)
689 return name;
691 name = malloc(1024);
693 strcpy(name, GetUnixFileName(WindowsDirectory));
694 strcat(name, "/");
695 strcat(name, "win.ini");
696 ToUnix(name);
698 name = realloc(name, strlen(name) + 1);
700 return name;
703 static int match(char *filename, char *filemask)
705 int x, masklength = strlen(filemask);
707 #ifdef DEBUG
708 fprintf(stderr, "match: %s, %s\n", filename, filemask);
709 #endif
711 for (x = 0; x != masklength ; x++) {
712 /* printf("(%c%c) ", *filename, filemask[x]);
714 if (!*filename)
715 /* stop if EOFname */
716 return 1;
718 if (filemask[x] == '?') {
719 /* skip the next char */
720 filename++;
721 continue;
724 if (filemask[x] == '*') {
725 /* skip each char until '.' or EOFname */
726 while (*filename && *filename !='.')
727 filename++;
728 continue;
730 if (filemask[x] != *filename)
731 return 0;
733 filename++;
735 return 1;
738 struct dosdirent *DOS_opendir(char *dosdirname)
740 int x,y;
741 char *unixdirname;
742 char temp[256];
744 for (x=0; x != MAX_OPEN_DIRS && DosDirs[x].inuse; x++)
747 if (x == MAX_OPEN_DIRS)
748 return NULL;
750 if ((unixdirname = GetUnixFileName(dosdirname)) == NULL)
751 return NULL;
753 strcpy(temp, unixdirname);
754 y = strlen(temp);
755 while (y--)
757 if (temp[y] == '/')
759 temp[y++] = '\0';
760 strcpy(DosDirs[x].filemask, temp +y);
761 ToDos(DosDirs[x].filemask);
762 break;
766 #ifdef DEBUG
767 fprintf(stderr,"DOS_opendir: %s -> %s\n", unixdirname, temp);
768 #endif
770 DosDirs[x].inuse = 1;
771 strcpy(DosDirs[x].unixpath, temp);
773 if ((DosDirs[x].ds = opendir(temp)) == NULL)
774 return NULL;
776 return &DosDirs[x];
780 struct dosdirent *DOS_readdir(struct dosdirent *de)
782 char temp[256];
783 struct dirent *d;
784 struct stat st;
786 if (!de->inuse)
787 return NULL;
789 do {
790 if ((d = readdir(de->ds)) == NULL)
791 return NULL;
793 strcpy(de->filename, d->d_name);
794 if (d->d_reclen > 12)
795 de->filename[12] = '\0';
797 ToDos(de->filename);
798 } while ( !match(de->filename, de->filemask) );
800 strcpy(temp,de->unixpath);
801 strcat(temp,"/");
802 strcat(temp,de->filename);
803 ToUnix(temp);
805 stat (temp, &st);
806 de->attribute = 0x0;
807 if S_ISDIR(st.st_mode)
808 de->attribute |= FA_DIREC;
810 de->filesize = st.st_size;
811 de->filetime = st.st_mtime;
813 return de;
816 void DOS_closedir(struct dosdirent *de)
818 if (de && de->inuse)
820 closedir(de->ds);
821 de->inuse = 0;