2
* aufs sample -- ULOOP driver
4
* Copyright (C) 2007 Junjiro Okajima
6
* This program, aufs is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
/* $Id: ulohttp.c,v 1.2 2007/11/26 01:35:40 sfjro Exp $ */
23
#include <linux/uloop.h>
34
#include <curl/curl.h>
36
static int timeout = 30;
37
static char *me, *g_url;
39
static char range[32];
40
static struct arg_for_curl {
47
#define Dbg(fmt, args...) printf("%s:%d:" fmt, __func__, __LINE__, ##args)
48
#define DbgErr(e) if (e) Dbg("err %d\n", e)
50
/* ---------------------------------------------------------------------- */
52
static int err_curl(CURLcode curle)
57
fprintf(stderr, "%s: %s\n", me, curl_easy_strerror(curle));
62
static size_t store_from_curl(void *got, size_t size, size_t nmemb, void *arg)
67
Dbg("size %u, nmemb %u, arg_for_curl->err %d\n",
68
size, nmemb, arg_for_curl.err);
70
if (!size || !nmemb || arg_for_curl.err)
73
real_bytes = size * nmemb;
74
if (arg_for_curl.size < arg_for_curl.written + real_bytes) {
79
memcpy(arg_for_curl.p, got, real_bytes);
80
arg_for_curl.written += real_bytes;
81
arg_for_curl.p += real_bytes;
85
static int store(unsigned long long start, int size, void *arg)
90
unsigned long long m, tsize;
93
//Dbg("start %Lu, size %d\n", start, size);
94
assert(start + size <= uloop->cache_size);
96
m = start % uloop->pagesize;
98
arg_for_curl.size = size + m;
99
tsize = uloop->tgt_size;
100
if (tsize < start + arg_for_curl.size)
101
arg_for_curl.size = tsize - start;
102
o = mmap(NULL, arg_for_curl.size, PROT_WRITE, MAP_SHARED, ulo_cache_fd,
107
arg_for_curl.written = 0;
108
arg_for_curl.err = 0;
110
snprintf(range, sizeof(range) - 1, "%Lu-%Lu",
111
start, start + arg_for_curl.size - 1);
112
curle = curl_easy_perform(ezcurl);
114
assert(arg_for_curl.written == arg_for_curl.size);
115
err = munmap(o, arg_for_curl.size);
116
if (curle != CURLE_OK)
117
return err_curl(curle);
123
/* ---------------------------------------------------------------------- */
125
static unsigned long long get_size(void)
127
unsigned long long size;
130
const int hsz = 1024;
132
size = ULONG_MAX; /* error */
133
header = malloc(hsz);
136
arg_for_curl.p = header;
137
arg_for_curl.size = hsz;
138
arg_for_curl.written = 0;
139
arg_for_curl.err = 0;
141
curle = curl_easy_setopt(ezcurl, CURLOPT_HEADERFUNCTION,
143
if (curle == CURLE_OK)
144
curle = curl_easy_setopt(ezcurl, CURLOPT_RANGE, "0-1");
146
if (curle == CURLE_OK)
147
curle = curl_easy_setopt(ezcurl, CURLOPT_WRITEHEADER,
150
if (curle == CURLE_OK)
151
curle = curl_easy_perform(ezcurl);
152
if (curle != CURLE_OK) {
156
if (arg_for_curl.err) {
157
fprintf(stderr, "%s: internal error.\n", me);
162
//Dbg("%s\n", header);
163
p = strstr(header, "Content-Range: bytes ");
167
fprintf(stderr, "%s: no range header, %s\n", me, g_url);
171
size = strtoull(p + 1, NULL, 10);
175
curle = curl_easy_setopt(ezcurl, CURLOPT_HEADERFUNCTION, NULL);
176
if (curle == CURLE_OK)
177
curle = curl_easy_setopt(ezcurl, CURLOPT_RANGE, NULL);
178
if (curle == CURLE_OK)
179
curle = curl_easy_setopt(ezcurl, CURLOPT_WRITEHEADER, NULL);
180
if (curle == CURLE_OK)
181
return size; /* success */
184
return ULONG_MAX; /* error */
187
static unsigned long long init_curl_and_size(void)
189
unsigned long long sz;
194
ezcurl = curl_easy_init();
198
curle = curl_easy_setopt(ezcurl, CURLOPT_URL, g_url);
199
if (curle == CURLE_OK)
200
curle = curl_easy_setopt(ezcurl, CURLOPT_TIMEOUT, timeout);
202
if (curle == CURLE_OK)
203
curle = curl_easy_setopt(ezcurl, CURLOPT_VERBOSE, 1);
206
if (curle == CURLE_OK)
207
curle = curl_easy_setopt(ezcurl, CURLOPT_NOPROGRESS, 1);
208
if (curle == CURLE_OK)
209
curle = curl_easy_setopt(ezcurl, CURLOPT_FAILONERROR, 1);
211
if (curle != CURLE_OK)
219
curle = curl_easy_setopt(ezcurl, CURLOPT_WRITEFUNCTION,
222
if (curle == CURLE_OK)
223
curle = curl_easy_setopt(ezcurl, CURLOPT_WRITEDATA,
226
if (curle == CURLE_OK)
227
curle = curl_easy_setopt(ezcurl, CURLOPT_RANGE, range);
228
if (curle == CURLE_OK)
236
/* ---------------------------------------------------------------------- */
238
static int init(struct ulo_init *init_args)
242
init_args->size = init_curl_and_size();
243
err = init_args->size;
245
err = ulo_init(init_args);
249
static void usage(void)
255
" /dev/loopN url_for_fs_image_file\n"
256
"and then, \"mount /dev/loopN /wherever/you/like\n",
261
static int parse(int argc, char *argv[], struct ulo_init *init_args)
264
static char bitmap_def[] = "/tmp/123456.bitmap",
265
cache_def[] = "/tmp/123456.cache";
267
while ((opt = getopt(argc, argv, "b:c:t:")) != -1) {
270
init_args->path[ULO_BITMAP] = optarg;
273
init_args->path[ULO_CACHE] = optarg;
277
timeout = strtol(optarg, NULL, 0);
289
if (argc - optind != 2) {
294
init_args->path[ULO_DEV] = argv[optind];
295
g_url = argv[optind + 1];
297
if (!init_args->path[ULO_CACHE]) {
298
snprintf(cache_def, sizeof(cache_def) - 1, "/tmp/%d.cache",
300
init_args->path[ULO_CACHE] = cache_def;
302
if (!init_args->path[ULO_BITMAP]) {
303
snprintf(bitmap_def, sizeof(bitmap_def) - 1, "/tmp/%d.bitmap",
305
init_args->path[ULO_BITMAP] = bitmap_def;
308
//Dbg("to %d, %s\n", timeout, g_url);
312
/* ---------------------------------------------------------------------- */
314
int main(int argc, char *argv[])
318
struct ulo_init init_args = {
319
.dev_flags = O_RDONLY
323
err = parse(argc, argv, &init_args);
325
err = init(&init_args);
329
err = ulo_loop(SIGUSR1, store, ezcurl);
330
curl_easy_cleanup(ezcurl);