summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark H Weaver <mhw@netris.org>2013-04-08 00:36:00 -0400
committerMark H Weaver <mhw@netris.org>2013-04-08 00:36:00 -0400
commit7f3be1db9949b0566d3a2cb6bd9d0e84287bbb0a (patch)
tree47fdc2104ccb0a0bbeb8761a083e3c89a2f5577f
parenteed0d26cc0668a309b610113554be5df8dfb32e9 (diff)
downloadguile-7f3be1db9949b0566d3a2cb6bd9d0e84287bbb0a.tar.gz
Miscellaneous 'sendfile' fixes and improved tests.
* libguile/filesys.c (scm_sendfile): In Linux-style sendfile(2) code, if EINTR or EAGAIN occurs, set result to 1 (not 0) so that we actually keep going. In non-sendfile(2) code, deal gracefully with short reads due to EOF. * test-suite/tests/filesys.test ("sendfile"): Use 'let*' to guarantee the needed order of operations: write (test-file) and then read it. Add code to check the written data (not just the returned length) in all tests, including the cases that hit EOF prematurely.
-rw-r--r--libguile/filesys.c20
-rw-r--r--test-suite/tests/filesys.test66
2 files changed, 53 insertions, 33 deletions
diff --git a/libguile/filesys.c b/libguile/filesys.c
index d2e565bf8..5f6208d82 100644
--- a/libguile/filesys.c
+++ b/libguile/filesys.c
@@ -1160,7 +1160,7 @@ SCM_DEFINE (scm_sendfile, "sendfile", 3, 1, 0,
total += result;
else if (result < 0 && (errno == EINTR || errno == EAGAIN))
/* Keep going. */
- result = 0;
+ result = 1;
}
while (total < c_count && result > 0);
}
@@ -1175,6 +1175,7 @@ SCM_DEFINE (scm_sendfile, "sendfile", 3, 1, 0,
{
char buf[8192];
size_t left;
+ int reached_eof = 0;
if (!SCM_UNBNDP (offset))
{
@@ -1187,22 +1188,27 @@ SCM_DEFINE (scm_sendfile, "sendfile", 3, 1, 0,
}
}
- for (total = 0, left = c_count; total < c_count; )
+ for (total = 0, left = c_count; total < c_count && !reached_eof; )
{
- size_t asked, obtained;
+ size_t asked, obtained, written;
asked = SCM_MIN (sizeof buf, left);
obtained = full_read (in_fd, buf, asked);
if (obtained < asked)
- SCM_SYSERROR;
+ {
+ if (errno == 0)
+ reached_eof = 1;
+ else
+ SCM_SYSERROR;
+ }
left -= obtained;
- obtained = full_write (out_fd, buf, asked);
- if (obtained < asked)
+ written = full_write (out_fd, buf, obtained);
+ if (written < obtained)
SCM_SYSERROR;
- total += obtained;
+ total += written;
}
}
diff --git a/test-suite/tests/filesys.test b/test-suite/tests/filesys.test
index 7998bc710..049c9a2b0 100644
--- a/test-suite/tests/filesys.test
+++ b/test-suite/tests/filesys.test
@@ -135,38 +135,52 @@
(ref (call-with-input-file file get-bytevector-all)))
(pass-if-equal "file" (cons len ref)
- (cons (call-with-input-file file
- (lambda (input)
- (call-with-output-file (test-file)
- (lambda (output)
- (sendfile output input len 0)))))
- (call-with-input-file (test-file) get-bytevector-all)))
+ (let* ((result (call-with-input-file file
+ (lambda (input)
+ (call-with-output-file (test-file)
+ (lambda (output)
+ (sendfile output input len 0))))))
+ (out (call-with-input-file (test-file) get-bytevector-all)))
+ (cons result out)))
(pass-if-equal "file with offset"
(cons (- len 777) (call-with-input-file file
(lambda (input)
(seek input 777 SEEK_SET)
(get-bytevector-all input))))
- (cons (call-with-input-file file
- (lambda (input)
- (call-with-output-file (test-file)
- (lambda (output)
- (sendfile output input (- len 777) 777)))))
- (call-with-input-file (test-file) get-bytevector-all)))
-
- (pass-if-equal "file with offset past the end" (- len 777)
- (call-with-input-file file
- (lambda (input)
- (call-with-output-file (test-file)
- (lambda (output)
- (sendfile output input len 777))))))
-
- (pass-if-equal "file with offset near the end" 77
- (call-with-input-file file
- (lambda (input)
- (call-with-output-file (test-file)
- (lambda (output)
- (sendfile output input len (- len 77)))))))
+ (let* ((result (call-with-input-file file
+ (lambda (input)
+ (call-with-output-file (test-file)
+ (lambda (output)
+ (sendfile output input (- len 777) 777))))))
+ (out (call-with-input-file (test-file) get-bytevector-all)))
+ (cons result out)))
+
+ (pass-if-equal "file with offset past the end"
+ (cons (- len 777) (call-with-input-file file
+ (lambda (input)
+ (seek input 777 SEEK_SET)
+ (get-bytevector-all input))))
+ (let* ((result (call-with-input-file file
+ (lambda (input)
+ (call-with-output-file (test-file)
+ (lambda (output)
+ (sendfile output input len 777))))))
+ (out (call-with-input-file (test-file) get-bytevector-all)))
+ (cons result out)))
+
+ (pass-if-equal "file with offset near the end"
+ (cons 77 (call-with-input-file file
+ (lambda (input)
+ (seek input (- len 77) SEEK_SET)
+ (get-bytevector-all input))))
+ (let* ((result (call-with-input-file file
+ (lambda (input)
+ (call-with-output-file (test-file)
+ (lambda (output)
+ (sendfile output input len (- len 77)))))))
+ (out (call-with-input-file (test-file) get-bytevector-all)))
+ (cons result out)))
(pass-if-equal "pipe" (cons len ref)
(if (provided? 'threads)