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:
Kenny Root 2010-07-12 09:59:49 -07:00
parent fb7c4d5a8a
commit 508c0e1605
6 changed files with 115 additions and 46 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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