17a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev/* 27a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev * Copyright (C) 2016 The Android Open Source Project 37a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev * 47a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev * Licensed under the Apache License, Version 2.0 (the "License"); 57a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev * you may not use this file except in compliance with the License. 67a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev * You may obtain a copy of the License at 77a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev * 87a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev * http://www.apache.org/licenses/LICENSE-2.0 97a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev * 107a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev * Unless required by applicable law or agreed to in writing, software 117a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev * distributed under the License is distributed on an "AS IS" BASIS, 127a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev * See the License for the specific language governing permissions and 147a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev * limitations under the License. 157a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev */ 167a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#include <errno.h> 177a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#include <fcntl.h> 187a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#include <inttypes.h> 197a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#include <stdbool.h> 207a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#include <stdlib.h> 217a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#include <string.h> 227a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#include <sys/stat.h> 237a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#include <sys/syscall.h> 247a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#include <sys/types.h> 257a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#include <unistd.h> 267a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 277a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#include "log.h" 287a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#include "ipc.h" 297a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#include "storage.h" 307a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 317a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#define FD_TBL_SIZE 64 327a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#define MAX_READ_SIZE 4096 337a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 347a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleevenum sync_state { 357a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev SS_UNUSED = -1, 367a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev SS_CLEAN = 0, 377a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev SS_DIRTY = 1, 387a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev}; 397a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 407a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleevstatic int ssdir_fd = -1; 417a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleevstatic const char *ssdir_name; 427a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 437a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleevstatic enum sync_state fs_state; 447a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleevstatic enum sync_state dir_state; 457a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleevstatic enum sync_state fd_state[FD_TBL_SIZE]; 467a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 477a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleevstatic struct { 487a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev struct storage_file_read_resp hdr; 497a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev uint8_t data[MAX_READ_SIZE]; 507a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev} read_rsp; 517a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 527a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleevstatic uint32_t insert_fd(int open_flags, int fd) 537a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev{ 547a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev uint32_t handle = fd; 557a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 567a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (open_flags & O_CREAT) { 577a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev dir_state = SS_DIRTY; 587a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 597a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 607a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (handle < FD_TBL_SIZE) { 617a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev fd_state[fd] = SS_CLEAN; /* fd clean */ 627a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (open_flags & O_TRUNC) { 637a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev fd_state[fd] = SS_DIRTY; /* set fd dirty */ 647a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 657a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } else { 667a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGW("%s: untracked fd %u\n", __func__, fd); 677a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (open_flags & (O_TRUNC | O_CREAT)) { 687a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev fs_state = SS_DIRTY; 697a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 707a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 717a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev return handle; 727a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev} 737a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 747a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleevstatic int lookup_fd(uint32_t handle, bool dirty) 757a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev{ 767a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (dirty) { 777a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (handle < FD_TBL_SIZE) { 787a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev fd_state[handle] = SS_DIRTY; 797a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } else { 807a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev fs_state = SS_DIRTY; 817a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 827a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 837a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev return handle; 847a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev} 857a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 867a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleevstatic int remove_fd(uint32_t handle) 877a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev{ 887a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (handle < FD_TBL_SIZE) { 897a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev fd_state[handle] = SS_UNUSED; /* set to uninstalled */ 907a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 917a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev return handle; 927a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev} 937a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 947a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleevstatic enum storage_err translate_errno(int error) 957a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev{ 967a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev enum storage_err result; 977a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev switch (error) { 987a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev case 0: 997a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev result = STORAGE_NO_ERROR; 1007a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev break; 1017a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev case EBADF: 1027a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev case EINVAL: 1037a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev case ENOTDIR: 1047a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev case EISDIR: 1057a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev case ENAMETOOLONG: 1067a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev result = STORAGE_ERR_NOT_VALID; 1077a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev break; 1087a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev case ENOENT: 1097a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev result = STORAGE_ERR_NOT_FOUND; 1107a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev break; 1117a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev case EEXIST: 1127a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev result = STORAGE_ERR_EXIST; 1137a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev break; 1147a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev case EPERM: 1157a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev case EACCES: 1167a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev result = STORAGE_ERR_ACCESS; 1177a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev break; 1187a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev default: 1197a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev result = STORAGE_ERR_GENERIC; 1207a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev break; 1217a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 1227a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 1237a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev return result; 1247a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev} 1257a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 1267a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleevstatic ssize_t write_with_retry(int fd, const void *buf_, size_t size, off_t offset) 1277a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev{ 1287a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ssize_t rc; 1297a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev const uint8_t *buf = buf_; 1307a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 1317a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev while (size > 0) { 1327a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev rc = TEMP_FAILURE_RETRY(pwrite(fd, buf, size, offset)); 1337a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (rc < 0) 1347a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev return rc; 1357a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev size -= rc; 1367a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev buf += rc; 1377a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev offset += rc; 1387a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 1397a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev return 0; 1407a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev} 1417a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 1427a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleevstatic ssize_t read_with_retry(int fd, void *buf_, size_t size, off_t offset) 1437a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev{ 1447a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ssize_t rc; 1457a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev size_t rcnt = 0; 1467a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev uint8_t *buf = buf_; 1477a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 1487a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev while (size > 0) { 1497a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev rc = TEMP_FAILURE_RETRY(pread(fd, buf, size, offset)); 1507a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (rc < 0) 1517a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev return rc; 1527a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (rc == 0) 1537a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev break; 1547a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev size -= rc; 1557a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev buf += rc; 1567a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev offset += rc; 1577a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev rcnt += rc; 1587a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 1597a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev return rcnt; 1607a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev} 1617a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 1627a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleevint storage_file_delete(struct storage_msg *msg, 1637a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev const void *r, size_t req_len) 1647a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev{ 1657a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev char *path = NULL; 1667a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev const struct storage_file_delete_req *req = r; 1677a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 1687a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (req_len < sizeof(*req)) { 1697a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGE("%s: invalid request length (%zd < %zd)\n", 1707a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev __func__, req_len, sizeof(*req)); 1717a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = STORAGE_ERR_NOT_VALID; 1727a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev goto err_response; 1737a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 1747a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 1757a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev size_t fname_len = strlen(req->name); 1767a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (fname_len != req_len - sizeof(*req)) { 1777a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGE("%s: invalid filename length (%zd != %zd)\n", 1787a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev __func__, fname_len, req_len - sizeof(*req)); 1797a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = STORAGE_ERR_NOT_VALID; 1807a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev goto err_response; 1817a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 1827a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 1837a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev int rc = asprintf(&path, "%s/%s", ssdir_name, req->name); 1847a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (rc < 0) { 1857a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGE("%s: asprintf failed\n", __func__); 1867a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = STORAGE_ERR_GENERIC; 1877a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev goto err_response; 1887a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 1897a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 1907a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev dir_state = SS_DIRTY; 1917a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev rc = unlink(path); 1927a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (rc < 0) { 1937a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev rc = errno; 1947a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (errno == ENOENT) { 1957a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGV("%s: error (%d) unlinking file '%s'\n", 1967a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev __func__, rc, path); 1977a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } else { 1987a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGE("%s: error (%d) unlinking file '%s'\n", 1997a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev __func__, rc, path); 2007a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 2017a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = translate_errno(rc); 2027a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev goto err_response; 2037a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 2047a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 2057a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGV("%s: \"%s\"\n", __func__, path); 2067a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = STORAGE_NO_ERROR; 2077a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 2087a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleeverr_response: 2097a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (path) 2107a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev free(path); 2117a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev return ipc_respond(msg, NULL, 0); 2127a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev} 2137a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 2147a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 2157a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleevint storage_file_open(struct storage_msg *msg, 2167a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev const void *r, size_t req_len) 2177a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev{ 2187a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev char *path = NULL; 2197a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev const struct storage_file_open_req *req = r; 2207a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev struct storage_file_open_resp resp = {0}; 2217a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 2227a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (req_len < sizeof(*req)) { 2237a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGE("%s: invalid request length (%zd < %zd)\n", 2247a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev __func__, req_len, sizeof(*req)); 2257a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = STORAGE_ERR_NOT_VALID; 2267a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev goto err_response; 2277a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 2287a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 2297a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev size_t fname_len = strlen(req->name); 2307a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (fname_len != req_len - sizeof(*req)) { 2317a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGE("%s: invalid filename length (%zd != %zd)\n", 2327a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev __func__, fname_len, req_len - sizeof(*req)); 2337a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = STORAGE_ERR_NOT_VALID; 2347a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev goto err_response; 2357a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 2367a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 2377a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev int rc = asprintf(&path, "%s/%s", ssdir_name, req->name); 2387a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (rc < 0) { 2397a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGE("%s: asprintf failed\n", __func__); 2407a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = STORAGE_ERR_GENERIC; 2417a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev goto err_response; 2427a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 2437a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 2447a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev int open_flags = O_RDWR; 2457a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 2467a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (req->flags & STORAGE_FILE_OPEN_TRUNCATE) 2477a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev open_flags |= O_TRUNC; 2487a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 2497a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (req->flags & STORAGE_FILE_OPEN_CREATE) { 2507a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev /* open or create */ 2517a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (req->flags & STORAGE_FILE_OPEN_CREATE_EXCLUSIVE) { 2527a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev /* create exclusive */ 2537a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev open_flags |= O_CREAT | O_EXCL; 2547a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev rc = TEMP_FAILURE_RETRY(open(path, open_flags, S_IRUSR | S_IWUSR)); 2557a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } else { 2567a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev /* try open first */ 2577a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev rc = TEMP_FAILURE_RETRY(open(path, open_flags, S_IRUSR | S_IWUSR)); 2587a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (rc == -1 && errno == ENOENT) { 2597a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev /* then try open with O_CREATE */ 2607a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev open_flags |= O_CREAT; 2617a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev rc = TEMP_FAILURE_RETRY(open(path, open_flags, S_IRUSR | S_IWUSR)); 2627a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 2637a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 2647a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 2657a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } else { 2667a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev /* open an existing file */ 2677a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev rc = TEMP_FAILURE_RETRY(open(path, open_flags, S_IRUSR | S_IWUSR)); 2687a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 2697a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 2707a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (rc < 0) { 2717a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev rc = errno; 2727a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (errno == EEXIST || errno == ENOENT) { 2737a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGV("%s: failed to open file \"%s\": %s\n", 2747a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev __func__, path, strerror(errno)); 2757a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } else { 2767a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGE("%s: failed to open file \"%s\": %s\n", 2777a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev __func__, path, strerror(errno)); 2787a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 2797a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = translate_errno(rc); 2807a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev goto err_response; 2817a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 2827a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev free(path); 2837a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 2847a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev /* at this point rc contains storage file fd */ 2857a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = STORAGE_NO_ERROR; 2867a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev resp.handle = insert_fd(open_flags, rc); 2877a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGV("%s: \"%s\": fd = %u: handle = %d\n", 2887a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev __func__, path, rc, resp.handle); 2897a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 2907a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev return ipc_respond(msg, &resp, sizeof(resp)); 2917a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 2927a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleeverr_response: 2937a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (path) 2947a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev free(path); 2957a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev return ipc_respond(msg, NULL, 0); 2967a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev} 2977a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 2987a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleevint storage_file_close(struct storage_msg *msg, 2997a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev const void *r, size_t req_len) 3007a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev{ 3017a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev const struct storage_file_close_req *req = r; 3027a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 3037a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (req_len != sizeof(*req)) { 3047a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGE("%s: invalid request length (%zd != %zd)\n", 3057a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev __func__, req_len, sizeof(*req)); 3067a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = STORAGE_ERR_NOT_VALID; 3077a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev goto err_response; 3087a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 3097a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 3107a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev int fd = remove_fd(req->handle); 3117a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGV("%s: handle = %u: fd = %u\n", __func__, req->handle, fd); 3127a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 3137a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev int rc = fsync(fd); 3147a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (rc < 0) { 3157a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev rc = errno; 3167a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGE("%s: fsync failed for fd=%u: %s\n", 3177a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev __func__, fd, strerror(errno)); 3187a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = translate_errno(rc); 3197a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev goto err_response; 3207a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 3217a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 3227a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev rc = close(fd); 3237a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (rc < 0) { 3247a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev rc = errno; 3257a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGE("%s: close failed for fd=%u: %s\n", 3267a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev __func__, fd, strerror(errno)); 3277a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = translate_errno(rc); 3287a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev goto err_response; 3297a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 3307a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 3317a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = STORAGE_NO_ERROR; 3327a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 3337a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleeverr_response: 3347a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev return ipc_respond(msg, NULL, 0); 3357a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev} 3367a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 3377a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 3387a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleevint storage_file_write(struct storage_msg *msg, 3397a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev const void *r, size_t req_len) 3407a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev{ 3417a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev int rc; 3427a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev const struct storage_file_write_req *req = r; 3437a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 3447a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (req_len < sizeof(*req)) { 3457a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGE("%s: invalid request length (%zd < %zd)\n", 3467a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev __func__, req_len, sizeof(*req)); 3477a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = STORAGE_ERR_NOT_VALID; 3487a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev goto err_response; 3497a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 3507a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 3517a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev int fd = lookup_fd(req->handle, true); 3527a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (write_with_retry(fd, &req->data[0], req_len - sizeof(*req), 3537a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev req->offset) < 0) { 3547a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev rc = errno; 3557a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGW("%s: error writing file (fd=%d): %s\n", 3567a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev __func__, fd, strerror(errno)); 3577a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = translate_errno(rc); 3587a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev goto err_response; 3597a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 3607a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 3617a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = STORAGE_NO_ERROR; 3627a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 3637a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleeverr_response: 3647a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev return ipc_respond(msg, NULL, 0); 3657a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev} 3667a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 3677a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 3687a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleevint storage_file_read(struct storage_msg *msg, 3697a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev const void *r, size_t req_len) 3707a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev{ 3717a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev int rc; 3727a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev const struct storage_file_read_req *req = r; 3737a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 3747a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (req_len != sizeof(*req)) { 3757a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGE("%s: invalid request length (%zd != %zd)\n", 3767a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev __func__, req_len, sizeof(*req)); 3777a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = STORAGE_ERR_NOT_VALID; 3787a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev goto err_response; 3797a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 3807a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 3817a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (req->size > MAX_READ_SIZE) { 3827a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGW("%s: request is too large (%zd > %zd) - refusing\n", 3837a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev __func__, req->size, MAX_READ_SIZE); 3847a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = STORAGE_ERR_NOT_VALID; 3857a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev goto err_response; 3867a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 3877a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 3887a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev int fd = lookup_fd(req->handle, false); 3897a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ssize_t read_res = read_with_retry(fd, read_rsp.hdr.data, req->size, 3907a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev (off_t)req->offset); 3917a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (read_res < 0) { 3927a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev rc = errno; 3937a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGW("%s: error reading file (fd=%d): %s\n", 3947a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev __func__, fd, strerror(errno)); 3957a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = translate_errno(rc); 3967a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev goto err_response; 3977a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 3987a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 3997a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = STORAGE_NO_ERROR; 4007a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev return ipc_respond(msg, &read_rsp, read_res + sizeof(read_rsp.hdr)); 4017a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 4027a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleeverr_response: 4037a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev return ipc_respond(msg, NULL, 0); 4047a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev} 4057a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 4067a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 4077a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleevint storage_file_get_size(struct storage_msg *msg, 4087a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev const void *r, size_t req_len) 4097a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev{ 4107a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev const struct storage_file_get_size_req *req = r; 4117a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev struct storage_file_get_size_resp resp = {0}; 4127a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 4137a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (req_len != sizeof(*req)) { 4147a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGE("%s: invalid request length (%zd != %zd)\n", 4157a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev __func__, req_len, sizeof(*req)); 4167a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = STORAGE_ERR_NOT_VALID; 4177a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev goto err_response; 4187a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 4197a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 4207a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev struct stat stat; 4217a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev int fd = lookup_fd(req->handle, false); 4227a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev int rc = fstat(fd, &stat); 4237a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (rc < 0) { 4247a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev rc = errno; 4257a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGE("%s: error stat'ing file (fd=%d): %s\n", 4267a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev __func__, fd, strerror(errno)); 4277a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = translate_errno(rc); 4287a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev goto err_response; 4297a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 4307a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 4317a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev resp.size = stat.st_size; 4327a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = STORAGE_NO_ERROR; 4337a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev return ipc_respond(msg, &resp, sizeof(resp)); 4347a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 4357a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleeverr_response: 4367a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev return ipc_respond(msg, NULL, 0); 4377a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev} 4387a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 4397a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 4407a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleevint storage_file_set_size(struct storage_msg *msg, 4417a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev const void *r, size_t req_len) 4427a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev{ 4437a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev const struct storage_file_set_size_req *req = r; 4447a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 4457a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (req_len != sizeof(*req)) { 4467a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGE("%s: invalid request length (%zd != %zd)\n", 4477a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev __func__, req_len, sizeof(*req)); 4487a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = STORAGE_ERR_NOT_VALID; 4497a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev goto err_response; 4507a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 4517a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 4527a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev int fd = lookup_fd(req->handle, true); 4537a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev int rc = TEMP_FAILURE_RETRY(ftruncate(fd, req->size)); 4547a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (rc < 0) { 4557a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev rc = errno; 4567a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGE("%s: error truncating file (fd=%d): %s\n", 4577a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev __func__, fd, strerror(errno)); 4587a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = translate_errno(rc); 4597a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev goto err_response; 4607a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 4617a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 4627a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = STORAGE_NO_ERROR; 4637a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 4647a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleeverr_response: 4657a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev return ipc_respond(msg, NULL, 0); 4667a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev} 4677a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 4687a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleevint storage_init(const char *dirname) 4697a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev{ 4707a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev fs_state = SS_CLEAN; 4717a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev dir_state = SS_CLEAN; 4727a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev for (uint i = 0; i < FD_TBL_SIZE; i++) { 4737a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev fd_state[i] = SS_UNUSED; /* uninstalled */ 4747a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 4757a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 4767a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ssdir_fd = open(dirname, O_RDONLY); 4777a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (ssdir_fd < 0) { 4787a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGE("failed to open ss root dir \"%s\": %s\n", 4797a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev dirname, strerror(errno)); 4807a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev return -1; 4817a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 4827a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ssdir_name = dirname; 4837a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev return 0; 4847a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev} 4857a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 4867a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleevint storage_sync_checkpoint(void) 4877a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev{ 4887a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev int rc; 4897a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 4907a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev /* sync fd table and reset it to clean state first */ 4917a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev for (uint fd = 0; fd < FD_TBL_SIZE; fd++) { 4927a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (fd_state[fd] == SS_DIRTY) { 4937a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (fs_state == SS_CLEAN) { 4947a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev /* need to sync individual fd */ 4957a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev rc = fsync(fd); 4967a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (rc < 0) { 4977a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGE("fsync for fd=%d failed: %s\n", fd, strerror(errno)); 4987a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev return rc; 4997a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 5007a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 5017a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev fd_state[fd] = SS_CLEAN; /* set to clean */ 5027a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 5037a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 5047a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 5057a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev /* check if we need to sync the directory */ 5067a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (dir_state == SS_DIRTY) { 5077a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (fs_state == SS_CLEAN) { 5087a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev rc = fsync(ssdir_fd); 5097a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (rc < 0) { 5107a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGE("fsync for ssdir failed: %s\n", strerror(errno)); 5117a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev return rc; 5127a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 5137a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 5147a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev dir_state = SS_CLEAN; /* set to clean */ 5157a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 5167a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 5177a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev /* check if we need to sync the whole fs */ 5187a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (fs_state == SS_DIRTY) { 5197a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev rc = syscall(SYS_syncfs, ssdir_fd); 5207a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (rc < 0) { 5217a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGE("syncfs failed: %s\n", strerror(errno)); 5227a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev return rc; 5237a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 5247a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev fs_state = SS_CLEAN; 5257a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 5267a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 5277a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev return 0; 5287a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev} 5297a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 530