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 } 51 52 status_t 53 Icb::InitCheck() 54 { 55 return fInitStatus; 56 } 57 58 time_t 59 Icb::AccessTime() 60 { 61 return make_time(FileEntry()->access_date_and_time()); 62 } 63 64 time_t 65 Icb::ModificationTime() 66 { 67 return make_time(FileEntry()->modification_date_and_time()); 68 } 69 70 status_t 71 Icb::Read(off_t pos, void *buffer, size_t *length, uint32 *block) 72 { 73 DEBUG_INIT_ETC("Icb", 74 ("pos: %Ld, buffer: %p, length: (%p)->%ld", pos, buffer, length, (length ? *length : 0))); 75 76 if (!buffer || !length || pos < 0) 77 RETURN(B_BAD_VALUE); 78 79 if (uint64(pos) >= Length()) { 80 *length = 0; 81 return B_OK; 82 } 83 84 switch (IcbTag().descriptor_flags()) { 85 case ICB_DESCRIPTOR_TYPE_SHORT: { 86 PRINT(("descriptor type: short\n")); 87 AllocationDescriptorList<ShortDescriptorAccessor> list(this, ShortDescriptorAccessor(0)); 88 RETURN(_Read(list, pos, buffer, length, block)); 89 break; 90 } 91 92 case ICB_DESCRIPTOR_TYPE_LONG: { 93 PRINT(("descriptor type: long\n")); 94 AllocationDescriptorList<LongDescriptorAccessor> list(this); 95 RETURN(_Read(list, pos, buffer, length, block)); 96 break; 97 } 98 99 case ICB_DESCRIPTOR_TYPE_EXTENDED: { 100 PRINT(("descriptor type: extended\n")); 101 // AllocationDescriptorList<ExtendedDescriptorAccessor> list(this, ExtendedDescriptorAccessor(0)); 102 // RETURN(_Read(list, pos, buffer, length, block)); 103 RETURN(B_ERROR); 104 break; 105 } 106 107 case ICB_DESCRIPTOR_TYPE_EMBEDDED: { 108 PRINT(("descriptor type: embedded\n")); 109 RETURN(B_ERROR); 110 break; 111 } 112 113 default: 114 PRINT(("Invalid icb descriptor flags! (flags = %d)\n", IcbTag().descriptor_flags())); 115 RETURN(B_BAD_VALUE); 116 break; 117 } 118 } 119 120 status_t 121 Icb::GetDirectoryIterator(DirectoryIterator **iterator) 122 { 123 status_t error = iterator ? B_OK : B_BAD_VALUE; 124 125 if (!error) { 126 *iterator = new(nothrow) DirectoryIterator(this); 127 if (*iterator) { 128 error = fIteratorList.PushBack(*iterator); 129 } else { 130 error = B_NO_MEMORY; 131 } 132 } 133 134 return error; 135 } 136 137 status_t 138 Icb::Find(const char *filename, vnode_id *id) 139 { 140 DEBUG_INIT_ETC("Icb", 141 ("filename: `%s', id: %p", filename, id)); 142 143 if (!filename || !id) 144 RETURN(B_BAD_VALUE); 145 146 DirectoryIterator *i; 147 status_t error = GetDirectoryIterator(&i); 148 if (!error) { 149 vnode_id entryId; 150 uint32 length = B_FILE_NAME_LENGTH; 151 char name[B_FILE_NAME_LENGTH]; 152 153 bool foundIt = false; 154 while (i->GetNextEntry(name, &length, &entryId) == B_OK) 155 { 156 if (strcmp(filename, name) == 0) { 157 foundIt = true; 158 break; 159 } 160 } 161 162 if (foundIt) { 163 *id = entryId; 164 } else { 165 error = B_ENTRY_NOT_FOUND; 166 } 167 } 168 169 RETURN(error); 170 } 171