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 |
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 | ||||
19 | status_t | |||
20 | DirectoryIterator::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. */ | |||
83 | void | |||
84 | DirectoryIterator::Rewind() | |||
85 | { | |||
86 | fAtBeginning = true; | |||
87 | fPosition = 0; | |||
88 | } | |||
89 | ||||
90 | ||||
91 | // #pragma mark - Private methods | |||
92 | ||||
93 | ||||
94 | DirectoryIterator::DirectoryIterator(Icb *parent) | |||
95 | : | |||
96 | fAtBeginning(true), | |||
97 | fParent(parent), | |||
98 | fPosition(0) | |||
99 | { | |||
100 | } | |||
101 | ||||
102 | ||||
103 | Icb::Icb(Volume *volume, long_address address) | |||
104 | : | |||
105 | fVolume(volume), | |||
| ||||
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) | |||
120 | fInitStatus = B_BAD_VALUE((-2147483647 - 1) + 5); | |||
121 | ||||
122 | off_t block; | |||
123 | status_t status = fVolume->MapBlock(address, &block); | |||
| ||||
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 | ||||
151 | Icb::~Icb() | |||
152 | { | |||
153 | if (fFileCache != NULL__null) { | |||
154 | file_cache_delete(fFileCache); | |||
155 | file_map_delete(fFileMap); | |||
156 | } | |||
157 | } | |||
158 | ||||
159 | ||||
160 | status_t | |||
161 | Icb::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 | ||||
177 | status_t | |||
178 | Icb::InitCheck() | |||
179 | { | |||
180 | return fInitStatus; | |||
181 | } | |||
182 | ||||
183 | ||||
184 | void | |||
185 | Icb::GetAccessTime(struct timespec ×pec) 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 | ||||
201 | void | |||
202 | Icb::GetModificationTime(struct timespec ×pec) 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 | ||||
218 | status_t | |||
219 | Icb::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 | ||||
294 | status_t | |||
295 | Icb::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 | */ | |||
359 | template <class DescriptorList> | |||
360 | status_t | |||
361 | Icb::_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 | ||||
468 | status_t | |||
469 | Icb::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 | ||||
496 | template<class DescriptorList> | |||
497 | status_t | |||
498 | Icb::_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 | ||||
552 | status_t | |||
553 | Icb::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 | } |