vfs: check userland buffers before reading them.
[haiku.git] / src / kits / media / Buffer.cpp
bloba3560a00de610eb91fb17238d08bbdbdfde03b20
1 /*
2 * Copyright 2009, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
6 /*
7 * Copyright (c) 2002, 2003 Marcus Overhagen <Marcus@Overhagen.de>
9 * Permission is hereby granted, free of charge, to any person obtaining
10 * a copy of this software and associated documentation files or portions
11 * thereof (the "Software"), to deal in the Software without restriction,
12 * including without limitation the rights to use, copy, modify, merge,
13 * publish, distribute, sublicense, and/or sell copies of the Software,
14 * and to permit persons to whom the Software is furnished to do so, subject
15 * to the following conditions:
17 * * Redistributions of source code must retain the above copyright notice,
18 * this list of conditions and the following disclaimer.
20 * * Redistributions in binary form must reproduce the above copyright notice
21 * in the binary, as well as this list of conditions and the following
22 * disclaimer in the documentation and/or other materials provided with
23 * the distribution.
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
26 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
28 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
31 * THE SOFTWARE.
35 #include <Buffer.h>
37 #include <AppMisc.h>
38 #include <MediaDefs.h>
40 #include "debug.h"
41 #include "DataExchange.h"
42 #include "SharedBufferList.h"
45 using namespace BPrivate::media;
48 // #pragma mark - buffer_clone_info
51 buffer_clone_info::buffer_clone_info()
53 CALLED();
54 buffer = 0;
55 area = 0;
56 offset = 0;
57 size = 0;
58 flags = 0;
62 buffer_clone_info::~buffer_clone_info()
64 CALLED();
68 // #pragma mark - public BBuffer
71 void*
72 BBuffer::Data()
74 CALLED();
75 return fData;
79 size_t
80 BBuffer::SizeAvailable()
82 CALLED();
83 return fSize;
87 size_t
88 BBuffer::SizeUsed()
90 CALLED();
91 return fMediaHeader.size_used;
95 void
96 BBuffer::SetSizeUsed(size_t size_used)
98 CALLED();
99 fMediaHeader.size_used = min_c(size_used, fSize);
103 uint32
104 BBuffer::Flags()
106 CALLED();
107 return fFlags;
111 void
112 BBuffer::Recycle()
114 CALLED();
115 if (fBufferList == NULL)
116 return;
117 fBufferList->RecycleBuffer(this);
121 buffer_clone_info
122 BBuffer::CloneInfo() const
124 CALLED();
125 buffer_clone_info info;
127 info.buffer = fMediaHeader.buffer;
128 info.area = fArea;
129 info.offset = fOffset;
130 info.size = fSize;
131 info.flags = fFlags;
133 return info;
137 media_buffer_id
138 BBuffer::ID()
140 CALLED();
141 return fMediaHeader.buffer;
145 media_type
146 BBuffer::Type()
148 CALLED();
149 return fMediaHeader.type;
153 media_header*
154 BBuffer::Header()
156 CALLED();
157 return &fMediaHeader;
161 media_audio_header*
162 BBuffer::AudioHeader()
164 CALLED();
165 return &fMediaHeader.u.raw_audio;
169 media_video_header*
170 BBuffer::VideoHeader()
172 CALLED();
173 return &fMediaHeader.u.raw_video;
177 size_t
178 BBuffer::Size()
180 CALLED();
181 return SizeAvailable();
185 // #pragma mark - private BBuffer
188 BBuffer::BBuffer(const buffer_clone_info& info)
190 fBufferList(NULL),
191 fArea(-1),
192 fData(NULL),
193 fOffset(0),
194 fSize(0),
195 fFlags(0)
197 CALLED();
199 // Ensure that the media_header is clean
200 memset(&fMediaHeader, 0, sizeof(fMediaHeader));
201 // special case for BSmallBuffer
202 if (info.area == 0 && info.buffer == 0)
203 return;
205 // Must be -1 if registration fail
206 fMediaHeader.buffer = -1;
208 fBufferList = BPrivate::SharedBufferList::Get();
209 if (fBufferList == NULL) {
210 ERROR("BBuffer::BBuffer: BPrivate::SharedBufferList::Get() failed\n");
211 return;
214 server_register_buffer_request request;
215 server_register_buffer_reply reply;
217 request.team = BPrivate::current_team();
218 request.info = info;
220 // ask media_server to register this buffer,
221 // either identified by "buffer" or by area information.
222 // media_server either has a copy of the area identified
223 // by "buffer", or creates a new area.
224 // the information and the area is cached by the media_server
225 // until the last buffer has been unregistered
226 // the area_id of the cached area is passed back to us, and we clone it.
228 if (QueryServer(SERVER_REGISTER_BUFFER, &request, sizeof(request), &reply,
229 sizeof(reply)) != B_OK) {
230 ERROR("BBuffer::BBuffer: failed to register buffer with "
231 "media_server\n");
232 return;
235 ASSERT(reply.info.buffer > 0);
236 ASSERT(reply.info.area > 0);
237 ASSERT(reply.info.size > 0);
239 fArea = clone_area("a cloned BBuffer", &fData, B_ANY_ADDRESS,
240 B_READ_AREA | B_WRITE_AREA, reply.info.area);
241 if (fArea < 0) {
242 ERROR("BBuffer::BBuffer: buffer cloning failed"
243 ", unregistering buffer\n");
244 server_unregister_buffer_command cmd;
245 cmd.team = BPrivate::current_team();
246 cmd.buffer_id = reply.info.buffer;
247 SendToServer(SERVER_UNREGISTER_BUFFER, &cmd, sizeof(cmd));
248 return;
251 // the response from media server contains enough information
252 // to clone the memory for this buffer
253 fSize = reply.info.size;
254 fFlags = reply.info.flags;
255 fOffset = reply.info.offset;
256 fMediaHeader.size_used = 0;
257 fMediaHeader.buffer = reply.info.buffer;
258 fData = (char*)fData + fOffset;
262 BBuffer::~BBuffer()
264 CALLED();
266 // unmap the BufferList
267 if (fBufferList != NULL)
268 fBufferList->Put();
270 // unmap the Data
271 if (fData != NULL) {
272 delete_area(fArea);
274 // Ask media_server to unregister the buffer when the last clone of
275 // this buffer is gone, media_server will also remove its cached area.
276 server_unregister_buffer_command cmd;
277 cmd.team = BPrivate::current_team();
278 cmd.buffer_id = fMediaHeader.buffer;
279 SendToServer(SERVER_UNREGISTER_BUFFER, &cmd, sizeof(cmd));
284 void
285 BBuffer::SetHeader(const media_header* header)
287 CALLED();
288 ASSERT(header->buffer == fMediaHeader.buffer);
289 if (header->buffer != fMediaHeader.buffer)
290 debugger("oops");
291 fMediaHeader = *header;
295 // #pragma mark - public BSmallBuffer
298 static const buffer_clone_info sSmallBufferInfo;
301 BSmallBuffer::BSmallBuffer()
303 BBuffer(sSmallBufferInfo)
305 UNIMPLEMENTED();
306 debugger("BSmallBuffer::BSmallBuffer called\n");
310 size_t
311 BSmallBuffer::SmallBufferSizeLimit()
313 CALLED();
314 return 64;