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