xref: /haiku/src/add-ons/kernel/file_systems/udf/Icb.cpp (revision 1d9d47fc72028bb71b5f232a877231e59cfe2438)
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