ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/sys_unix.cpp
(Generate patch)

Comparing BasiliskII/src/Unix/sys_unix.cpp (file contents):
Revision 1.20 by gbeauche, 2003-10-12T21:55:44Z vs.
Revision 1.34 by asvitkine, 2012-03-01T04:22:27Z

# Line 1 | Line 1
1   /*
2   *  sys_unix.cpp - System dependent routines, Unix implementation
3   *
4 < *  Basilisk II (C) 1997-2003 Christian Bauer
4 > *  Basilisk II (C) Christian Bauer
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 24 | Line 24
24   #include <sys/stat.h>
25   #include <errno.h>
26  
27 + #ifdef HAVE_AVAILABILITYMACROS_H
28 + #include <AvailabilityMacros.h>
29 + #endif
30 +
31   #ifdef __linux__
32   #include <sys/mount.h>
33   #include <linux/cdrom.h>
34   #include <linux/fd.h>
35   #include <linux/major.h>
36   #include <linux/kdev_t.h>
33 #include <linux/unistd.h>
37   #include <dirent.h>
38 <
36 < #ifdef __NR__llseek
37 < _syscall5(int, _llseek, unsigned int, fd, unsigned long, hi, unsigned long, lo, loff_t *, res, unsigned int, wh);
38 < #else
39 < static int _llseek(unsigned int fd, unsigned long hi, unsigned long lo, loff_t *res, unsigned int wh)
40 < {
41 <        if (hi)
42 <                return -1;
43 <        *res = lseek(fd, lo, wh);
44 <        if (*res == -1)
45 <                return -1;
46 <        return 0;
47 < }
48 < #endif
38 > #include <limits.h>
39   #endif
40  
41   #if defined(__FreeBSD__) || defined(__NetBSD__)
42   #include <sys/cdio.h>
43   #endif
44  
45 + #if defined __APPLE__ && defined __MACH__
46 + #include <sys/disk.h>
47 + #if (defined AQUA || defined HAVE_FRAMEWORK_COREFOUNDATION)
48 + #ifndef __MACOSX__
49 + #define __MACOSX__ MAC_OS_X_VERSION_MIN_REQUIRED
50 + #endif
51 + #endif
52 + #endif
53 +
54   #include "main.h"
55   #include "macos_util.h"
56   #include "prefs.h"
57   #include "user_strings.h"
58   #include "sys.h"
59  
60 + #if defined(BINCUE)
61 + #include "bincue_unix.h"
62 + #endif
63 +
64 + #if defined(HAVE_LIBVHD)
65 + #include "vhd_unix.h"
66 + #endif
67 +
68 +
69   #define DEBUG 0
70   #include "debug.h"
71  
64
72   // File handles are pointers to these structures
73 < struct file_handle {
74 <        char *name;             // Copy of device/file name
73 > struct mac_file_handle {
74 >        char *name;             // Copy of device/file name
75          int fd;
76 +
77          bool is_file;           // Flag: plain file or /dev/something?
78          bool is_floppy;         // Flag: floppy device
79          bool is_cdrom;          // Flag: CD-ROM device
80          bool read_only;         // Copy of Sys_open() flag
81 +
82          loff_t start_byte;      // Size of file header (if any)
83          loff_t file_size;       // Size of file data (only valid if is_file is true)
84  
85 +        bool is_media_present;          // Flag: media is inserted and available
86 +
87   #if defined(__linux__)
88          int cdrom_cap;          // CD-ROM capability flags (only valid if is_cdrom is true)
89   #elif defined(__FreeBSD__)
90          struct ioc_capability cdrom_cap;
91   #elif defined(__APPLE__) && defined(__MACH__)
92 <        char    *ioctl_name;    // For CDs on OS X - a device for special ioctls
93 <        int             ioctl_fd;
92 >        char *ioctl_name;       // For CDs on OS X - a device for special ioctls
93 >        int ioctl_fd;
94   #endif
95 +
96 + #if defined(BINCUE)
97 +        bool is_bincue;         // Flag: BIN CUE file
98 +        void *bincue_fd;
99 + #endif
100 +
101 + #if defined(HAVE_LIBVHD)
102 +        bool is_vhd;            // Flag: VHD file
103 +        void *vhd_fd;
104 + #endif
105 + };
106 +
107 + // Open file handles
108 + struct open_mac_file_handle {
109 +        mac_file_handle *fh;
110 +        open_mac_file_handle *next;
111   };
112 + static open_mac_file_handle *open_mac_file_handles = NULL;
113  
114   // File handle of first floppy drive (for SysMountFirstFloppy())
115 < static file_handle *first_floppy = NULL;
115 > static mac_file_handle *first_floppy = NULL;
116 >
117 > // Prototypes
118 > static void cdrom_close(mac_file_handle *fh);
119 > static bool cdrom_open(mac_file_handle *fh, const char *path = NULL);
120  
121  
122   /*
# Line 93 | Line 125 | static file_handle *first_floppy = NULL;
125  
126   void SysInit(void)
127   {
128 + #if defined __MACOSX__
129 +        extern void DarwinSysInit(void);
130 +        DarwinSysInit();
131 + #endif
132   }
133  
134  
# Line 102 | Line 138 | void SysInit(void)
138  
139   void SysExit(void)
140   {
141 + #if defined __MACOSX__
142 +        extern void DarwinSysExit(void);
143 +        DarwinSysExit();
144 + #endif
145 + }
146 +
147 +
148 + /*
149 + *  Manage open file handles
150 + */
151 +
152 + static void sys_add_mac_file_handle(mac_file_handle *fh)
153 + {
154 +        open_mac_file_handle *p = new open_mac_file_handle;
155 +        p->fh = fh;
156 +        p->next = open_mac_file_handles;
157 +        open_mac_file_handles = p;
158 + }
159 +
160 + static void sys_remove_mac_file_handle(mac_file_handle *fh)
161 + {
162 +        open_mac_file_handle *p = open_mac_file_handles;
163 +        open_mac_file_handle *q = NULL;
164 +
165 +        while (p) {
166 +                if (p->fh == fh) {
167 +                        if (q)
168 +                                q->next = p->next;
169 +                        else
170 +                                open_mac_file_handles = p->next;
171 +                        delete p;
172 +                        break;
173 +                }
174 +                q = p;
175 +                p = p->next;
176 +        }
177 + }
178 +
179 +
180 + /*
181 + *  Account for media that has just arrived
182 + */
183 +
184 + void SysMediaArrived(const char *path, int type)
185 + {
186 +        // Replace the "cdrom" entry (we are polling, it's unique)
187 +        if (type == MEDIA_CD && !PrefsFindBool("nocdrom"))
188 +                PrefsReplaceString("cdrom", path);
189 +
190 +        // Wait for media to be available for reading
191 +        if (open_mac_file_handles) {
192 +                const int MAX_WAIT = 5;
193 +                for (int i = 0; i < MAX_WAIT; i++) {
194 +                        if (access(path, R_OK) == 0)
195 +                                break;
196 +                        switch (errno) {
197 +                        case ENOENT: // Unlikely
198 +                        case EACCES: // MacOS X is mounting the media
199 +                                sleep(1);
200 +                                continue;
201 +                        }
202 +                        printf("WARNING: Cannot access %s (%s)\n", path, strerror(errno));
203 +                        return;
204 +                }
205 +        }
206 +
207 +        for (open_mac_file_handle *p = open_mac_file_handles; p != NULL; p = p->next) {
208 +                mac_file_handle * const fh = p->fh;
209 +
210 +                // Re-open CD-ROM device
211 +                if (fh->is_cdrom && type == MEDIA_CD) {
212 +                        cdrom_close(fh);
213 +                        if (cdrom_open(fh, path)) {
214 +                                fh->is_media_present = true;
215 +                                MountVolume(fh);
216 +                        }
217 +                }
218 +        }
219 + }
220 +
221 +
222 + /*
223 + *  Account for media that has just been removed
224 + */
225 +
226 + void SysMediaRemoved(const char *path, int type)
227 + {
228 +        if ((type & MEDIA_REMOVABLE) != MEDIA_CD)
229 +                return;
230 +
231 +        for (open_mac_file_handle *p = open_mac_file_handles; p != NULL; p = p->next) {
232 +                mac_file_handle * const fh = p->fh;
233 +
234 +                // Mark media as not available
235 +                if (!fh->is_cdrom || !fh->is_media_present)
236 +                        continue;
237 +                if (fh->name && strcmp(fh->name, path) == 0) {
238 +                        fh->is_media_present = false;
239 +                        break;
240 +                }
241 + #if defined __MACOSX__
242 +                if (fh->ioctl_name && strcmp(fh->ioctl_name, path) == 0) {
243 +                        fh->is_media_present = false;
244 +                        break;
245 +                }
246 + #endif
247 +        }
248   }
249  
250  
# Line 124 | Line 267 | void SysMountFirstFloppy(void)
267   void SysAddFloppyPrefs(void)
268   {
269   #if defined(__linux__)
270 <        if (access("/dev/.devfsd", F_OK) < 0) {
271 <                PrefsAddString("floppy", "/dev/fd0u1440");
272 <                PrefsAddString("floppy", "/dev/fd1u1440");
273 <        } else {
274 <                DIR *fd_dir = opendir("/dev/floppy");
275 <                if (fd_dir) {
276 <                        struct dirent *floppy_dev;
277 <                        while ((floppy_dev = readdir(fd_dir)) != NULL) {
135 <                                if (strstr(floppy_dev->d_name, "u1440") != NULL) {
136 <                                        char fd_dev[20];
137 <                                        sprintf(fd_dev, "/dev/floppy/%s", floppy_dev->d_name);
138 <                                        PrefsAddString("floppy", fd_dev);
139 <                                }
270 >        DIR *fd_dir = opendir("/dev/floppy");
271 >        if (fd_dir) {
272 >                struct dirent *floppy_dev;
273 >                while ((floppy_dev = readdir(fd_dir)) != NULL) {
274 >                        if (strstr(floppy_dev->d_name, "u1440") != NULL) {
275 >                                char fd_dev[20];
276 >                                sprintf(fd_dev, "/dev/floppy/%s", floppy_dev->d_name);
277 >                                PrefsAddString("floppy", fd_dev);
278                          }
141                        closedir(fd_dir);
279                  }
280 +                closedir(fd_dir);
281 +        } else {
282 +                PrefsAddString("floppy", "/dev/fd0");
283 +                PrefsAddString("floppy", "/dev/fd1");
284          }
285   #elif defined(__NetBSD__)
286          PrefsAddString("floppy", "/dev/fd0a");
287          PrefsAddString("floppy", "/dev/fd1a");
288   #elif defined(__APPLE__) && defined(__MACH__)
289 <        // FIXME: We assume an Aqua build causes <AvailabilityMacros.h> to
290 <        // be included, thusly enabling this part of code that would cause
291 <        // Basilisk II to hang otherwise.
292 < #ifdef MAC_OS_X_VERSION_10_0
293 <        PrefsAddString("floppy", "/dev/fd/0");
294 <        PrefsAddString("floppy", "/dev/fd/1");
295 < #endif
289 >  #if defined(AQUA) || defined(HAVE_FRAMEWORK_COREFOUNDATION)
290 >        extern  void DarwinAddFloppyPrefs(void);
291 >
292 >        DarwinAddFloppyPrefs();
293 >  #else
294 >        // Until I can convince the other guys that my Darwin code is useful,
295 >        // we just add something safe (a non-existant device):
296 >        PrefsAddString("floppy", "/dev/null");
297 >  #endif
298   #else
299          PrefsAddString("floppy", "/dev/fd0");
300          PrefsAddString("floppy", "/dev/fd1");
# Line 222 | Line 365 | void SysAddCDROMPrefs(void)
365                          closedir(cd_dir);
366                  }
367          }
368 < #elif defined(__APPLE__) && defined(__MACH__) && defined(MAC_OS_X_VERSION_10_0)
369 <        extern  void DarwinAddCDROMPrefs(void);
370 <
371 <        DarwinAddCDROMPrefs();
368 > #elif defined __MACOSX__
369 >        // There is no predefined path for CD-ROMs on MacOS X. Rather, we
370 >        // define a single fake CD-ROM entry for the emulated MacOS.
371 >        // XXX this means we handle only CD-ROM drive at a time, wherever
372 >        // the disk is, the latest one is used.
373 >        PrefsAddString("cdrom", "/dev/poll/cdrom");
374   #elif defined(__FreeBSD__) || defined(__NetBSD__)
375          PrefsAddString("cdrom", "/dev/cd0c");
376   #endif
# Line 253 | Line 398 | void SysAddSerialPrefs(void)
398          PrefsAddString("seriala", "/dev/tty00");
399          PrefsAddString("serialb", "/dev/tty01");
400   #elif defined(__APPLE__) && defined(__MACH__)
401 <        // FIXME: We assume an Aqua build causes <AvailabilityMacros.h> to
402 <        // be included, thusly enabling this part of code that would cause
403 <        // Basilisk II to hang otherwise.
404 < #ifdef MAC_OS_X_VERSION_10_0
405 <        PrefsAddString("seriala", "/dev/ttys0");
406 <        PrefsAddString("serialb", "/dev/ttys1");
401 >  #if defined(AQUA) || defined(HAVE_FRAMEWORK_COREFOUNDATION)
402 >        extern  void DarwinAddSerialPrefs(void);
403 >
404 >        DarwinAddSerialPrefs();
405 >  #else
406 >        // Until I can convince the other guys that my Darwin code is useful,
407 >        // we just add something safe (non-existant devices):
408 >        PrefsAddString("seriala", "/dev/null");
409 >        PrefsAddString("serialb", "/dev/null");
410 >  #endif
411   #endif
412 < //      PrefsAddString("seriala", "/dev/cu.modem");
413 < //      PrefsAddString("serialb", "/dev/cu.IrDA-IrCOMMch-b");
412 > }
413 >
414 >
415 > /*
416 > *  Open CD-ROM device and initialize internal data
417 > */
418 >
419 > static bool cdrom_open_1(mac_file_handle *fh)
420 > {
421 > #if defined __MACOSX__
422 >        // In OS X, the device name is OK for sending ioctls to,
423 >        // but not for reading raw CDROM data from.
424 >        // (it seems to have extra data padded in)
425 >        //
426 >        // So, we keep the already opened file handle,
427 >        // and open a slightly different file for CDROM data
428 >        //
429 >        fh->ioctl_fd = fh->fd;
430 >        fh->ioctl_name = fh->name;
431 >        fh->fd = -1;
432 >        fh->name = (char *)malloc(strlen(fh->ioctl_name) + 3);
433 >        if (fh->name) {
434 >                strcpy(fh->name, fh->ioctl_name);
435 >                strcat(fh->name, "s1");
436 >                fh->fd = open(fh->name, O_RDONLY, O_NONBLOCK);
437 >        }
438 >        if (fh->ioctl_fd < 0)
439 >                return false;
440 > #endif
441 >        return true;
442 > }
443 >
444 > bool cdrom_open(mac_file_handle *fh, const char *path)
445 > {
446 >        if (path)
447 >                fh->name = strdup(path);
448 >        fh->fd = open(fh->name, O_RDONLY, O_NONBLOCK);
449 >        fh->start_byte = 0;
450 >        if (!cdrom_open_1(fh))
451 >                return false;
452 >        return fh->fd >= 0;
453 > }
454 >
455 >
456 > /*
457 > *  Close a CD-ROM device
458 > */
459 >
460 > void cdrom_close(mac_file_handle *fh)
461 > {
462 >
463 >        if (fh->fd >= 0) {
464 >                close(fh->fd);
465 >                fh->fd = -1;
466 >        }
467 >        if (fh->name) {
468 >                free(fh->name);
469 >                fh->name = NULL;
470 >        }
471 > #if defined __MACOSX__
472 >        if (fh->ioctl_fd >= 0) {
473 >                close(fh->ioctl_fd);
474 >                fh->ioctl_fd = -1;
475 >        }
476 >        if (fh->ioctl_name) {
477 >                free(fh->ioctl_name);
478 >                fh->ioctl_name = NULL;
479 >        }
480   #endif
481   }
482  
# Line 303 | Line 518 | static bool is_drive_mounted(const char
518   /*
519   *  Open file/device, create new file handle (returns NULL on error)
520   */
521 +
522 + static mac_file_handle *open_filehandle(const char *name)
523 + {
524 +                mac_file_handle *fh = new mac_file_handle;
525 +                memset(fh, 0, sizeof(mac_file_handle));
526 +                fh->name = strdup(name);
527 +                fh->fd = -1;
528 + #if defined __MACOSX__
529 +                fh->ioctl_fd = -1;
530 +                fh->ioctl_name = NULL;
531 + #endif
532 +                return fh;
533 + }
534  
535   void *Sys_open(const char *name, bool read_only)
536   {
# Line 313 | Line 541 | void *Sys_open(const char *name, bool re
541   #else
542          bool is_cdrom = strncmp(name, "/dev/cd", 7) == 0;
543   #endif
544 +        bool is_floppy = strncmp(name, "/dev/fd", 7) == 0;
545  
546 < #if defined(__APPLE__) && defined(__MACH__)
547 <        //
546 >        bool is_polled_media = strncmp(name, "/dev/poll/", 10) == 0;
547 >        if (is_floppy) // Floppy open fails if there's no disk inserted
548 >                is_polled_media = true;
549 >
550 > #if defined __MACOSX__
551          // There is no set filename in /dev which is the cdrom,
552          // so we have to see if it is any of the devices that we found earlier
321        //
322        const char      *cdrom;
323        int                     tmp = 0;
324
325        while ( (cdrom = PrefsFindString("cdrom", tmp) ) != NULL )
553          {
554 <                if ( strcmp(name, cdrom) == 0 )
555 <                {
556 <                        is_cdrom = 1;
557 <                        read_only = 1;
558 <                        break;
554 >                int index = 0;
555 >                const char *str;
556 >                while ((str = PrefsFindString("cdrom", index++)) != NULL) {
557 >                        if (is_polled_media || strcmp(str, name) == 0) {
558 >                                is_cdrom = true;
559 >                                read_only = true;
560 >                                break;
561 >                        }
562                  }
333                ++tmp;
563          }
564   #endif
565  
# Line 355 | Line 584 | void *Sys_open(const char *name, bool re
584          }
585  
586          // Open file/device
587 < #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
587 >
588 > #if defined(BINCUE)
589 >        void *binfd = open_bincue(name);
590 >        if (binfd) {
591 >                mac_file_handle *fh = open_filehandle(name);
592 >                D(bug("opening %s as bincue\n", name));
593 >                fh->bincue_fd = binfd;
594 >                fh->is_bincue = true;
595 >                fh->read_only = true;
596 >                fh->is_media_present = true;
597 >                sys_add_mac_file_handle(fh);
598 >                return fh;
599 >        }
600 > #endif
601 >
602 >
603 > #if defined(HAVE_LIBVHD)
604 >        int vhdsize;
605 >        void *vhdfd = vhd_unix_open(name, &vhdsize, read_only);
606 >        if (vhdfd) {
607 >                mac_file_handle *fh = open_filehandle(name);
608 >                D(bug("opening %s as vnd\n", name));
609 >                fh->is_vhd = true;
610 >                fh->vhd_fd = vhdfd;
611 >                fh->read_only = read_only;
612 >                fh->file_size = vhdsize;
613 >                fh->is_media_present = true;
614 >                sys_add_mac_file_handle(fh);
615 >                return fh;
616 >        }
617 > #endif
618 >
619 > #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__MACOSX__)
620          int fd = open(name, (read_only ? O_RDONLY : O_RDWR) | (is_cdrom ? O_NONBLOCK : 0));
621   #else
622          int fd = open(name, read_only ? O_RDONLY : O_RDWR);
# Line 365 | Line 626 | void *Sys_open(const char *name, bool re
626                  read_only = true;
627                  fd = open(name, O_RDONLY);
628          }
629 <        if (fd >= 0) {
630 <                file_handle *fh = new file_handle;
370 <                fh->name = strdup(name);
629 >        if (fd >= 0 || is_polled_media) {
630 >                mac_file_handle *fh = open_filehandle(name);
631                  fh->fd = fd;
632                  fh->is_file = is_file;
633                  fh->read_only = read_only;
634 <                fh->start_byte = 0;
635 <                fh->is_floppy = false;
376 <                fh->is_cdrom = false;
634 >                fh->is_floppy = is_floppy;
635 >                fh->is_cdrom = is_cdrom;
636                  if (fh->is_file) {
637 +                        fh->is_media_present = true;
638                          // Detect disk image file layout
639                          loff_t size = 0;
380 #if defined(__linux__)
381                        _llseek(fh->fd, 0, 0, &size, SEEK_END);
382 #else
640                          size = lseek(fd, 0, SEEK_END);
384 #endif
641                          uint8 data[256];
642                          lseek(fd, 0, SEEK_SET);
643                          read(fd, data, 256);
# Line 389 | Line 645 | void *Sys_open(const char *name, bool re
645                  } else {
646                          struct stat st;
647                          if (fstat(fd, &st) == 0) {
648 +                                fh->is_media_present = true;
649                                  if (S_ISBLK(st.st_mode)) {
650                                          fh->is_cdrom = is_cdrom;
651   #if defined(__linux__)
# Line 399 | Line 656 | void *Sys_open(const char *name, bool re
656                                                  if (fh->cdrom_cap < 0)
657                                                          fh->cdrom_cap = 0;
658                                          }
402 #else
403                                        fh->cdrom_cap = 0;
659   #endif
660   #elif defined(__FreeBSD__)
661                                          fh->is_floppy = ((st.st_rdev >> 16) == 2);
# Line 409 | Line 664 | void *Sys_open(const char *name, bool re
664                                                  if (ioctl(fh->fd, CDIOCCAPABILITY, &fh->cdrom_cap) < 0)
665                                                          memset(&fh->cdrom_cap, 0, sizeof(fh->cdrom_cap));
666                                          }
412 #else
413                                        fh->cdrom_cap = 0;
667   #endif
668   #elif defined(__NetBSD__)
669                                          fh->is_floppy = ((st.st_rdev >> 16) == 2);
670   #endif
671                                  }
672 < #if defined(__APPLE__) && defined(__MACH__)
673 <
674 <                                // In OS X, the device name is OK for sending ioctls to,
675 <                                // but not for reading raw CDROM data from.
676 <                                // (it seems to have extra data padded in)
677 <                                //
425 <                                // So, we keep the already opened fiole handle,
426 <                                // and open a slightly different file for CDROM data
427 <                                //
428 <                                if ( is_cdrom )
429 <                                {
430 <                                        fh->ioctl_name  = fh->name;
431 <                                        fh->ioctl_fd    = fh->fd;
432 <
433 <                                        fh->name = (char *) malloc(strlen(name) + 2);
434 <                                        if ( fh->name )
435 <                                        {
436 <                                                *fh->name = '\0';
437 <                                                strcat(fh->name, name);
438 <                                                strcat(fh->name, "s1");
439 <                                                fh->fd = open(fh->name, (read_only ? O_RDONLY : O_RDWR));
440 <                                                if ( fh->fd < 0 ) {
441 <                                                        printf("WARNING: Cannot open %s (%s)\n",
442 <                                                                                        fh->name, strerror(errno));
443 <                                                        return NULL;
444 <                                                }
445 <                                        }
672 > #if defined __MACOSX__
673 >                                if (is_cdrom) {
674 >                                        fh->is_cdrom = true;
675 >                                        fh->is_floppy = false;
676 >                                        if (cdrom_open_1(fh))
677 >                                                fh->is_media_present = true;
678                                  }
679   #endif
680                          }
681                  }
682                  if (fh->is_floppy && first_floppy == NULL)
683                          first_floppy = fh;
684 +                sys_add_mac_file_handle(fh);
685                  return fh;
686          } else {
687                  printf("WARNING: Cannot open %s (%s)\n", name, strerror(errno));
# Line 463 | Line 696 | void *Sys_open(const char *name, bool re
696  
697   void Sys_close(void *arg)
698   {
699 <        file_handle *fh = (file_handle *)arg;
699 >        mac_file_handle *fh = (mac_file_handle *)arg;
700          if (!fh)
701                  return;
702  
703 <        close(fh->fd);
703 >        sys_remove_mac_file_handle(fh);
704 >
705 > #if defined(HAVE_LIBVHD)
706 >        if (fh->is_vhd)
707 >                vhd_unix_close(fh->vhd_fd);
708 > #endif
709 >
710 > #if defined(BINCUE)
711 >        if (fh->is_bincue)
712 >                close_bincue(fh->bincue_fd);
713 > #endif
714 >
715 >        if (fh->is_cdrom)
716 >                cdrom_close(fh);
717 >        if (fh->fd >= 0)
718 >                close(fh->fd);
719          if (fh->name)
720                  free(fh->name);
721          delete fh;
# Line 481 | Line 729 | void Sys_close(void *arg)
729  
730   size_t Sys_read(void *arg, void *buffer, loff_t offset, size_t length)
731   {
732 <        file_handle *fh = (file_handle *)arg;
732 >        mac_file_handle *fh = (mac_file_handle *)arg;
733          if (!fh)
734                  return 0;
735  
736 + #if defined(BINCUE)
737 +        if (fh->is_bincue)
738 +                return read_bincue(fh->bincue_fd, buffer, offset, length);
739 + #endif
740 +
741 + #if defined(HAVE_LIBVHD)
742 +        if (fh->is_vhd)
743 +                return vhd_unix_read(fh->vhd_fd, buffer, offset, length);
744 + #endif
745 +
746          // Seek to position
489 #if defined(__linux__)
490        loff_t pos = offset + fh->start_byte, res;
491        if (_llseek(fh->fd, pos >> 32, pos, &res, SEEK_SET) < 0)
492                return 0;
493 #else
747          if (lseek(fh->fd, offset + fh->start_byte, SEEK_SET) < 0)
748                  return 0;
496 #endif
749  
750          // Read data
751          return read(fh->fd, buffer, length);
# Line 507 | Line 759 | size_t Sys_read(void *arg, void *buffer,
759  
760   size_t Sys_write(void *arg, void *buffer, loff_t offset, size_t length)
761   {
762 <        file_handle *fh = (file_handle *)arg;
762 >        mac_file_handle *fh = (mac_file_handle *)arg;
763          if (!fh)
764                  return 0;
765  
766 + #if defined(HAVE_LIBVHD)
767 +        if (fh->is_vhd)
768 +                return vhd_unix_write(fh->vhd_fd, buffer, offset, length);
769 + #endif
770 +
771          // Seek to position
515 #if defined(__linux__)
516        loff_t pos = offset + fh->start_byte, res;
517        if (_llseek(fh->fd, pos >> 32, pos, &res, SEEK_SET) < 0)
518                return 0;
519 #else
772          if (lseek(fh->fd, offset + fh->start_byte, SEEK_SET) < 0)
773                  return 0;
522 #endif
774  
775          // Write data
776          return write(fh->fd, buffer, length);
# Line 532 | Line 783 | size_t Sys_write(void *arg, void *buffer
783  
784   loff_t SysGetFileSize(void *arg)
785   {
786 <        file_handle *fh = (file_handle *)arg;
786 >        mac_file_handle *fh = (mac_file_handle *)arg;
787          if (!fh)
788                  return true;
789  
790 + #if defined(BINCUE)
791 +        if (fh->is_bincue)
792 +                return size_bincue(fh->bincue_fd);
793 + #endif
794 +
795 + #if defined(HAVE_LIBVHD)
796 +        if (fh->is_vhd)
797 +                return fh->file_size;
798 + #endif
799 +
800          if (fh->is_file)
801                  return fh->file_size;
802          else {
542 #if defined(__linux__)
803                  long blocks;
804 + #if defined(__linux__)
805                  if (ioctl(fh->fd, BLKGETSIZE, &blocks) < 0)
806                          return 0;
807                  D(bug(" BLKGETSIZE returns %d blocks\n", blocks));
808                  return (loff_t)blocks * 512;
809 + #elif defined __MACOSX__
810 +                uint32 block_size;
811 +                if (ioctl(fh->ioctl_fd, DKIOCGETBLOCKSIZE, &block_size) < 0)
812 +                        return 0;
813 +                D(bug(" DKIOCGETBLOCKSIZE returns %lu bytes\n", (unsigned long)block_size));
814 +                uint64 block_count;
815 +                if (ioctl(fh->ioctl_fd, DKIOCGETBLOCKCOUNT, &block_count) < 0)
816 +                        return 0;
817 +                D(bug(" DKIOCGETBLOCKCOUNT returns %llu blocks\n", (unsigned long long)block_count));
818 +                return block_count * block_size;
819   #else
820                  return lseek(fh->fd, 0, SEEK_END) - fh->start_byte;
821   #endif
# Line 558 | Line 829 | loff_t SysGetFileSize(void *arg)
829  
830   void SysEject(void *arg)
831   {
832 <        file_handle *fh = (file_handle *)arg;
832 >        mac_file_handle *fh = (mac_file_handle *)arg;
833          if (!fh)
834                  return;
835  
836   #if defined(__linux__)
837          if (fh->is_floppy) {
838 <                fsync(fh->fd);
839 <                ioctl(fh->fd, FDFLUSH);
840 <                ioctl(fh->fd, FDEJECT);
841 <                close(fh->fd);  // Close and reopen so the driver will see the media change
838 >                if (fh->fd >= 0) {
839 >                        fsync(fh->fd);
840 >                        ioctl(fh->fd, FDFLUSH);
841 >                        ioctl(fh->fd, FDEJECT);
842 >                        close(fh->fd);  // Close and reopen so the driver will see the media change
843 >                }
844                  fh->fd = open(fh->name, fh->read_only ? O_RDONLY : O_RDWR);
845          } else if (fh->is_cdrom) {
846                  ioctl(fh->fd, CDROMEJECT);
# Line 583 | Line 856 | void SysEject(void *arg)
856                  fh->fd = open(fh->name, O_RDONLY | O_NONBLOCK);
857          }
858   #elif defined(__APPLE__) && defined(__MACH__)
859 <        if ( fh->is_cdrom ) {
587 <
588 <                // Stolen from IOKit/storage/IOMediaBSDClient.h
589 <                #define DKIOCEJECT _IO('d', 21)
590 <
859 >        if (fh->is_cdrom && fh->is_media_present) {
860                  close(fh->fd);
861 <                if ( ioctl(fh->ioctl_fd, DKIOCEJECT) < 0 )
862 <                {
863 <                        printf("ioctl(DKIOCEJECT) failed on file %s: %s\n",
864 <                                                                fh->ioctl_name, strerror(errno));
596 <
597 <                        // If we are running OSX, the device may be is busy
598 <                        // due to the Finder having the disk mounted and open,
599 <                        // so we have to use another method.
600 <
601 <                        // The only problem is that this takes about 5 seconds:
602 <
603 <                        char    *cmd = (char *) malloc(30+sizeof(fh->name));
861 >                fh->fd = -1;
862 >                if (ioctl(fh->ioctl_fd, DKIOCEJECT) < 0) {
863 >                        D(bug(" DKIOCEJECT failed on file %s: %s\n",
864 >                                   fh->ioctl_name, strerror(errno)));
865  
866 <                        if ( ! cmd )
867 <                                return;
866 >                        // If we are running MacOS X, the device may be in busy
867 >                        // state because the Finder has mounted the disk
868                          close(fh->ioctl_fd);
869 <                        sprintf(cmd, "diskutil eject %s 2>&1 >/dev/null", fh->name);
869 >                        fh->ioctl_fd = -1;
870 >
871 >                        // Try to use "diskutil eject" but it can take up to 5
872 >                        // seconds to complete
873 >                        static const char eject_cmd[] = "/usr/sbin/diskutil eject %s 2>&1 >/dev/null";
874 >                        char *cmd = (char *)alloca(strlen(eject_cmd) + strlen(fh->ioctl_name) + 1);
875 >                        sprintf(cmd, eject_cmd, fh->ioctl_name);
876                          system(cmd);
877                  }
878 +                fh->is_media_present = false;
879          }
880   #endif
881   }
# Line 619 | Line 887 | void SysEject(void *arg)
887  
888   bool SysFormat(void *arg)
889   {
890 <        file_handle *fh = (file_handle *)arg;
890 >        mac_file_handle *fh = (mac_file_handle *)arg;
891          if (!fh)
892                  return false;
893  
# Line 634 | Line 902 | bool SysFormat(void *arg)
902  
903   bool SysIsReadOnly(void *arg)
904   {
905 <        file_handle *fh = (file_handle *)arg;
905 >        mac_file_handle *fh = (mac_file_handle *)arg;
906          if (!fh)
907                  return true;
908  
909   #if defined(__linux__)
910          if (fh->is_floppy) {
911 <                struct floppy_drive_struct stat;
912 <                ioctl(fh->fd, FDGETDRVSTAT, &stat);
913 <                return !(stat.flags & FD_DISK_WRITABLE);
911 >                if (fh->fd >= 0) {
912 >                        struct floppy_drive_struct stat;
913 >                        ioctl(fh->fd, FDGETDRVSTAT, &stat);
914 >                        return !(stat.flags & FD_DISK_WRITABLE);
915 >                } else
916 >                        return true;
917          } else
918   #endif
919                  return fh->read_only;
# Line 655 | Line 926 | bool SysIsReadOnly(void *arg)
926  
927   bool SysIsFixedDisk(void *arg)
928   {
929 <        file_handle *fh = (file_handle *)arg;
929 >        mac_file_handle *fh = (mac_file_handle *)arg;
930          if (!fh)
931                  return true;
932  
933 + #if defined(HAVE_LIBVHD)
934 +        if (fh->is_vhd)
935 +                return true;
936 + #endif
937 +
938          if (fh->is_file)
939                  return true;
940          else if (fh->is_floppy || fh->is_cdrom)
# Line 674 | Line 950 | bool SysIsFixedDisk(void *arg)
950  
951   bool SysIsDiskInserted(void *arg)
952   {
953 <        file_handle *fh = (file_handle *)arg;
953 >        mac_file_handle *fh = (mac_file_handle *)arg;
954          if (!fh)
955                  return false;
956  
957 + #if defined(HAVE_LIBVHD)
958 +        if (fh->is_vhd)
959 +                return true;
960 + #endif
961 +
962          if (fh->is_file) {
963                  return true;
964  
# Line 717 | Line 998 | bool SysIsDiskInserted(void *arg)
998          } else if (fh->is_cdrom) {
999                  struct ioc_toc_header header;
1000                  return ioctl(fh->fd, CDIOREADTOCHEADER, &header) == 0;
1001 + #elif defined __MACOSX__
1002 +        } else if (fh->is_cdrom || fh->is_floppy) {
1003 +                return fh->is_media_present;
1004   #endif
1005  
1006          } else
# Line 730 | Line 1014 | bool SysIsDiskInserted(void *arg)
1014  
1015   void SysPreventRemoval(void *arg)
1016   {
1017 <        file_handle *fh = (file_handle *)arg;
1017 >        mac_file_handle *fh = (mac_file_handle *)arg;
1018          if (!fh)
1019                  return;
1020  
# Line 747 | Line 1031 | void SysPreventRemoval(void *arg)
1031  
1032   void SysAllowRemoval(void *arg)
1033   {
1034 <        file_handle *fh = (file_handle *)arg;
1034 >        mac_file_handle *fh = (mac_file_handle *)arg;
1035          if (!fh)
1036                  return;
1037  
# Line 764 | Line 1048 | void SysAllowRemoval(void *arg)
1048  
1049   bool SysCDReadTOC(void *arg, uint8 *toc)
1050   {
1051 <        file_handle *fh = (file_handle *)arg;
1051 >        mac_file_handle *fh = (mac_file_handle *)arg;
1052          if (!fh)
1053                  return false;
1054  
1055 + #if defined(BINCUE)
1056 +        if (fh->is_bincue)
1057 +                return readtoc_bincue(fh->bincue_fd, toc);
1058 + #endif
1059 +
1060          if (fh->is_cdrom) {
1061 +
1062   #if defined(__linux__)
1063                  uint8 *p = toc + 2;
1064  
# Line 815 | Line 1105 | bool SysCDReadTOC(void *arg, uint8 *toc)
1105                  *toc++ = toc_size >> 8;
1106                  *toc++ = toc_size & 0xff;
1107                  return true;
1108 < #elif defined(__APPLE__) && defined(__MACH__) && defined(MAC_OS_X_VERSION_10_2)
1109 <                extern  bool    DarwinCDReadTOC(char *name, uint8 *toc);
1110 <
1111 <                return  DarwinCDReadTOC(fh->name, toc);
1108 > #elif defined __MACOSX__ && defined MAC_OS_X_VERSION_10_2
1109 >                if (fh->is_media_present) {
1110 >                        extern bool DarwinCDReadTOC(char *name, uint8 *toc);
1111 >                        return DarwinCDReadTOC(fh->name, toc);
1112 >                }
1113 >                return false;
1114   #elif defined(__FreeBSD__)
1115                  uint8 *p = toc + 2;
1116  
# Line 903 | Line 1195 | bool SysCDReadTOC(void *arg, uint8 *toc)
1195  
1196   bool SysCDGetPosition(void *arg, uint8 *pos)
1197   {
1198 <        file_handle *fh = (file_handle *)arg;
1198 >        mac_file_handle *fh = (mac_file_handle *)arg;
1199          if (!fh)
1200                  return false;
1201  
1202 + #if defined(BINCUE)
1203 +        if (fh->is_bincue)
1204 +                return GetPosition_bincue(fh->bincue_fd, pos);
1205 + #endif
1206 +
1207          if (fh->is_cdrom) {
1208   #if defined(__linux__)
1209                  cdrom_subchnl chan;
# Line 968 | Line 1265 | bool SysCDGetPosition(void *arg, uint8 *
1265  
1266   bool SysCDPlay(void *arg, uint8 start_m, uint8 start_s, uint8 start_f, uint8 end_m, uint8 end_s, uint8 end_f)
1267   {
1268 <        file_handle *fh = (file_handle *)arg;
1268 >        mac_file_handle *fh = (mac_file_handle *)arg;
1269          if (!fh)
1270                  return false;
1271  
1272 + #if defined(BINCUE)
1273 +        if (fh->is_bincue)
1274 +                return CDPlay_bincue(fh->bincue_fd, start_m, start_s, start_f, end_m, end_s, end_f);
1275 + #endif
1276 +
1277          if (fh->is_cdrom) {
1278   #if defined(__linux__)
1279                  cdrom_msf play;
# Line 1005 | Line 1307 | bool SysCDPlay(void *arg, uint8 start_m,
1307  
1308   bool SysCDPause(void *arg)
1309   {
1310 <        file_handle *fh = (file_handle *)arg;
1310 >        mac_file_handle *fh = (mac_file_handle *)arg;
1311          if (!fh)
1312                  return false;
1313  
1314 + #if defined(BINCUE)
1315 +        if (fh->is_bincue)
1316 +                return CDPause_bincue(fh->bincue_fd);
1317 + #endif
1318 +
1319          if (fh->is_cdrom) {
1320   #if defined(__linux__)
1321                  return ioctl(fh->fd, CDROMPAUSE) == 0;
# Line 1028 | Line 1335 | bool SysCDPause(void *arg)
1335  
1336   bool SysCDResume(void *arg)
1337   {
1338 <        file_handle *fh = (file_handle *)arg;
1338 >        mac_file_handle *fh = (mac_file_handle *)arg;
1339          if (!fh)
1340                  return false;
1341  
1342 + #if defined(BINCUE)
1343 +        if (fh->is_bincue)
1344 +                return CDResume_bincue(fh->bincue_fd);
1345 + #endif
1346 +
1347 +
1348          if (fh->is_cdrom) {
1349   #if defined(__linux__)
1350                  return ioctl(fh->fd, CDROMRESUME) == 0;
# Line 1051 | Line 1364 | bool SysCDResume(void *arg)
1364  
1365   bool SysCDStop(void *arg, uint8 lead_out_m, uint8 lead_out_s, uint8 lead_out_f)
1366   {
1367 <        file_handle *fh = (file_handle *)arg;
1367 >        mac_file_handle *fh = (mac_file_handle *)arg;
1368          if (!fh)
1369                  return false;
1370  
1371 + #if defined(BINCUE)
1372 +        if (fh->is_bincue)
1373 +                return CDStop_bincue(fh->bincue_fd);
1374 + #endif
1375 +
1376 +
1377          if (fh->is_cdrom) {
1378   #if defined(__linux__)
1379                  return ioctl(fh->fd, CDROMSTOP) == 0;
# Line 1074 | Line 1393 | bool SysCDStop(void *arg, uint8 lead_out
1393  
1394   bool SysCDScan(void *arg, uint8 start_m, uint8 start_s, uint8 start_f, bool reverse)
1395   {
1396 <        file_handle *fh = (file_handle *)arg;
1396 >        mac_file_handle *fh = (mac_file_handle *)arg;
1397          if (!fh)
1398                  return false;
1399  
# Line 1089 | Line 1408 | bool SysCDScan(void *arg, uint8 start_m,
1408  
1409   void SysCDSetVolume(void *arg, uint8 left, uint8 right)
1410   {
1411 <        file_handle *fh = (file_handle *)arg;
1411 >        mac_file_handle *fh = (mac_file_handle *)arg;
1412          if (!fh)
1413                  return;
1414  
# Line 1115 | Line 1434 | void SysCDSetVolume(void *arg, uint8 lef
1434  
1435   void SysCDGetVolume(void *arg, uint8 &left, uint8 &right)
1436   {
1437 <        file_handle *fh = (file_handle *)arg;
1437 >        mac_file_handle *fh = (mac_file_handle *)arg;
1438          if (!fh)
1439                  return;
1440  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines