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