Merge "storageproxyd: Added support for getting max size of file"
diff --git a/trusty/storage/proxy/proxy.c b/trusty/storage/proxy/proxy.c
index b970406..4f77fa2 100644
--- a/trusty/storage/proxy/proxy.c
+++ b/trusty/storage/proxy/proxy.c
@@ -136,6 +136,10 @@
             rc = storage_file_set_size(msg, req, req_len);
             break;
 
+        case STORAGE_FILE_GET_MAX_SIZE:
+            rc = storage_file_get_max_size(msg, req, req_len);
+            break;
+
         case STORAGE_RPMB_SEND:
             rc = rpmb_send(msg, req, req_len);
             break;
diff --git a/trusty/storage/proxy/storage.c b/trusty/storage/proxy/storage.c
index 033dc21..a96ddcb 100644
--- a/trusty/storage/proxy/storage.c
+++ b/trusty/storage/proxy/storage.c
@@ -18,6 +18,7 @@
 #include <fcntl.h>
 #include <inttypes.h>
 #include <libgen.h>
+#include <linux/fs.h>
 #include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
@@ -36,6 +37,9 @@
 
 #define ALTERNATE_DATA_DIR "alternate/"
 
+/* Maximum file size for filesystem backed storage (i.e. not block dev backed storage) */
+#define MAX_FILE_SIZE (0x10000000000)
+
 enum sync_state {
     SS_UNUSED = -1,
     SS_CLEAN =  0,
@@ -549,6 +553,45 @@
     return ipc_respond(msg, NULL, 0);
 }
 
+int storage_file_get_max_size(struct storage_msg* msg, const void* r, size_t req_len) {
+    const struct storage_file_get_max_size_req* req = r;
+    struct storage_file_get_max_size_resp resp = {0};
+    uint64_t max_size = 0;
+
+    if (req_len != sizeof(*req)) {
+        ALOGE("%s: invalid request length (%zd != %zd)\n", __func__, req_len, sizeof(*req));
+        msg->result = STORAGE_ERR_NOT_VALID;
+        goto err_response;
+    }
+
+    struct stat stat;
+    int fd = lookup_fd(req->handle, false);
+    int rc = fstat(fd, &stat);
+    if (rc < 0) {
+        ALOGE("%s: error stat'ing file (fd=%d): %s\n", __func__, fd, strerror(errno));
+        goto err_response;
+    }
+
+    if ((stat.st_mode & S_IFMT) == S_IFBLK) {
+        rc = ioctl(fd, BLKGETSIZE64, &max_size);
+        if (rc < 0) {
+            rc = errno;
+            ALOGE("%s: error calling ioctl on file (fd=%d): %s\n", __func__, fd, strerror(errno));
+            msg->result = translate_errno(rc);
+            goto err_response;
+        }
+    } else {
+        max_size = MAX_FILE_SIZE;
+    }
+
+    resp.max_size = max_size;
+    msg->result = STORAGE_NO_ERROR;
+    return ipc_respond(msg, &resp, sizeof(resp));
+
+err_response:
+    return ipc_respond(msg, NULL, 0);
+}
+
 int storage_init(const char *dirname)
 {
     /* If there is an active DSU image, use the alternate fs mode. */
diff --git a/trusty/storage/proxy/storage.h b/trusty/storage/proxy/storage.h
index 5a670d4..77bfa13 100644
--- a/trusty/storage/proxy/storage.h
+++ b/trusty/storage/proxy/storage.h
@@ -39,6 +39,8 @@
 int storage_file_set_size(struct storage_msg *msg,
                           const void *req, size_t req_len);
 
+int storage_file_get_max_size(struct storage_msg* msg, const void* req, size_t req_len);
+
 int storage_init(const char *dirname);
 
 int storage_sync_checkpoint(void);