1 #include "Icb.h" 2 3 #include "time.h" 4 5 #include "AllocationDescriptorList.h" 6 #include "DirectoryIterator.h" 7 #include "Utils.h" 8 #include "Volume.h" 9 10 using namespace Udf; 11 12 Icb::Icb(Volume *volume, udf_long_address address) 13 : fVolume(volume) 14 , fData(volume) 15 , fInitStatus(B_NO_INIT) 16 , fId(to_vnode_id(address)) 17 , fFileEntry(&fData) 18 , fExtendedEntry(&fData) 19 { 20 DEBUG_INIT_ETC(CF_PUBLIC, "Icb", ("volume: %p, address(block: %ld, " 21 "partition: %d, length: %ld)", volume, address.block(), 22 address.partition(), address.length())); 23 status_t err = volume ? B_OK : B_BAD_VALUE; 24 if (!err) { 25 off_t block; 26 err = fVolume->MapBlock(address, &block); 27 if (!err) { 28 udf_icb_header *header = reinterpret_cast<udf_icb_header*>(fData.SetTo(block)); 29 PDUMP(header); 30 err = header->tag().init_check(address.block()); 31 } 32 } 33 fInitStatus = err; 34 } 35 36 status_t 37 Icb::InitCheck() 38 { 39 return fInitStatus; 40 } 41 42 time_t 43 Icb::AccessTime() 44 { 45 return make_time(FileEntry()->access_date_and_time()); 46 } 47 48 time_t 49 Icb::ModificationTime() 50 { 51 return make_time(FileEntry()->modification_date_and_time()); 52 } 53 54 status_t 55 Icb::Read(off_t pos, void *buffer, size_t *length, uint32 *block) 56 { 57 DEBUG_INIT_ETC(CF_PUBLIC | CF_HIGH_VOLUME, "Icb", 58 ("pos: %Ld, buffer: %p, length: (%p)->%ld", pos, buffer, length, (length ? *length : 0))); 59 60 if (!buffer || !length || pos < 0) 61 RETURN(B_BAD_VALUE); 62 63 if (uint64(pos) >= Length()) { 64 *length = 0; 65 return B_OK; 66 } 67 68 switch (IcbTag().descriptor_flags()) { 69 case ICB_DESCRIPTOR_TYPE_SHORT: { 70 PRINT(("descriptor type: short\n")); 71 AllocationDescriptorList<ShortDescriptorAccessor> list(this, ShortDescriptorAccessor(0)); 72 RETURN(_Read(list, pos, buffer, length, block)); 73 break; 74 } 75 76 case ICB_DESCRIPTOR_TYPE_LONG: { 77 PRINT(("descriptor type: long\n")); 78 AllocationDescriptorList<LongDescriptorAccessor> list(this); 79 RETURN(_Read(list, pos, buffer, length, block)); 80 break; 81 } 82 83 case ICB_DESCRIPTOR_TYPE_EXTENDED: { 84 PRINT(("descriptor type: extended\n")); 85 // AllocationDescriptorList<ExtendedDescriptorAccessor> list(this, ExtendedDescriptorAccessor(0)); 86 // RETURN(_Read(list, pos, buffer, length, block)); 87 RETURN(B_ERROR); 88 break; 89 } 90 91 case ICB_DESCRIPTOR_TYPE_EMBEDDED: { 92 PRINT(("descriptor type: embedded\n")); 93 RETURN(B_ERROR); 94 break; 95 } 96 97 default: 98 PRINT(("Invalid icb descriptor flags! (flags = %d)\n", IcbTag().descriptor_flags())); 99 RETURN(B_BAD_VALUE); 100 break; 101 } 102 } 103 104 status_t 105 Icb::GetDirectoryIterator(DirectoryIterator **iterator) 106 { 107 status_t err = iterator ? B_OK : B_BAD_VALUE; 108 109 if (!err) { 110 *iterator = new DirectoryIterator(this); 111 if (*iterator) { 112 err = fIteratorList.PushBack(*iterator); 113 } else { 114 err = B_NO_MEMORY; 115 } 116 } 117 118 return err; 119 } 120 121 status_t 122 Icb::Find(const char *filename, vnode_id *id) 123 { 124 DEBUG_INIT_ETC(CF_PUBLIC | CF_DIRECTORY_OPS | CF_HIGH_VOLUME, "Icb", 125 ("filename: `%s', id: %p", filename, id)); 126 127 if (!filename || !id) 128 RETURN(B_BAD_VALUE); 129 130 DirectoryIterator *i; 131 status_t err = GetDirectoryIterator(&i); 132 if (!err) { 133 vnode_id entryId; 134 uint32 length = B_FILE_NAME_LENGTH; 135 char name[B_FILE_NAME_LENGTH]; 136 137 bool foundIt = false; 138 while (i->GetNextEntry(name, &length, &entryId) == B_OK) 139 { 140 if (strcmp(filename, name) == 0) { 141 foundIt = true; 142 break; 143 } 144 } 145 146 if (foundIt) { 147 *id = entryId; 148 } else { 149 err = B_ENTRY_NOT_FOUND; 150 } 151 } 152 153 RETURN(err); 154 } 155