blob: 14328992bb0cfbf56afc7f4c6fa9588a443e76c7 [file] [log] [blame]
Doug Zongker945fc682014-07-10 10:50:39 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
Tom Marshall5b4a9d82018-12-17 15:57:44 -08003 * Copyright (C) 2019 The LineageOS Project
Doug Zongker945fc682014-07-10 10:50:39 -07004 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
Tao Bao91a7aa42017-05-01 15:57:38 -070018#include "fuse_sdcard_provider.h"
19
Doug Zongker945fc682014-07-10 10:50:39 -070020#include <errno.h>
Tao Bao91a7aa42017-05-01 15:57:38 -070021#include <fcntl.h>
Tom Marshallb4591eb2017-09-08 21:51:49 +000022#include <pthread.h>
Tao Bao91a7aa42017-05-01 15:57:38 -070023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
Doug Zongker945fc682014-07-10 10:50:39 -070026#include <sys/mount.h>
27#include <sys/stat.h>
Tom Marshall5b4a9d82018-12-17 15:57:44 -080028#include <sys/wait.h>
Doug Zongker945fc682014-07-10 10:50:39 -070029#include <unistd.h>
Tao Bao91a7aa42017-05-01 15:57:38 -070030
31#include <functional>
Doug Zongker945fc682014-07-10 10:50:39 -070032
Tianjie Xu71e182b2016-08-31 18:06:33 -070033#include <android-base/file.h>
34
Doug Zongker945fc682014-07-10 10:50:39 -070035#include "fuse_sideload.h"
36
37struct file_data {
Tao Bao91a7aa42017-05-01 15:57:38 -070038 int fd; // the underlying sdcard file
Doug Zongker945fc682014-07-10 10:50:39 -070039
Tao Bao91a7aa42017-05-01 15:57:38 -070040 uint64_t file_size;
41 uint32_t block_size;
Doug Zongker945fc682014-07-10 10:50:39 -070042};
43
Tao Bao91a7aa42017-05-01 15:57:38 -070044static int read_block_file(const file_data& fd, uint32_t block, uint8_t* buffer,
45 uint32_t fetch_size) {
46 off64_t offset = static_cast<off64_t>(block) * fd.block_size;
47 if (TEMP_FAILURE_RETRY(lseek64(fd.fd, offset, SEEK_SET)) == -1) {
48 fprintf(stderr, "seek on sdcard failed: %s\n", strerror(errno));
49 return -EIO;
50 }
Doug Zongker945fc682014-07-10 10:50:39 -070051
Tao Bao91a7aa42017-05-01 15:57:38 -070052 if (!android::base::ReadFully(fd.fd, buffer, fetch_size)) {
53 fprintf(stderr, "read on sdcard failed: %s\n", strerror(errno));
54 return -EIO;
55 }
Doug Zongker945fc682014-07-10 10:50:39 -070056
Tao Bao91a7aa42017-05-01 15:57:38 -070057 return 0;
Doug Zongker945fc682014-07-10 10:50:39 -070058}
59
Tom Marshallb4591eb2017-09-08 21:51:49 +000060struct token {
Tom Marshall5b4a9d82018-12-17 15:57:44 -080061 pid_t pid;
Tom Marshallb4591eb2017-09-08 21:51:49 +000062 const char* path;
63 int result;
64};
65
66static void* run_sdcard_fuse(void* cookie) {
67 token* t = reinterpret_cast<token*>(cookie);
68
Tao Bao91a7aa42017-05-01 15:57:38 -070069 struct stat sb;
Tom Marshallb4591eb2017-09-08 21:51:49 +000070 if (stat(t->path, &sb) < 0) {
71 fprintf(stderr, "failed to stat %s: %s\n", t->path, strerror(errno));
72 t->result = -1;
73 return nullptr;
Tao Bao91a7aa42017-05-01 15:57:38 -070074 }
Doug Zongker945fc682014-07-10 10:50:39 -070075
Tom Marshallb4591eb2017-09-08 21:51:49 +000076 struct file_data fd;
77 struct provider_vtab vtab;
78
79 fd.fd = open(t->path, O_RDONLY);
80 if (fd.fd < 0) {
81 fprintf(stderr, "failed to open %s: %s\n", t->path, strerror(errno));
82 t->result = -1;
83 return nullptr;
Tao Bao91a7aa42017-05-01 15:57:38 -070084 }
85 fd.file_size = sb.st_size;
86 fd.block_size = 65536;
Doug Zongker945fc682014-07-10 10:50:39 -070087
Tao Bao91a7aa42017-05-01 15:57:38 -070088 vtab.read_block = std::bind(&read_block_file, fd, std::placeholders::_1, std::placeholders::_2,
89 std::placeholders::_3);
90 vtab.close = [&fd]() { close(fd.fd); };
Doug Zongker945fc682014-07-10 10:50:39 -070091
Tom Marshallb4591eb2017-09-08 21:51:49 +000092 t->result = run_fuse_sideload(vtab, fd.file_size, fd.block_size);
93 return nullptr;
94}
95
96// How long (in seconds) we wait for the fuse-provided package file to
97// appear, before timing out.
98#define SDCARD_INSTALL_TIMEOUT 10
99
100void* start_sdcard_fuse(const char* path) {
101 token* t = new token;
102
103 t->path = path;
Tom Marshall5b4a9d82018-12-17 15:57:44 -0800104 if ((t->pid = fork()) < 0) {
105 free(t);
106 return nullptr;
107 }
108 if (t->pid == 0) {
109 run_sdcard_fuse(t);
110 _exit(0);
111 }
Tom Marshallb4591eb2017-09-08 21:51:49 +0000112
Tom Marshall5b4a9d82018-12-17 15:57:44 -0800113 time_t start_time = time(nullptr);
114 time_t now = start_time;
115
116 while (now - start_time < SDCARD_INSTALL_TIMEOUT) {
117 struct stat st;
118 if (stat(FUSE_SIDELOAD_HOST_PATHNAME, &st) == 0) {
119 break;
Tom Marshallb4591eb2017-09-08 21:51:49 +0000120 }
Tom Marshall5b4a9d82018-12-17 15:57:44 -0800121 if (errno != ENOENT && errno != ENOTCONN) {
122 free(t);
123 t = nullptr;
124 break;
125 }
126 sleep(1);
127 now = time(nullptr);
Tom Marshallb4591eb2017-09-08 21:51:49 +0000128 }
129
Tom Marshallb4591eb2017-09-08 21:51:49 +0000130 return t;
131}
132
133void finish_sdcard_fuse(void* cookie) {
134 if (cookie == NULL) return;
135 token* t = reinterpret_cast<token*>(cookie);
136
Tom Marshall5b4a9d82018-12-17 15:57:44 -0800137 kill(t->pid, SIGTERM);
138 int status;
139 waitpid(t->pid, &status, 0);
Tom Marshallb4591eb2017-09-08 21:51:49 +0000140
Tom Marshallb4591eb2017-09-08 21:51:49 +0000141 delete t;
Doug Zongker945fc682014-07-10 10:50:39 -0700142}