disk_generic: Distinguish between unknown disks, and unmountable disks

This commit is contained in:
Dave Vasilevsky 2013-03-11 17:08:27 -04:00
parent cdb0338883
commit c79a52f3b8
4 changed files with 42 additions and 26 deletions

View File

@ -255,39 +255,40 @@ static int try_open(const char *path, bool read_only, bool *locked) {
return fd;
}
disk_generic *disk_sparsebundle_factory(const char *path, bool read_only) {
disk_generic::status disk_sparsebundle_factory(const char *path,
bool read_only, disk_generic **disk) {
// 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;
return disk_generic::DISK_UNKNOWN;
plist pl;
if (!pl.open(buf))
return NULL;
return disk_generic::DISK_UNKNOWN;
const char *type;
if (!(type = pl.str_val("diskimage-bundle-type")))
return NULL;
return disk_generic::DISK_UNKNOWN;
if (strcmp(type, "com.apple.diskimage.sparsebundle") != 0)
return NULL;
return disk_generic::DISK_UNKNOWN;
// 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;
return disk_generic::DISK_UNKNOWN;
}
if (!pl.int_val("band-size", &band_size)
|| !pl.int_val("size", &total_size)) {
fprintf(stderr, "sparsebundle: Can't find size\n");
return NULL;
return disk_generic::DISK_INVALID;
}
// Check if we can open it
if (snprintf(buf, PATH_MAX, "%s/%s", path, "token") >= PATH_MAX)
return NULL;
return disk_generic::DISK_INVALID;
bool locked = false;
int token = try_open(buf, read_only, &locked);
if (token == -1 && !read_only) { // try again, read-only
@ -301,13 +302,14 @@ disk_generic *disk_sparsebundle_factory(const char *path, bool read_only) {
fprintf(stderr, "sparsebundle: Refusing to double-mount\n");
else
perror("sparsebundle: open failed:");
return NULL;
return disk_generic::DISK_INVALID;
}
// We're good to go!
if (snprintf(buf, PATH_MAX, "%s/%s", path, "bands") >= PATH_MAX)
return NULL;
return new disk_sparsebundle(buf, token, read_only, band_size,
return disk_generic::DISK_INVALID;
*disk = new disk_sparsebundle(buf, token, read_only, band_size,
total_size);
return disk_generic::DISK_VALID;
}

View File

@ -24,6 +24,12 @@
#include "sysdeps.h"
struct disk_generic {
enum status {
DISK_UNKNOWN,
DISK_INVALID,
DISK_VALID,
};
disk_generic() { }
virtual ~disk_generic() { };
@ -33,7 +39,8 @@ struct disk_generic {
virtual loff_t size() = 0;
};
typedef disk_generic *(disk_factory)(const char *path, bool read_only);
typedef disk_generic::status (disk_factory)(const char *path, bool read_only,
disk_generic **disk);
extern disk_factory disk_sparsebundle_factory;
extern disk_factory disk_vhd_factory;

View File

@ -604,8 +604,11 @@ void *Sys_open(const char *name, bool read_only)
for (disk_factory **f = disk_factories; *f; ++f) {
disk_generic *generic = (*f)(name, read_only);
if (generic) {
disk_generic *generic;
disk_generic::status st = (*f)(name, read_only, &generic);
if (st == disk_generic::DISK_INVALID)
return NULL;
if (st == disk_generic::DISK_VALID) {
mac_file_handle *fh = open_filehandle(name);
fh->generic_disk = generic;
fh->file_size = generic->size();

View File

@ -32,7 +32,8 @@ extern "C" {
#define DEBUG 0
#include "debug.h"
static void *vhd_unix_open(const char *name, int *size, bool read_only)
static disk_generic::status vhd_unix_open(const char *name, int *size,
bool read_only, vhd_context_t **ctx)
{
int amode = read_only ? R_OK : (R_OK | W_OK);
int fid;
@ -42,12 +43,12 @@ static void *vhd_unix_open(const char *name, int *size, bool read_only)
if (access(name, amode)) {
D(bug("vhd open -- incorrect permissions %s\n", name));
return NULL;
return disk_generic::DISK_UNKNOWN;
}
if (! (fid = open(name, O_RDONLY))) {
D(bug("vhd open -- couldn't open file %s\n", name));
return NULL;
return disk_generic::DISK_UNKNOWN;
}
else {
char buf[9];
@ -56,7 +57,7 @@ static void *vhd_unix_open(const char *name, int *size, bool read_only)
close(fid);
if (strcmp("conectix", buf) != 0) {
D(bug("vhd open -- not vhd magic = %s\n", buf));
return NULL;
return disk_generic::DISK_UNKNOWN;
}
if (vhd = (vhd_context_t *) malloc(sizeof(vhd_context_t))) {
int err;
@ -64,17 +65,18 @@ static void *vhd_unix_open(const char *name, int *size, bool read_only)
VHD_OPEN_RDONLY : VHD_OPEN_RDWR)) {
D(bug("vhd_open failed (%d)\n", err));
free(vhd);
return NULL;
return disk_generic::DISK_INVALID;
}
else {
*size = (int) vhd->footer.curr_size;
printf("VHD Open %s\n", name);
return (void *) vhd;
*ctx = vhd;
return disk_generic::DISK_VALID;
}
}
else {
D(bug("vhd open -- malloc failed\n"));
return NULL;
return disk_generic::DISK_INVALID;
}
}
}
@ -147,10 +149,12 @@ protected:
loff_t file_size;
};
disk_generic *disk_vhd_factory(const char *path, bool read_only) {
disk_generic::status disk_vhd_factory(const char *path,
bool read_only, disk_generic **disk) {
int size;
vhd_context_t *ctx = (vhd_context_t*)vhd_unix_open(path, &size, read_only);
if (!ctx)
return NULL;
return new disk_vhd(ctx, read_only, size);
vhd_context_t *ctx = NULL;
disk_generic::status st = vhd_unix_open(path, &size, read_only, &ctx);
if (st == disk_generic::DISK_VALID)
*disk = new disk_vhd(ctx, read_only, size);
return st;
}