OSDN Git Service

ksmutils: ksminfo: Add option to display all KSM pages
[android-x86/system-extras.git] / fatblock / fatblock.c
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 "fatblock.h"
26 #include "fs.h"
27 #include "utils.h"
28
29 static struct fs fs;
30 static struct ublock_ctx *ub;
31 static int ums_lun = 0;
32
33 static int fs_import(struct fs *fs,
34                      uint16_t cluster_size, offset_t data_size,
35                      offset_t *total_size_out)
36 {
37         int ret;
38
39         ret = fs_init(fs, cluster_size, data_size, total_size_out);
40         if (ret)
41                 return ret;
42
43         ret = import_tree(fs, ".");
44         if (ret)
45                 return ret;
46
47         return 0;
48 }
49
50
51
52 static int read_callback(char *buf, uint64_t length, uint64_t offset)
53 {
54         int result;
55         int i;
56
57         result = fs_read(&fs, buf, offset, length);
58         if (result == SKY_IS_FALLING) {
59                 WARN("underlying filesystem has been modified; stopping.\n");
60                 ublock_stop(ub);
61         }
62
63         return result ? -EINVAL : 0;
64 }
65
66 static int write_callback(const char *buf, uint64_t length, uint64_t offset)
67 {
68         DEBUG("writing to (%llu, %llu): we are read-only\n", offset, length);
69
70         return -EINVAL;
71 }
72
73 static struct ublock_ops ops = {
74         .read = &read_callback,
75         .write = &write_callback
76 };
77
78
79
80 static int set_ums_file(int index)
81 {
82         char filename[PATH_MAX];
83         FILE *file;
84
85         sprintf(filename, "/sys/devices/platform/usb_mass_storage/lun%d/file",
86                 ums_lun);
87         file = fopen(filename, "w");
88         if (!file) {
89                 WARN("setting USB mass storage file: fopen(%s) failed: %s\n",
90                      filename, strerror(errno));
91                 return -1;
92         }
93
94         WARN("writing '/dev/block/ublock%d' to %s.\n", index, filename);
95
96         fprintf(file, "/dev/block/ublock%d", index);
97
98         fclose(file);
99
100         return 0;
101 }
102
103 static int clear_ums_file(void)
104 {
105         char filename[PATH_MAX];
106         FILE *file;
107
108         sprintf(filename, "/sys/devices/platform/usb_mass_storage/lun%d/file",
109                 ums_lun);
110         file = fopen(filename, "w");
111         if (!file) {
112                 WARN("clearing USB mass storage file: fopen(%s) failed: %s\n",
113                      filename, strerror(errno));
114                 return -1;
115         }
116
117         fclose(file);
118
119         return 0;
120 }
121
122
123
124
125 static void cleanup(void)
126 {
127         WARN("cleanup: clearing USB mass storage file\n");
128         clear_ums_file();
129         WARN("cleanup: destroying block device\n");
130         ublock_destroy(ub);
131 }
132
133 static void signal_handler(int sig)
134 {
135         WARN("received signal %d\n", sig);
136         cleanup();
137         exit(0);
138 }
139
140 static int normal_exit = 0;
141
142 static void atexit_handler(void)
143 {
144         if (normal_exit)
145                 return;
146
147         cleanup();
148 }
149
150 int main(int argc, char *argv[]) {
151         char *path;
152         int mb;
153         offset_t total_size;
154         int index;
155         int ret;
156
157         signal(SIGINT, &signal_handler);
158         signal(SIGTERM, &signal_handler);
159         atexit(&atexit_handler);
160
161         if (argc != 3)
162                 DIE("Usage: fatblock <path> <size in MB>\n");
163
164         path = argv[1];
165         mb = atoi(argv[2]);
166
167         INFO("fatblock: importing filesystem from %s (%d MB)\n", path, mb);
168
169         ret = chdir(path);
170         if (ret < 0)
171                 DIE("fatblock: chdir(%s) failed: %s; aborting\n", path, strerror(errno));
172
173         ret = fs_import(&fs, 32768, 1048576LL * mb, &total_size);
174         if (ret)
175                 DIE("fatblock: couldn't import filesystem; aborting\n");
176
177         INFO("fatblock: filesystem imported (%llu bytes)\n", total_size);
178
179         ret = ublock_init(&ub, &ops, total_size);
180         if (ret)
181                 DIE("fatblock: couldn't create block device; aborting\n");
182         index = ublock_index(ub);
183         if (index < 0)
184                 DIE("fatblock: invalid ublock index %d; aborting\n", index);
185
186         INFO("fatblock: block device ublock%d created\n", index);
187         set_ums_file(index);
188
189         INFO("fatblock: entering main loop\n");
190         ublock_run(ub);
191
192         INFO("fatblock: destroying block device\n");
193         clear_ums_file();
194         ublock_destroy(ub);
195
196         normal_exit = 1;
197
198         INFO("fatblock: goodbye!\n");
199         return 0;
200 }