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