Update Red Hat Copyright Notices
[nbdkit.git] / common / replacements / open_memstream.c
blob2185ef837223380a01b51e195968685c4eb65130
1 /* nbdkit
2 * Copyright Red Hat
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 /* Replacement for open_memstream for platforms which lack this function. */
35 #include <config.h>
37 #include <stdio.h>
39 #include "open_memstream.h"
41 #ifndef HAVE_OPEN_MEMSTREAM
43 #ifdef WIN32
45 /* Replacement open_memstream for Win32. */
47 #include <windows.h>
49 #include <assert.h>
51 /* This is provided by common/utils which hasn't been compiled yet.
52 * Programs using this replacement will need to link to
53 * libutils.la. XXX
55 #include "../utils/vector.h"
56 #include "../utils/nbdkit-string.h"
58 /* Map FILE* that we return to the user buffer. */
59 struct file_to_memstream {
60 FILE *fp;
61 char tmpname[MAX_PATH];
62 char **ptr;
63 size_t *size;
65 DEFINE_VECTOR_TYPE (file_vector, struct file_to_memstream);
66 static file_vector files = empty_vector;
68 FILE *
69 open_memstream (char **ptr, size_t *size)
71 struct file_to_memstream f2m;
72 char tmppath[MAX_PATH];
73 DWORD ret;
74 FILE *fp;
76 ret = GetTempPath (MAX_PATH, tmppath);
77 if (ret > MAX_PATH || ret == 0)
78 return NULL;
80 ret = GetTempFileName (tmppath, TEXT ("nbdkit"), 0, f2m.tmpname);
81 if (!ret)
82 return NULL;
84 fp = fopen (f2m.tmpname, "w+");
85 if (fp == NULL)
86 return NULL;
88 f2m.fp = fp;
89 f2m.ptr = ptr;
90 f2m.size = size;
91 if (file_vector_append (&files, f2m) == -1) {
92 fclose (fp);
93 return NULL;
96 return fp;
99 int
100 close_memstream (FILE *fp)
102 size_t i;
103 int c, r;
104 string content = empty_vector;
105 struct file_to_memstream *f2m;
107 for (i = 0; i < files.len; ++i) {
108 if (files.ptr[i].fp == fp)
109 break;
111 assert (i < files.len);
112 f2m = &files.ptr[i];
114 /* Read the file back into memory. */
115 rewind (fp);
116 while ((c = getc (fp)) != EOF) {
117 if (string_append (&content, c) == -1) {
118 append_failed:
119 fclose (fp);
120 unlink (f2m->tmpname);
121 free (content.ptr);
122 file_vector_remove (&files, i);
123 return -1;
126 /* Make sure the buffer is \0-terminated but don't include this
127 * in the buffer size returned below.
129 if (string_append (&content, 0) == -1) goto append_failed;
131 r = fclose (fp);
132 unlink (f2m->tmpname);
133 if (r == EOF) {
134 free (content.ptr);
135 file_vector_remove (&files, i);
136 return -1;
139 /* Pass the buffer to the user. User will free it. */
140 *(files.ptr[i].ptr) = content.ptr;
141 *(files.ptr[i].size) = content.len - 1;
142 file_vector_remove (&files, i);
143 return 0;
146 #else /* !WIN32 */
147 #error "no replacement open_memstream is available on this platform"
148 #endif
150 #endif /* !HAVE_OPEN_MEMSTREAM */