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.1 by cebix, 1999-10-03T14:16:25Z vs.
Revision 1.35 by asvitkine, 2012-03-01T04:24:45Z

# Line 1 | Line 1
1   /*
2   *  sys_unix.cpp - System dependent routines, Unix implementation
3   *
4 < *  Basilisk II (C) 1997-1999 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>
37 < #include <linux/unistd.h>
38 <
34 < #ifdef __NR__llseek
35 < _syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, loff_t *, res, uint, wh);
36 < #else
37 < static int _llseek(uint fd, ulong hi, ulong lo, loff_t *res, uint wh)
38 < {
39 <        if (hi)
40 <                return -1;
41 <        *res = lseek(fd, lo, wh);
42 <        if (*res == -1)
43 <                return -1;
44 <        return 0;
45 < }
46 < #endif
37 > #include <dirent.h>
38 > #include <limits.h>
39   #endif
40  
41 < #ifdef __FreeBSD__
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  
62
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;
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 88 | 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 97 | 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 119 | Line 267 | void SysMountFirstFloppy(void)
267   void SysAddFloppyPrefs(void)
268   {
269   #if defined(__linux__)
270 <        PrefsAddString("floppy", "/dev/fd0H1440");
271 <        PrefsAddString("floppy", "/dev/fd1H1440");
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 >                        }
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 >  #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 131 | Line 305 | void SysAddFloppyPrefs(void)
305   /*
306   *  This gets called when no "disk" prefs items are found
307   *  It scans for available HFS volumes and adds appropriate prefs items
308 + *      On OS X, we could do the same, but on an OS X machine I think it is
309 + *      very unlikely that any mounted volumes would contain a system which
310 + *      is old enough to boot a 68k Mac, so we just do nothing here for now.
311   */
312  
313   void SysAddDiskPrefs(void)
# Line 142 | Line 319 | void SysAddDiskPrefs(void)
319                  while(fgets(line, 255, f)) {
320                          // Read line
321                          int len = strlen(line);
322 <                        if (len == 0)
322 >                        if (len == 0 || line[0] == '#')
323                                  continue;
324                          line[len-1] = 0;
325  
326                          // Parse line
327                          char *dev, *mnt_point, *fstype;
328 <                        if (sscanf(line, "%s %s %s", &dev, &mnt_point, &fstype) == 3) {
328 >                        if (sscanf(line, "%as %as %as", &dev, &mnt_point, &fstype) == 3) {
329                                  if (strcmp(fstype, "hfs") == 0)
330                                          PrefsAddString("disk", dev);
331                          }
332 +                        free(dev); free(mnt_point); free(fstype);
333                  }
334                  fclose(f);
335          }
# Line 171 | Line 349 | void SysAddCDROMPrefs(void)
349                  return;
350  
351   #if defined(__linux__)
352 <        PrefsAddString("cdrom", "/dev/cdrom");
353 < #elif defined(__FreeBSD__)
352 >        if (access("/dev/.devfsd", F_OK) < 0)
353 >                PrefsAddString("cdrom", "/dev/cdrom");
354 >        else {
355 >                DIR *cd_dir = opendir("/dev/cdroms");
356 >                if (cd_dir) {
357 >                        struct dirent *cdrom_dev;
358 >                        while ((cdrom_dev = readdir(cd_dir)) != NULL) {
359 >                                if (strcmp(cdrom_dev->d_name, ".") != 0 && strcmp(cdrom_dev->d_name, "..") != 0) {
360 >                                        char cd_dev[20];
361 >                                        sprintf(cd_dev, "/dev/cdroms/%s", cdrom_dev->d_name);
362 >                                        PrefsAddString("cdrom", cd_dev);
363 >                                }
364 >                        }
365 >                        closedir(cd_dir);
366 >                }
367 >        }
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
377   }
# Line 185 | Line 384 | void SysAddCDROMPrefs(void)
384   void SysAddSerialPrefs(void)
385   {
386   #if defined(__linux__)
387 <        PrefsAddString("seriala", "/dev/ttyS0");
388 <        PrefsAddString("serialb", "/dev/ttyS1");
387 >        if (access("/dev/.devfsd", F_OK) < 0) {
388 >                PrefsAddString("seriala", "/dev/ttyS0");
389 >                PrefsAddString("serialb", "/dev/ttyS1");
390 >        } else {
391 >                PrefsAddString("seriala", "/dev/tts/0");
392 >                PrefsAddString("serialb", "/dev/tts/1");
393 >        }
394   #elif defined(__FreeBSD__)
395          PrefsAddString("seriala", "/dev/cuaa0");
396          PrefsAddString("serialb", "/dev/cuaa1");
397 + #elif defined(__NetBSD__)
398 +        PrefsAddString("seriala", "/dev/tty00");
399 +        PrefsAddString("serialb", "/dev/tty01");
400 + #elif defined(__APPLE__) && defined(__MACH__)
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 + }
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 214 | Line 501 | static bool is_drive_mounted(const char
501                          // Parse line
502                          if (strncmp(line, dev_name, strlen(dev_name)) == 0) {
503                                  mount_name[0] = 0;
504 <                                char dummy[256];
505 <                                sscanf(line, "%s %s", dummy, mount_name);
504 >                                char *dummy;
505 >                                sscanf(line, "%as %s", &dummy, mount_name);
506 >                                free(dummy);
507                                  fclose(f);
508                                  return true;
509                          }
# Line 230 | 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   {
537          bool is_file = strncmp(name, "/dev/", 5) != 0;
538 < #ifdef __FreeBSD__
538 > #if defined(__FreeBSD__)
539                          // SCSI                             IDE
540          bool is_cdrom = strncmp(name, "/dev/cd", 7) == 0 || strncmp(name, "/dev/acd", 8) == 0;
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 +        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
553 +        {
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 +                }
563 +        }
564 + #endif
565  
566          D(bug("Sys_open(%s, %s)\n", name, read_only ? "read-only" : "read/write"));
567  
# Line 262 | Line 584 | void *Sys_open(const char *name, bool re
584          }
585  
586          // Open file/device
587 < #ifdef __linux__
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 272 | 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;
277 <                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;
283 <                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;
287 #ifdef __linux__
288                        _llseek(fh->fd, 0, 0, &size, SEEK_END);
289 #else
640                          size = lseek(fd, 0, SEEK_END);
291 #endif
641                          uint8 data[256];
642                          lseek(fd, 0, SEEK_SET);
643                          read(fd, data, 256);
# Line 296 | 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 306 | Line 656 | void *Sys_open(const char *name, bool re
656                                                  if (fh->cdrom_cap < 0)
657                                                          fh->cdrom_cap = 0;
658                                          }
309 #else
310                                        fh->cdrom_cap = 0;
659   #endif
660   #elif defined(__FreeBSD__)
661                                          fh->is_floppy = ((st.st_rdev >> 16) == 2);
# Line 316 | 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                                          }
319 #else
320                                        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 __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 339 | 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 357 | 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
365 #ifdef __linux__
366        loff_t pos = offset + fh->start_byte, res;
367        if (_llseek(fh->fd, pos >> 32, pos, &res, SEEK_SET) < 0)
368                return 0;
369 #else
747          if (lseek(fh->fd, offset + fh->start_byte, SEEK_SET) < 0)
748                  return 0;
372 #endif
749  
750          // Read data
751          return read(fh->fd, buffer, length);
# Line 383 | 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
391 #ifdef __linux__
392        loff_t pos = offset + fh->start_byte, res;
393        if (_llseek(fh->fd, pos >> 32, pos, &res, SEEK_SET) < 0)
394                return 0;
395 #else
772          if (lseek(fh->fd, offset + fh->start_byte, SEEK_SET) < 0)
773                  return 0;
398 #endif
774  
775          // Write data
776          return write(fh->fd, buffer, length);
# Line 408 | 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 {
803 < #ifdef __linux__
804 <                loff_t pos = 0;
805 <                _llseek(fh->fd, 0, 0, &pos, SEEK_END);
806 <                return pos - fh->start_byte;
803 > #if defined(__linux__)
804 >                long blocks;
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 432 | 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);
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);
847                  close(fh->fd);  // Close and reopen so the driver will see the media change
848                  fh->fd = open(fh->name, O_RDONLY | O_NONBLOCK);
849          }
850 < #elif defined(__FreeBSD__)
850 > #elif defined(__FreeBSD__) || defined(__NetBSD__)
851          if (fh->is_floppy) {
852                  fsync(fh->fd);
452                //ioctl(fh->fd, FDFLUSH);
453                //ioctl(fh->fd, FDEJECT);
853          } else if (fh->is_cdrom) {
854                  ioctl(fh->fd, CDIOCEJECT);
855                  close(fh->fd);  // Close and reopen so the driver will see the media change
856                  fh->fd = open(fh->name, O_RDONLY | O_NONBLOCK);
857          }
858 + #elif defined(__APPLE__) && defined(__MACH__)
859 +        if (fh->is_cdrom && fh->is_media_present) {
860 +                close(fh->fd);
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 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 +                        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   }
882  
# Line 466 | 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 481 | 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 < #ifdef __linux__
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 502 | 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 521 | 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 532 | Line 966 | bool SysIsDiskInserted(void *arg)
966          } else if (fh->is_floppy) {
967                  char block[512];
968                  lseek(fh->fd, 0, SEEK_SET);
969 <                return read(fh->fd, block, 512) == 512;
969 >                ssize_t actual = read(fh->fd, block, 512);
970 >                if (actual < 0) {
971 >                        close(fh->fd);  // Close and reopen so the driver will see the media change
972 >                        fh->fd = open(fh->name, fh->read_only ? O_RDONLY : O_RDWR);
973 >                        actual = read(fh->fd, block, 512);
974 >                }
975 >                return actual == 512;
976          } else if (fh->is_cdrom) {
977 + #ifdef CDROM_MEDIA_CHANGED
978 +                if (fh->cdrom_cap & CDC_MEDIA_CHANGED) {
979 +                        // If we don't do this, all attempts to read from a disc fail
980 +                        // once the tray has been opened (altough the TOC reads fine).
981 +                        // Can somebody explain this to me?
982 +                        if (ioctl(fh->fd, CDROM_MEDIA_CHANGED) == 1) {
983 +                                close(fh->fd);
984 +                                fh->fd = open(fh->name, O_RDONLY | O_NONBLOCK);
985 +                        }
986 +                }
987 + #endif
988   #ifdef CDROM_DRIVE_STATUS
989                  if (fh->cdrom_cap & CDC_DRIVE_STATUS) {
990                          return ioctl(fh->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT) == CDS_DISC_OK;
# Line 541 | Line 992 | bool SysIsDiskInserted(void *arg)
992   #endif
993                  cdrom_tochdr header;
994                  return ioctl(fh->fd, CDROMREADTOCHDR, &header) == 0;
995 < #elif defined(__FreeBSD__)
995 > #elif defined(__FreeBSD__) || defined(__NetBSD__)
996          } else if (fh->is_floppy) {
997                  return false;   //!!
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 560 | 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 577 | 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  
1038 < #ifdef defined(__linux__) && defined(CDROM_LOCKDOOR)
1038 > #if defined(__linux__) && defined(CDROM_LOCKDOOR)
1039          if (fh->is_cdrom)
1040                  ioctl(fh->fd, CDROM_LOCKDOOR, 0);      
1041   #endif
# Line 594 | 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 645 | Line 1105 | bool SysCDReadTOC(void *arg, uint8 *toc)
1105                  *toc++ = toc_size >> 8;
1106                  *toc++ = toc_size & 0xff;
1107                  return true;
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 691 | Line 1157 | bool SysCDReadTOC(void *arg, uint8 *toc)
1157                  *toc++ = toc_size >> 8;
1158                  *toc++ = toc_size & 0xff;
1159                  return true;
1160 + #elif defined(__NetBSD__)
1161 +                uint8 *p = toc + 2;
1162 +
1163 +                // Header
1164 +                struct ioc_toc_header header;
1165 +                if (ioctl(fh->fd, CDIOREADTOCHEADER, &header) < 0)
1166 +                        return false;
1167 +                *p++ = header.starting_track;
1168 +                *p++ = header.ending_track;
1169 +
1170 +                // Tracks (this is nice... :-)
1171 +                struct ioc_read_toc_entry entries;
1172 +                entries.address_format = CD_MSF_FORMAT;
1173 +                entries.starting_track = 1;
1174 +                entries.data_len = 800;
1175 +                entries.data = (cd_toc_entry *)p;
1176 +                if (ioctl(fh->fd, CDIOREADTOCENTRIES, &entries) < 0)
1177 +                        return false;
1178 +
1179 +                // TOC size
1180 +                int toc_size = p - toc;
1181 +                *toc++ = toc_size >> 8;
1182 +                *toc++ = toc_size & 0xff;
1183 +                return true;
1184 + #else
1185 +                return false;
1186   #endif
1187          } else
1188                  return false;
# Line 703 | 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 730 | Line 1227 | bool SysCDGetPosition(void *arg, uint8 *
1227                  *pos++ = chan.cdsc_reladdr.msf.second;
1228                  *pos++ = chan.cdsc_reladdr.msf.frame;
1229                  return true;
1230 < #elif defined(__FreeBSD__)
1230 > #elif defined(__FreeBSD__) || defined(__NetBSD__)
1231                  struct ioc_read_subchannel chan;
1232                  chan.data_format = CD_MSF_FORMAT;
1233                  chan.address_format = CD_MSF_FORMAT;
# Line 754 | Line 1251 | bool SysCDGetPosition(void *arg, uint8 *
1251                  *pos++ = chan.data->what.position.reladdr.msf.second;
1252                  *pos++ = chan.data->what.position.reladdr.msf.frame;
1253                  return true;
1254 + #else
1255 +                return false;
1256   #endif
1257          } else
1258                  return false;
# Line 766 | 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 780 | Line 1284 | bool SysCDPlay(void *arg, uint8 start_m,
1284                  play.cdmsf_sec1 = end_s;
1285                  play.cdmsf_frame1 = end_f;
1286                  return ioctl(fh->fd, CDROMPLAYMSF, &play) == 0;
1287 < #elif defined(__FreeBSD__)
1287 > #elif defined(__FreeBSD__) || defined(__NetBSD__)
1288                  struct ioc_play_msf play;
1289                  play.start_m = start_m;
1290                  play.start_s = start_s;
# Line 789 | Line 1293 | bool SysCDPlay(void *arg, uint8 start_m,
1293                  play.end_s = end_s;
1294                  play.end_f = end_f;
1295                  return ioctl(fh->fd, CDIOCPLAYMSF, &play) == 0;
1296 + #else
1297 +                return false;
1298   #endif
1299          } else
1300                  return false;
# Line 801 | 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;
1322 < #elif defined(__FreeBSD__)
1322 > #elif defined(__FreeBSD__) || defined(__NetBSD__)
1323                  return ioctl(fh->fd, CDIOCPAUSE) == 0;
1324 + #else
1325 +                return false;
1326   #endif
1327          } else
1328                  return false;
# Line 822 | 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;
1351 < #elif defined(__FreeBSD__)
1351 > #elif defined(__FreeBSD__) || defined(__NetBSD__)
1352                  return ioctl(fh->fd, CDIOCRESUME) == 0;
1353 + #else
1354 +                return false;
1355   #endif
1356          } else
1357                  return false;
# Line 843 | 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;
1380 < #elif defined(__FreeBSD__)
1380 > #elif defined(__FreeBSD__) || defined(__NetBSD__)
1381                  return ioctl(fh->fd, CDIOCSTOP) == 0;
1382 + #else
1383 +                return false;
1384   #endif
1385          } else
1386                  return false;
# Line 864 | 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 879 | 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 889 | Line 1418 | void SysCDSetVolume(void *arg, uint8 lef
1418                  vol.channel0 = vol.channel2 = left;
1419                  vol.channel1 = vol.channel3 = right;
1420                  ioctl(fh->fd, CDROMVOLCTRL, &vol);
1421 < #elif defined(__FreeBSD__)
1421 > #elif defined(__FreeBSD__) || defined(__NetBSD__)
1422                  struct ioc_vol vol;
1423                  vol.vol[0] = vol.vol[2] = left;
1424                  vol.vol[1] = vol.vol[3] = right;
# Line 905 | 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  
# Line 916 | Line 1445 | void SysCDGetVolume(void *arg, uint8 &le
1445                  ioctl(fh->fd, CDROMVOLREAD, &vol);
1446                  left = vol.channel0;
1447                  right = vol.channel1;
1448 < #elif defined(__FreeBSD__)
1448 > #elif defined(__FreeBSD__) || defined(__NetBSD__)
1449                  struct ioc_vol vol;
1450                  ioctl(fh->fd, CDIOCGETVOL, &vol);
1451                  left = vol.vol[0];

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines