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.17 by gbeauche, 2002-03-29T16:24:18Z vs.
Revision 1.32 by asvitkine, 2010-10-06T00:30:23Z

# Line 1 | Line 1
1   /*
2   *  sys_unix.cpp - System dependent routines, Unix implementation
3   *
4 < *  Basilisk II (C) 1997-2002 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   #define DEBUG 0
65   #include "debug.h"
66  
64
67   // File handles are pointers to these structures
68   struct file_handle {
69 <        char *name;             // Copy of device/file name
69 >        char *name;             // Copy of device/file name
70          int fd;
71          bool is_file;           // Flag: plain file or /dev/something?
72          bool is_floppy;         // Flag: floppy device
73          bool is_cdrom;          // Flag: CD-ROM device
74 + #if defined(BINCUE)
75 +        bool is_bincue;         // Flag: BIN CUE file
76 + #endif
77          bool read_only;         // Copy of Sys_open() flag
78 <        loff_t start_byte;      // Size of file header (if any)
78 >    loff_t start_byte;  // Size of file header (if any)
79          loff_t file_size;       // Size of file data (only valid if is_file is true)
80 +        bool is_media_present;          // Flag: media is inserted and available
81  
82   #if defined(__linux__)
83          int cdrom_cap;          // CD-ROM capability flags (only valid if is_cdrom is true)
84   #elif defined(__FreeBSD__)
85          struct ioc_capability cdrom_cap;
86 + #elif defined(__APPLE__) && defined(__MACH__)
87 +        char *ioctl_name;       // For CDs on OS X - a device for special ioctls
88 +        int ioctl_fd;
89 + #endif
90 +
91 + #if defined(BINCUE)
92 +        void *bincue_fd;
93   #endif
94   };
95  
96 + // Open file handles
97 + struct open_file_handle {
98 +        file_handle *fh;
99 +        open_file_handle *next;
100 + };
101 + static open_file_handle *open_file_handles = NULL;
102 +
103   // File handle of first floppy drive (for SysMountFirstFloppy())
104   static file_handle *first_floppy = NULL;
105  
106 + // Prototypes
107 + static void cdrom_close(file_handle *fh);
108 + static bool cdrom_open(file_handle *fh, const char *path = NULL);
109 +
110  
111   /*
112   *  Initialization
# Line 90 | Line 114 | static file_handle *first_floppy = NULL;
114  
115   void SysInit(void)
116   {
117 + #if defined __MACOSX__
118 +        extern void DarwinSysInit(void);
119 +        DarwinSysInit();
120 + #endif
121   }
122  
123  
# Line 99 | Line 127 | void SysInit(void)
127  
128   void SysExit(void)
129   {
130 + #if defined __MACOSX__
131 +        extern void DarwinSysExit(void);
132 +        DarwinSysExit();
133 + #endif
134 + }
135 +
136 +
137 + /*
138 + *  Manage open file handles
139 + */
140 +
141 + static void sys_add_file_handle(file_handle *fh)
142 + {
143 +        open_file_handle *p = new open_file_handle;
144 +        p->fh = fh;
145 +        p->next = open_file_handles;
146 +        open_file_handles = p;
147 + }
148 +
149 + static void sys_remove_file_handle(file_handle *fh)
150 + {
151 +        open_file_handle *p = open_file_handles;
152 +        open_file_handle *q = NULL;
153 +
154 +        while (p) {
155 +                if (p->fh == fh) {
156 +                        if (q)
157 +                                q->next = p->next;
158 +                        else
159 +                                open_file_handles = p->next;
160 +                        delete p;
161 +                        break;
162 +                }
163 +                q = p;
164 +                p = p->next;
165 +        }
166 + }
167 +
168 +
169 + /*
170 + *  Account for media that has just arrived
171 + */
172 +
173 + void SysMediaArrived(const char *path, int type)
174 + {
175 +        // Replace the "cdrom" entry (we are polling, it's unique)
176 +        if (type == MEDIA_CD && !PrefsFindBool("nocdrom"))
177 +                PrefsReplaceString("cdrom", path);
178 +
179 +        // Wait for media to be available for reading
180 +        if (open_file_handles) {
181 +                const int MAX_WAIT = 5;
182 +                for (int i = 0; i < MAX_WAIT; i++) {
183 +                        if (access(path, R_OK) == 0)
184 +                                break;
185 +                        switch (errno) {
186 +                        case ENOENT: // Unlikely
187 +                        case EACCES: // MacOS X is mounting the media
188 +                                sleep(1);
189 +                                continue;
190 +                        }
191 +                        printf("WARNING: Cannot access %s (%s)\n", path, strerror(errno));
192 +                        return;
193 +                }
194 +        }
195 +
196 +        for (open_file_handle *p = open_file_handles; p != NULL; p = p->next) {
197 +                file_handle * const fh = p->fh;
198 +
199 +                // Re-open CD-ROM device
200 +                if (fh->is_cdrom && type == MEDIA_CD) {
201 +                        cdrom_close(fh);
202 +                        if (cdrom_open(fh, path)) {
203 +                                fh->is_media_present = true;
204 +                                MountVolume(fh);
205 +                        }
206 +                }
207 +        }
208 + }
209 +
210 +
211 + /*
212 + *  Account for media that has just been removed
213 + */
214 +
215 + void SysMediaRemoved(const char *path, int type)
216 + {
217 +        if ((type & MEDIA_REMOVABLE) != MEDIA_CD)
218 +                return;
219 +
220 +        for (open_file_handle *p = open_file_handles; p != NULL; p = p->next) {
221 +                file_handle * const fh = p->fh;
222 +
223 +                // Mark media as not available
224 +                if (!fh->is_cdrom || !fh->is_media_present)
225 +                        continue;
226 +                if (fh->name && strcmp(fh->name, path) == 0) {
227 +                        fh->is_media_present = false;
228 +                        break;
229 +                }
230 + #if defined __MACOSX__
231 +                if (fh->ioctl_name && strcmp(fh->ioctl_name, path) == 0) {
232 +                        fh->is_media_present = false;
233 +                        break;
234 +                }
235 + #endif
236 +        }
237   }
238  
239  
# Line 121 | Line 256 | void SysMountFirstFloppy(void)
256   void SysAddFloppyPrefs(void)
257   {
258   #if defined(__linux__)
259 <        if (access("/dev/.devfsd", F_OK) < 0) {
260 <                PrefsAddString("floppy", "/dev/fd0u1440");
261 <                PrefsAddString("floppy", "/dev/fd1u1440");
262 <        } else {
263 <                DIR *fd_dir = opendir("/dev/floppy");
264 <                if (fd_dir) {
265 <                        struct dirent *floppy_dev;
266 <                        while ((floppy_dev = readdir(fd_dir)) != NULL) {
132 <                                if (strstr(floppy_dev->d_name, "u1440") != NULL) {
133 <                                        char fd_dev[20];
134 <                                        sprintf(fd_dev, "/dev/floppy/%s", floppy_dev->d_name);
135 <                                        PrefsAddString("floppy", fd_dev);
136 <                                }
259 >        DIR *fd_dir = opendir("/dev/floppy");
260 >        if (fd_dir) {
261 >                struct dirent *floppy_dev;
262 >                while ((floppy_dev = readdir(fd_dir)) != NULL) {
263 >                        if (strstr(floppy_dev->d_name, "u1440") != NULL) {
264 >                                char fd_dev[20];
265 >                                sprintf(fd_dev, "/dev/floppy/%s", floppy_dev->d_name);
266 >                                PrefsAddString("floppy", fd_dev);
267                          }
138                        closedir(fd_dir);
268                  }
269 +                closedir(fd_dir);
270 +        } else {
271 +                PrefsAddString("floppy", "/dev/fd0");
272 +                PrefsAddString("floppy", "/dev/fd1");
273          }
274   #elif defined(__NetBSD__)
275          PrefsAddString("floppy", "/dev/fd0a");
276          PrefsAddString("floppy", "/dev/fd1a");
277 + #elif defined(__APPLE__) && defined(__MACH__)
278 +  #if defined(AQUA) || defined(HAVE_FRAMEWORK_COREFOUNDATION)
279 +        extern  void DarwinAddFloppyPrefs(void);
280 +
281 +        DarwinAddFloppyPrefs();
282 +  #else
283 +        // Until I can convince the other guys that my Darwin code is useful,
284 +        // we just add something safe (a non-existant device):
285 +        PrefsAddString("floppy", "/dev/null");
286 +  #endif
287   #else
288          PrefsAddString("floppy", "/dev/fd0");
289          PrefsAddString("floppy", "/dev/fd1");
# Line 151 | Line 294 | void SysAddFloppyPrefs(void)
294   /*
295   *  This gets called when no "disk" prefs items are found
296   *  It scans for available HFS volumes and adds appropriate prefs items
297 + *      On OS X, we could do the same, but on an OS X machine I think it is
298 + *      very unlikely that any mounted volumes would contain a system which
299 + *      is old enough to boot a 68k Mac, so we just do nothing here for now.
300   */
301  
302   void SysAddDiskPrefs(void)
# Line 208 | Line 354 | void SysAddCDROMPrefs(void)
354                          closedir(cd_dir);
355                  }
356          }
357 < #elif defined(__FreeBSD__)
357 > #elif defined __MACOSX__
358 >        // There is no predefined path for CD-ROMs on MacOS X. Rather, we
359 >        // define a single fake CD-ROM entry for the emulated MacOS.
360 >        // XXX this means we handle only CD-ROM drive at a time, wherever
361 >        // the disk is, the latest one is used.
362 >        PrefsAddString("cdrom", "/dev/poll/cdrom");
363 > #elif defined(__FreeBSD__) || defined(__NetBSD__)
364          PrefsAddString("cdrom", "/dev/cd0c");
213 #elif defined(__NetBSD__)
214        PrefsAddString("cdrom", "/dev/cd0d");
365   #endif
366   }
367  
# Line 236 | Line 386 | void SysAddSerialPrefs(void)
386   #elif defined(__NetBSD__)
387          PrefsAddString("seriala", "/dev/tty00");
388          PrefsAddString("serialb", "/dev/tty01");
389 + #elif defined(__APPLE__) && defined(__MACH__)
390 +  #if defined(AQUA) || defined(HAVE_FRAMEWORK_COREFOUNDATION)
391 +        extern  void DarwinAddSerialPrefs(void);
392 +
393 +        DarwinAddSerialPrefs();
394 +  #else
395 +        // Until I can convince the other guys that my Darwin code is useful,
396 +        // we just add something safe (non-existant devices):
397 +        PrefsAddString("seriala", "/dev/null");
398 +        PrefsAddString("serialb", "/dev/null");
399 +  #endif
400 + #endif
401 + }
402 +
403 +
404 + /*
405 + *  Open CD-ROM device and initialize internal data
406 + */
407 +
408 + static bool cdrom_open_1(file_handle *fh)
409 + {
410 + #if defined __MACOSX__
411 +        // In OS X, the device name is OK for sending ioctls to,
412 +        // but not for reading raw CDROM data from.
413 +        // (it seems to have extra data padded in)
414 +        //
415 +        // So, we keep the already opened file handle,
416 +        // and open a slightly different file for CDROM data
417 +        //
418 +        fh->ioctl_fd = fh->fd;
419 +        fh->ioctl_name = fh->name;
420 +        fh->fd = -1;
421 +        fh->name = (char *)malloc(strlen(fh->ioctl_name) + 3);
422 +        if (fh->name) {
423 +                strcpy(fh->name, fh->ioctl_name);
424 +                strcat(fh->name, "s1");
425 +                fh->fd = open(fh->name, O_RDONLY, O_NONBLOCK);
426 +        }
427 +        if (fh->ioctl_fd < 0)
428 +                return false;
429 + #endif
430 +        return true;
431 + }
432 +
433 + bool cdrom_open(file_handle *fh, const char *path)
434 + {
435 +        if (path)
436 +                fh->name = strdup(path);
437 +        fh->fd = open(fh->name, O_RDONLY, O_NONBLOCK);
438 +        fh->start_byte = 0;
439 +        if (!cdrom_open_1(fh))
440 +                return false;
441 +        return fh->fd >= 0;
442 + }
443 +
444 +
445 + /*
446 + *  Close a CD-ROM device
447 + */
448 +
449 + void cdrom_close(file_handle *fh)
450 + {
451 +
452 +        if (fh->fd >= 0) {
453 +                close(fh->fd);
454 +                fh->fd = -1;
455 +        }
456 +        if (fh->name) {
457 +                free(fh->name);
458 +                fh->name = NULL;
459 +        }
460 + #if defined __MACOSX__
461 +        if (fh->ioctl_fd >= 0) {
462 +                close(fh->ioctl_fd);
463 +                fh->ioctl_fd = -1;
464 +        }
465 +        if (fh->ioctl_name) {
466 +                free(fh->ioctl_name);
467 +                fh->ioctl_name = NULL;
468 +        }
469   #endif
470   }
471  
# Line 287 | Line 517 | void *Sys_open(const char *name, bool re
517   #else
518          bool is_cdrom = strncmp(name, "/dev/cd", 7) == 0;
519   #endif
520 +        bool is_floppy = strncmp(name, "/dev/fd", 7) == 0;
521 +
522 +        bool is_polled_media = strncmp(name, "/dev/poll/", 10) == 0;
523 +        if (is_floppy) // Floppy open fails if there's no disk inserted
524 +                is_polled_media = true;
525 +
526 + #if defined __MACOSX__
527 +        // There is no set filename in /dev which is the cdrom,
528 +        // so we have to see if it is any of the devices that we found earlier
529 +        {
530 +                int index = 0;
531 +                const char *str;
532 +                while ((str = PrefsFindString("cdrom", index++)) != NULL) {
533 +                        if (is_polled_media || strcmp(str, name) == 0) {
534 +                                is_cdrom = true;
535 +                                read_only = true;
536 +                                break;
537 +                        }
538 +                }
539 +        }
540 + #endif
541  
542          D(bug("Sys_open(%s, %s)\n", name, read_only ? "read-only" : "read/write"));
543  
# Line 309 | Line 560 | void *Sys_open(const char *name, bool re
560          }
561  
562          // Open file/device
563 < #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
563 >
564 > #if defined(BINCUE)
565 >
566 >        void *binfd = open_bincue(name);
567 >        if (binfd) {
568 >                file_handle *fh = new file_handle;
569 >                fh->fd = 0;
570 >                fh->is_file = false;
571 >                fh->name = strdup(name);
572 >                fh->bincue_fd = binfd;
573 >                fh->is_bincue = true;
574 >                fh->read_only  = true;
575 >                fh->start_byte = 0;
576 >                fh->is_floppy = false;
577 >                fh->is_cdrom = false;
578 >                fh->is_media_present = true;
579 > #if defined __MACOSX__
580 >            fh->ioctl_fd = -1;
581 >            fh->ioctl_name = NULL;
582 > #endif
583 >            sys_add_file_handle(fh);
584 >            return fh;
585 >          }
586 > #endif
587 >
588 > #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__MACOSX__)
589          int fd = open(name, (read_only ? O_RDONLY : O_RDWR) | (is_cdrom ? O_NONBLOCK : 0));
590   #else
591          int fd = open(name, read_only ? O_RDONLY : O_RDWR);
# Line 319 | Line 595 | void *Sys_open(const char *name, bool re
595                  read_only = true;
596                  fd = open(name, O_RDONLY);
597          }
598 <        if (fd >= 0) {
598 >        if (fd >= 0 || is_polled_media) {
599                  file_handle *fh = new file_handle;
600                  fh->name = strdup(name);
601                  fh->fd = fd;
602                  fh->is_file = is_file;
603                  fh->read_only = read_only;
604                  fh->start_byte = 0;
605 <                fh->is_floppy = false;
606 <                fh->is_cdrom = false;
605 >                fh->is_floppy = is_floppy;
606 >                fh->is_cdrom = is_cdrom;
607 >                fh->is_media_present = false;
608 > #if defined __linux__
609 >                fh->cdrom_cap = 0;
610 > #endif
611 > #if defined __MACOSX__
612 >                fh->ioctl_fd = -1;
613 >                fh->ioctl_name = NULL;
614 > #endif
615 > #if defined(BINCUE)
616 >                fh->is_bincue = false;
617 >                fh->bincue_fd = NULL;
618 > #endif
619                  if (fh->is_file) {
620 +                        fh->is_media_present = true;
621                          // Detect disk image file layout
622                          loff_t size = 0;
334 #if defined(__linux__)
335                        _llseek(fh->fd, 0, 0, &size, SEEK_END);
336 #else
623                          size = lseek(fd, 0, SEEK_END);
338 #endif
624                          uint8 data[256];
625                          lseek(fd, 0, SEEK_SET);
626                          read(fd, data, 256);
# Line 343 | Line 628 | void *Sys_open(const char *name, bool re
628                  } else {
629                          struct stat st;
630                          if (fstat(fd, &st) == 0) {
631 +                                fh->is_media_present = true;
632                                  if (S_ISBLK(st.st_mode)) {
633                                          fh->is_cdrom = is_cdrom;
634   #if defined(__linux__)
# Line 370 | Line 656 | void *Sys_open(const char *name, bool re
656                                          fh->is_floppy = ((st.st_rdev >> 16) == 2);
657   #endif
658                                  }
659 + #if defined __MACOSX__
660 +                                if (is_cdrom) {
661 +                                        fh->is_cdrom = true;
662 +                                        fh->is_floppy = false;
663 +                                        if (cdrom_open_1(fh))
664 +                                                fh->is_media_present = true;
665 +                                }
666 + #endif
667                          }
668                  }
669                  if (fh->is_floppy && first_floppy == NULL)
670                          first_floppy = fh;
671 +                sys_add_file_handle(fh);
672                  return fh;
673          } else {
674                  printf("WARNING: Cannot open %s (%s)\n", name, strerror(errno));
# Line 392 | Line 687 | void Sys_close(void *arg)
687          if (!fh)
688                  return;
689  
690 <        close(fh->fd);
690 >        sys_remove_file_handle(fh);
691 >
692 > #if defined(BINCUE)
693 >        if (fh->is_bincue) {
694 >            close_bincue(fh->bincue_fd);
695 >            fh->bincue_fd = NULL;
696 >        }
697 > #endif
698 >
699 >        if (fh->is_cdrom)
700 >                cdrom_close(fh);
701 >        if (fh->fd >= 0)
702 >                close(fh->fd);
703          if (fh->name)
704                  free(fh->name);
705          delete fh;
# Line 410 | Line 717 | size_t Sys_read(void *arg, void *buffer,
717          if (!fh)
718                  return 0;
719  
720 + #if defined(BINCUE)
721 +        if (fh->is_bincue) {
722 +            return read_bincue(fh->bincue_fd, buffer, offset, length);
723 +        }
724 + #endif
725 +
726          // Seek to position
414 #if defined(__linux__)
415        loff_t pos = offset + fh->start_byte, res;
416        if (_llseek(fh->fd, pos >> 32, pos, &res, SEEK_SET) < 0)
417                return 0;
418 #else
727          if (lseek(fh->fd, offset + fh->start_byte, SEEK_SET) < 0)
728                  return 0;
421 #endif
729  
730          // Read data
731          return read(fh->fd, buffer, length);
# Line 437 | Line 744 | size_t Sys_write(void *arg, void *buffer
744                  return 0;
745  
746          // Seek to position
440 #if defined(__linux__)
441        loff_t pos = offset + fh->start_byte, res;
442        if (_llseek(fh->fd, pos >> 32, pos, &res, SEEK_SET) < 0)
443                return 0;
444 #else
747          if (lseek(fh->fd, offset + fh->start_byte, SEEK_SET) < 0)
748                  return 0;
447 #endif
749  
750          // Write data
751          return write(fh->fd, buffer, length);
# Line 464 | Line 765 | loff_t SysGetFileSize(void *arg)
765          if (fh->is_file)
766                  return fh->file_size;
767          else {
467 #if defined(__linux__)
768                  long blocks;
769 + #if defined(BINCUE)
770 +                if (fh->is_bincue) {
771 +                    return size_bincue(fh->bincue_fd);
772 +                }
773 + #endif
774 + #if defined(__linux__)
775 +
776                  if (ioctl(fh->fd, BLKGETSIZE, &blocks) < 0)
777                          return 0;
778                  D(bug(" BLKGETSIZE returns %d blocks\n", blocks));
779                  return (loff_t)blocks * 512;
780 + #elif defined __MACOSX__
781 +                uint32 block_size;
782 +                if (ioctl(fh->ioctl_fd, DKIOCGETBLOCKSIZE, &block_size) < 0)
783 +                        return 0;
784 +                D(bug(" DKIOCGETBLOCKSIZE returns %lu bytes\n", (unsigned long)block_size));
785 +                uint64 block_count;
786 +                if (ioctl(fh->ioctl_fd, DKIOCGETBLOCKCOUNT, &block_count) < 0)
787 +                        return 0;
788 +                D(bug(" DKIOCGETBLOCKCOUNT returns %llu blocks\n", (unsigned long long)block_count));
789 +                return block_count * block_size;
790   #else
791                  return lseek(fh->fd, 0, SEEK_END) - fh->start_byte;
792   #endif
# Line 489 | Line 806 | void SysEject(void *arg)
806  
807   #if defined(__linux__)
808          if (fh->is_floppy) {
809 <                fsync(fh->fd);
810 <                ioctl(fh->fd, FDFLUSH);
811 <                ioctl(fh->fd, FDEJECT);
812 <                close(fh->fd);  // Close and reopen so the driver will see the media change
809 >                if (fh->fd >= 0) {
810 >                        fsync(fh->fd);
811 >                        ioctl(fh->fd, FDFLUSH);
812 >                        ioctl(fh->fd, FDEJECT);
813 >                        close(fh->fd);  // Close and reopen so the driver will see the media change
814 >                }
815                  fh->fd = open(fh->name, fh->read_only ? O_RDONLY : O_RDWR);
816          } else if (fh->is_cdrom) {
817                  ioctl(fh->fd, CDROMEJECT);
# Line 507 | Line 826 | void SysEject(void *arg)
826                  close(fh->fd);  // Close and reopen so the driver will see the media change
827                  fh->fd = open(fh->name, O_RDONLY | O_NONBLOCK);
828          }
829 + #elif defined(__APPLE__) && defined(__MACH__)
830 +        if (fh->is_cdrom && fh->is_media_present) {
831 +                close(fh->fd);
832 +                fh->fd = -1;
833 +                if (ioctl(fh->ioctl_fd, DKIOCEJECT) < 0) {
834 +                        D(bug(" DKIOCEJECT failed on file %s: %s\n",
835 +                                   fh->ioctl_name, strerror(errno)));
836 +
837 +                        // If we are running MacOS X, the device may be in busy
838 +                        // state because the Finder has mounted the disk
839 +                        close(fh->ioctl_fd);
840 +                        fh->ioctl_fd = -1;
841 +
842 +                        // Try to use "diskutil eject" but it can take up to 5
843 +                        // seconds to complete
844 +                        static const char eject_cmd[] = "/usr/sbin/diskutil eject %s 2>&1 >/dev/null";
845 +                        char *cmd = (char *)alloca(strlen(eject_cmd) + strlen(fh->ioctl_name) + 1);
846 +                        sprintf(cmd, eject_cmd, fh->ioctl_name);
847 +                        system(cmd);
848 +                }
849 +                fh->is_media_present = false;
850 +        }
851   #endif
852   }
853  
# Line 538 | Line 879 | bool SysIsReadOnly(void *arg)
879  
880   #if defined(__linux__)
881          if (fh->is_floppy) {
882 <                struct floppy_drive_struct stat;
883 <                ioctl(fh->fd, FDGETDRVSTAT, &stat);
884 <                return !(stat.flags & FD_DISK_WRITABLE);
882 >                if (fh->fd >= 0) {
883 >                        struct floppy_drive_struct stat;
884 >                        ioctl(fh->fd, FDGETDRVSTAT, &stat);
885 >                        return !(stat.flags & FD_DISK_WRITABLE);
886 >                } else
887 >                        return true;
888          } else
889   #endif
890                  return fh->read_only;
# Line 615 | Line 959 | bool SysIsDiskInserted(void *arg)
959          } else if (fh->is_cdrom) {
960                  struct ioc_toc_header header;
961                  return ioctl(fh->fd, CDIOREADTOCHEADER, &header) == 0;
962 + #elif defined __MACOSX__
963 +        } else if (fh->is_cdrom || fh->is_floppy) {
964 +                return fh->is_media_present;
965   #endif
966  
967          } else
# Line 666 | Line 1013 | bool SysCDReadTOC(void *arg, uint8 *toc)
1013          if (!fh)
1014                  return false;
1015  
1016 + #if defined(BINCUE)
1017 +        if (fh->is_bincue){
1018 +                return readtoc_bincue(fh->bincue_fd, toc);
1019 +        }
1020 + #endif
1021 +
1022          if (fh->is_cdrom) {
1023 +
1024   #if defined(__linux__)
1025                  uint8 *p = toc + 2;
1026  
# Line 713 | Line 1067 | bool SysCDReadTOC(void *arg, uint8 *toc)
1067                  *toc++ = toc_size >> 8;
1068                  *toc++ = toc_size & 0xff;
1069                  return true;
1070 + #elif defined __MACOSX__ && defined MAC_OS_X_VERSION_10_2
1071 +                if (fh->is_media_present) {
1072 +                        extern bool DarwinCDReadTOC(char *name, uint8 *toc);
1073 +                        return DarwinCDReadTOC(fh->name, toc);
1074 +                }
1075 +                return false;
1076   #elif defined(__FreeBSD__)
1077                  uint8 *p = toc + 2;
1078  
# Line 801 | Line 1161 | bool SysCDGetPosition(void *arg, uint8 *
1161          if (!fh)
1162                  return false;
1163  
1164 + #if defined(BINCUE)
1165 +        if (fh->is_bincue) {
1166 +
1167 +                return GetPosition_bincue(fh->bincue_fd, pos);
1168 +        }
1169 + #endif
1170 +
1171          if (fh->is_cdrom) {
1172   #if defined(__linux__)
1173                  cdrom_subchnl chan;
# Line 866 | Line 1233 | bool SysCDPlay(void *arg, uint8 start_m,
1233          if (!fh)
1234                  return false;
1235  
1236 + #if defined(BINCUE)
1237 +        if (fh->is_bincue) {
1238 +            return CDPlay_bincue(fh->bincue_fd, start_m, start_s,
1239 +                                                         start_f, end_m, end_s, end_f);
1240 +        }
1241 + #endif
1242 +
1243          if (fh->is_cdrom) {
1244   #if defined(__linux__)
1245                  cdrom_msf play;
# Line 903 | Line 1277 | bool SysCDPause(void *arg)
1277          if (!fh)
1278                  return false;
1279  
1280 + #if defined(BINCUE)
1281 +        if (fh->is_bincue){
1282 +            return CDPause_bincue(fh->bincue_fd);
1283 +        }
1284 + #endif
1285 +
1286          if (fh->is_cdrom) {
1287   #if defined(__linux__)
1288                  return ioctl(fh->fd, CDROMPAUSE) == 0;
# Line 926 | Line 1306 | bool SysCDResume(void *arg)
1306          if (!fh)
1307                  return false;
1308  
1309 + #if defined(BINCUE)
1310 +        if (fh->is_bincue) {
1311 +            return CDResume_bincue(fh->bincue_fd);
1312 +        }
1313 + #endif
1314 +
1315 +
1316          if (fh->is_cdrom) {
1317   #if defined(__linux__)
1318                  return ioctl(fh->fd, CDROMRESUME) == 0;
# Line 949 | Line 1336 | bool SysCDStop(void *arg, uint8 lead_out
1336          if (!fh)
1337                  return false;
1338  
1339 + #if defined(BINCUE)
1340 +        if (fh->is_bincue) {
1341 +            return CDStop_bincue(fh->bincue_fd);
1342 +        }
1343 + #endif
1344 +
1345 +
1346          if (fh->is_cdrom) {
1347   #if defined(__linux__)
1348                  return ioctl(fh->fd, CDROMSTOP) == 0;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines