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