xref: /haiku/src/kits/support/DataIO.cpp (revision b1f1332ebbd496f2bdc7e15bf4ab4096f3cacdff)
1 /*
2  * Copyright 2005-2014 Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Stefano Ceccherini, burton666@libero.it
7  */
8 
9 
10 #include <DataIO.h>
11 
12 #include <stdio.h>
13 #include <string.h>
14 #include <stdlib.h>
15 
16 #include <Errors.h>
17 
18 #if defined(_KERNEL_MODE) && !defined(_BOOT_MODE)
19 // for user_memcpy() and IS_USER_ADDRESS()
20 #include <KernelExport.h>
21 
22 #include <kernel.h>
23 #endif
24 
25 
BDataIO()26 BDataIO::BDataIO()
27 {
28 }
29 
30 
~BDataIO()31 BDataIO::~BDataIO()
32 {
33 }
34 
35 
36 ssize_t
Read(void * buffer,size_t size)37 BDataIO::Read(void* buffer, size_t size)
38 {
39 	return B_NOT_SUPPORTED;
40 }
41 
42 
43 ssize_t
Write(const void * buffer,size_t size)44 BDataIO::Write(const void* buffer, size_t size)
45 {
46 	return B_NOT_SUPPORTED;
47 }
48 
49 
50 status_t
Flush()51 BDataIO::Flush()
52 {
53 	return B_OK;
54 }
55 
56 
57 status_t
ReadExactly(void * buffer,size_t size,size_t * _bytesRead)58 BDataIO::ReadExactly(void* buffer, size_t size, size_t* _bytesRead)
59 {
60 	uint8* out = (uint8*)buffer;
61 	size_t bytesRemaining = size;
62 	status_t error = B_OK;
63 
64 	while (bytesRemaining > 0) {
65 		ssize_t bytesRead = Read(out, bytesRemaining);
66 		if (bytesRead < 0) {
67 			error = bytesRead;
68 			break;
69 		}
70 
71 		if (bytesRead == 0) {
72 			error = B_PARTIAL_READ;
73 			break;
74 		}
75 
76 		out += bytesRead;
77 		bytesRemaining -= bytesRead;
78 	}
79 
80 	if (_bytesRead != NULL)
81 		*_bytesRead = size - bytesRemaining;
82 
83 	return error;
84 }
85 
86 
87 status_t
WriteExactly(const void * buffer,size_t size,size_t * _bytesWritten)88 BDataIO::WriteExactly(const void* buffer, size_t size, size_t* _bytesWritten)
89 {
90 	const uint8* in = (const uint8*)buffer;
91 	size_t bytesRemaining = size;
92 	status_t error = B_OK;
93 
94 	while (bytesRemaining > 0) {
95 		ssize_t bytesWritten = Write(in, bytesRemaining);
96 		if (bytesWritten < 0) {
97 			error = bytesWritten;
98 			break;
99 		}
100 
101 		if (bytesWritten == 0) {
102 			error = B_PARTIAL_WRITE;
103 			break;
104 		}
105 
106 		in += bytesWritten;
107 		bytesRemaining -= bytesWritten;
108 	}
109 
110 	if (_bytesWritten != NULL)
111 		*_bytesWritten = size - bytesRemaining;
112 
113 	return error;
114 }
115 
116 
117 // Private or Reserved
118 
BDataIO(const BDataIO &)119 BDataIO::BDataIO(const BDataIO &)
120 {
121 	// Copying not allowed
122 }
123 
124 
125 BDataIO &
operator =(const BDataIO &)126 BDataIO::operator=(const BDataIO &)
127 {
128 	// Copying not allowed
129 	return *this;
130 }
131 
132 
133 #if __GNUC__ == 2
134 
135 
136 extern "C" status_t
_ReservedDataIO1__7BDataIO(BDataIO * self)137 _ReservedDataIO1__7BDataIO(BDataIO* self)
138 {
139 	return self->BDataIO::Flush();
140 }
141 
142 
143 #else
144 
145 
146 // TODO: RELEASE: Remove!
147 
148 extern "C" status_t
_ZN7BDataIO16_ReservedDataIO1Ev(BDataIO * self)149 _ZN7BDataIO16_ReservedDataIO1Ev(BDataIO* self)
150 {
151 	return self->BDataIO::Flush();
152 }
153 
154 
155 #endif
156 
157 
158 // FBC
_ReservedDataIO2()159 void BDataIO::_ReservedDataIO2(){}
_ReservedDataIO3()160 void BDataIO::_ReservedDataIO3(){}
_ReservedDataIO4()161 void BDataIO::_ReservedDataIO4(){}
_ReservedDataIO5()162 void BDataIO::_ReservedDataIO5(){}
_ReservedDataIO6()163 void BDataIO::_ReservedDataIO6(){}
_ReservedDataIO7()164 void BDataIO::_ReservedDataIO7(){}
_ReservedDataIO8()165 void BDataIO::_ReservedDataIO8(){}
_ReservedDataIO9()166 void BDataIO::_ReservedDataIO9(){}
_ReservedDataIO10()167 void BDataIO::_ReservedDataIO10(){}
_ReservedDataIO11()168 void BDataIO::_ReservedDataIO11(){}
_ReservedDataIO12()169 void BDataIO::_ReservedDataIO12(){}
170 
171 
172 //	#pragma mark -
173 
174 
BPositionIO()175 BPositionIO::BPositionIO()
176 {
177 }
178 
179 
~BPositionIO()180 BPositionIO::~BPositionIO()
181 {
182 }
183 
184 
185 ssize_t
Read(void * buffer,size_t size)186 BPositionIO::Read(void* buffer, size_t size)
187 {
188 	off_t curPos = Position();
189 	ssize_t result = ReadAt(curPos, buffer, size);
190 	if (result > 0)
191 		Seek(result, SEEK_CUR);
192 
193 	return result;
194 }
195 
196 
197 ssize_t
Write(const void * buffer,size_t size)198 BPositionIO::Write(const void* buffer, size_t size)
199 {
200 	off_t curPos = Position();
201 	ssize_t result = WriteAt(curPos, buffer, size);
202 	if (result > 0)
203 		Seek(result, SEEK_CUR);
204 
205 	return result;
206 }
207 
208 
209 status_t
ReadAtExactly(off_t position,void * buffer,size_t size,size_t * _bytesRead)210 BPositionIO::ReadAtExactly(off_t position, void* buffer, size_t size,
211 	size_t* _bytesRead)
212 {
213 	uint8* out = (uint8*)buffer;
214 	size_t bytesRemaining = size;
215 	status_t error = B_OK;
216 
217 	while (bytesRemaining > 0) {
218 		ssize_t bytesRead = ReadAt(position, out, bytesRemaining);
219 		if (bytesRead < 0) {
220 			error = bytesRead;
221 			break;
222 		}
223 
224 		if (bytesRead == 0) {
225 			error = B_PARTIAL_READ;
226 			break;
227 		}
228 
229 		out += bytesRead;
230 		bytesRemaining -= bytesRead;
231 		position += bytesRead;
232 	}
233 
234 	if (_bytesRead != NULL)
235 		*_bytesRead = size - bytesRemaining;
236 
237 	return error;
238 }
239 
240 
241 status_t
WriteAtExactly(off_t position,const void * buffer,size_t size,size_t * _bytesWritten)242 BPositionIO::WriteAtExactly(off_t position, const void* buffer, size_t size,
243 	size_t* _bytesWritten)
244 {
245 	const uint8* in = (const uint8*)buffer;
246 	size_t bytesRemaining = size;
247 	status_t error = B_OK;
248 
249 	while (bytesRemaining > 0) {
250 		ssize_t bytesWritten = WriteAt(position, in, bytesRemaining);
251 		if (bytesWritten < 0) {
252 			error = bytesWritten;
253 			break;
254 		}
255 
256 		if (bytesWritten == 0) {
257 			error = B_PARTIAL_WRITE;
258 			break;
259 		}
260 
261 		in += bytesWritten;
262 		bytesRemaining -= bytesWritten;
263 		position += bytesWritten;
264 	}
265 
266 	if (_bytesWritten != NULL)
267 		*_bytesWritten = size - bytesRemaining;
268 
269 	return error;
270 }
271 
272 
273 status_t
SetSize(off_t size)274 BPositionIO::SetSize(off_t size)
275 {
276 	return B_ERROR;
277 }
278 
279 
280 status_t
GetSize(off_t * size) const281 BPositionIO::GetSize(off_t* size) const
282 {
283 	if (!size)
284 		return B_BAD_VALUE;
285 
286 	off_t currentPos = Position();
287 	if (currentPos < 0)
288 		return (status_t)currentPos;
289 
290 	*size = const_cast<BPositionIO*>(this)->Seek(0, SEEK_END);
291 	if (*size < 0)
292 		return (status_t)*size;
293 
294 	off_t pos = const_cast<BPositionIO*>(this)->Seek(currentPos, SEEK_SET);
295 
296 	if (pos != currentPos)
297 		return pos < 0 ? (status_t)pos : B_ERROR;
298 
299 	return B_OK;
300 }
301 
302 
303 // FBC
_ReservedPositionIO1__11BPositionIO()304 extern "C" void _ReservedPositionIO1__11BPositionIO() {}
_ReservedPositionIO2()305 void BPositionIO::_ReservedPositionIO2(){}
_ReservedPositionIO3()306 void BPositionIO::_ReservedPositionIO3(){}
_ReservedPositionIO4()307 void BPositionIO::_ReservedPositionIO4(){}
_ReservedPositionIO5()308 void BPositionIO::_ReservedPositionIO5(){}
_ReservedPositionIO6()309 void BPositionIO::_ReservedPositionIO6(){}
_ReservedPositionIO7()310 void BPositionIO::_ReservedPositionIO7(){}
_ReservedPositionIO8()311 void BPositionIO::_ReservedPositionIO8(){}
_ReservedPositionIO9()312 void BPositionIO::_ReservedPositionIO9(){}
_ReservedPositionIO10()313 void BPositionIO::_ReservedPositionIO10(){}
_ReservedPositionIO11()314 void BPositionIO::_ReservedPositionIO11(){}
_ReservedPositionIO12()315 void BPositionIO::_ReservedPositionIO12(){}
316 
317 
318 //	#pragma mark -
319 
320 
BMemoryIO(void * buffer,size_t length)321 BMemoryIO::BMemoryIO(void* buffer, size_t length)
322 	:
323 	fReadOnly(false),
324 	fBuffer(static_cast<char*>(buffer)),
325 	fLength(length),
326 	fBufferSize(length),
327 	fPosition(0)
328 {
329 }
330 
331 
BMemoryIO(const void * buffer,size_t length)332 BMemoryIO::BMemoryIO(const void* buffer, size_t length)
333 	:
334 	fReadOnly(true),
335 	fBuffer(const_cast<char*>(static_cast<const char*>(buffer))),
336 	fLength(length),
337 	fBufferSize(length),
338 	fPosition(0)
339 {
340 }
341 
342 
~BMemoryIO()343 BMemoryIO::~BMemoryIO()
344 {
345 }
346 
347 
348 ssize_t
ReadAt(off_t pos,void * buffer,size_t size)349 BMemoryIO::ReadAt(off_t pos, void* buffer, size_t size)
350 {
351 	if (buffer == NULL || pos < 0)
352 		return B_BAD_VALUE;
353 
354 	ssize_t sizeRead = 0;
355 	if (pos < (off_t)fLength) {
356 		sizeRead = min_c((off_t)size, (off_t)fLength - pos);
357 		memcpy(buffer, fBuffer + pos, sizeRead);
358 	}
359 
360 	return sizeRead;
361 }
362 
363 
364 ssize_t
WriteAt(off_t pos,const void * buffer,size_t size)365 BMemoryIO::WriteAt(off_t pos, const void* buffer, size_t size)
366 {
367 	if (fReadOnly)
368 		return B_NOT_ALLOWED;
369 
370 	if (buffer == NULL || pos < 0)
371 		return B_BAD_VALUE;
372 
373 	ssize_t sizeWritten = 0;
374 	if (pos < (off_t)fBufferSize) {
375 		sizeWritten = min_c((off_t)size, (off_t)fBufferSize - pos);
376 #if defined(_KERNEL_MODE) && !defined(_BOOT_MODE)
377 		if (IS_USER_ADDRESS(fBuffer)) {
378 			if (user_memcpy(fBuffer + pos, buffer, sizeWritten) != B_OK)
379 				return B_BAD_ADDRESS;
380 		} else
381 #endif
382 		memcpy(fBuffer + pos, buffer, sizeWritten);
383 	}
384 
385 	if (pos + sizeWritten > (off_t)fLength)
386 		fLength = pos + sizeWritten;
387 
388 	return sizeWritten;
389 }
390 
391 
392 off_t
Seek(off_t position,uint32 seek_mode)393 BMemoryIO::Seek(off_t position, uint32 seek_mode)
394 {
395 	switch (seek_mode) {
396 		case SEEK_SET:
397 			fPosition = position;
398 			break;
399 		case SEEK_CUR:
400 			fPosition += position;
401 			break;
402 		case SEEK_END:
403 			fPosition = fLength + position;
404 			break;
405 		default:
406 			break;
407 	}
408 
409 	return fPosition;
410 }
411 
412 
413 off_t
Position() const414 BMemoryIO::Position() const
415 {
416 	return fPosition;
417 }
418 
419 
420 status_t
SetSize(off_t size)421 BMemoryIO::SetSize(off_t size)
422 {
423 	if (fReadOnly)
424 		return B_NOT_ALLOWED;
425 
426 	if (size > (off_t)fBufferSize)
427 		return B_ERROR;
428 
429 	fLength = size;
430 
431 	return B_OK;
432 }
433 
434 
435 // Private or Reserved
436 
BMemoryIO(const BMemoryIO &)437 BMemoryIO::BMemoryIO(const BMemoryIO &)
438 {
439 	//Copying not allowed
440 }
441 
442 
443 BMemoryIO &
operator =(const BMemoryIO &)444 BMemoryIO::operator=(const BMemoryIO &)
445 {
446 	//Copying not allowed
447 	return *this;
448 }
449 
450 
451 // FBC
_ReservedMemoryIO1()452 void BMemoryIO::_ReservedMemoryIO1(){}
_ReservedMemoryIO2()453 void BMemoryIO::_ReservedMemoryIO2(){}
454 
455 
456 //	#pragma mark -
457 
458 
BMallocIO()459 BMallocIO::BMallocIO()
460 	:
461 	fBlockSize(256),
462 	fMallocSize(0),
463 	fLength(0),
464 	fData(NULL),
465 	fPosition(0)
466 {
467 }
468 
469 
~BMallocIO()470 BMallocIO::~BMallocIO()
471 {
472 	free(fData);
473 }
474 
475 
476 ssize_t
ReadAt(off_t pos,void * buffer,size_t size)477 BMallocIO::ReadAt(off_t pos, void* buffer, size_t size)
478 {
479 	if (buffer == NULL)
480 		return B_BAD_VALUE;
481 
482 	ssize_t sizeRead = 0;
483 	if (pos < (off_t)fLength) {
484 		sizeRead = min_c((off_t)size, (off_t)fLength - pos);
485 		memcpy(buffer, fData + pos, sizeRead);
486 	}
487 
488 	return sizeRead;
489 }
490 
491 
492 ssize_t
WriteAt(off_t pos,const void * buffer,size_t size)493 BMallocIO::WriteAt(off_t pos, const void* buffer, size_t size)
494 {
495 	if (buffer == NULL)
496 		return B_BAD_VALUE;
497 
498 	size_t newSize = max_c(pos + (off_t)size, (off_t)fLength);
499 	status_t error = B_OK;
500 
501 	if (newSize > fMallocSize)
502 		error = SetSize(newSize);
503 
504 	if (error == B_OK) {
505 		memcpy(fData + pos, buffer, size);
506 		if (pos + size > fLength)
507 			fLength = pos + size;
508 	}
509 
510 	return error != B_OK ? error : size;
511 }
512 
513 
514 off_t
Seek(off_t position,uint32 seekMode)515 BMallocIO::Seek(off_t position, uint32 seekMode)
516 {
517 	switch (seekMode) {
518 		case SEEK_SET:
519 			fPosition = position;
520 			break;
521 		case SEEK_END:
522 			fPosition = fLength + position;
523 			break;
524 		case SEEK_CUR:
525 			fPosition += position;
526 			break;
527 		default:
528 			break;
529 	}
530 	return fPosition;
531 }
532 
533 
534 off_t
Position() const535 BMallocIO::Position() const
536 {
537 	return fPosition;
538 }
539 
540 
541 status_t
SetSize(off_t size)542 BMallocIO::SetSize(off_t size)
543 {
544 	status_t error = B_OK;
545 	if (size == 0) {
546 		// size == 0, free the memory
547 		free(fData);
548 		fData = NULL;
549 		fMallocSize = 0;
550 	} else {
551 		// size != 0, see, if necessary to resize
552 		size_t newSize = (size + fBlockSize - 1) / fBlockSize * fBlockSize;
553 		if (size != (off_t)fMallocSize) {
554 			// we need to resize
555 			if (char* newData = static_cast<char*>(realloc(fData, newSize))) {
556 				// set the new area to 0
557 				if (newSize > fMallocSize)
558 					memset(newData + fMallocSize, 0, newSize - fMallocSize);
559 				fData = newData;
560 				fMallocSize = newSize;
561 			} else	// couldn't alloc the memory
562 				error = B_NO_MEMORY;
563 		}
564 	}
565 
566 	if (error == B_OK)
567 		fLength = size;
568 
569 	return error;
570 }
571 
572 
573 void
SetBlockSize(size_t blockSize)574 BMallocIO::SetBlockSize(size_t blockSize)
575 {
576 	if (blockSize == 0)
577 		blockSize = 1;
578 
579 	if (blockSize != fBlockSize)
580 		fBlockSize = blockSize;
581 }
582 
583 
584 const void*
Buffer() const585 BMallocIO::Buffer() const
586 {
587 	return fData;
588 }
589 
590 
591 size_t
BufferLength() const592 BMallocIO::BufferLength() const
593 {
594 	return fLength;
595 }
596 
597 
598 // Private or Reserved
599 
BMallocIO(const BMallocIO &)600 BMallocIO::BMallocIO(const BMallocIO &)
601 {
602 	// copying not allowed...
603 }
604 
605 
606 BMallocIO &
operator =(const BMallocIO &)607 BMallocIO::operator=(const BMallocIO &)
608 {
609 	// copying not allowed...
610 	return *this;
611 }
612 
613 
614 // FBC
_ReservedMallocIO1()615 void BMallocIO::_ReservedMallocIO1() {}
_ReservedMallocIO2()616 void BMallocIO::_ReservedMallocIO2() {}
617