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