Bug Summary

File:/boot/home/haiku/haiku/src/add-ons/kernel/file_systems/udf/Icb.cpp
Location:line 123, column 20
Description:Called C++ object pointer is null

Annotated Source Code

1/*
2 * Copyright 2012, Jérôme Duval, korli@users.berlios.de.
3 * Copyright 2010, Michael Lotz, mmlr@mlotz.ch.
4 * Copyright 2003, Tyler Dauwalder, tyler@dauwalder.net.
5 * Distributed under the terms of the MIT License.
6 */
7
8#include "Icb.h"
9
10#include "time.h"
11
12#include "AllocationDescriptorList.h"
13#include "Utils.h"
14#include "Volume.h"
15
16#include <file_cache.h>
17
18
19status_t
20DirectoryIterator::GetNextEntry(char *name, uint32 *length, ino_t *id)
21{
22 if (!id || !name || !length)
23 return B_BAD_VALUE((-2147483647 - 1) + 5);
24
25 TRACE(("DirectoryIterator::GetNextEntry: name = %p, length = %" B_PRIu32
26 ", id = %p, position = %" B_PRIdOFF ", parent length = %" B_PRIu64
27 "\n", name, *length, id, fPosition, Parent()->Length()));
28
29 status_t status = B_OK((int)0);
30 if (fAtBeginning) {
31 TRACE(("DirectoryIterator::GetNextEntry: .\n"));
32 sprintf(name, ".");
33 *length = 2;
34 *id = Parent()->Id();
35 fAtBeginning = false;
36 } else {
37 if (uint64(fPosition) >= Parent()->Length()) {
38 TRACE(("DirectoryIterator::GetNextEntry: end of dir\n"));
39 return B_ENTRY_NOT_FOUND(((-2147483647 - 1) + 0x6000) + 3);
40 }
41
42 uint8 data[kMaxFileIdSize(sizeof(file_id_descriptor)+512+3)];
43 file_id_descriptor *entry = (file_id_descriptor *)data;
44
45 uint32 block = 0;
46 off_t offset = fPosition;
47
48 size_t entryLength = kMaxFileIdSize(sizeof(file_id_descriptor)+512+3);
49 // First read in the static portion of the file id descriptor,
50 // then, based on the information therein, read in the variable
51 // length tail portion as well.
52 status = Parent()->Read(offset, entry, &entryLength, &block);
53 if (!status && entryLength >= sizeof(file_id_descriptor)
54 && entry->tag().init_check(block) == B_OK((int)0)) {
55 PDUMP(entry);;
56 offset += entry->total_length();
57
58 if (entry->is_parent()) {
59 TRACE(("DirectoryIterator::GetNextEntry: ..\n"));
60 sprintf(name, "..");
61 *length = 3;
62 } else {
63 UdfString string(entry->id(), entry->id_length());
64 TRACE(("DirectoryIterator::GetNextEntry: UfdString id == `%s', "
65 "length = %" B_PRIu32 "\n", string.Utf8(),
66 string.Utf8Length()));
67 DUMP(entry->icb());;
68 sprintf(name, "%s", string.Utf8());
69 *length = string.Utf8Length();
70 }
71 *id = to_vnode_id(entry->icb());
72 }
73
74 if (!status)
75 fPosition = offset;
76 }
77
78 return status;
79}
80
81
82/* \brief Rewinds the iterator to point to the first entry in the directory. */
83void
84DirectoryIterator::Rewind()
85{
86 fAtBeginning = true;
87 fPosition = 0;
88}
89
90
91// #pragma mark - Private methods
92
93
94DirectoryIterator::DirectoryIterator(Icb *parent)
95 :
96 fAtBeginning(true),
97 fParent(parent),
98 fPosition(0)
99{
100}
101
102
103Icb::Icb(Volume *volume, long_address address)
104 :
105 fVolume(volume),
1
Value assigned to field 'fVolume'
106 fData(volume),
107 fInitStatus(B_NO_INIT((-2147483647 - 1) + 13)),
108 fId(to_vnode_id(address)),
109 fPartition(address.partition()),
110 fFileEntry(&fData),
111 fExtendedEntry(&fData),
112 fFileCache(NULL__null),
113 fFileMap(NULL__null)
114{
115 TRACE(("Icb::Icb: volume = %p, address(block = %" B_PRIu32 ", partition = "
116 "%d, length = %" B_PRIu32 ")\n", volume, address.block(),
117 address.partition(), address.length()));
118
119 if (volume == NULL__null)
2
Assuming pointer value is null
3
Taking true branch
120 fInitStatus = B_BAD_VALUE((-2147483647 - 1) + 5);
121
122 off_t block;
123 status_t status = fVolume->MapBlock(address, &block);
4
Called C++ object pointer is null
124 if (!status) {
125 icb_header *header = (icb_header *)fData.SetTo(block);
126 if (header->tag().id() == TAGID_FILE_ENTRY) {
127 file_icb_entry *entry = (file_icb_entry *)header;
128 PDUMP(entry);;
129 (void)entry; // warning death
130 } else if (header->tag().id() == TAGID_EXTENDED_FILE_ENTRY) {
131 extended_file_icb_entry *entry = (extended_file_icb_entry *)header;
132 PDUMP(entry);;
133 (void)entry; // warning death
134 } else {
135 PDUMP(header);;
136 }
137 status = header->tag().init_check(address.block());
138 }
139
140 if (IsFile()) {
141 fFileCache = file_cache_create(fVolume->ID(), fId, Length());
142 fFileMap = file_map_create(fVolume->ID(), fId, Length());
143 }
144
145 fInitStatus = status;
146 TRACE(("Icb::Icb: status = 0x%" B_PRIx32 ", `%s'\n", status,
147 strerror(status)));
148}
149
150
151Icb::~Icb()
152{
153 if (fFileCache != NULL__null) {
154 file_cache_delete(fFileCache);
155 file_map_delete(fFileMap);
156 }
157}
158
159
160status_t
161Icb::GetDirectoryIterator(DirectoryIterator **iterator)
162{
163 status_t error = iterator ? B_OK((int)0) : B_BAD_VALUE((-2147483647 - 1) + 5);
164
165 if (!error) {
166 *iterator = new(std::nothrow) DirectoryIterator(this);
167 if (*iterator)
168 fIteratorList.Add(*iterator);
169 else
170 error = B_NO_MEMORY((-2147483647 - 1) + 0);
171 }
172
173 return error;
174}
175
176
177status_t
178Icb::InitCheck()
179{
180 return fInitStatus;
181}
182
183
184void
185Icb::GetAccessTime(struct timespec &timespec) const
186{
187 timestamp ts;
188 if (_Tag().id() == TAGID_EXTENDED_FILE_ENTRY)
189 ts = _ExtendedEntry()->access_date_and_time();
190 else
191 ts = _FileEntry()->access_date_and_time();
192
193 if (decode_time(ts, timespec) != B_OK((int)0)) {
194 decode_time(
195 fVolume->PrimaryVolumeDescriptor()->recording_date_and_time(),
196 timespec);
197 }
198}
199
200
201void
202Icb::GetModificationTime(struct timespec &timespec) const
203{
204 timestamp ts;
205 if (_Tag().id() == TAGID_EXTENDED_FILE_ENTRY)
206 ts = _ExtendedEntry()->modification_date_and_time();
207 else
208 ts = _FileEntry()->modification_date_and_time();
209
210 if (decode_time(ts, timespec) != B_OK((int)0)) {
211 decode_time(
212 fVolume->PrimaryVolumeDescriptor()->recording_date_and_time(),
213 timespec);
214 }
215}
216
217
218status_t
219Icb::FindBlock(uint32 logicalBlock, off_t &block, bool &recorded)
220{
221 off_t pos = logicalBlock << fVolume->BlockShift();
222 if (uint64(pos) >= Length()) {
223 block = -1;
224 return B_ERROR(-1);
225 }
226
227 DEBUG_INIT_ETC("Icb", ("pos: %" B_PRIdOFF, pos));;
228
229 status_t status = B_OK((int)0);
230 long_address extent;
231 bool isEmpty = false;
232 recorded = false;
233
234 switch (_IcbTag().descriptor_flags()) {
235 case ICB_DESCRIPTOR_TYPE_SHORT:
236 {
237 TRACE(("Icb::FindBlock: descriptor type -> short\n"));
238 AllocationDescriptorList<ShortDescriptorAccessor> list(this,
239 ShortDescriptorAccessor(fPartition));
240 status = list.FindExtent(pos, &extent, &isEmpty);
241 if (status != B_OK((int)0)) {
242 TRACE_ERROR(("Icb::FindBlock: error finding extent for offset "dprintf ("Icb::FindBlock: error finding extent for offset " "%"
"ll" "d" ". status = 0x%" "l" "x" " `%s'\n", pos, status, strerror
(status))
243 "%" B_PRIdOFF ". status = 0x%" B_PRIx32 " `%s'\n", pos, status,dprintf ("Icb::FindBlock: error finding extent for offset " "%"
"ll" "d" ". status = 0x%" "l" "x" " `%s'\n", pos, status, strerror
(status))
244 strerror(status)))dprintf ("Icb::FindBlock: error finding extent for offset " "%"
"ll" "d" ". status = 0x%" "l" "x" " `%s'\n", pos, status, strerror
(status))
;
245 }
246 break;
247 }
248
249 case ICB_DESCRIPTOR_TYPE_LONG:
250 {
251 TRACE(("Icb::FindBlock: descriptor type -> long\n"));
252 AllocationDescriptorList<LongDescriptorAccessor> list(this);
253 status = list.FindExtent(pos, &extent, &isEmpty);
254 if (status != B_OK((int)0)) {
255 TRACE_ERROR(("Icb::FindBlock: error finding extent for offset "dprintf ("Icb::FindBlock: error finding extent for offset " "%"
"ll" "d" ". status = 0x%" "l" "x" " `%s'\n", pos, status, strerror
(status))
256 "%" B_PRIdOFF ". status = 0x%" B_PRIx32 " `%s'\n", pos,dprintf ("Icb::FindBlock: error finding extent for offset " "%"
"ll" "d" ". status = 0x%" "l" "x" " `%s'\n", pos, status, strerror
(status))
257 status, strerror(status)))dprintf ("Icb::FindBlock: error finding extent for offset " "%"
"ll" "d" ". status = 0x%" "l" "x" " `%s'\n", pos, status, strerror
(status))
;
258 }
259 break;
260 }
261
262 case ICB_DESCRIPTOR_TYPE_EXTENDED:
263 {
264 TRACE(("Icb::FindBlock: descriptor type -> extended\n"));
265// AllocationDescriptorList<ExtendedDescriptorAccessor> list(this, ExtendedDescriptorAccessor(0));
266// RETURN(_Read(list, pos, buffer, length, block));
267 RETURN(B_ERROR)return (-1);;
268 break;
269 }
270
271 case ICB_DESCRIPTOR_TYPE_EMBEDDED:
272 {
273 TRACE(("Icb::FindBlock: descriptor type: embedded\n"));
274 RETURN(B_ERROR)return (-1);;
275 break;
276 }
277
278 default:
279 TRACE(("Icb::FindBlock: invalid icb descriptor flags! (flags = %d)\n",
280 _IcbTag().descriptor_flags()));
281 RETURN(B_BAD_VALUE)return ((-2147483647 - 1) + 5);;
282 break;
283 }
284
285 if (status == B_OK((int)0)) {
286 block = extent.block();
287 recorded = extent.type() == EXTENT_TYPE_RECORDED;
288 TRACE(("Icb::FindBlock: block %" B_PRIdOFF "\n", block));
289 }
290 return status;
291}
292
293
294status_t
295Icb::Read(off_t pos, void *buffer, size_t *length, uint32 *block)
296{
297 TRACE(("Icb::Read: pos = %" B_PRIdOFF ", buffer = %p, length = (%p)->%ld\n",
298 pos, buffer, length, (length ? *length : 0)));
299
300 if (!buffer || !length || pos < 0)
301 return B_BAD_VALUE((-2147483647 - 1) + 5);
302
303 if (uint64(pos) >= Length()) {
304 *length = 0;
305 return B_OK((int)0);
306 }
307
308 DEBUG_INIT_ETC("Icb", ("pos: %lld, length: %ld", pos, *length));;
309
310 if (fFileCache != NULL__null)
311 return file_cache_read(fFileCache, NULL__null, pos, buffer, length);
312
313 switch (_IcbTag().descriptor_flags()) {
314 case ICB_DESCRIPTOR_TYPE_SHORT:
315 {
316 TRACE(("Icb::Read: descriptor type -> short\n"));
317 AllocationDescriptorList<ShortDescriptorAccessor> list(this,
318 ShortDescriptorAccessor(fPartition));
319 RETURN(_Read(list, pos, buffer, length, block))return _Read(list, pos, buffer, length, block);;
320 break;
321 }
322
323 case ICB_DESCRIPTOR_TYPE_LONG:
324 {
325 TRACE(("Icb::Read: descriptor type -> long\n"));
326 AllocationDescriptorList<LongDescriptorAccessor> list(this);
327 RETURN(_Read(list, pos, buffer, length, block))return _Read(list, pos, buffer, length, block);;
328 break;
329 }
330
331 case ICB_DESCRIPTOR_TYPE_EXTENDED:
332 {
333 TRACE(("Icb::Read: descriptor type -> extended\n"));
334// AllocationDescriptorList<ExtendedDescriptorAccessor> list(this, ExtendedDescriptorAccessor(0));
335// RETURN(_Read(list, pos, buffer, length, block));
336 RETURN(B_ERROR)return (-1);;
337 break;
338 }
339
340 case ICB_DESCRIPTOR_TYPE_EMBEDDED:
341 {
342 TRACE(("Icb::Read: descriptor type: embedded\n"));
343 RETURN(B_ERROR)return (-1);;
344 break;
345 }
346
347 default:
348 TRACE(("Icb::Read: invalid icb descriptor flags! (flags = %d)\n",
349 _IcbTag().descriptor_flags()));
350 RETURN(B_BAD_VALUE)return ((-2147483647 - 1) + 5);;
351 break;
352 }
353}
354
355
356/*! \brief Does the dirty work of reading using the given DescriptorList object
357 to access the allocation descriptors properly.
358*/
359template <class DescriptorList>
360status_t
361Icb::_Read(DescriptorList &list, off_t pos, void *_buffer, size_t *length, uint32 *block)
362{
363 TRACE(("Icb::_Read(): list = %p, pos = %" B_PRIdOFF ", buffer = %p, "
364 "length = %ld\n", &list, pos, _buffer, (length ? *length : 0)));
365
366 uint64 bytesLeftInFile = uint64(pos) > Length() ? 0 : Length() - pos;
367 size_t bytesLeft = (*length >= bytesLeftInFile) ? bytesLeftInFile : *length;
368 size_t bytesRead = 0;
369
370 Volume *volume = GetVolume();
371 status_t status = B_OK((int)0);
372 uint8 *buffer = (uint8 *)_buffer;
373 bool isFirstBlock = true;
374
375 while (bytesLeft > 0) {
376
377 TRACE(("Icb::_Read(): pos: %" B_PRIdOFF ", bytesLeft: %ld\n", pos,
378 bytesLeft));
379 long_address extent;
380 bool isEmpty = false;
381 status = list.FindExtent(pos, &extent, &isEmpty);
382 if (status != B_OK((int)0)) {
383 TRACE_ERROR(("Icb::_Read: error finding extent for offset %"dprintf ("Icb::_Read: error finding extent for offset %" "ll"
"d" ". status = 0x%" "l" "x" " `%s'\n", pos, status, strerror
(status))
384 B_PRIdOFF ". status = 0x%" B_PRIx32 " `%s'\n", pos, status,dprintf ("Icb::_Read: error finding extent for offset %" "ll"
"d" ". status = 0x%" "l" "x" " `%s'\n", pos, status, strerror
(status))
385 strerror(status)))dprintf ("Icb::_Read: error finding extent for offset %" "ll"
"d" ". status = 0x%" "l" "x" " `%s'\n", pos, status, strerror
(status))
;
386 break;
387 }
388
389 TRACE(("Icb::_Read(): found extent for offset %" B_PRIdOFF ": (block: "
390 "%" B_PRIu32 ", partition: %d, length: %" B_PRIu32 ", type: %d)\n",
391 pos, extent.block(), extent.partition(), extent.length(),
392 extent.type()));
393
394 switch (extent.type()) {
395 case EXTENT_TYPE_RECORDED:
396 isEmpty = false;
397 break;
398
399 case EXTENT_TYPE_ALLOCATED:
400 case EXTENT_TYPE_UNALLOCATED:
401 isEmpty = true;
402 break;
403
404 default:
405 TRACE_ERROR(("Icb::_Read(): Invalid extent type found: %d\n",dprintf ("Icb::_Read(): Invalid extent type found: %d\n", extent
.type())
406 extent.type()))dprintf ("Icb::_Read(): Invalid extent type found: %d\n", extent
.type())
;
407 status = B_ERROR(-1);
408 break;
409 }
410
411 if (status != B_OK((int)0))
412 break;
413
414 // Note the unmapped first block of the total read in
415 // the block output parameter if provided
416 if (isFirstBlock) {
417 isFirstBlock = false;
418 if (block)
419 *block = extent.block();
420 }
421
422 off_t blockOffset
423 = pos - off_t((pos >> volume->BlockShift()) << volume->BlockShift());
424
425 size_t readLength = volume->BlockSize() - blockOffset;
426 if (bytesLeft < readLength)
427 readLength = bytesLeft;
428 if (extent.length() < readLength)
429 readLength = extent.length();
430
431 TRACE(("Icb::_Read: reading block. offset = %" B_PRIdOFF
432 ", length: %ld\n", blockOffset, readLength));
433
434 if (isEmpty) {
435 TRACE(("Icb::_Read: reading %ld empty bytes as zeros\n",
436 readLength));
437 memset(buffer, 0, readLength);
438 } else {
439 off_t diskBlock;
440 status = volume->MapBlock(extent, &diskBlock);
441 if (status != B_OK((int)0)) {
442 TRACE_ERROR(("Icb::_Read: could not map extent\n"))dprintf ("Icb::_Read: could not map extent\n");
443 break;
444 }
445
446 TRACE(("Icb::_Read: %ld bytes from disk block %" B_PRIdOFF " using"
447 " block_cache_get_etc()\n", readLength, diskBlock));
448 uint8 *data = (uint8*)block_cache_get_etc(volume->BlockCache(),
449 diskBlock, 0, readLength);
450 if (data == NULL__null)
451 break;
452 memcpy(buffer, data + blockOffset, readLength);
453 block_cache_put(volume->BlockCache(), diskBlock);
454 }
455
456 bytesLeft -= readLength;
457 bytesRead += readLength;
458 pos += readLength;
459 buffer += readLength;
460 }
461
462 *length = bytesRead;
463
464 return status;
465}
466
467
468status_t
469Icb::GetFileMap(off_t offset, size_t size, file_io_vec *vecs, size_t *count)
470{
471 switch (_IcbTag().descriptor_flags()) {
472 case ICB_DESCRIPTOR_TYPE_SHORT:
473 {
474 AllocationDescriptorList<ShortDescriptorAccessor> list(this,
475 ShortDescriptorAccessor(0));
476 return _GetFileMap(list, offset, size, vecs, count);
477 }
478
479 case ICB_DESCRIPTOR_TYPE_LONG:
480 {
481 AllocationDescriptorList<LongDescriptorAccessor> list(this);
482 return _GetFileMap(list, offset, size, vecs, count);
483 }
484
485 case ICB_DESCRIPTOR_TYPE_EXTENDED:
486 case ICB_DESCRIPTOR_TYPE_EMBEDDED:
487 default:
488 {
489 // TODO: implement?
490 return B_UNSUPPORTED(((-2147483647 - 1) + 0x6000) + 14);
491 }
492 }
493}
494
495
496template<class DescriptorList>
497status_t
498Icb::_GetFileMap(DescriptorList &list, off_t offset, size_t size,
499 struct file_io_vec *vecs, size_t *count)
500{
501 size_t index = 0;
502 size_t max = *count;
503
504 while (true) {
505 long_address extent;
506 bool isEmpty = false;
507 status_t status = list.FindExtent(offset, &extent, &isEmpty);
508 if (status != B_OK((int)0))
509 return status;
510
511 switch (extent.type()) {
512 case EXTENT_TYPE_RECORDED:
513 isEmpty = false;
514 break;
515
516 case EXTENT_TYPE_ALLOCATED:
517 case EXTENT_TYPE_UNALLOCATED:
518 isEmpty = true;
519 break;
520
521 default:
522 return B_ERROR(-1);
523 }
524
525 if (isEmpty)
526 vecs[index].offset = -1;
527 else {
528 off_t diskBlock;
529 fVolume->MapBlock(extent, &diskBlock);
530 vecs[index].offset = diskBlock << fVolume->BlockShift();
531 }
532
533 off_t length = extent.length();
534 vecs[index].length = length;
535
536 offset += length;
537 size -= length;
538 index++;
539
540 if (index >= max || (off_t)size <= vecs[index - 1].length
541 || offset >= (off_t)Length()) {
542 *count = index;
543 return index >= max ? B_BUFFER_OVERFLOW((((-2147483647 - 1) + 0x7000) + 41)) : B_OK((int)0);
544 }
545 }
546
547 // can never get here
548 return B_ERROR(-1);
549}
550
551
552status_t
553Icb::Find(const char *filename, ino_t *id)
554{
555 TRACE(("Icb::Find: filename = `%s', id = %p\n", filename, id));
556
557 if (!filename || !id)
558 return B_BAD_VALUE((-2147483647 - 1) + 5);
559
560 DirectoryIterator *i;
561 status_t status = GetDirectoryIterator(&i);
562 if (status != B_OK((int)0))
563 return status;
564
565 ino_t entryId;
566 uint32 length = B_FILE_NAME_LENGTH(256);
567 char name[B_FILE_NAME_LENGTH(256)];
568
569 bool foundIt = false;
570 while (i->GetNextEntry(name, &length, &entryId) == B_OK((int)0)) {
571 if (strcmp(filename, name) == 0) {
572 foundIt = true;
573 break;
574 }
575
576 // reset overwritten length
577 length = B_FILE_NAME_LENGTH(256);
578 }
579
580 if (foundIt)
581 *id = entryId;
582 else
583 status = B_ENTRY_NOT_FOUND(((-2147483647 - 1) + 0x6000) + 3);
584
585 return status;
586}