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