Additional Obb functionality
* Rename all functions dealing with OBB files to mention Obb * Add 'path' and 'list' functionality to OBB commands * Store hashed filename in loop's lo_crypt_name and keep lo_file_name for the real source filename. That way we can recover it later with an ioctl call. Change-Id: I29e468265988bfb931d981532d86d7be7b3adfc8
This commit is contained in:
parent
fb7c4d5a8a
commit
508c0e1605
6 changed files with 115 additions and 46 deletions
|
@ -41,7 +41,7 @@ CommandListener::CommandListener() :
|
|||
registerCmd(new DumpCmd());
|
||||
registerCmd(new VolumeCmd());
|
||||
registerCmd(new AsecCmd());
|
||||
registerCmd(new ImageCmd());
|
||||
registerCmd(new ObbCmd());
|
||||
registerCmd(new ShareCmd());
|
||||
registerCmd(new StorageCmd());
|
||||
registerCmd(new XwarpCmd());
|
||||
|
@ -398,11 +398,11 @@ int CommandListener::AsecCmd::runCommand(SocketClient *cli,
|
|||
return 0;
|
||||
}
|
||||
|
||||
CommandListener::ImageCmd::ImageCmd() :
|
||||
VoldCommand("image") {
|
||||
CommandListener::ObbCmd::ObbCmd() :
|
||||
VoldCommand("obb") {
|
||||
}
|
||||
|
||||
int CommandListener::ImageCmd::runCommand(SocketClient *cli,
|
||||
int CommandListener::ObbCmd::runCommand(SocketClient *cli,
|
||||
int argc, char **argv) {
|
||||
if (argc < 2) {
|
||||
cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
|
||||
|
@ -412,35 +412,51 @@ int CommandListener::ImageCmd::runCommand(SocketClient *cli,
|
|||
VolumeManager *vm = VolumeManager::Instance();
|
||||
int rc = 0;
|
||||
|
||||
if (!strcmp(argv[1], "mount")) {
|
||||
if (!strcmp(argv[1], "list")) {
|
||||
dumpArgs(argc, argv, -1);
|
||||
|
||||
rc = vm->listMountedObbs(cli);
|
||||
} else if (!strcmp(argv[1], "mount")) {
|
||||
dumpArgs(argc, argv, 3);
|
||||
if (argc != 5) {
|
||||
cli->sendMsg(ResponseCode::CommandSyntaxError,
|
||||
"Usage: image mount <filename> <key> <ownerUid>", false);
|
||||
"Usage: obb mount <filename> <key> <ownerUid>", false);
|
||||
return 0;
|
||||
}
|
||||
rc = vm->mountImage(argv[2], argv[3], atoi(argv[4]));
|
||||
rc = vm->mountObb(argv[2], argv[3], atoi(argv[4]));
|
||||
} else if (!strcmp(argv[1], "unmount")) {
|
||||
dumpArgs(argc, argv, -1);
|
||||
if (argc < 3) {
|
||||
cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: image unmount <container-id> [force]", false);
|
||||
cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: obb unmount <source file> [force]", false);
|
||||
return 0;
|
||||
}
|
||||
bool force = false;
|
||||
if (argc > 3 && !strcmp(argv[3], "force")) {
|
||||
force = true;
|
||||
}
|
||||
rc = vm->unmountImage(argv[2], force);
|
||||
rc = vm->unmountObb(argv[2], force);
|
||||
} else if (!strcmp(argv[1], "path")) {
|
||||
dumpArgs(argc, argv, -1);
|
||||
if (argc != 3) {
|
||||
cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: obb path <source file>", false);
|
||||
return 0;
|
||||
}
|
||||
char path[255];
|
||||
|
||||
if (!(rc = vm->getObbMountPath(argv[2], path, sizeof(path)))) {
|
||||
cli->sendMsg(ResponseCode::AsecPathResult, path, false);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
dumpArgs(argc, argv, -1);
|
||||
cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown image cmd", false);
|
||||
cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown obb cmd", false);
|
||||
}
|
||||
|
||||
if (!rc) {
|
||||
cli->sendMsg(ResponseCode::CommandOkay, "image operation succeeded", false);
|
||||
cli->sendMsg(ResponseCode::CommandOkay, "obb operation succeeded", false);
|
||||
} else {
|
||||
rc = ResponseCode::convertFromErrno();
|
||||
cli->sendMsg(rc, "image operation failed", true);
|
||||
cli->sendMsg(rc, "obb operation failed", true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -56,10 +56,10 @@ private:
|
|||
int runCommand(SocketClient *c, int argc, char ** argv);
|
||||
};
|
||||
|
||||
class ImageCmd : public VoldCommand {
|
||||
class ObbCmd : public VoldCommand {
|
||||
public:
|
||||
ImageCmd();
|
||||
virtual ~ImageCmd() {}
|
||||
ObbCmd();
|
||||
virtual ~ObbCmd() {}
|
||||
int runCommand(SocketClient *c, int argc, char ** argv);
|
||||
};
|
||||
|
||||
|
|
24
Loop.cpp
24
Loop.cpp
|
@ -38,7 +38,7 @@ int Loop::dumpState(SocketClient *c) {
|
|||
char filename[256];
|
||||
|
||||
for (i = 0; i < LOOP_MAX; i++) {
|
||||
struct loop_info li;
|
||||
struct loop_info64 li;
|
||||
int rc;
|
||||
|
||||
sprintf(filename, "/dev/block/loop%d", i);
|
||||
|
@ -52,7 +52,7 @@ int Loop::dumpState(SocketClient *c) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
rc = ioctl(fd, LOOP_GET_STATUS, &li);
|
||||
rc = ioctl(fd, LOOP_GET_STATUS64, &li);
|
||||
close(fd);
|
||||
if (rc < 0 && errno == ENXIO) {
|
||||
continue;
|
||||
|
@ -64,9 +64,10 @@ int Loop::dumpState(SocketClient *c) {
|
|||
return -1;
|
||||
}
|
||||
char *tmp = NULL;
|
||||
asprintf(&tmp, "%s %d %d:%d %lu %d:%d %d 0x%x {%s}", filename, li.lo_number,
|
||||
asprintf(&tmp, "%s %d %lld:%lld %llu %lld:%lld %lld 0x%x {%s} {%s}", filename, li.lo_number,
|
||||
MAJOR(li.lo_device), MINOR(li.lo_device), li.lo_inode, MAJOR(li.lo_rdevice),
|
||||
MINOR(li.lo_rdevice), li.lo_offset, li.lo_flags, li.lo_name);
|
||||
MINOR(li.lo_rdevice), li.lo_offset, li.lo_flags, li.lo_crypt_name,
|
||||
li.lo_file_name);
|
||||
c->sendMsg(0, tmp, false);
|
||||
free(tmp);
|
||||
}
|
||||
|
@ -81,7 +82,7 @@ int Loop::lookupActive(const char *id, char *buffer, size_t len) {
|
|||
memset(buffer, 0, len);
|
||||
|
||||
for (i = 0; i < LOOP_MAX; i++) {
|
||||
struct loop_info li;
|
||||
struct loop_info64 li;
|
||||
int rc;
|
||||
|
||||
sprintf(filename, "/dev/block/loop%d", i);
|
||||
|
@ -95,7 +96,7 @@ int Loop::lookupActive(const char *id, char *buffer, size_t len) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
rc = ioctl(fd, LOOP_GET_STATUS, &li);
|
||||
rc = ioctl(fd, LOOP_GET_STATUS64, &li);
|
||||
close(fd);
|
||||
if (rc < 0 && errno == ENXIO) {
|
||||
continue;
|
||||
|
@ -106,7 +107,7 @@ int Loop::lookupActive(const char *id, char *buffer, size_t len) {
|
|||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (!strncmp(li.lo_name, id, LO_NAME_SIZE)) {
|
||||
if (!strncmp((const char*) li.lo_crypt_name, id, LO_NAME_SIZE)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -148,7 +149,7 @@ int Loop::create(const char *id, const char *loopFile, char *loopDeviceBuffer, s
|
|||
return -1;
|
||||
}
|
||||
|
||||
rc = ioctl(fd, LOOP_GET_STATUS, &li);
|
||||
rc = ioctl(fd, LOOP_GET_STATUS64, &li);
|
||||
if (rc < 0 && errno == ENXIO)
|
||||
break;
|
||||
|
||||
|
@ -184,12 +185,13 @@ int Loop::create(const char *id, const char *loopFile, char *loopDeviceBuffer, s
|
|||
return -1;
|
||||
}
|
||||
|
||||
struct loop_info li;
|
||||
struct loop_info64 li;
|
||||
|
||||
memset(&li, 0, sizeof(li));
|
||||
strncpy(li.lo_name, id, LO_NAME_SIZE);
|
||||
strncpy((char*) li.lo_crypt_name, id, LO_NAME_SIZE);
|
||||
strncpy((char*) li.lo_file_name, loopFile, LO_NAME_SIZE);
|
||||
|
||||
if (ioctl(fd, LOOP_SET_STATUS, &li) < 0) {
|
||||
if (ioctl(fd, LOOP_SET_STATUS64, &li) < 0) {
|
||||
SLOGE("Error setting loopback status (%s)", strerror(errno));
|
||||
close(file_fd);
|
||||
close(fd);
|
||||
|
|
|
@ -74,9 +74,9 @@ const char *Volume::SEC_ASECDIR = "/mnt/secure/asec";
|
|||
const char *Volume::ASECDIR = "/mnt/asec";
|
||||
|
||||
/*
|
||||
* Path to where loop devices are mounted
|
||||
* Path to where OBBs are mounted
|
||||
*/
|
||||
const char *Volume::LOOPDIR = "/mnt/loop";
|
||||
const char *Volume::LOOPDIR = "/mnt/obb";
|
||||
|
||||
static const char *stateToStr(int state) {
|
||||
if (state == Volume::State_Init)
|
||||
|
|
|
@ -253,6 +253,24 @@ int VolumeManager::formatVolume(const char *label) {
|
|||
return v->formatVol();
|
||||
}
|
||||
|
||||
int VolumeManager::getObbMountPath(const char *sourceFile, char *mountPath, int mountPathLen) {
|
||||
char idHash[33];
|
||||
if (!asecHash(sourceFile, idHash, sizeof(idHash))) {
|
||||
SLOGE("Hash of '%s' failed (%s)", sourceFile, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(mountPath, 0, mountPathLen);
|
||||
snprintf(mountPath, mountPathLen, "%s/%s", Volume::LOOPDIR, idHash);
|
||||
|
||||
if (access(mountPath, F_OK)) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int VolumeManager::getAsecMountPath(const char *id, char *buffer, int maxlen) {
|
||||
char asecFileName[255];
|
||||
snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
|
||||
|
@ -523,7 +541,7 @@ int VolumeManager::unmountAsec(const char *id, bool force) {
|
|||
return unmountLoopImage(id, idHash, asecFileName, mountPoint, force);
|
||||
}
|
||||
|
||||
int VolumeManager::unmountImage(const char *fileName, bool force) {
|
||||
int VolumeManager::unmountObb(const char *fileName, bool force) {
|
||||
char mountPoint[255];
|
||||
|
||||
char idHash[33];
|
||||
|
@ -782,23 +800,9 @@ int VolumeManager::mountAsec(const char *id, const char *key, int ownerUid) {
|
|||
/**
|
||||
* Mounts an image file <code>img</code>.
|
||||
*/
|
||||
int VolumeManager::mountImage(const char *img, const char *key, int ownerUid) {
|
||||
int VolumeManager::mountObb(const char *img, const char *key, int ownerUid) {
|
||||
char mountPoint[255];
|
||||
|
||||
#if 0
|
||||
struct stat imgStat;
|
||||
if (stat(img, &imgStat) != 0) {
|
||||
SLOGE("Could not stat '%s': %s", img, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (imgStat.st_uid != ownerUid) {
|
||||
SLOGW("Image UID does not match requestor UID (%d != %d)",
|
||||
imgStat.st_uid, ownerUid);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
char idHash[33];
|
||||
if (!asecHash(img, idHash, sizeof(idHash))) {
|
||||
SLOGE("Hash of '%s' failed (%s)", img, strerror(errno));
|
||||
|
@ -908,6 +912,51 @@ int VolumeManager::mountVolume(const char *label) {
|
|||
return v->mountVol();
|
||||
}
|
||||
|
||||
int VolumeManager::listMountedObbs(SocketClient* cli) {
|
||||
char device[256];
|
||||
char mount_path[256];
|
||||
char rest[256];
|
||||
FILE *fp;
|
||||
char line[1024];
|
||||
|
||||
if (!(fp = fopen("/proc/mounts", "r"))) {
|
||||
SLOGE("Error opening /proc/mounts (%s)", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Create a string to compare against that has a trailing slash
|
||||
int loopDirLen = sizeof(Volume::LOOPDIR);
|
||||
char loopDir[loopDirLen + 2];
|
||||
strcpy(loopDir, Volume::LOOPDIR);
|
||||
loopDir[loopDirLen++] = '/';
|
||||
loopDir[loopDirLen] = '\0';
|
||||
|
||||
while(fgets(line, sizeof(line), fp)) {
|
||||
line[strlen(line)-1] = '\0';
|
||||
|
||||
/*
|
||||
* Should look like:
|
||||
* /dev/block/loop0 /mnt/obb/fc99df1323fd36424f864dcb76b76d65 ...
|
||||
*/
|
||||
sscanf(line, "%255s %255s %255s\n", device, mount_path, rest);
|
||||
|
||||
if (!strncmp(mount_path, loopDir, loopDirLen)) {
|
||||
int fd = open(device, O_RDONLY);
|
||||
if (fd >= 0) {
|
||||
struct loop_info64 li;
|
||||
if (ioctl(fd, LOOP_GET_STATUS64, &li) >= 0) {
|
||||
cli->sendMsg(ResponseCode::AsecListResult,
|
||||
(const char*) li.lo_file_name, false);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int VolumeManager::shareAvailable(const char *method, bool *avail) {
|
||||
|
||||
if (strcmp(method, "ums")) {
|
||||
|
|
|
@ -75,8 +75,10 @@ public:
|
|||
int getAsecMountPath(const char *id, char *buffer, int maxlen);
|
||||
|
||||
/* Loopback images */
|
||||
int mountImage(const char *fileName, const char *key, int ownerUid);
|
||||
int unmountImage(const char *fileName, bool force);
|
||||
int listMountedObbs(SocketClient* cli);
|
||||
int mountObb(const char *fileName, const char *key, int ownerUid);
|
||||
int unmountObb(const char *fileName, bool force);
|
||||
int getObbMountPath(const char *id, char *buffer, int maxlen);
|
||||
|
||||
/* Shared between ASEC and Loopback images */
|
||||
int unmountLoopImage(const char *containerId, const char *loopId,
|
||||
|
|
Loading…
Reference in a new issue