ASEC resize tweaking, allow read-write mounting.

Resize is no-op when sector count is unchanged; the caller can't
anticipate how vold does its sector calculations.

After resizing, we need to mount the container read-write, so allow
the caller to request "ro" or "rw" mode.

Handle ENOTSUP when trying to fallocate() on some filesystems

Bug: 16514385
Change-Id: I0d3a378280d4c36d14f8108ff428102283d583fa
diff --git a/CommandListener.cpp b/CommandListener.cpp
index 26d9b24..8003095 100644
--- a/CommandListener.cpp
+++ b/CommandListener.cpp
@@ -403,12 +403,16 @@
         rc = vm->destroyAsec(argv[2], force);
     } else if (!strcmp(argv[1], "mount")) {
         dumpArgs(argc, argv, 3);
-        if (argc != 5) {
+        if (argc != 6) {
             cli->sendMsg(ResponseCode::CommandSyntaxError,
-                    "Usage: asec mount <namespace-id> <key> <ownerUid>", false);
+                    "Usage: asec mount <namespace-id> <key> <ownerUid> <ro|rw>", false);
             return 0;
         }
-        rc = vm->mountAsec(argv[2], argv[3], atoi(argv[4]));
+        bool readOnly = true;
+        if (!strcmp(argv[5], "rw")) {
+            readOnly = false;
+        }
+        rc = vm->mountAsec(argv[2], argv[3], atoi(argv[4]), readOnly);
     } else if (!strcmp(argv[1], "unmount")) {
         dumpArgs(argc, argv, -1);
         if (argc < 3) {
diff --git a/Loop.cpp b/Loop.cpp
index 8672d93..11c114f 100644
--- a/Loop.cpp
+++ b/Loop.cpp
@@ -260,7 +260,7 @@
     SLOGD("Attempting to increase size of %s to %d sectors.", file, numSectors);
 
     if (fallocate(fd, 0, 0, numSectors * 512)) {
-        if (errno == ENOSYS) {
+        if (errno == ENOSYS || errno == ENOTSUP) {
             SLOGW("fallocate not found. Falling back to ftruncate.");
             if (ftruncate(fd, numSectors * 512) < 0) {
                 SLOGE("Error truncating imagefile (%s)", strerror(errno));
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index 06daf40..b2b0cf6 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -641,7 +641,10 @@
      *  add one block for the superblock
      */
     SLOGD("Resizing from %d sectors to %d sectors", oldNumSec, numImgSectors + 1);
-    if (oldNumSec >= numImgSectors + 1) {
+    if (oldNumSec == numImgSectors + 1) {
+        SLOGW("Size unchanged; ignoring resize request");
+        return 0;
+    } else if (oldNumSec > numImgSectors + 1) {
         SLOGE("Only growing is currently supported.");
         close(fd);
         return -1;
@@ -1249,7 +1252,7 @@
     return 0;
 }
 
-int VolumeManager::mountAsec(const char *id, const char *key, int ownerUid) {
+int VolumeManager::mountAsec(const char *id, const char *key, int ownerUid, bool readOnly) {
     char asecFileName[255];
     char mountPoint[255];
 
@@ -1330,9 +1333,9 @@
 
     int result;
     if (sb.c_opts & ASEC_SB_C_OPTS_EXT4) {
-        result = Ext4::doMount(dmDevice, mountPoint, true, false, true);
+        result = Ext4::doMount(dmDevice, mountPoint, readOnly, false, readOnly);
     } else {
-        result = Fat::doMount(dmDevice, mountPoint, true, false, true, ownerUid, 0, 0222, false);
+        result = Fat::doMount(dmDevice, mountPoint, readOnly, false, readOnly, ownerUid, 0, 0222, false);
     }
 
     if (result) {
diff --git a/VolumeManager.h b/VolumeManager.h
index 0d41b23..17fa6f7 100644
--- a/VolumeManager.h
+++ b/VolumeManager.h
@@ -106,7 +106,7 @@
      */
     int fixupAsecPermissions(const char *id, gid_t gid, const char* privateFilename);
     int destroyAsec(const char *id, bool force);
-    int mountAsec(const char *id, const char *key, int ownerUid);
+    int mountAsec(const char *id, const char *key, int ownerUid, bool readOnly);
     int unmountAsec(const char *id, bool force);
     int renameAsec(const char *id1, const char *id2);
     int getAsecMountPath(const char *id, char *buffer, int maxlen);