fatblock.c revision f79b2dff1024db4f6326f3422236bed169dd902f
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <assert.h> 18#include <errno.h> 19#include <stdint.h> 20#include <stdio.h> 21#include <unistd.h> 22 23#include <ublock/ublock.h> 24 25#include "errors.h" 26#include "import.h" 27#include "fs.h" 28#include "read.h" 29#include "utils.h" 30 31static struct fs fs; 32static struct ublock_ctx *ub; 33static int ums_lun = 0; 34 35static int fs_import(struct fs *fs, uint16_t cluster_size, offset_t data_size, offset_t *total_size_out) { 36 int ret; 37 38 ret = fs_init(fs, cluster_size, data_size, total_size_out); 39 if (ret) 40 return ret; 41 42 ret = import_tree(fs, "."); 43 if (ret) 44 return ret; 45 46 return 0; 47} 48 49 50 51static int read_callback(char *buf, uint64_t length, uint64_t offset) { 52 int result; 53 int i; 54 55 result = fs_read(&fs, buf, offset, length); 56 if (result == SKY_IS_FALLING) { 57 WARN("underlying filesystem has been modified; stopping.\n"); 58 ublock_stop(ub); 59 } 60 61 return result ? -EINVAL : 0; 62} 63 64static int write_callback(const char *buf, uint64_t length, uint64_t offset) { 65 DEBUG("writing to (%llu, %llu): we are read-only\n", offset, length); 66 67 return -EINVAL; 68} 69 70static struct ublock_ops ops = { 71 .read = &read_callback, 72 .write = &write_callback 73}; 74 75 76 77static int set_ums_file(int index) 78{ 79 char filename[PATH_MAX]; 80 FILE *file; 81 82 sprintf(filename, "/sys/devices/platform/usb_mass_storage/lun%d/file", ums_lun); 83 file = fopen(filename, "w"); 84 if (!file) { 85 WARN("setting USB mass storage file: fopen(%s) failed: %s\n", filename, strerror(errno)); 86 return -1; 87 } 88 89 WARN("writing '/dev/block/ublock%d' to %s.\n", index, filename); 90 91 fprintf(file, "/dev/block/ublock%d", index); 92 93 fclose(file); 94 95 return 0; 96} 97 98static int clear_ums_file(void) 99{ 100 char filename[PATH_MAX]; 101 FILE *file; 102 103 sprintf(filename, "/sys/devices/platform/usb_mass_storage/lun%d/file", ums_lun); 104 file = fopen(filename, "w"); 105 if (!file) { 106 WARN("clearing USB mass storage file: fopen(%s) failed: %s\n", filename, strerror(errno)); 107 return -1; 108 } 109 110 fclose(file); 111 112 return 0; 113} 114 115 116 117 118static void cleanup(void) 119{ 120 WARN("cleanup: clearing USB mass storage file\n"); 121 clear_ums_file(); 122 WARN("cleanup: destroying block device\n"); 123 ublock_destroy(ub); 124} 125 126static void signal_handler(int sig) 127{ 128 WARN("received signal %d\n", sig); 129 cleanup(); 130 exit(0); 131} 132 133static int normal_exit = 0; 134 135static void atexit_handler(void) 136{ 137 if (normal_exit) 138 return; 139 140 cleanup(); 141} 142 143int main(int argc, char *argv[]) { 144 char *path; 145 int mb; 146 offset_t total_size; 147 int index; 148 int ret; 149 150 signal(SIGINT, &signal_handler); 151 signal(SIGTERM, &signal_handler); 152 atexit(&atexit_handler); 153 154 if (argc != 3) 155 DIE("Usage: fatblock <path> <size in MB>\n"); 156 157 path = argv[1]; 158 mb = atoi(argv[2]); 159 160 INFO("fatblock: importing filesystem from %s (%d MB)\n", path, mb); 161 162 ret = chdir(path); 163 if (ret < 0) 164 DIE("fatblock: chdir(%s) failed: %s; aborting\n", path, strerror(errno)); 165 166 ret = fs_import(&fs, 32768, 1048576LL * mb, &total_size); 167 if (ret) 168 DIE("fatblock: couldn't import filesystem; aborting\n"); 169 170 INFO("fatblock: filesystem imported (%llu bytes)\n", total_size); 171 172 ret = ublock_init(&ub, &ops, total_size); 173 if (ret) 174 DIE("fatblock: couldn't create block device; aborting\n"); 175 index = ublock_index(ub); 176 if (index < 0) 177 DIE("fatblock: invalid ublock index %d; aborting\n", index); 178 179 INFO("fatblock: block device ublock%d created\n", index); 180 set_ums_file(index); 181 182 INFO("fatblock: entering main loop\n"); 183 ublock_run(ub); 184 185 INFO("fatblock: destroying block device\n"); 186 clear_ums_file(); 187 ublock_destroy(ub); 188 189 normal_exit = 1; 190 191 INFO("fatblock: goodbye!\n"); 192 return 0; 193} 194