~ubuntu-branches/ubuntu/vivid/aufs/vivid

« back to all changes in this revision

Viewing changes to sample/uloop/ulohttp.c

  • Committer: Bazaar Package Importer
  • Author(s): Julian Andres Klode
  • Date: 2007-12-15 23:32:51 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20071215233251-2vgs2lmg8mai5d9e
Tags: 0+20071211-1ubuntu1
* Merge from debian unstable (LP: #175705), remaining changes:
  - Fix for Ubuntu Kernels (updated)
* patches/01_vserver.dpatch: Removed
* patches/06_ubuntu.dpatch: Added (update of ubuntu patch)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * aufs sample -- ULOOP driver
 
3
 *
 
4
 * Copyright (C) 2007 Junjiro Okajima
 
5
 *
 
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.
 
10
 *
 
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.
 
15
 *
 
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
 
19
 */
 
20
 
 
21
/* $Id: ulohttp.c,v 1.2 2007/11/26 01:35:40 sfjro Exp $ */
 
22
 
 
23
#include <linux/uloop.h>
 
24
#include <sys/mman.h>
 
25
#include <assert.h>
 
26
#include <errno.h>
 
27
#include <fcntl.h>
 
28
#include <getopt.h>
 
29
#include <signal.h>
 
30
#include <stdlib.h>
 
31
#include <string.h>
 
32
#include <unistd.h>
 
33
 
 
34
#include <curl/curl.h>
 
35
 
 
36
static int timeout = 30;
 
37
static char *me, *g_url;
 
38
static CURL *ezcurl;
 
39
static char range[32];
 
40
static struct arg_for_curl {
 
41
        char    *p;
 
42
        int     written;
 
43
        int     size;
 
44
        int     err;
 
45
} arg_for_curl;
 
46
 
 
47
#define Dbg(fmt, args...) printf("%s:%d:" fmt, __func__, __LINE__, ##args)
 
48
#define DbgErr(e) if (e) Dbg("err %d\n", e)
 
49
 
 
50
/* ---------------------------------------------------------------------- */
 
51
 
 
52
static int err_curl(CURLcode curle)
 
53
{
 
54
        int e;
 
55
 
 
56
        e = errno;
 
57
        fprintf(stderr, "%s: %s\n", me, curl_easy_strerror(curle));
 
58
        me = NULL;
 
59
        return e;
 
60
}
 
61
 
 
62
static size_t store_from_curl(void *got, size_t size, size_t nmemb, void *arg)
 
63
{
 
64
        int real_bytes;
 
65
 
 
66
#if 0
 
67
        Dbg("size %u, nmemb %u, arg_for_curl->err %d\n",
 
68
            size, nmemb, arg_for_curl.err);
 
69
#endif
 
70
        if (!size || !nmemb || arg_for_curl.err)
 
71
                return 0;
 
72
 
 
73
        real_bytes = size * nmemb;
 
74
        if (arg_for_curl.size < arg_for_curl.written + real_bytes) {
 
75
                arg_for_curl.err++;
 
76
                return 0;
 
77
        }
 
78
 
 
79
        memcpy(arg_for_curl.p, got, real_bytes);
 
80
        arg_for_curl.written += real_bytes;
 
81
        arg_for_curl.p += real_bytes;
 
82
        return nmemb;
 
83
}
 
84
 
 
85
static int store(unsigned long long start, int size, void *arg)
 
86
{
 
87
        CURL *ezcurl = arg;
 
88
        CURLcode curle;
 
89
        int err;
 
90
        unsigned long long m, tsize;
 
91
        char *o;
 
92
 
 
93
        //Dbg("start %Lu, size %d\n", start, size);
 
94
        assert(start + size <= uloop->cache_size);
 
95
 
 
96
        m = start % uloop->pagesize;
 
97
        start -= m;
 
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,
 
103
                 start);
 
104
        if (o == MAP_FAILED)
 
105
                return -1;
 
106
        arg_for_curl.p = o;
 
107
        arg_for_curl.written = 0;
 
108
        arg_for_curl.err = 0;
 
109
 
 
110
        snprintf(range, sizeof(range) - 1, "%Lu-%Lu",
 
111
                 start, start + arg_for_curl.size - 1);
 
112
        curle = curl_easy_perform(ezcurl);
 
113
 
 
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);
 
118
        if (!err)
 
119
                return 0;
 
120
        return err;
 
121
}
 
122
 
 
123
/* ---------------------------------------------------------------------- */
 
124
 
 
125
static unsigned long long get_size(void)
 
126
{
 
127
        unsigned long long size;
 
128
        CURLcode curle;
 
129
        char *header, *p;
 
130
        const int hsz = 1024;
 
131
 
 
132
        size = ULONG_MAX; /* error */
 
133
        header = malloc(hsz);
 
134
        if (!header)
 
135
                return size;
 
136
        arg_for_curl.p = header;
 
137
        arg_for_curl.size = hsz;
 
138
        arg_for_curl.written = 0;
 
139
        arg_for_curl.err = 0;
 
140
 
 
141
        curle = curl_easy_setopt(ezcurl, CURLOPT_HEADERFUNCTION,
 
142
                                 store_from_curl);
 
143
        if (curle == CURLE_OK)
 
144
                curle = curl_easy_setopt(ezcurl, CURLOPT_RANGE, "0-1");
 
145
#if 0
 
146
        if (curle == CURLE_OK)
 
147
                curle = curl_easy_setopt(ezcurl, CURLOPT_WRITEHEADER,
 
148
                                         &arg_for_curl);
 
149
#endif
 
150
        if (curle == CURLE_OK)
 
151
                curle = curl_easy_perform(ezcurl);
 
152
        if (curle != CURLE_OK) {
 
153
                err_curl(curle);
 
154
                return size;
 
155
        }
 
156
        if (arg_for_curl.err) {
 
157
                fprintf(stderr, "%s: internal error.\n", me);
 
158
                errno = EINVAL;
 
159
                return size;
 
160
        }
 
161
 
 
162
        //Dbg("%s\n", header);
 
163
        p = strstr(header, "Content-Range: bytes ");
 
164
        if (p)
 
165
                p = strchr(p, '/');
 
166
        if (!p) {
 
167
                fprintf(stderr, "%s: no range header, %s\n", me, g_url);
 
168
                errno = EINVAL;
 
169
                return size;
 
170
        }
 
171
        size = strtoull(p + 1, NULL, 10);
 
172
        free(header);
 
173
 
 
174
        /* reset */
 
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 */
 
182
 
 
183
        err_curl(curle);
 
184
        return ULONG_MAX; /* error */
 
185
}
 
186
 
 
187
static unsigned long long init_curl_and_size(void)
 
188
{
 
189
        unsigned long long sz;
 
190
        CURLcode curle;
 
191
 
 
192
        sz = -1;
 
193
        errno = ENOMEM;
 
194
        ezcurl = curl_easy_init();
 
195
        if (!ezcurl)
 
196
                return -1;
 
197
 
 
198
        curle = curl_easy_setopt(ezcurl, CURLOPT_URL, g_url);
 
199
        if (curle == CURLE_OK)
 
200
                curle = curl_easy_setopt(ezcurl, CURLOPT_TIMEOUT, timeout);
 
201
#if 0
 
202
        if (curle == CURLE_OK)
 
203
                curle = curl_easy_setopt(ezcurl, CURLOPT_VERBOSE, 1);
 
204
#endif
 
205
#if 0
 
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);
 
210
#endif
 
211
        if (curle != CURLE_OK)
 
212
                goto out_curl;
 
213
 
 
214
        errno = ERANGE;
 
215
        sz = get_size();
 
216
        if (sz == ULONG_MAX)
 
217
                goto out_curl;
 
218
 
 
219
        curle = curl_easy_setopt(ezcurl, CURLOPT_WRITEFUNCTION,
 
220
                                 store_from_curl);
 
221
#if 0
 
222
        if (curle == CURLE_OK)
 
223
                curle = curl_easy_setopt(ezcurl, CURLOPT_WRITEDATA,
 
224
                                         &arg_for_curl);
 
225
#endif
 
226
        if (curle == CURLE_OK)
 
227
                curle = curl_easy_setopt(ezcurl, CURLOPT_RANGE, range);
 
228
        if (curle == CURLE_OK)
 
229
                return sz;
 
230
 
 
231
 out_curl:
 
232
        err_curl(curle);
 
233
        return sz;
 
234
}
 
235
 
 
236
/* ---------------------------------------------------------------------- */
 
237
 
 
238
static int init(struct ulo_init *init_args)
 
239
{
 
240
        int err;
 
241
 
 
242
        init_args->size = init_curl_and_size();
 
243
        err = init_args->size;
 
244
        if (err != -1)
 
245
                err = ulo_init(init_args);
 
246
        return err;
 
247
}
 
248
 
 
249
static void usage(void)
 
250
{
 
251
        fprintf(stderr, "%s"
 
252
                " [-b bitmap]"
 
253
                " [-c cache]"
 
254
                " [-t timeout]"
 
255
                " /dev/loopN url_for_fs_image_file\n"
 
256
                "and then, \"mount /dev/loopN /wherever/you/like\n",
 
257
                me);
 
258
        exit(EINVAL);
 
259
}
 
260
 
 
261
static int parse(int argc, char *argv[], struct ulo_init *init_args)
 
262
{
 
263
        int opt;
 
264
        static char bitmap_def[] = "/tmp/123456.bitmap",
 
265
                cache_def[] = "/tmp/123456.cache";
 
266
 
 
267
        while ((opt = getopt(argc, argv, "b:c:t:")) != -1) {
 
268
                switch (opt) {
 
269
                case 'b':
 
270
                        init_args->path[ULO_BITMAP] = optarg;
 
271
                        break;
 
272
                case 'c':
 
273
                        init_args->path[ULO_CACHE] = optarg;
 
274
                        break;
 
275
                case 't':
 
276
                        errno = 0;
 
277
                        timeout = strtol(optarg, NULL, 0);
 
278
                        if (errno) {
 
279
                                me = optarg;
 
280
                                return ERANGE;
 
281
                        }
 
282
                        break;
 
283
                default:
 
284
                        usage();
 
285
                        break;
 
286
                }
 
287
        }
 
288
 
 
289
        if (argc - optind != 2) {
 
290
                usage();
 
291
                return EINVAL;
 
292
        }
 
293
 
 
294
        init_args->path[ULO_DEV] = argv[optind];
 
295
        g_url = argv[optind + 1];
 
296
 
 
297
        if (!init_args->path[ULO_CACHE]) {
 
298
                snprintf(cache_def, sizeof(cache_def) - 1, "/tmp/%d.cache",
 
299
                         getpid());
 
300
                init_args->path[ULO_CACHE] = cache_def;
 
301
        }
 
302
        if (!init_args->path[ULO_BITMAP]) {
 
303
                snprintf(bitmap_def, sizeof(bitmap_def) - 1, "/tmp/%d.bitmap",
 
304
                         getpid());
 
305
                init_args->path[ULO_BITMAP] = bitmap_def;
 
306
        }
 
307
 
 
308
        //Dbg("to %d, %s\n", timeout, g_url);
 
309
        return 0;
 
310
}
 
311
 
 
312
/* ---------------------------------------------------------------------- */
 
313
 
 
314
int main(int argc, char *argv[])
 
315
{
 
316
        int err;
 
317
        pid_t pid;
 
318
        struct ulo_init init_args = {
 
319
                .dev_flags = O_RDONLY
 
320
        };
 
321
 
 
322
        me = argv[0];
 
323
        err = parse(argc, argv, &init_args);
 
324
        if (!err)
 
325
                err = init(&init_args);
 
326
        if (!err) {
 
327
                pid = fork();
 
328
                if (!pid) {
 
329
                        err = ulo_loop(SIGUSR1, store, ezcurl);
 
330
                        curl_easy_cleanup(ezcurl);
 
331
                } else if (pid > 0)
 
332
                        sleep(1);
 
333
        }
 
334
 
 
335
        if (err && me)
 
336
                perror(me);
 
337
        return err;
 
338
}