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
diff --git a/CommandListener.cpp b/CommandListener.cpp
index fead4f8..b0fc551 100644
--- a/CommandListener.cpp
+++ b/CommandListener.cpp
@@ -41,7 +41,7 @@
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 @@
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 @@
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;
diff --git a/CommandListener.h b/CommandListener.h
index 23933bc..75c7e81 100644
--- a/CommandListener.h
+++ b/CommandListener.h
@@ -56,10 +56,10 @@
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);
};
diff --git a/Loop.cpp b/Loop.cpp
index 374cac0..2209f1a 100644
--- a/Loop.cpp
+++ b/Loop.cpp
@@ -38,7 +38,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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);
diff --git a/Volume.cpp b/Volume.cpp
index f43d375..f945b15 100644
--- a/Volume.cpp
+++ b/Volume.cpp
@@ -74,9 +74,9 @@
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)
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index 2127eab..2cdac70 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -253,6 +253,24 @@
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 @@
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 @@
/**
* 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 @@
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")) {
diff --git a/VolumeManager.h b/VolumeManager.h
index 31870e5..0619c73 100644
--- a/VolumeManager.h
+++ b/VolumeManager.h
@@ -75,8 +75,10 @@
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,