]> git.proxmox.com Git - qemu.git/blobdiff - buffered_file.c
slirp: Fix restricted mode
[qemu.git] / buffered_file.c
index ec4f6641ccb628b896727fa95446937c8f56db64..41b42c3d5a287395eb7b57e53058407e378019c3 100644 (file)
@@ -14,7 +14,6 @@
 #include "qemu-common.h"
 #include "hw/hw.h"
 #include "qemu-timer.h"
-#include "sysemu.h"
 #include "qemu-char.h"
 #include "buffered_file.h"
 
@@ -39,10 +38,10 @@ typedef struct QEMUFileBuffered
 } QEMUFileBuffered;
 
 #ifdef DEBUG_BUFFERED_FILE
-#define dprintf(fmt, ...) \
+#define DPRINTF(fmt, ...) \
     do { printf("buffered-file: " fmt, ## __VA_ARGS__); } while (0)
 #else
-#define dprintf(fmt, ...) \
+#define DPRINTF(fmt, ...) \
     do { } while (0)
 #endif
 
@@ -52,7 +51,7 @@ static void buffered_append(QEMUFileBuffered *s,
     if (size > (s->buffer_capacity - s->buffer_size)) {
         void *tmp;
 
-        dprintf("increasing buffer capacity from %ld by %ld\n",
+        DPRINTF("increasing buffer capacity from %zu by %zu\n",
                 s->buffer_capacity, size + 1024);
 
         s->buffer_capacity += size + 1024;
@@ -75,11 +74,11 @@ static void buffered_flush(QEMUFileBuffered *s)
     size_t offset = 0;
 
     if (s->has_error) {
-        dprintf("flush when error, bailing\n");
+        DPRINTF("flush when error, bailing\n");
         return;
     }
 
-    dprintf("flushing %ld byte(s) of data\n", s->buffer_size);
+    DPRINTF("flushing %zu byte(s) of data\n", s->buffer_size);
 
     while (offset < s->buffer_size) {
         ssize_t ret;
@@ -87,22 +86,22 @@ static void buffered_flush(QEMUFileBuffered *s)
         ret = s->put_buffer(s->opaque, s->buffer + offset,
                             s->buffer_size - offset);
         if (ret == -EAGAIN) {
-            dprintf("backend not ready, freezing\n");
+            DPRINTF("backend not ready, freezing\n");
             s->freeze_output = 1;
             break;
         }
 
         if (ret <= 0) {
-            dprintf("error flushing data, %ld\n", ret);
+            DPRINTF("error flushing data, %zd\n", ret);
             s->has_error = 1;
             break;
         } else {
-            dprintf("flushed %ld byte(s)\n", ret);
+            DPRINTF("flushed %zd byte(s)\n", ret);
             offset += ret;
         }
     }
 
-    dprintf("flushed %ld of %ld byte(s)\n", offset, s->buffer_size);
+    DPRINTF("flushed %zu of %zu byte(s)\n", offset, s->buffer_size);
     memmove(s->buffer, s->buffer + offset, s->buffer_size - offset);
     s->buffer_size -= offset;
 }
@@ -113,49 +112,57 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, in
     int offset = 0;
     ssize_t ret;
 
-    dprintf("putting %ld bytes at %Ld\n", size, pos);
+    DPRINTF("putting %d bytes at %" PRId64 "\n", size, pos);
 
     if (s->has_error) {
-        dprintf("flush when error, bailing\n");
+        DPRINTF("flush when error, bailing\n");
         return -EINVAL;
     }
 
-    dprintf("unfreezing output\n");
+    DPRINTF("unfreezing output\n");
     s->freeze_output = 0;
 
     buffered_flush(s);
 
     while (!s->freeze_output && offset < size) {
         if (s->bytes_xfer > s->xfer_limit) {
-            dprintf("transfer limit exceeded when putting\n");
+            DPRINTF("transfer limit exceeded when putting\n");
             break;
         }
 
         ret = s->put_buffer(s->opaque, buf + offset, size - offset);
         if (ret == -EAGAIN) {
-            dprintf("backend not ready, freezing\n");
+            DPRINTF("backend not ready, freezing\n");
             s->freeze_output = 1;
             break;
         }
 
         if (ret <= 0) {
-            dprintf("error putting\n");
+            DPRINTF("error putting\n");
             s->has_error = 1;
             offset = -EINVAL;
             break;
         }
 
-        dprintf("put %ld byte(s)\n", ret);
+        DPRINTF("put %zd byte(s)\n", ret);
         offset += ret;
         s->bytes_xfer += ret;
     }
 
     if (offset >= 0) {
-        dprintf("buffering %ld bytes\n", size - offset);
+        DPRINTF("buffering %d bytes\n", size - offset);
         buffered_append(s, buf + offset, size - offset);
         offset = size;
     }
 
+    if (pos == 0 && size == 0) {
+        DPRINTF("file is ready\n");
+        if (s->bytes_xfer <= s->xfer_limit) {
+            DPRINTF("notifying client\n");
+            s->put_ready(s->opaque);
+        }
+    }
+
     return offset;
 }
 
@@ -164,7 +171,7 @@ static int buffered_close(void *opaque)
     QEMUFileBuffered *s = opaque;
     int ret;
 
-    dprintf("closing\n");
+    DPRINTF("closing\n");
 
     while (!s->has_error && s->buffer_size) {
         buffered_flush(s);
@@ -198,14 +205,39 @@ static int buffered_rate_limit(void *opaque)
     return 0;
 }
 
+static int64_t buffered_set_rate_limit(void *opaque, int64_t new_rate)
+{
+    QEMUFileBuffered *s = opaque;
+    if (s->has_error)
+        goto out;
+
+    if (new_rate > SIZE_MAX) {
+        new_rate = SIZE_MAX;
+    }
+
+    s->xfer_limit = new_rate / 10;
+    
+out:
+    return s->xfer_limit;
+}
+
+static int64_t buffered_get_rate_limit(void *opaque)
+{
+    QEMUFileBuffered *s = opaque;
+  
+    return s->xfer_limit;
+}
+
 static void buffered_rate_tick(void *opaque)
 {
     QEMUFileBuffered *s = opaque;
 
-    if (s->has_error)
+    if (s->has_error) {
+        buffered_close(s);
         return;
+    }
 
-    qemu_mod_timer(s->timer, qemu_get_clock(rt_clock) + 100);
+    qemu_mod_timer(s->timer, qemu_get_clock_ms(rt_clock) + 100);
 
     if (s->freeze_output)
         return;
@@ -237,11 +269,13 @@ QEMUFile *qemu_fopen_ops_buffered(void *opaque,
     s->close = close;
 
     s->file = qemu_fopen_ops(s, buffered_put_buffer, NULL,
-                             buffered_close, buffered_rate_limit);
+                             buffered_close, buffered_rate_limit,
+                             buffered_set_rate_limit,
+                            buffered_get_rate_limit);
 
-    s->timer = qemu_new_timer(rt_clock, buffered_rate_tick, s);
+    s->timer = qemu_new_timer_ms(rt_clock, buffered_rate_tick, s);
 
-    qemu_mod_timer(s->timer, qemu_get_clock(rt_clock) + 100);
+    qemu_mod_timer(s->timer, qemu_get_clock_ms(rt_clock) + 100);
 
     return s->file;
 }