void *Sys_open(const char *name, bool read_only) { static bool published_all = false; bool is_file = (strstr(name, "/dev/") != name); D(bug("Sys_open(%s, %s)\n", name, read_only ? "read-only" : "read/write")); // Print warning message and eventually unmount drive when this is an HFS volume mounted under BeOS (double mounting will corrupt the volume) char mount_name[B_FILE_NAME_LENGTH]; if (!is_file && !read_only && is_drive_mounted(name, mount_name)) { char str[256 + B_FILE_NAME_LENGTH]; sprintf(str, GetString(STR_VOLUME_IS_MOUNTED_WARN), mount_name); WarningAlert(str); #warning TODO: unmount disk! #if 0 if (unmount(mount_name) != 0) { sprintf(str, GetString(STR_CANNOT_UNMOUNT_WARN), mount_name); WarningAlert(str); return NULL; } #endif } int fd = open(name, read_only ? O_RDONLY : O_RDWR); if (fd < 0 && !published_all) { // Open failed, create all device nodes and try again, but only the first time system("mountvolume -publishall"); published_all = true; fd = open(name, read_only ? O_RDONLY : O_RDWR); } if (fd >= 0) { file_handle *fh = new file_handle; fh->name = strdup(name); fh->fd = fd; fh->is_file = is_file; fh->read_only = read_only; fh->start_byte = 0; if (fh->is_file) { // Detect disk image file layout loff_t size = lseek(fd, 0, SEEK_END); uint8 data[256]; lseek(fd, 0, SEEK_SET); read(fd, data, 256); FileDiskLayout(size, data, fh->start_byte, fh->file_size); } // Enqueue file handle fh->next = NULL; file_handle *q = first_file_handle; if (q) { while (q->next) q = q->next; q->next = fh; } else first_file_handle = fh; return fh; } else return NULL; }
void *Sys_open(const char *name, bool read_only) { bool is_file = strncmp(name, "/dev/", 5) != 0; #if defined(__FreeBSD__) // SCSI IDE bool is_cdrom = strncmp(name, "/dev/cd", 7) == 0 || strncmp(name, "/dev/acd", 8) == 0; #else bool is_cdrom = strncmp(name, "/dev/cd", 7) == 0; #endif bool is_floppy = strncmp(name, "/dev/fd", 7) == 0; bool is_polled_media = strncmp(name, "/dev/poll/", 10) == 0; if (is_floppy) // Floppy open fails if there's no disk inserted is_polled_media = true; #if defined __MACOSX__ // There is no set filename in /dev which is the cdrom, // so we have to see if it is any of the devices that we found earlier { int index = 0; const char *str; while ((str = PrefsFindString("cdrom", index++)) != NULL) { if (is_polled_media || strcmp(str, name) == 0) { is_cdrom = true; read_only = true; break; } } } #endif D(bug("Sys_open(%s, %s)\n", name, read_only ? "read-only" : "read/write")); // Check if write access is allowed, set read-only flag if not if (!read_only && access(name, W_OK)) read_only = true; // Print warning message and eventually unmount drive when this is an HFS volume mounted under Linux (double mounting will corrupt the volume) char mount_name[256]; if (!is_file && !read_only && is_drive_mounted(name, mount_name)) { char str[512]; sprintf(str, GetString(STR_VOLUME_IS_MOUNTED_WARN), mount_name); WarningAlert(str); sprintf(str, "umount %s", mount_name); if (system(str)) { sprintf(str, GetString(STR_CANNOT_UNMOUNT_WARN), mount_name, strerror(errno)); WarningAlert(str); return NULL; } } // Open file/device #if defined(BINCUE) void *binfd = open_bincue(name); if (binfd) { su_file_handle *fh = open_filehandle(name); D(bug("opening %s as bincue\n", name)); fh->bincue_fd = binfd; fh->is_bincue = true; fh->read_only = true; fh->is_media_present = true; sys_add_su_file_handle(fh); return fh; } #endif #if defined(HAVE_LIBVHD) int vhdsize; void *vhdfd = vhd_unix_open(name, &vhdsize, read_only); if (vhdfd) { su_file_handle *fh = open_filehandle(name); D(bug("opening %s as vnd\n", name)); fh->is_vhd = true; fh->vhd_fd = vhdfd; fh->read_only = read_only; fh->file_size = vhdsize; fh->is_media_present = true; sys_add_su_file_handle(fh); return fh; } #endif #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__MACOSX__) int fd = open(name, (read_only ? O_RDONLY : O_RDWR) | (is_cdrom ? O_NONBLOCK : 0)); #else int fd = open(name, read_only ? O_RDONLY : O_RDWR); #endif if (fd < 0 && !read_only) { // Read-write failed, try read-only read_only = true; fd = open(name, O_RDONLY); } if (fd >= 0 || is_polled_media) { su_file_handle *fh = open_filehandle(name); fh->fd = fd; fh->is_file = is_file; fh->read_only = read_only; fh->is_floppy = is_floppy; fh->is_cdrom = is_cdrom; if (fh->is_file) { fh->is_media_present = true; // Detect disk image file layout loff_t size = 0; size = lseek(fd, 0, SEEK_END); uint8 data[256]; lseek(fd, 0, SEEK_SET); read(fd, data, 256); FileDiskLayout(size, data, fh->start_byte, fh->file_size); } else { struct stat st; if (fstat(fd, &st) == 0) { fh->is_media_present = true; if (S_ISBLK(st.st_mode)) { fh->is_cdrom = is_cdrom; #if defined(__linux__) fh->is_floppy = (MAJOR(st.st_rdev) == FLOPPY_MAJOR); #ifdef CDROM_GET_CAPABILITY if (is_cdrom) { fh->cdrom_cap = ioctl(fh->fd, CDROM_GET_CAPABILITY); if (fh->cdrom_cap < 0) fh->cdrom_cap = 0; } #endif #elif defined(__FreeBSD__) fh->is_floppy = ((st.st_rdev >> 16) == 2); #ifdef CDIOCCAPABILITY if (is_cdrom) { if (ioctl(fh->fd, CDIOCCAPABILITY, &fh->cdrom_cap) < 0) memset(&fh->cdrom_cap, 0, sizeof(fh->cdrom_cap)); } #endif #elif defined(__NetBSD__) fh->is_floppy = ((st.st_rdev >> 16) == 2); #endif } #if defined __MACOSX__ if (is_cdrom) { fh->is_cdrom = true; fh->is_floppy = false; if (cdrom_open_1(fh)) fh->is_media_present = true; } #endif }