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.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-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   #define DEBUG 0
65   #include "debug.h"
66  
62
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 88 | 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 97 | 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 119 | Line 256 | void SysMountFirstFloppy(void)
256   void SysAddFloppyPrefs(void)
257   {
258   #if defined(__linux__)
259 <        PrefsAddString("floppy", "/dev/fd0H1440");
260 <        PrefsAddString("floppy", "/dev/fd1H1440");
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 >                        }
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 131 | 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 142 | Line 308 | void SysAddDiskPrefs(void)
308                  while(fgets(line, 255, f)) {
309                          // Read line
310                          int len = strlen(line);
311 <                        if (len == 0)
311 >                        if (len == 0 || line[0] == '#')
312                                  continue;
313                          line[len-1] = 0;
314  
315                          // Parse line
316                          char *dev, *mnt_point, *fstype;
317 <                        if (sscanf(line, "%s %s %s", &dev, &mnt_point, &fstype) == 3) {
317 >                        if (sscanf(line, "%as %as %as", &dev, &mnt_point, &fstype) == 3) {
318                                  if (strcmp(fstype, "hfs") == 0)
319                                          PrefsAddString("disk", dev);
320                          }
321 +                        free(dev); free(mnt_point); free(fstype);
322                  }
323                  fclose(f);
324          }
# Line 171 | Line 338 | void SysAddCDROMPrefs(void)
338                  return;
339  
340   #if defined(__linux__)
341 <        PrefsAddString("cdrom", "/dev/cdrom");
342 < #elif defined(__FreeBSD__)
341 >        if (access("/dev/.devfsd", F_OK) < 0)
342 >                PrefsAddString("cdrom", "/dev/cdrom");
343 >        else {
344 >                DIR *cd_dir = opendir("/dev/cdroms");
345 >                if (cd_dir) {
346 >                        struct dirent *cdrom_dev;
347 >                        while ((cdrom_dev = readdir(cd_dir)) != NULL) {
348 >                                if (strcmp(cdrom_dev->d_name, ".") != 0 && strcmp(cdrom_dev->d_name, "..") != 0) {
349 >                                        char cd_dev[20];
350 >                                        sprintf(cd_dev, "/dev/cdroms/%s", cdrom_dev->d_name);
351 >                                        PrefsAddString("cdrom", cd_dev);
352 >                                }
353 >                        }
354 >                        closedir(cd_dir);
355 >                }
356 >        }
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");
365   #endif
366   }
# Line 185 | Line 373 | void SysAddCDROMPrefs(void)
373   void SysAddSerialPrefs(void)
374   {
375   #if defined(__linux__)
376 <        PrefsAddString("seriala", "/dev/ttyS0");
377 <        PrefsAddString("serialb", "/dev/ttyS1");
376 >        if (access("/dev/.devfsd", F_OK) < 0) {
377 >                PrefsAddString("seriala", "/dev/ttyS0");
378 >                PrefsAddString("serialb", "/dev/ttyS1");
379 >        } else {
380 >                PrefsAddString("seriala", "/dev/tts/0");
381 >                PrefsAddString("serialb", "/dev/tts/1");
382 >        }
383   #elif defined(__FreeBSD__)
384          PrefsAddString("seriala", "/dev/cuaa0");
385          PrefsAddString("serialb", "/dev/cuaa1");
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 214 | Line 490 | static bool is_drive_mounted(const char
490                          // Parse line
491                          if (strncmp(line, dev_name, strlen(dev_name)) == 0) {
492                                  mount_name[0] = 0;
493 <                                char dummy[256];
494 <                                sscanf(line, "%s %s", dummy, mount_name);
493 >                                char *dummy;
494 >                                sscanf(line, "%as %s", &dummy, mount_name);
495 >                                free(dummy);
496                                  fclose(f);
497                                  return true;
498                          }
# Line 234 | Line 511 | static bool is_drive_mounted(const char
511   void *Sys_open(const char *name, bool read_only)
512   {
513          bool is_file = strncmp(name, "/dev/", 5) != 0;
514 < #ifdef __FreeBSD__
514 > #if defined(__FreeBSD__)
515                          // SCSI                             IDE
516          bool is_cdrom = strncmp(name, "/dev/cd", 7) == 0 || strncmp(name, "/dev/acd", 8) == 0;
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 262 | Line 560 | void *Sys_open(const char *name, bool re
560          }
561  
562          // Open file/device
563 < #ifdef __linux__
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 272 | 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;
287 #ifdef __linux__
288                        _llseek(fh->fd, 0, 0, &size, SEEK_END);
289 #else
623                          size = lseek(fd, 0, SEEK_END);
291 #endif
624                          uint8 data[256];
625                          lseek(fd, 0, SEEK_SET);
626                          read(fd, data, 256);
# Line 296 | 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 319 | Line 652 | void *Sys_open(const char *name, bool re
652   #else
653                                          fh->cdrom_cap = 0;
654   #endif
655 + #elif defined(__NetBSD__)
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 343 | 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 361 | 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
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
727          if (lseek(fh->fd, offset + fh->start_byte, SEEK_SET) < 0)
728                  return 0;
372 #endif
729  
730          // Read data
731          return read(fh->fd, buffer, length);
# Line 388 | Line 744 | size_t Sys_write(void *arg, void *buffer
744                  return 0;
745  
746          // 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
747          if (lseek(fh->fd, offset + fh->start_byte, SEEK_SET) < 0)
748                  return 0;
398 #endif
749  
750          // Write data
751          return write(fh->fd, buffer, length);
# Line 415 | Line 765 | loff_t SysGetFileSize(void *arg)
765          if (fh->is_file)
766                  return fh->file_size;
767          else {
768 < #ifdef __linux__
769 <                loff_t pos = 0;
770 <                _llseek(fh->fd, 0, 0, &pos, SEEK_END);
771 <                return pos - fh->start_byte;
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 438 | 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);
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);
818                  close(fh->fd);  // Close and reopen so the driver will see the media change
819                  fh->fd = open(fh->name, O_RDONLY | O_NONBLOCK);
820          }
821 < #elif defined(__FreeBSD__)
821 > #elif defined(__FreeBSD__) || defined(__NetBSD__)
822          if (fh->is_floppy) {
823                  fsync(fh->fd);
452                //ioctl(fh->fd, FDFLUSH);
453                //ioctl(fh->fd, FDEJECT);
824          } else if (fh->is_cdrom) {
825                  ioctl(fh->fd, CDIOCEJECT);
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 485 | Line 877 | bool SysIsReadOnly(void *arg)
877          if (!fh)
878                  return true;
879  
880 < #ifdef __linux__
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 532 | Line 927 | bool SysIsDiskInserted(void *arg)
927          } else if (fh->is_floppy) {
928                  char block[512];
929                  lseek(fh->fd, 0, SEEK_SET);
930 <                return read(fh->fd, block, 512) == 512;
930 >                ssize_t actual = read(fh->fd, block, 512);
931 >                if (actual < 0) {
932 >                        close(fh->fd);  // Close and reopen so the driver will see the media change
933 >                        fh->fd = open(fh->name, fh->read_only ? O_RDONLY : O_RDWR);
934 >                        actual = read(fh->fd, block, 512);
935 >                }
936 >                return actual == 512;
937          } else if (fh->is_cdrom) {
938 + #ifdef CDROM_MEDIA_CHANGED
939 +                if (fh->cdrom_cap & CDC_MEDIA_CHANGED) {
940 +                        // If we don't do this, all attempts to read from a disc fail
941 +                        // once the tray has been opened (altough the TOC reads fine).
942 +                        // Can somebody explain this to me?
943 +                        if (ioctl(fh->fd, CDROM_MEDIA_CHANGED) == 1) {
944 +                                close(fh->fd);
945 +                                fh->fd = open(fh->name, O_RDONLY | O_NONBLOCK);
946 +                        }
947 +                }
948 + #endif
949   #ifdef CDROM_DRIVE_STATUS
950                  if (fh->cdrom_cap & CDC_DRIVE_STATUS) {
951                          return ioctl(fh->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT) == CDS_DISC_OK;
# Line 541 | Line 953 | bool SysIsDiskInserted(void *arg)
953   #endif
954                  cdrom_tochdr header;
955                  return ioctl(fh->fd, CDROMREADTOCHDR, &header) == 0;
956 < #elif defined(__FreeBSD__)
956 > #elif defined(__FreeBSD__) || defined(__NetBSD__)
957          } else if (fh->is_floppy) {
958                  return false;   //!!
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 581 | Line 996 | void SysAllowRemoval(void *arg)
996          if (!fh)
997                  return;
998  
999 < #ifdef defined(__linux__) && defined(CDROM_LOCKDOOR)
999 > #if defined(__linux__) && defined(CDROM_LOCKDOOR)
1000          if (fh->is_cdrom)
1001                  ioctl(fh->fd, CDROM_LOCKDOOR, 0);      
1002   #endif
# Line 598 | 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 645 | 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 691 | Line 1119 | bool SysCDReadTOC(void *arg, uint8 *toc)
1119                  *toc++ = toc_size >> 8;
1120                  *toc++ = toc_size & 0xff;
1121                  return true;
1122 + #elif defined(__NetBSD__)
1123 +                uint8 *p = toc + 2;
1124 +
1125 +                // Header
1126 +                struct ioc_toc_header header;
1127 +                if (ioctl(fh->fd, CDIOREADTOCHEADER, &header) < 0)
1128 +                        return false;
1129 +                *p++ = header.starting_track;
1130 +                *p++ = header.ending_track;
1131 +
1132 +                // Tracks (this is nice... :-)
1133 +                struct ioc_read_toc_entry entries;
1134 +                entries.address_format = CD_MSF_FORMAT;
1135 +                entries.starting_track = 1;
1136 +                entries.data_len = 800;
1137 +                entries.data = (cd_toc_entry *)p;
1138 +                if (ioctl(fh->fd, CDIOREADTOCENTRIES, &entries) < 0)
1139 +                        return false;
1140 +
1141 +                // TOC size
1142 +                int toc_size = p - toc;
1143 +                *toc++ = toc_size >> 8;
1144 +                *toc++ = toc_size & 0xff;
1145 +                return true;
1146 + #else
1147 +                return false;
1148   #endif
1149          } else
1150                  return false;
# Line 707 | 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 730 | Line 1191 | bool SysCDGetPosition(void *arg, uint8 *
1191                  *pos++ = chan.cdsc_reladdr.msf.second;
1192                  *pos++ = chan.cdsc_reladdr.msf.frame;
1193                  return true;
1194 < #elif defined(__FreeBSD__)
1194 > #elif defined(__FreeBSD__) || defined(__NetBSD__)
1195                  struct ioc_read_subchannel chan;
1196                  chan.data_format = CD_MSF_FORMAT;
1197                  chan.address_format = CD_MSF_FORMAT;
# Line 754 | Line 1215 | bool SysCDGetPosition(void *arg, uint8 *
1215                  *pos++ = chan.data->what.position.reladdr.msf.second;
1216                  *pos++ = chan.data->what.position.reladdr.msf.frame;
1217                  return true;
1218 + #else
1219 +                return false;
1220   #endif
1221          } else
1222                  return false;
# Line 770 | 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 780 | Line 1250 | bool SysCDPlay(void *arg, uint8 start_m,
1250                  play.cdmsf_sec1 = end_s;
1251                  play.cdmsf_frame1 = end_f;
1252                  return ioctl(fh->fd, CDROMPLAYMSF, &play) == 0;
1253 < #elif defined(__FreeBSD__)
1253 > #elif defined(__FreeBSD__) || defined(__NetBSD__)
1254                  struct ioc_play_msf play;
1255                  play.start_m = start_m;
1256                  play.start_s = start_s;
# Line 789 | Line 1259 | bool SysCDPlay(void *arg, uint8 start_m,
1259                  play.end_s = end_s;
1260                  play.end_f = end_f;
1261                  return ioctl(fh->fd, CDIOCPLAYMSF, &play) == 0;
1262 + #else
1263 +                return false;
1264   #endif
1265          } else
1266                  return false;
# Line 805 | 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;
1289 < #elif defined(__FreeBSD__)
1289 > #elif defined(__FreeBSD__) || defined(__NetBSD__)
1290                  return ioctl(fh->fd, CDIOCPAUSE) == 0;
1291 + #else
1292 +                return false;
1293   #endif
1294          } else
1295                  return false;
# Line 826 | 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;
1319 < #elif defined(__FreeBSD__)
1319 > #elif defined(__FreeBSD__) || defined(__NetBSD__)
1320                  return ioctl(fh->fd, CDIOCRESUME) == 0;
1321 + #else
1322 +                return false;
1323   #endif
1324          } else
1325                  return false;
# Line 847 | 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;
1349 < #elif defined(__FreeBSD__)
1349 > #elif defined(__FreeBSD__) || defined(__NetBSD__)
1350                  return ioctl(fh->fd, CDIOCSTOP) == 0;
1351 + #else
1352 +                return false;
1353   #endif
1354          } else
1355                  return false;
# Line 889 | Line 1387 | void SysCDSetVolume(void *arg, uint8 lef
1387                  vol.channel0 = vol.channel2 = left;
1388                  vol.channel1 = vol.channel3 = right;
1389                  ioctl(fh->fd, CDROMVOLCTRL, &vol);
1390 < #elif defined(__FreeBSD__)
1390 > #elif defined(__FreeBSD__) || defined(__NetBSD__)
1391                  struct ioc_vol vol;
1392                  vol.vol[0] = vol.vol[2] = left;
1393                  vol.vol[1] = vol.vol[3] = right;
# Line 916 | Line 1414 | void SysCDGetVolume(void *arg, uint8 &le
1414                  ioctl(fh->fd, CDROMVOLREAD, &vol);
1415                  left = vol.channel0;
1416                  right = vol.channel1;
1417 < #elif defined(__FreeBSD__)
1417 > #elif defined(__FreeBSD__) || defined(__NetBSD__)
1418                  struct ioc_vol vol;
1419                  ioctl(fh->fd, CDIOCGETVOL, &vol);
1420                  left = vol.vol[0];

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines