1abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev/*
2abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev * Copyright (C) 2016 The Android Open Source Project
3abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev *
4abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev * Licensed under the Apache License, Version 2.0 (the "License");
5abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev * you may not use this file except in compliance with the License.
6abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev * You may obtain a copy of the License at
7abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev *
8abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev *      http://www.apache.org/licenses/LICENSE-2.0
9abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev *
10abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev * Unless required by applicable law or agreed to in writing, software
11abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev * distributed under the License is distributed on an "AS IS" BASIS,
12abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev * See the License for the specific language governing permissions and
14abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev * limitations under the License.
15abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev */
16abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
1766ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn#define LOG_TAG "trusty_storage_client"
1866ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn
19abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev#include <errno.h>
20abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev#include <stdarg.h>
21abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev#include <stdbool.h>
22abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev#include <stdint.h>
23abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev#include <string.h>
24abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev#include <sys/uio.h>
25abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
2630f991f251940be3ed11566fb71139852286f68aMark Salyzyn#include <log/log.h>
27abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev#include <trusty/tipc.h>
28abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev#include <trusty/lib/storage.h>
29abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
30abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev#define MAX_CHUNK_SIZE 4040
31abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
32abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleevstatic inline file_handle_t make_file_handle(storage_session_t s, uint32_t fid)
33abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev{
34abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    return ((uint64_t)s << 32) | fid;
35abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev}
36abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
37abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleevstatic inline storage_session_t _to_session(file_handle_t fh)
38abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev{
39abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    return (storage_session_t)(fh >> 32);
40abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev}
41abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
42abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleevstatic inline uint32_t _to_handle(file_handle_t fh)
43abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev{
44abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    return (uint32_t) fh;
45abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev}
46abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
47abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleevstatic inline uint32_t _to_msg_flags(uint32_t opflags)
48abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev{
49abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    uint32_t msg_flags = 0;
50abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
51abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    if (opflags & STORAGE_OP_COMPLETE)
52abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        msg_flags |= STORAGE_MSG_FLAG_TRANSACT_COMPLETE;
53abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
54abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    return msg_flags;
55abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev}
56abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
57abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleevstatic ssize_t check_response(struct storage_msg *msg, ssize_t res)
58abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev{
59abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    if (res < 0)
60abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        return res;
61abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
62abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    if ((size_t)res < sizeof(*msg)) {
63abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        ALOGE("invalid msg length (%zd < %zd)\n", res, sizeof(*msg));
64abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        return -EIO;
65abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    }
66abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
67abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    ALOGV("cmd 0x%x: server returned %u\n", msg->cmd, msg->result);
68abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
69abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    switch(msg->result) {
70abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        case STORAGE_NO_ERROR:
71abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev            return res - sizeof(*msg);
72abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
73abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        case STORAGE_ERR_NOT_FOUND:
74abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev            return -ENOENT;
75abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
76abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        case STORAGE_ERR_EXIST:
77abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev            return -EEXIST;
78abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
79abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        case STORAGE_ERR_NOT_VALID:
80abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev            return -EINVAL;
81abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
82abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        case STORAGE_ERR_UNIMPLEMENTED:
83abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev            ALOGE("cmd 0x%x: is unhandles command\n", msg->cmd);
84abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev            return -EINVAL;
85abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
86abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        case STORAGE_ERR_ACCESS:
87abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev             return -EACCES;
88abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
89abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        case STORAGE_ERR_TRANSACT:
90abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev             return -EBUSY;
91abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
92abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        case STORAGE_ERR_GENERIC:
93abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev            ALOGE("cmd 0x%x: internal server error\n", msg->cmd);
94abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev            return -EIO;
95abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
96abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        default:
97abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev            ALOGE("cmd 0x%x: unhandled server response %u\n",
98abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev                   msg->cmd, msg->result);
99abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    }
100abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
101abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    return -EIO;
102abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev}
103abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
104abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleevstatic ssize_t send_reqv(storage_session_t session,
105abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev                         const struct iovec *tx_iovs, uint tx_iovcnt,
106abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev                         const struct iovec *rx_iovs, uint rx_iovcnt)
107abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev{
108abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    ssize_t rc;
109abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
110abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    rc = writev(session, tx_iovs, tx_iovcnt);
111abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    if (rc < 0) {
112abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        rc = -errno;
113abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        ALOGE("failed to send request: %s\n", strerror(errno));
114abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        return rc;
115abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    }
116abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
117abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    rc = readv(session, rx_iovs, rx_iovcnt);
118abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    if (rc < 0) {
119abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        rc = -errno;
120abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        ALOGE("failed to recv response: %s\n", strerror(errno));
121abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        return rc;
122abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    }
123abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
124abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    return rc;
125abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev}
126abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
127abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleevint storage_open_session(const char *device, storage_session_t *session_p,
128abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev                         const char *port)
129abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev{
130abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    int rc = tipc_connect(device, port);
131abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    if (rc < 0)
132abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        return rc;
133abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    *session_p = (storage_session_t) rc;
134abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    return 0;
135abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev}
136abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
137abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleevvoid storage_close_session(storage_session_t session)
138abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev{
139abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    tipc_close(session);
140abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev}
141abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
142abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
143abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleevint storage_open_file(storage_session_t session, file_handle_t *handle_p, const char *name,
144abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev                      uint32_t flags, uint32_t opflags)
145abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev{
146abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct storage_msg msg = { .cmd = STORAGE_FILE_OPEN, .flags = _to_msg_flags(opflags)};
147abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct storage_file_open_req req = { .flags = flags };
148abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct iovec tx[3] = {{&msg, sizeof(msg)}, {&req, sizeof(req)}, {(void *)name, strlen(name)}};
149abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct storage_file_open_resp rsp = { 0 };
150abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct iovec rx[2] = {{&msg, sizeof(msg)}, {&rsp, sizeof(rsp)}};
151abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
152abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    ssize_t rc = send_reqv(session, tx, 3, rx, 2);
153abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    rc = check_response(&msg, rc);
154abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    if (rc < 0)
155abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        return rc;
156abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
157abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    if ((size_t)rc != sizeof(rsp)) {
158abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        ALOGE("%s: invalid response length (%zd != %zd)\n", __func__, rc, sizeof(rsp));
159abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        return -EIO;
160abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    }
161abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
162abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    *handle_p = make_file_handle(session, rsp.handle);
163abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    return 0;
164abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev}
165abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
166abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleevvoid storage_close_file(file_handle_t fh)
167abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev{
168abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct storage_msg msg = { .cmd = STORAGE_FILE_CLOSE };
169abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct storage_file_close_req req = { .handle = _to_handle(fh)};
170abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct iovec tx[2] = {{&msg, sizeof(msg)}, {&req, sizeof(req)}};
171abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct iovec rx[1] = {{&msg, sizeof(msg)}};
172abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
173abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    ssize_t rc = send_reqv(_to_session(fh), tx, 2, rx, 1);
174abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    rc = check_response(&msg, rc);
175abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    if (rc < 0) {
176abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        ALOGE("close file failed (%d)\n", (int)rc);
177abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    }
178abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev}
179abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
180abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleevint storage_delete_file(storage_session_t session, const char *name, uint32_t opflags)
181abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev{
182abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct storage_msg msg = { .cmd = STORAGE_FILE_DELETE, .flags = _to_msg_flags(opflags)};
183abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct storage_file_delete_req req = { .flags = 0, };
184abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct iovec tx[3] = {{&msg, sizeof(msg)}, {&req, sizeof(req)}, {(void *)name, strlen(name)}};
185abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct iovec rx[1] = {{&msg, sizeof(msg)}};
186abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
187abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    ssize_t rc = send_reqv(session, tx, 3, rx, 1);
188abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    return check_response(&msg, rc);
189abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev}
190abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
191abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleevstatic int _read_chunk(file_handle_t fh, storage_off_t off, void *buf, size_t size)
192abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev{
193abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct storage_msg msg = { .cmd = STORAGE_FILE_READ };
194abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct storage_file_read_req req = { .handle = _to_handle(fh), .size = size, .offset = off };
195abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct iovec tx[2] = {{&msg, sizeof(msg)}, {&req, sizeof(req)}};
196abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct iovec rx[2] = {{&msg, sizeof(msg)}, {buf, size}};
197abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
198abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    ssize_t rc = send_reqv(_to_session(fh), tx, 2, rx, 2);
199abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    return check_response(&msg, rc);
200abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev}
201abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
202abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleevssize_t storage_read(file_handle_t fh, storage_off_t off, void *buf, size_t size)
203abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev{
204abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    int rc;
205abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    size_t bytes_read = 0;
206abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    size_t chunk = MAX_CHUNK_SIZE;
207abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    uint8_t *ptr = buf;
208abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
209abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    while (size) {
210abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        if (chunk > size)
211abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev            chunk = size;
212abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        rc = _read_chunk(fh, off, ptr, chunk);
213abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        if (rc < 0)
214abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev            return rc;
215abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        if (rc == 0)
216abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev            break;
217abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        off += rc;
218abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        ptr += rc;
219abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        bytes_read += rc;
220abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        size -= rc;
221abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    }
222abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    return bytes_read;
223abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev}
224abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
225abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleevstatic int _write_req(file_handle_t fh, storage_off_t off,
226abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev                      const void *buf, size_t size, uint32_t msg_flags)
227abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev{
228abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct storage_msg msg = { .cmd = STORAGE_FILE_WRITE, .flags = msg_flags, };
229abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct storage_file_write_req req = { .handle = _to_handle(fh), .offset = off, };
230abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct iovec tx[3] = {{&msg, sizeof(msg)}, {&req, sizeof(req)}, {(void *)buf, size}};
231abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct iovec rx[1] = {{&msg, sizeof(msg)}};
232abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
233abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    ssize_t rc = send_reqv(_to_session(fh), tx, 3, rx, 1);
234abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    rc = check_response(&msg, rc);
235abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    return rc < 0 ? rc : size;
236abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev}
237abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
238abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleevssize_t storage_write(file_handle_t fh, storage_off_t off,
239abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev                      const void *buf, size_t size, uint32_t opflags)
240abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev{
241abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    int rc;
242abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    size_t bytes_written = 0;
243abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    size_t chunk = MAX_CHUNK_SIZE;
244abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    const uint8_t *ptr = buf;
245abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    uint32_t msg_flags = _to_msg_flags(opflags & ~STORAGE_OP_COMPLETE);
246abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
247abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    while (size) {
248abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        if (chunk >= size) {
249abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev            /* last chunk in sequence */
250abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev            chunk = size;
251abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev            msg_flags = _to_msg_flags(opflags);
252abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        }
253abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        rc = _write_req(fh, off, ptr, chunk, msg_flags);
254abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        if (rc < 0)
255abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev            return rc;
256abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        if ((size_t)rc != chunk) {
257abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev            ALOGE("got partial write (%d)\n", (int)rc);
258abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev            return -EIO;
259abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        }
260abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        off += chunk;
261abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        ptr += chunk;
262abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        bytes_written += chunk;
263abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        size -= chunk;
264abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    }
265abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    return bytes_written;
266abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev}
267abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
268abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleevint storage_set_file_size(file_handle_t fh, storage_off_t file_size, uint32_t opflags)
269abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev{
270abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct storage_msg msg = { .cmd = STORAGE_FILE_SET_SIZE, .flags = _to_msg_flags(opflags)};
271abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct storage_file_set_size_req req = { .handle = _to_handle(fh), .size = file_size, };
272abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct iovec tx[2] = {{&msg, sizeof(msg)}, {&req, sizeof(req)}};
273abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct iovec rx[1] = {{&msg, sizeof(msg)}};
274abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
275abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    ssize_t rc = send_reqv(_to_session(fh), tx, 2, rx, 1);
276abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    return check_response(&msg, rc);
277abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev}
278abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
279abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleevint storage_get_file_size(file_handle_t fh, storage_off_t *size_p)
280abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev{
281abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct storage_msg msg = { .cmd = STORAGE_FILE_GET_SIZE };
282abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct storage_file_get_size_req  req = { .handle = _to_handle(fh), };
283abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct iovec tx[2] = {{&msg, sizeof(msg)}, {&req, sizeof(req)}};
284abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct storage_file_get_size_resp rsp;
285abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct iovec rx[2] = {{&msg, sizeof(msg)}, {&rsp, sizeof(rsp)}};
286abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
287abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    ssize_t rc = send_reqv(_to_session(fh), tx, 2, rx, 2);
288abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    rc = check_response(&msg, rc);
289abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    if (rc < 0)
290abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        return rc;
291abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
292abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    if ((size_t)rc != sizeof(rsp)) {
293abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        ALOGE("%s: invalid response length (%zd != %zd)\n", __func__, rc, sizeof(rsp));
294abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        return -EIO;
295abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    }
296abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
297abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    *size_p = rsp.size;
298abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    return 0;
299abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev}
300abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
301abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleevint storage_end_transaction(storage_session_t session, bool complete)
302abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev{
303abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct storage_msg msg = {
304abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        .cmd = STORAGE_END_TRANSACTION,
305abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev        .flags = complete ? STORAGE_MSG_FLAG_TRANSACT_COMPLETE : 0,
306abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    };
307abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    struct iovec iov = {&msg, sizeof(msg)};
308abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev
309abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    ssize_t rc = send_reqv(session, &iov, 1, &iov, 1);
310abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev    return check_response(&msg, rc);
311abebb89359d7388fee8d1ca1411e2ae435dd3210Michael Ryleev}
312