mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-11-23 04:33:24 +00:00
Partial implementation of sparsebundles; still needs Info.plist parsing
This commit is contained in:
parent
0c3516ef5a
commit
091db05aac
154
BasiliskII/src/Unix/disk_sparsebundle.cpp
Normal file
154
BasiliskII/src/Unix/disk_sparsebundle.cpp
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
* disk_sparsebundle.cpp - Apple sparse bundle implementation
|
||||||
|
*
|
||||||
|
* Basilisk II (C) Dave Vasilevsky
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "disk_unix.h"
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// - Factory needs to actually check stuff
|
||||||
|
// - Add to basilisk build
|
||||||
|
// - Add to 'make links'
|
||||||
|
|
||||||
|
typedef ssize_t (band_func)(int fd, void *buf, size_t len);
|
||||||
|
|
||||||
|
static ssize_t band_read(int fd, void *buf, size_t len) {
|
||||||
|
ssize_t err = (fd == -1 ? 0 : ::read(fd, buf, len));
|
||||||
|
if (err == -1)
|
||||||
|
return err;
|
||||||
|
if (err < len)
|
||||||
|
memset((char*)buf + err, 0, len - err);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t band_write(int fd, void *buf, size_t len) {
|
||||||
|
return ::write(fd, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct disk_sparsebundle : disk_generic {
|
||||||
|
disk_sparsebundle(char *bands, int fd, bool read_only, loff_t band_size,
|
||||||
|
loff_t total_size)
|
||||||
|
: token_fd(fd), read_only(read_only), band_size(band_size),
|
||||||
|
total_size(total_size), band_dir(bands), band_cur(-1), band_fd(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~disk_sparsebundle() {
|
||||||
|
if (band_fd)
|
||||||
|
close(band_fd);
|
||||||
|
close(token_fd);
|
||||||
|
free(band_dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool is_read_only() { return read_only; }
|
||||||
|
virtual loff_t size() { return total_size; }
|
||||||
|
|
||||||
|
virtual size_t read(void *buf, loff_t offset, size_t length) {
|
||||||
|
return band_do(&band_read, buf, offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual size_t write(void *buf, loff_t offset, size_t length) {
|
||||||
|
return band_do(&band_write, buf, offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int token_fd;
|
||||||
|
bool read_only;
|
||||||
|
loff_t band_size, total_size;
|
||||||
|
char *band_dir;
|
||||||
|
|
||||||
|
loff_t band_cur;
|
||||||
|
int band_fd;
|
||||||
|
|
||||||
|
size_t band_do(band_func func, void *buf, loff_t offset, size_t length) {
|
||||||
|
char *b = (char*)buf;
|
||||||
|
loff_t band = offset / band_size;
|
||||||
|
size_t done = 0;
|
||||||
|
while (length) {
|
||||||
|
if (!open_band(band))
|
||||||
|
break;
|
||||||
|
|
||||||
|
size_t start = offset % band_size;
|
||||||
|
size_t segment = band_size - start;
|
||||||
|
if (segment > length)
|
||||||
|
segment = length;
|
||||||
|
|
||||||
|
if (band_fd != -1 && lseek(band_fd, start, SEEK_SET) == -1)
|
||||||
|
return done;
|
||||||
|
ssize_t err = func(band_fd, buf, segment);
|
||||||
|
if (err > 0)
|
||||||
|
done += err;
|
||||||
|
if (err < segment)
|
||||||
|
break;
|
||||||
|
|
||||||
|
b += segment;
|
||||||
|
offset += segment;
|
||||||
|
length -= segment;
|
||||||
|
++band;
|
||||||
|
}
|
||||||
|
return done;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open band index 'band', return false on error
|
||||||
|
bool open_band(loff_t band) {
|
||||||
|
if (band_cur == band)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
char path[PATH_MAX + 1];
|
||||||
|
if (snprintf(path, PATH_MAX, "%s/%lx", band_dir,
|
||||||
|
(unsigned long)band) >= PATH_MAX) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int oflags = read_only ? O_RDONLY : (O_RDWR | O_CREAT);
|
||||||
|
band_fd = open(path, oflags, 0644);
|
||||||
|
if (band_fd == -1) {
|
||||||
|
if (read_only) {
|
||||||
|
band_cur == -1;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
band_cur = band;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
disk_generic *disk_sparsebundle_factory(const char *path, bool read_only) {
|
||||||
|
if (strstr(path, ".sparsebundle") == NULL)
|
||||||
|
return NULL; // FIXME: real test
|
||||||
|
|
||||||
|
// FIXME: actually read these
|
||||||
|
loff_t band_size = 1048576;
|
||||||
|
loff_t total_size = 53687091200;
|
||||||
|
|
||||||
|
// FIXME: check for double-mount, writable
|
||||||
|
int token = 0;
|
||||||
|
read_only = false;
|
||||||
|
|
||||||
|
char buf[PATH_MAX + 1];
|
||||||
|
if (snprintf(buf, PATH_MAX, "%s/%s", path, "bands") >= PATH_MAX)
|
||||||
|
return NULL;
|
||||||
|
char *bands = strdup(buf);
|
||||||
|
|
||||||
|
return new disk_sparsebundle(bands, token, read_only, band_size,
|
||||||
|
total_size);
|
||||||
|
}
|
40
BasiliskII/src/Unix/disk_unix.h
Normal file
40
BasiliskII/src/Unix/disk_unix.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* disk_unix.h - Generic disk interface
|
||||||
|
*
|
||||||
|
* Basilisk II (C) Dave Vasilevsky
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DISK_UNIX_H
|
||||||
|
#define DISK_UNIX_H
|
||||||
|
|
||||||
|
#include "sysdeps.h"
|
||||||
|
|
||||||
|
struct disk_generic {
|
||||||
|
disk_generic() { }
|
||||||
|
virtual ~disk_generic() { };
|
||||||
|
|
||||||
|
virtual bool is_read_only() = 0;
|
||||||
|
virtual size_t read(void *buf, loff_t offset, size_t length) = 0;
|
||||||
|
virtual size_t write(void *buf, loff_t offset, size_t length) = 0;
|
||||||
|
virtual loff_t size() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef disk_generic *(disk_factory)(const char *path, bool read_only);
|
||||||
|
|
||||||
|
extern disk_factory disk_sparsebundle_factory;
|
||||||
|
|
||||||
|
#endif
|
@ -56,6 +56,7 @@
|
|||||||
#include "prefs.h"
|
#include "prefs.h"
|
||||||
#include "user_strings.h"
|
#include "user_strings.h"
|
||||||
#include "sys.h"
|
#include "sys.h"
|
||||||
|
#include "disk_unix.h"
|
||||||
|
|
||||||
#if defined(BINCUE)
|
#if defined(BINCUE)
|
||||||
#include "bincue_unix.h"
|
#include "bincue_unix.h"
|
||||||
@ -83,6 +84,7 @@ struct mac_file_handle {
|
|||||||
loff_t file_size; // Size of file data (only valid if is_file is true)
|
loff_t file_size; // Size of file data (only valid if is_file is true)
|
||||||
|
|
||||||
bool is_media_present; // Flag: media is inserted and available
|
bool is_media_present; // Flag: media is inserted and available
|
||||||
|
disk_generic *generic_disk;
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
int cdrom_cap; // CD-ROM capability flags (only valid if is_cdrom is true)
|
int cdrom_cap; // CD-ROM capability flags (only valid if is_cdrom is true)
|
||||||
@ -525,6 +527,7 @@ static mac_file_handle *open_filehandle(const char *name)
|
|||||||
memset(fh, 0, sizeof(mac_file_handle));
|
memset(fh, 0, sizeof(mac_file_handle));
|
||||||
fh->name = strdup(name);
|
fh->name = strdup(name);
|
||||||
fh->fd = -1;
|
fh->fd = -1;
|
||||||
|
fh->generic_disk = NULL;
|
||||||
#if defined __MACOSX__
|
#if defined __MACOSX__
|
||||||
fh->ioctl_fd = -1;
|
fh->ioctl_fd = -1;
|
||||||
fh->ioctl_name = NULL;
|
fh->ioctl_name = NULL;
|
||||||
@ -615,6 +618,18 @@ void *Sys_open(const char *name, bool read_only)
|
|||||||
return fh;
|
return fh;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// FIXME
|
||||||
|
disk_generic *generic = disk_sparsebundle_factory(name, read_only);
|
||||||
|
if (generic) {
|
||||||
|
mac_file_handle *fh = open_filehandle(name);
|
||||||
|
fh->generic_disk = generic;
|
||||||
|
fh->file_size = generic->size();
|
||||||
|
fh->read_only = generic->is_read_only();
|
||||||
|
fh->is_media_present = true;
|
||||||
|
sys_add_mac_file_handle(fh);
|
||||||
|
return fh;
|
||||||
|
}
|
||||||
|
|
||||||
int open_flags = (read_only ? O_RDONLY : O_RDWR);
|
int open_flags = (read_only ? O_RDONLY : O_RDWR);
|
||||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__MACOSX__)
|
#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__MACOSX__)
|
||||||
@ -727,6 +742,8 @@ void Sys_close(void *arg)
|
|||||||
if (fh->is_bincue)
|
if (fh->is_bincue)
|
||||||
close_bincue(fh->bincue_fd);
|
close_bincue(fh->bincue_fd);
|
||||||
#endif
|
#endif
|
||||||
|
if (fh->generic_disk)
|
||||||
|
delete fh->generic_disk;
|
||||||
|
|
||||||
if (fh->is_cdrom)
|
if (fh->is_cdrom)
|
||||||
cdrom_close(fh);
|
cdrom_close(fh);
|
||||||
@ -759,6 +776,9 @@ size_t Sys_read(void *arg, void *buffer, loff_t offset, size_t length)
|
|||||||
return vhd_unix_read(fh->vhd_fd, buffer, offset, length);
|
return vhd_unix_read(fh->vhd_fd, buffer, offset, length);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (fh->generic_disk)
|
||||||
|
return fh->generic_disk->read(buffer, offset, length);
|
||||||
|
|
||||||
// Seek to position
|
// Seek to position
|
||||||
if (lseek(fh->fd, offset + fh->start_byte, SEEK_SET) < 0)
|
if (lseek(fh->fd, offset + fh->start_byte, SEEK_SET) < 0)
|
||||||
return 0;
|
return 0;
|
||||||
@ -784,6 +804,9 @@ size_t Sys_write(void *arg, void *buffer, loff_t offset, size_t length)
|
|||||||
return vhd_unix_write(fh->vhd_fd, buffer, offset, length);
|
return vhd_unix_write(fh->vhd_fd, buffer, offset, length);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (fh->generic_disk)
|
||||||
|
return fh->generic_disk->write(buffer, offset, length);
|
||||||
|
|
||||||
// Seek to position
|
// Seek to position
|
||||||
if (lseek(fh->fd, offset + fh->start_byte, SEEK_SET) < 0)
|
if (lseek(fh->fd, offset + fh->start_byte, SEEK_SET) < 0)
|
||||||
return 0;
|
return 0;
|
||||||
@ -813,6 +836,9 @@ loff_t SysGetFileSize(void *arg)
|
|||||||
return fh->file_size;
|
return fh->file_size;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (fh->generic_disk)
|
||||||
|
return fh->file_size;
|
||||||
|
|
||||||
if (fh->is_file)
|
if (fh->is_file)
|
||||||
return fh->file_size;
|
return fh->file_size;
|
||||||
else {
|
else {
|
||||||
@ -950,6 +976,9 @@ bool SysIsFixedDisk(void *arg)
|
|||||||
if (fh->is_vhd)
|
if (fh->is_vhd)
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (fh->generic_disk)
|
||||||
|
return true;
|
||||||
|
|
||||||
if (fh->is_file)
|
if (fh->is_file)
|
||||||
return true;
|
return true;
|
||||||
@ -975,6 +1004,9 @@ bool SysIsDiskInserted(void *arg)
|
|||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (fh->generic_disk)
|
||||||
|
return true;
|
||||||
|
|
||||||
if (fh->is_file) {
|
if (fh->is_file) {
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ SRCS = ../main.cpp main_unix.cpp ../prefs.cpp ../prefs_items.cpp prefs_unix.cpp
|
|||||||
../macos_util.cpp ../timer.cpp timer_unix.cpp ../xpram.cpp xpram_unix.cpp \
|
../macos_util.cpp ../timer.cpp timer_unix.cpp ../xpram.cpp xpram_unix.cpp \
|
||||||
../adb.cpp ../sony.cpp ../disk.cpp ../cdrom.cpp ../scsi.cpp \
|
../adb.cpp ../sony.cpp ../disk.cpp ../cdrom.cpp ../scsi.cpp \
|
||||||
../gfxaccel.cpp ../video.cpp video_blit.cpp ../audio.cpp ../ether.cpp ../thunks.cpp \
|
../gfxaccel.cpp ../video.cpp video_blit.cpp ../audio.cpp ../ether.cpp ../thunks.cpp \
|
||||||
../serial.cpp ../extfs.cpp \
|
../serial.cpp ../extfs.cpp disk_sparsebundle.cpp \
|
||||||
about_window_unix.cpp ../user_strings.cpp user_strings_unix.cpp \
|
about_window_unix.cpp ../user_strings.cpp user_strings_unix.cpp \
|
||||||
vm_alloc.cpp sigsegv.cpp rpc_unix.cpp \
|
vm_alloc.cpp sigsegv.cpp rpc_unix.cpp \
|
||||||
sshpty.c strlcpy.c $(SYSSRCS) $(CPUSRCS) $(MONSRCS) $(SLIRP_SRCS)
|
sshpty.c strlcpy.c $(SYSSRCS) $(CPUSRCS) $(MONSRCS) $(SLIRP_SRCS)
|
||||||
|
Loading…
Reference in New Issue
Block a user