mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-11-26 10:49:21 +00:00
Full sparsebundle implementation
This commit is contained in:
parent
091db05aac
commit
2a15911938
@ -19,13 +19,15 @@
|
||||
*/
|
||||
|
||||
#include "disk_unix.h"
|
||||
#include "tinyxml2.h"
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
// TODO
|
||||
// - Factory needs to actually check stuff
|
||||
// - Add to basilisk build
|
||||
// - Add to 'make links'
|
||||
// - Test on Linux
|
||||
// - Iterate through factories
|
||||
|
||||
typedef ssize_t (band_func)(int fd, void *buf, size_t len);
|
||||
|
||||
@ -132,23 +134,131 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
using tinyxml2::XML_NO_ERROR;
|
||||
using tinyxml2::XMLElement;
|
||||
|
||||
// Simplistic plist parser
|
||||
struct plist {
|
||||
plist() : doc(true, tinyxml2::COLLAPSE_WHITESPACE) { }
|
||||
|
||||
bool open(const char *path) {
|
||||
if (doc.LoadFile(path) != XML_NO_ERROR)
|
||||
return false;
|
||||
tinyxml2::XMLHandle hnd(&doc);
|
||||
dict = hnd.FirstChildElement("plist").FirstChildElement("dict")
|
||||
.ToElement();
|
||||
return dict;
|
||||
}
|
||||
|
||||
const char *str_val(const char *key) {
|
||||
return value(key, "string");
|
||||
}
|
||||
|
||||
bool int_val(const char *key, loff_t *i) {
|
||||
const char *v = value(key, "integer");
|
||||
if (!v || !*v)
|
||||
return false;
|
||||
|
||||
char *endp;
|
||||
long long ll = strtoll(v, &endp, 10);
|
||||
if (*endp)
|
||||
return false;
|
||||
*i = ll;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
tinyxml2::XMLDocument doc;
|
||||
XMLElement *dict;
|
||||
|
||||
const char *value(const char *key, const char *type) {
|
||||
// Assume it's a flat plist
|
||||
XMLElement *cur = dict->FirstChildElement();
|
||||
bool found_key = false;
|
||||
while (cur) {
|
||||
if (found_key) {
|
||||
if (strcmp(cur->Name(), type) != 0)
|
||||
return NULL;
|
||||
return cur->GetText();
|
||||
}
|
||||
found_key = strcmp(cur->Name(), "key") == 0
|
||||
&& strcmp(cur->GetText(), key) == 0;
|
||||
cur = cur->NextSiblingElement();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static int try_open(const char *path, bool read_only) {
|
||||
int oflags = (read_only ? O_RDONLY : O_RDWR);
|
||||
#if defined(__MACOSX__)
|
||||
oflags |= O_EXLOCK;
|
||||
#endif
|
||||
int fd = open(path, oflags);
|
||||
#if defined(__MACOSX__)
|
||||
if (fd == -1) {
|
||||
if (errno == EOPNOTSUPP) { // no locking support
|
||||
oflags &= ~O_EXLOCK;
|
||||
fd = open(path, oflags);
|
||||
} else if (errno == EAGAIN) { // already locked
|
||||
fprintf(stderr, "sparsebundle: Refusing to double-mount\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return fd;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
// Does it look like a sparsebundle?
|
||||
char buf[PATH_MAX + 1];
|
||||
if (snprintf(buf, PATH_MAX, "%s/%s", path, "Info.plist") >= PATH_MAX)
|
||||
return NULL;
|
||||
|
||||
plist pl;
|
||||
if (!pl.open(buf))
|
||||
return NULL;
|
||||
|
||||
const char *type;
|
||||
if (!(type = pl.str_val("diskimage-bundle-type")))
|
||||
return NULL;
|
||||
if (strcmp(type, "com.apple.diskimage.sparsebundle") != 0)
|
||||
return NULL;
|
||||
|
||||
|
||||
// Find the sparsebundle parameters
|
||||
loff_t version, band_size, total_size;
|
||||
if (!pl.int_val("bundle-backingstore-version", &version) || version != 1) {
|
||||
fprintf(stderr, "sparsebundle: Bad version\n");
|
||||
return NULL;
|
||||
}
|
||||
if (!pl.int_val("band-size", &band_size)
|
||||
|| !pl.int_val("size", &total_size)) {
|
||||
fprintf(stderr, "sparsebundle: Can't find size\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// Check if we can open it
|
||||
if (snprintf(buf, PATH_MAX, "%s/%s", path, "token") >= PATH_MAX)
|
||||
return NULL;
|
||||
int token = try_open(buf, read_only);
|
||||
if (token == -1 && !read_only) { // try again, read-only
|
||||
read_only = true;
|
||||
token = try_open(buf, read_only);
|
||||
}
|
||||
if (token == -1) {
|
||||
fprintf(stderr, "sparsebundle: Can't open the bundle\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// We're good to go!
|
||||
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);
|
||||
}
|
||||
|
2095
BasiliskII/src/Unix/tinyxml2.cpp
Executable file
2095
BasiliskII/src/Unix/tinyxml2.cpp
Executable file
File diff suppressed because it is too large
Load Diff
1968
BasiliskII/src/Unix/tinyxml2.h
Executable file
1968
BasiliskII/src/Unix/tinyxml2.h
Executable file
File diff suppressed because it is too large
Load Diff
@ -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 disk_sparsebundle.cpp \
|
||||
../serial.cpp ../extfs.cpp disk_sparsebundle.cpp tinyxml2.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