server: Better newstyle .open failure handling
[nbdkit/ericb.git] / tests / test-streaming.c
blobe8c52ee82be5cd1a6b93f2d54b3e46a4741ec1da
1 /* nbdkit
2 * Copyright (C) 2014 Red Hat Inc.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of Red Hat nor the names of its contributors may be
16 * used to endorse or promote products derived from this software without
17 * specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
33 #include <config.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <stdint.h>
38 #include <inttypes.h>
39 #include <string.h>
40 #include <fcntl.h>
41 #include <unistd.h>
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #include <sys/wait.h>
46 #include <guestfs.h>
48 #include "test.h"
50 static char data[65536];
52 int
53 main (int argc, char *argv[])
55 pid_t md5pid;
56 guestfs_h *g;
57 int r;
58 size_t i;
59 int pipefd[2];
60 char md5[33];
61 int status;
63 unlink ("streaming.fifo");
64 if (mknod ("streaming.fifo", S_IFIFO | 0600, 0) == -1) {
65 perror ("streaming.fifo");
66 exit (EXIT_FAILURE);
69 if (test_start_nbdkit ("streaming", "pipe=streaming.fifo", "size=640k",
70 NULL) == -1)
71 exit (EXIT_FAILURE);
73 /* Fork to run a second process which reads from streaming.fifo and
74 * checks that the content is correct. The test doesn't care about
75 * fd leaks, so we don't bother with CLOEXEC.
77 if (pipe (pipefd) == -1) {
78 perror ("pipe");
79 exit (EXIT_FAILURE);
82 md5pid = fork ();
83 if (md5pid == -1) {
84 perror ("fork");
85 exit (EXIT_FAILURE);
88 if (md5pid == 0) {
89 /* Child: run md5sum on the pipe. */
90 char *argv[] = { "md5sum", NULL };
92 close (0);
93 open ("streaming.fifo", O_RDONLY);
94 close (1);
95 dup2 (pipefd[1], 1);
96 close (pipefd[0]);
98 execvp ("md5sum", argv);
99 perror ("md5sum");
100 _exit (EXIT_FAILURE);
103 close (pipefd[1]);
105 g = guestfs_create ();
106 if (g == NULL) {
107 perror ("guestfs_create");
108 exit (EXIT_FAILURE);
111 r = guestfs_add_drive_opts (g, "",
112 GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
113 GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "nbd",
114 GUESTFS_ADD_DRIVE_OPTS_SERVER, server,
115 -1);
116 if (r == -1)
117 exit (EXIT_FAILURE);
119 if (guestfs_launch (g) == -1)
120 exit (EXIT_FAILURE);
122 /* Write linearly to the virtual disk. */
123 memset (data, 1, sizeof data);
124 for (i = 0; i < 10; ++i) {
125 guestfs_pwrite_device (g, "/dev/sda", data, sizeof data,
126 i * sizeof data);
129 if (guestfs_shutdown (g) == -1)
130 exit (EXIT_FAILURE);
132 guestfs_close (g);
134 /* We have to explicitly kill nbdkit here so that it closes the
135 * pipe.
137 kill (pid, SIGINT);
139 /* Check the hash computed by the child process. */
140 if (read (pipefd[0], md5, 32) != 32) {
141 perror ("read");
142 exit (EXIT_FAILURE);
144 md5[32] = '\0';
146 if (strcmp (md5, "2c7f81c580f7f9eb52c1bd2f6f493b6f") != 0) {
147 fprintf (stderr, "unexpected hash: %s\n", md5);
148 exit (EXIT_FAILURE);
151 if (waitpid (md5pid, &status, 0) == -1) {
152 perror ("waitpid");
153 exit (EXIT_FAILURE);
155 if (status != 0) {
156 fprintf (stderr, "md5sum subprocess failed\n");
157 exit (EXIT_FAILURE);
160 exit (EXIT_SUCCESS);