curl-library
[PATCH] CURL : ADD WRITE SUPPORT NOT WORKING
From: Richard W.M. Jones <rjones_at_redhat.com>
Date: Sat, 21 Jun 2014 22:10:18 +0100
Date: Sat, 21 Jun 2014 22:10:18 +0100
---
plugins/curl/curl.c | 75 +++++++++++++++++++++++++++++++++++--
plugins/curl/nbdkit-curl-plugin.pod | 10 +++--
2 files changed, 78 insertions(+), 7 deletions(-)
diff --git a/plugins/curl/curl.c b/plugins/curl/curl.c
index f922832..7b99c06 100644
--- a/plugins/curl/curl.c
+++ b/plugins/curl/curl.c
@@ -31,6 +31,14 @@
* SUCH DAMAGE.
*/
+/* NB: The terminology used by libcurl is confusing!
+ *
+ * WRITEFUNCTION / write_cb is used when reading from the remote server
+ * READFUNCTION / read_cb is used when writing to the remote server.
+ *
+ * We use the same terminology as libcurl here.
+ */
+
#include <config.h>
#include <stdio.h>
@@ -145,6 +153,8 @@ struct curl_handle {
char errbuf[CURL_ERROR_SIZE];
char *write_buf;
uint32_t write_count;
+ const char *read_buf;
+ uint32_t read_count;
};
/* Translate CURLcode to nbdkit_error. */
@@ -156,6 +166,7 @@ struct curl_handle {
static size_t header_cb (void *ptr, size_t size, size_t nmemb, void *opaque);
static size_t write_cb (char *ptr, size_t size, size_t nmemb, void *opaque);
+static size_t read_cb (void *ptr, size_t size, size_t nmemb, void *opaque);
/* Create the per-connection handle. */
static void *
@@ -241,12 +252,15 @@ CURLOPT_PROXY
nbdkit_debug ("accept range supported (for HTTP/HTTPS)");
}
- /* Get set up for reading. */
+ /* Get set up for reading and writing. */
curl_easy_setopt (h->c, CURLOPT_HEADERFUNCTION, NULL);
curl_easy_setopt (h->c, CURLOPT_HEADERDATA, NULL);
- curl_easy_setopt (h->c, CURLOPT_NOBODY, 0); /* No Body, not nobody! */
curl_easy_setopt (h->c, CURLOPT_WRITEFUNCTION, write_cb);
curl_easy_setopt (h->c, CURLOPT_WRITEDATA, h);
+ if (!readonly) {
+ curl_easy_setopt (h->c, CURLOPT_READFUNCTION, read_cb);
+ curl_easy_setopt (h->c, CURLOPT_READDATA, h);
+ }
nbdkit_debug ("returning new handle %p", h);
@@ -307,7 +321,7 @@ curl_get_size (void *handle)
return h->exportsize;
}
-/* Read data from the file. */
+/* Read data from the remote server. */
static int
curl_pread (void *handle, void *buf, uint32_t count, uint64_t offset)
{
@@ -321,6 +335,9 @@ curl_pread (void *handle, void *buf, uint32_t count, uint64_t offset)
h->write_buf = buf;
h->write_count = count;
+ curl_easy_setopt (h->c, CURLOPT_NOBODY, 0); /* No Body, not nobody! */
+ curl_easy_setopt (h->c, CURLOPT_HTTPGET, 1);
+
/* Make an HTTP range request. */
snprintf (range, sizeof range, "%" PRIu64 "-%" PRIu64,
offset, offset + count);
@@ -361,6 +378,57 @@ write_cb (char *ptr, size_t size, size_t nmemb, void *opaque)
return orig_realsize;
}
+/* Write data to the remote server. */
+static int
+curl_pwrite (void *handle, const void *buf, uint32_t count, uint64_t offset)
+{
+ struct curl_handle *h = handle;
+ CURLcode r;
+ char range[128];
+
+ /* Tell the read_cb where we want the data to be read from. read_cb
+ * will update this if the data comes in multiple sections.
+ */
+ h->read_buf = buf;
+ h->read_count = count;
+
+ curl_easy_setopt (h->c, CURLOPT_UPLOAD, 1);
+
+ /* Make an HTTP range request. */
+ snprintf (range, sizeof range, "%" PRIu64 "-%" PRIu64,
+ offset, offset + count);
+ curl_easy_setopt (h->c, CURLOPT_RANGE, range);
+
+ /* The assumption here is that curl will look after timeouts. */
+ while (h->read_count > 0) {
+ r = curl_easy_perform (h->c);
+ if (r != CURLE_OK) {
+ display_curl_error (h, r, "pwrite: curl_easy_perform");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static size_t
+read_cb (void *ptr, size_t size, size_t nmemb, void *opaque)
+{
+ struct curl_handle *h = opaque;
+ size_t realsize = size * nmemb;
+
+ assert (h->read_buf);
+ if (realsize > h->read_count)
+ return CURL_READFUNC_ABORT;
+
+ memcpy (ptr, h->read_buf, realsize);
+
+ h->read_count -= realsize;
+ h->read_buf += realsize;
+
+ return realsize;
+}
+
static struct nbdkit_plugin plugin = {
.name = "curl",
.version = PACKAGE_VERSION,
@@ -373,6 +441,7 @@ static struct nbdkit_plugin plugin = {
.close = curl_close,
.get_size = curl_get_size,
.pread = curl_pread,
+ .pwrite = curl_pwrite,
};
NBDKIT_REGISTER_PLUGIN(plugin)
diff --git a/plugins/curl/nbdkit-curl-plugin.pod b/plugins/curl/nbdkit-curl-plugin.pod
index 79659a5..97b6e7d 100644
--- a/plugins/curl/nbdkit-curl-plugin.pod
+++ b/plugins/curl/nbdkit-curl-plugin.pod
@@ -8,7 +8,7 @@ nbdkit-curl-plugin - nbdkit curl plugin (HTTP, FTP, SSH and other protocols)
nbdkit -r curl url=http://example.com/disk.img
- nbdkit -r curl url=sftp://you@example.com/~/disk.img
+ nbdkit curl url=sftp://you@example.com/~/disk.img
=head1 DESCRIPTION
@@ -20,7 +20,9 @@ how it was compiled, but most versions will handle HTTP, HTTPS, FTP,
FTPS and SFTP (see: S<C<curl -V>>). For more information about
libcurl, see L<http://curl.haxx.se>.
-This plugin can B<only> handle B<readonly> connections.
+B<Note:> This plugin supports writable connections. However for HTTP,
+you may not want nbdkit to issue POST requests to the remote server.
+To force nbdkit to use a readonly connection, pass the I<-r> flag.
=head2 EXAMPLES
@@ -34,12 +36,12 @@ control ports and protocols used to serve NBD see L<nbdkit(1)>).
You can also access SSH servers. This uses the SFTP protocol which is
built into most SSH servers:
- nbdkit -r curl url=sftp://example.com/~/disk.img
+ nbdkit curl url=sftp://example.com/~/disk.img
You may need to specify a username and/or a password. In this example
the password is read from stdin:
- nbdkit -r curl url=sftp://example.com/~/disk.img username=fred password=-
+ nbdkit curl url=sftp://example.com/~/disk.img username=fred password=-
=head1 PARAMETERS
--
1.9.0
--NzB8fVQJ5HfG6fxh
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: base64
Content-Disposition: inline
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLQpMaXN0IGFkbWluOiBodHRwOi8vY29vbC5oYXh4LnNlL2xpc3QvbGlzdGluZm8v
Y3VybC1saWJyYXJ5CkV0aXF1ZXR0ZTogIGh0dHA6Ly9jdXJsLmhheHguc2UvbWFpbC9ldGlxdWV0
dGUuaHRtbA==
--NzB8fVQJ5HfG6fxh--
Received on 2001-09-17