mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-11-26 10:49:21 +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 "user_strings.h"
|
||||
#include "sys.h"
|
||||
#include "disk_unix.h"
|
||||
|
||||
#if defined(BINCUE)
|
||||
#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)
|
||||
|
||||
bool is_media_present; // Flag: media is inserted and available
|
||||
disk_generic *generic_disk;
|
||||
|
||||
#if defined(__linux__)
|
||||
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));
|
||||
fh->name = strdup(name);
|
||||
fh->fd = -1;
|
||||
fh->generic_disk = NULL;
|
||||
#if defined __MACOSX__
|
||||
fh->ioctl_fd = -1;
|
||||
fh->ioctl_name = NULL;
|
||||
@ -616,6 +619,18 @@ void *Sys_open(const char *name, bool read_only)
|
||||
}
|
||||
#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);
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__MACOSX__)
|
||||
open_flags |= (is_cdrom ? O_NONBLOCK : 0);
|
||||
@ -727,6 +742,8 @@ void Sys_close(void *arg)
|
||||
if (fh->is_bincue)
|
||||
close_bincue(fh->bincue_fd);
|
||||
#endif
|
||||
if (fh->generic_disk)
|
||||
delete fh->generic_disk;
|
||||
|
||||
if (fh->is_cdrom)
|
||||
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);
|
||||
#endif
|
||||
|
||||
if (fh->generic_disk)
|
||||
return fh->generic_disk->read(buffer, offset, length);
|
||||
|
||||
// Seek to position
|
||||
if (lseek(fh->fd, offset + fh->start_byte, SEEK_SET) < 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);
|
||||
#endif
|
||||
|
||||
if (fh->generic_disk)
|
||||
return fh->generic_disk->write(buffer, offset, length);
|
||||
|
||||
// Seek to position
|
||||
if (lseek(fh->fd, offset + fh->start_byte, SEEK_SET) < 0)
|
||||
return 0;
|
||||
@ -813,6 +836,9 @@ loff_t SysGetFileSize(void *arg)
|
||||
return fh->file_size;
|
||||
#endif
|
||||
|
||||
if (fh->generic_disk)
|
||||
return fh->file_size;
|
||||
|
||||
if (fh->is_file)
|
||||
return fh->file_size;
|
||||
else {
|
||||
@ -951,6 +977,9 @@ bool SysIsFixedDisk(void *arg)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
if (fh->generic_disk)
|
||||
return true;
|
||||
|
||||
if (fh->is_file)
|
||||
return true;
|
||||
else if (fh->is_floppy || fh->is_cdrom)
|
||||
@ -975,6 +1004,9 @@ bool SysIsDiskInserted(void *arg)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
if (fh->generic_disk)
|
||||
return true;
|
||||
|
||||
if (fh->is_file) {
|
||||
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 \
|
||||
../adb.cpp ../sony.cpp ../disk.cpp ../cdrom.cpp ../scsi.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 \
|
||||
vm_alloc.cpp sigsegv.cpp rpc_unix.cpp \
|
||||
sshpty.c strlcpy.c $(SYSSRCS) $(CPUSRCS) $(MONSRCS) $(SLIRP_SRCS)
|
||||
|
Loading…
Reference in New Issue
Block a user