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