Full sparsebundle implementation

This commit is contained in:
Dave Vasilevsky 2013-02-24 14:11:29 -05:00
parent 091db05aac
commit 2a15911938
4 changed files with 4187 additions and 14 deletions

View File

@ -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

File diff suppressed because it is too large Load Diff

1968
BasiliskII/src/Unix/tinyxml2.h Executable file

File diff suppressed because it is too large Load Diff

View File

@ -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)