xref: /haiku/src/add-ons/kernel/file_systems/iso9660/iso9660.cpp (revision 56b2febaadfa19cec3918e0018a6fa5f1161a274)
1eb097431SAxel Dörfler /*
2eb097431SAxel Dörfler  * Copyright 1999, Be Incorporated.   All Rights Reserved.
3eb097431SAxel Dörfler  * This file may be used under the terms of the Be Sample Code License.
4eb097431SAxel Dörfler  *
5eb097431SAxel Dörfler  * Copyright 2001, pinc Software.  All Rights Reserved.
6eb097431SAxel Dörfler  */
7eb097431SAxel Dörfler 
8eb097431SAxel Dörfler 
9eb097431SAxel Dörfler #include "iso9660.h"
10eb097431SAxel Dörfler 
11eb097431SAxel Dörfler #include <ctype.h>
12f47bff08SAxel Dörfler 
13f47bff08SAxel Dörfler #ifndef FS_SHELL
14eb097431SAxel Dörfler #	include <dirent.h>
15eb097431SAxel Dörfler #	include <fcntl.h>
16eb097431SAxel Dörfler #	include <stdlib.h>
17eb097431SAxel Dörfler #	include <string.h>
18eb097431SAxel Dörfler #	include <sys/stat.h>
19eb097431SAxel Dörfler #	include <time.h>
20eb097431SAxel Dörfler #	include <unistd.h>
21eb097431SAxel Dörfler 
22eb097431SAxel Dörfler #	include <ByteOrder.h>
23eb097431SAxel Dörfler #	include <Drivers.h>
24eb097431SAxel Dörfler #	include <KernelExport.h>
25eb097431SAxel Dörfler #	include <fs_cache.h>
26f47bff08SAxel Dörfler #endif
27eb097431SAxel Dörfler 
28eb097431SAxel Dörfler #include "rock_ridge.h"
29eb097431SAxel Dörfler 
30eb097431SAxel Dörfler //#define TRACE_ISO9660 1
31eb097431SAxel Dörfler #if TRACE_ISO9660
32eb097431SAxel Dörfler #	define TRACE(x) dprintf x
33eb097431SAxel Dörfler #else
34eb097431SAxel Dörfler #	define TRACE(x) ;
35eb097431SAxel Dörfler #endif
36eb097431SAxel Dörfler 
37eb097431SAxel Dörfler 
38eb097431SAxel Dörfler // Just needed here
39eb097431SAxel Dörfler static status_t unicode_to_utf8(const char	*src, int32	*srcLen, char *dst,
40eb097431SAxel Dörfler 	int32 *dstLen);
41eb097431SAxel Dörfler 
42eb097431SAxel Dörfler 
43eb097431SAxel Dörfler // ISO9660 should start with this string
44eb097431SAxel Dörfler const char *kISO9660IDString = "CD001";
45eb097431SAxel Dörfler 
46eb097431SAxel Dörfler 
47eb097431SAxel Dörfler static int
48eb097431SAxel Dörfler get_device_block_size(int fd)
49eb097431SAxel Dörfler {
50eb097431SAxel Dörfler 	device_geometry geometry;
51eb097431SAxel Dörfler 
52eb097431SAxel Dörfler 	if (ioctl(fd, B_GET_GEOMETRY, &geometry) < 0)  {
53eb097431SAxel Dörfler 		struct stat st;
54eb097431SAxel Dörfler 		if (fstat(fd, &st) < 0 || S_ISDIR(st.st_mode))
55eb097431SAxel Dörfler 			return 0;
56eb097431SAxel Dörfler 
57eb097431SAxel Dörfler 		return 512;   /* just assume it's a plain old file or something */
58eb097431SAxel Dörfler 	}
59eb097431SAxel Dörfler 
60eb097431SAxel Dörfler 	return geometry.bytes_per_sector;
61eb097431SAxel Dörfler }
62eb097431SAxel Dörfler 
63eb097431SAxel Dörfler 
64eb097431SAxel Dörfler // From EncodingComversions.cpp
65eb097431SAxel Dörfler 
66eb097431SAxel Dörfler // Pierre's (modified) Uber Macro
67eb097431SAxel Dörfler 
68eb097431SAxel Dörfler // NOTE: iso9660 seems to store the unicode text in big-endian form
69eb097431SAxel Dörfler #define u_to_utf8(str, uni_str)\
70eb097431SAxel Dörfler {\
71eb097431SAxel Dörfler 	if ((B_BENDIAN_TO_HOST_INT16(uni_str[0])&0xff80) == 0)\
72eb097431SAxel Dörfler 		*str++ = B_BENDIAN_TO_HOST_INT16(*uni_str++);\
73eb097431SAxel Dörfler 	else if ((B_BENDIAN_TO_HOST_INT16(uni_str[0])&0xf800) == 0) {\
74eb097431SAxel Dörfler 		str[0] = 0xc0|(B_BENDIAN_TO_HOST_INT16(uni_str[0])>>6);\
75eb097431SAxel Dörfler 		str[1] = 0x80|(B_BENDIAN_TO_HOST_INT16(*uni_str++)&0x3f);\
76eb097431SAxel Dörfler 		str += 2;\
77eb097431SAxel Dörfler 	} else if ((B_BENDIAN_TO_HOST_INT16(uni_str[0])&0xfc00) != 0xd800) {\
78eb097431SAxel Dörfler 		str[0] = 0xe0|(B_BENDIAN_TO_HOST_INT16(uni_str[0])>>12);\
79eb097431SAxel Dörfler 		str[1] = 0x80|((B_BENDIAN_TO_HOST_INT16(uni_str[0])>>6)&0x3f);\
80eb097431SAxel Dörfler 		str[2] = 0x80|(B_BENDIAN_TO_HOST_INT16(*uni_str++)&0x3f);\
81eb097431SAxel Dörfler 		str += 3;\
82eb097431SAxel Dörfler 	} else {\
83eb097431SAxel Dörfler 		int   val;\
84eb097431SAxel Dörfler 		val = ((B_BENDIAN_TO_HOST_INT16(uni_str[0])-0xd7c0)<<10) | (B_BENDIAN_TO_HOST_INT16(uni_str[1])&0x3ff);\
85eb097431SAxel Dörfler 		str[0] = 0xf0 | (val>>18);\
86eb097431SAxel Dörfler 		str[1] = 0x80 | ((val>>12)&0x3f);\
87eb097431SAxel Dörfler 		str[2] = 0x80 | ((val>>6)&0x3f);\
88eb097431SAxel Dörfler 		str[3] = 0x80 | (val&0x3f);\
89eb097431SAxel Dörfler 		uni_str += 2; str += 4;\
90eb097431SAxel Dörfler 	}\
91eb097431SAxel Dörfler }
92eb097431SAxel Dörfler 
93eb097431SAxel Dörfler 
94eb097431SAxel Dörfler static status_t
95eb097431SAxel Dörfler unicode_to_utf8(const char	*src, int32	*srcLen, char *dst, int32 *dstLen)
96eb097431SAxel Dörfler {
97eb097431SAxel Dörfler 	int32 srcLimit = *srcLen;
98eb097431SAxel Dörfler 	int32 dstLimit = *dstLen;
99eb097431SAxel Dörfler 	int32 srcCount = 0;
100eb097431SAxel Dörfler 	int32 dstCount = 0;
101eb097431SAxel Dörfler 
102eb097431SAxel Dörfler 	for (srcCount = 0; srcCount < srcLimit; srcCount += 2) {
103eb097431SAxel Dörfler 		uint16 *UNICODE = (uint16 *)&src[srcCount];
104f47bff08SAxel Dörfler 		uint8 utf8[4];
105f47bff08SAxel Dörfler 		uint8 *UTF8 = utf8;
106eb097431SAxel Dörfler 		int32 utf8Len;
107eb097431SAxel Dörfler 		int32 j;
108eb097431SAxel Dörfler 
109eb097431SAxel Dörfler 		u_to_utf8(UTF8, UNICODE);
110eb097431SAxel Dörfler 
111eb097431SAxel Dörfler 		utf8Len = UTF8 - utf8;
112eb097431SAxel Dörfler 		if (dstCount + utf8Len > dstLimit)
113eb097431SAxel Dörfler 			break;
114eb097431SAxel Dörfler 
115eb097431SAxel Dörfler 		for (j = 0; j < utf8Len; j++)
116eb097431SAxel Dörfler 			dst[dstCount + j] = utf8[j];
117eb097431SAxel Dörfler 		dstCount += utf8Len;
118eb097431SAxel Dörfler 	}
119eb097431SAxel Dörfler 
120eb097431SAxel Dörfler 	*srcLen = srcCount;
121eb097431SAxel Dörfler 	*dstLen = dstCount;
122eb097431SAxel Dörfler 
123eb097431SAxel Dörfler 	return dstCount > 0 ? B_NO_ERROR : B_ERROR;
124eb097431SAxel Dörfler }
125eb097431SAxel Dörfler 
126eb097431SAxel Dörfler 
127eb097431SAxel Dörfler static void
128eb097431SAxel Dörfler sanitize_iso_name(iso9660_inode* node, bool removeTrailingPoints)
129eb097431SAxel Dörfler {
130eb097431SAxel Dörfler 	// Get rid of semicolons, which are used to delineate file versions.
131eb097431SAxel Dörfler 	if (char* semi = strchr(node->name, ';')) {
132eb097431SAxel Dörfler 		semi[0] = '\0';
133eb097431SAxel Dörfler 		node->name_length = semi - node->name;
134eb097431SAxel Dörfler 	}
135eb097431SAxel Dörfler 
136eb097431SAxel Dörfler 	if (removeTrailingPoints) {
137eb097431SAxel Dörfler 		// Get rid of trailing points
138eb097431SAxel Dörfler 		if (node->name_length > 2 && node->name[node->name_length - 1] == '.')
139eb097431SAxel Dörfler 			node->name[--node->name_length] = '\0';
140eb097431SAxel Dörfler 	}
141eb097431SAxel Dörfler }
142eb097431SAxel Dörfler 
143eb097431SAxel Dörfler 
144eb097431SAxel Dörfler static int
145eb097431SAxel Dörfler init_volume_date(ISOVolDate *date, char *buffer)
146eb097431SAxel Dörfler {
147eb097431SAxel Dörfler 	memcpy(date, buffer, 17);
148eb097431SAxel Dörfler 	return 0;
149eb097431SAxel Dörfler }
150eb097431SAxel Dörfler 
151eb097431SAxel Dörfler 
152eb097431SAxel Dörfler static int
153eb097431SAxel Dörfler init_node_date(ISORecDate *date, char *buffer)
154eb097431SAxel Dörfler {
155eb097431SAxel Dörfler 	memcpy(date, buffer, 7);
156eb097431SAxel Dörfler 	return 0;
157eb097431SAxel Dörfler }
158eb097431SAxel Dörfler 
159eb097431SAxel Dörfler 
160eb097431SAxel Dörfler static status_t
161eb097431SAxel Dörfler InitVolDesc(iso9660_volume *volume, char *buffer)
162eb097431SAxel Dörfler {
163eb097431SAxel Dörfler 	TRACE(("InitVolDesc - ENTER\n"));
164eb097431SAxel Dörfler 
165eb097431SAxel Dörfler 	volume->volDescType = *(uint8 *)buffer++;
166eb097431SAxel Dörfler 
167eb097431SAxel Dörfler 	volume->stdIDString[5] = '\0';
168eb097431SAxel Dörfler 	strncpy(volume->stdIDString, buffer, 5);
169eb097431SAxel Dörfler 	buffer += 5;
170eb097431SAxel Dörfler 
171eb097431SAxel Dörfler 	volume->volDescVersion = *(uint8 *)buffer;
172eb097431SAxel Dörfler 	buffer += 2; // 8th byte unused
173eb097431SAxel Dörfler 
174eb097431SAxel Dörfler 	volume->systemIDString[32] = '\0';
175eb097431SAxel Dörfler 	strncpy(volume->systemIDString, buffer, 32);
176eb097431SAxel Dörfler 	buffer += 32;
177eb097431SAxel Dörfler 	TRACE(("InitVolDesc - system id string is %s\n", volume->systemIDString));
178eb097431SAxel Dörfler 
179eb097431SAxel Dörfler 	volume->volIDString[32] = '\0';
180eb097431SAxel Dörfler 	strncpy(volume->volIDString, buffer, 32);
181eb097431SAxel Dörfler 	buffer += (32 + 80-73 + 1);	// bytes 80-73 unused
182eb097431SAxel Dörfler 	TRACE(("InitVolDesc - volume id string is %s\n", volume->volIDString));
183eb097431SAxel Dörfler 
184eb097431SAxel Dörfler 	volume->volSpaceSize[LSB_DATA] = *(uint32 *)buffer;
185eb097431SAxel Dörfler 	buffer += 4;
186eb097431SAxel Dörfler 	volume->volSpaceSize[MSB_DATA] = *(uint32 *)buffer;
187eb097431SAxel Dörfler 	buffer+= (4 + 120-89 + 1); 		// bytes 120-89 unused
188eb097431SAxel Dörfler 
189eb097431SAxel Dörfler 	volume->volSetSize[LSB_DATA] = *(uint16*)buffer;
190eb097431SAxel Dörfler 	buffer += 2;
191eb097431SAxel Dörfler 	volume->volSetSize[MSB_DATA] = *(uint16*)buffer;
192eb097431SAxel Dörfler 	buffer += 2;
193eb097431SAxel Dörfler 
194eb097431SAxel Dörfler 	volume->volSeqNum[LSB_DATA] = *(uint16*)buffer;
195eb097431SAxel Dörfler 	buffer += 2;
196eb097431SAxel Dörfler 	volume->volSeqNum[MSB_DATA] = *(uint16*)buffer;
197eb097431SAxel Dörfler 	buffer += 2;
198eb097431SAxel Dörfler 
199eb097431SAxel Dörfler 	volume->logicalBlkSize[LSB_DATA] = *(uint16*)buffer;
200eb097431SAxel Dörfler 	buffer += 2;
201eb097431SAxel Dörfler 	volume->logicalBlkSize[MSB_DATA] = *(uint16*)buffer;
202eb097431SAxel Dörfler 	buffer += 2;
203eb097431SAxel Dörfler 
204eb097431SAxel Dörfler 	volume->pathTblSize[LSB_DATA] = *(uint32*)buffer;
205eb097431SAxel Dörfler 	buffer += 4;
206eb097431SAxel Dörfler 	volume->pathTblSize[MSB_DATA] = *(uint32*)buffer;
207eb097431SAxel Dörfler 	buffer += 4;
208eb097431SAxel Dörfler 
209eb097431SAxel Dörfler 	volume->lPathTblLoc[LSB_DATA] = *(uint16*)buffer;
210eb097431SAxel Dörfler 	buffer += 2;
211eb097431SAxel Dörfler 	volume->lPathTblLoc[MSB_DATA] = *(uint16*)buffer;
212eb097431SAxel Dörfler 	buffer += 2;
213eb097431SAxel Dörfler 
214eb097431SAxel Dörfler 	volume->optLPathTblLoc[LSB_DATA] = *(uint16*)buffer;
215eb097431SAxel Dörfler 	buffer += 2;
216eb097431SAxel Dörfler 	volume->optLPathTblLoc[MSB_DATA] = *(uint16*)buffer;
217eb097431SAxel Dörfler 	buffer += 2;
218eb097431SAxel Dörfler 
219eb097431SAxel Dörfler 	volume->mPathTblLoc[LSB_DATA] = *(uint16*)buffer;
220eb097431SAxel Dörfler 	buffer += 2;
221eb097431SAxel Dörfler 	volume->mPathTblLoc[MSB_DATA] = *(uint16*)buffer;
222eb097431SAxel Dörfler 	buffer += 2;
223eb097431SAxel Dörfler 
224eb097431SAxel Dörfler 	volume->optMPathTblLoc[LSB_DATA] = *(uint16*)buffer;
225eb097431SAxel Dörfler 	buffer += 2;
226eb097431SAxel Dörfler 	volume->optMPathTblLoc[MSB_DATA] = *(uint16*)buffer;
227eb097431SAxel Dörfler 	buffer += 2;
228eb097431SAxel Dörfler 
229eb097431SAxel Dörfler 	// Fill in directory record.
230*56b2febaSMichael Lotz 	volume->joliet_level = 0;
231*56b2febaSMichael Lotz 	InitNode(volume, &volume->rootDirRec, buffer, NULL);
232eb097431SAxel Dörfler 
233eb097431SAxel Dörfler 	volume->rootDirRec.id = ISO_ROOTNODE_ID;
234eb097431SAxel Dörfler 	buffer += 34;
235eb097431SAxel Dörfler 
236eb097431SAxel Dörfler 	volume->volSetIDString[128] = '\0';
237eb097431SAxel Dörfler 	strncpy(volume->volSetIDString, buffer, 128);
238eb097431SAxel Dörfler 	buffer += 128;
239eb097431SAxel Dörfler 	TRACE(("InitVolDesc - volume set id string is %s\n", volume->volSetIDString));
240eb097431SAxel Dörfler 
241eb097431SAxel Dörfler 	volume->pubIDString[128] = '\0';
242eb097431SAxel Dörfler 	strncpy(volume->pubIDString, buffer, 128);
243eb097431SAxel Dörfler 	buffer += 128;
244eb097431SAxel Dörfler 	TRACE(("InitVolDesc - volume pub id string is %s\n", volume->pubIDString));
245eb097431SAxel Dörfler 
246eb097431SAxel Dörfler 	volume->dataPreparer[128] = '\0';
247eb097431SAxel Dörfler 	strncpy(volume->dataPreparer, buffer, 128);
248eb097431SAxel Dörfler 	buffer += 128;
249eb097431SAxel Dörfler 	TRACE(("InitVolDesc - volume dataPreparer string is %s\n", volume->dataPreparer));
250eb097431SAxel Dörfler 
251eb097431SAxel Dörfler 	volume->appIDString[128] = '\0';
252eb097431SAxel Dörfler 	strncpy(volume->appIDString, buffer, 128);
253eb097431SAxel Dörfler 	buffer += 128;
254eb097431SAxel Dörfler 	TRACE(("InitVolDesc - volume app id string is %s\n", volume->appIDString));
255eb097431SAxel Dörfler 
256eb097431SAxel Dörfler 	volume->copyright[38] = '\0';
257eb097431SAxel Dörfler 	strncpy(volume->copyright, buffer, 38);
258eb097431SAxel Dörfler 	buffer += 38;
259eb097431SAxel Dörfler 	TRACE(("InitVolDesc - copyright is %s\n", volume->copyright));
260eb097431SAxel Dörfler 
261eb097431SAxel Dörfler 	volume->abstractFName[38] = '\0';
262eb097431SAxel Dörfler 	strncpy(volume->abstractFName, buffer, 38);
263eb097431SAxel Dörfler 	buffer += 38;
264eb097431SAxel Dörfler 
265eb097431SAxel Dörfler 	volume->biblioFName[38] = '\0';
266eb097431SAxel Dörfler 	strncpy(volume->biblioFName, buffer, 38);
267eb097431SAxel Dörfler 	buffer += 38;
268eb097431SAxel Dörfler 
269eb097431SAxel Dörfler 	init_volume_date(&volume->createDate, buffer);
270eb097431SAxel Dörfler 	buffer += 17;
271eb097431SAxel Dörfler 
272eb097431SAxel Dörfler 	init_volume_date(&volume->modDate, buffer);
273eb097431SAxel Dörfler 	buffer += 17;
274eb097431SAxel Dörfler 
275eb097431SAxel Dörfler 	init_volume_date(&volume->expireDate, buffer);
276eb097431SAxel Dörfler 	buffer += 17;
277eb097431SAxel Dörfler 
278eb097431SAxel Dörfler 	init_volume_date(&volume->effectiveDate, buffer);
279eb097431SAxel Dörfler 	buffer += 17;
280eb097431SAxel Dörfler 
281eb097431SAxel Dörfler 	volume->fileStructVers = *(uint8*)buffer;
282eb097431SAxel Dörfler 	return B_OK;
283eb097431SAxel Dörfler }
284eb097431SAxel Dörfler 
285eb097431SAxel Dörfler 
286eb097431SAxel Dörfler static status_t
287*56b2febaSMichael Lotz parse_rock_ridge(iso9660_volume* volume, iso9660_inode* node, char* buffer,
288*56b2febaSMichael Lotz 	char* end, bool relocated)
289eb097431SAxel Dörfler {
290eb097431SAxel Dörfler 	// Now we're at the start of the rock ridge stuff
291eb097431SAxel Dörfler 	char* altName = NULL;
292eb097431SAxel Dörfler 	char* slName = NULL;
293eb097431SAxel Dörfler 	uint16 altNameSize = 0;
294eb097431SAxel Dörfler 	uint16 slNameSize = 0;
295eb097431SAxel Dörfler 	uint8 slFlags = 0;
296eb097431SAxel Dörfler 	uint8 length = 0;
297eb097431SAxel Dörfler 	bool done = false;
298eb097431SAxel Dörfler 
299eb097431SAxel Dörfler 	TRACE(("RR: Start of extensions at %p\n", buffer));
300eb097431SAxel Dörfler 
301eb097431SAxel Dörfler 	while (!done) {
302eb097431SAxel Dörfler 		buffer += length;
303eb097431SAxel Dörfler 		if (buffer + 2 >= end)
304eb097431SAxel Dörfler 			break;
305eb097431SAxel Dörfler 		length = *(uint8*)(buffer + 2);
306eb097431SAxel Dörfler 		if (buffer + length > end)
307eb097431SAxel Dörfler 			break;
30847a214deSAxel Dörfler 		if (length == 0)
30947a214deSAxel Dörfler 			break;
310eb097431SAxel Dörfler 
311eb097431SAxel Dörfler 		switch (((int)buffer[0] << 8) + buffer[1]) {
312eb097431SAxel Dörfler 			// Stat structure stuff
313eb097431SAxel Dörfler 			case 'PX':
314eb097431SAxel Dörfler 			{
315eb097431SAxel Dörfler 				uint8 bytePos = 3;
316eb097431SAxel Dörfler 				TRACE(("RR: found PX, length %u\n", length));
317eb097431SAxel Dörfler 				node->attr.pxVer = *(uint8*)(buffer + bytePos++);
318eb097431SAxel Dörfler 
319eb097431SAxel Dörfler 				// st_mode
320eb097431SAxel Dörfler 				node->attr.stat[LSB_DATA].st_mode
321eb097431SAxel Dörfler 					= *(mode_t*)(buffer + bytePos);
322eb097431SAxel Dörfler 				bytePos += 4;
323eb097431SAxel Dörfler 				node->attr.stat[MSB_DATA].st_mode
324eb097431SAxel Dörfler 					= *(mode_t*)(buffer + bytePos);
325eb097431SAxel Dörfler 				bytePos += 4;
326eb097431SAxel Dörfler 
327eb097431SAxel Dörfler 				// st_nlink
328eb097431SAxel Dörfler 				node->attr.stat[LSB_DATA].st_nlink
329eb097431SAxel Dörfler 					= *(nlink_t*)(buffer+bytePos);
330eb097431SAxel Dörfler 				bytePos += 4;
331eb097431SAxel Dörfler 				node->attr.stat[MSB_DATA].st_nlink
332eb097431SAxel Dörfler 					= *(nlink_t*)(buffer + bytePos);
333eb097431SAxel Dörfler 				bytePos += 4;
334eb097431SAxel Dörfler 
335eb097431SAxel Dörfler 				// st_uid
336eb097431SAxel Dörfler 				node->attr.stat[LSB_DATA].st_uid
337eb097431SAxel Dörfler 					= *(uid_t*)(buffer + bytePos);
338eb097431SAxel Dörfler 				bytePos += 4;
339eb097431SAxel Dörfler 				node->attr.stat[MSB_DATA].st_uid
340eb097431SAxel Dörfler 					= *(uid_t*)(buffer + bytePos);
341eb097431SAxel Dörfler 				bytePos += 4;
342eb097431SAxel Dörfler 
343eb097431SAxel Dörfler 				// st_gid
344eb097431SAxel Dörfler 				node->attr.stat[LSB_DATA].st_gid
345eb097431SAxel Dörfler 					= *(gid_t*)(buffer + bytePos);
346eb097431SAxel Dörfler 				bytePos += 4;
347eb097431SAxel Dörfler 				node->attr.stat[MSB_DATA].st_gid
348eb097431SAxel Dörfler 					= *(gid_t*)(buffer + bytePos);
349eb097431SAxel Dörfler 				bytePos += 4;
350eb097431SAxel Dörfler 				break;
351eb097431SAxel Dörfler 			}
352eb097431SAxel Dörfler 
353eb097431SAxel Dörfler 			case 'PN':
354eb097431SAxel Dörfler 				TRACE(("RR: found PN, length %u\n", length));
355eb097431SAxel Dörfler 				break;
356eb097431SAxel Dörfler 
357eb097431SAxel Dörfler 			// Symbolic link info
358eb097431SAxel Dörfler 			case 'SL':
359eb097431SAxel Dörfler 			{
360eb097431SAxel Dörfler 				uint8 bytePos = 3;
361eb097431SAxel Dörfler 				uint8 lastCompFlag = 0;
362eb097431SAxel Dörfler 				uint8 addPos = 0;
363eb097431SAxel Dörfler 				bool slDone = false;
364eb097431SAxel Dörfler 				bool useSeparator = true;
365eb097431SAxel Dörfler 
366eb097431SAxel Dörfler 				TRACE(("RR: found SL, length %u\n", length));
367eb097431SAxel Dörfler 				TRACE(("Buffer is at %p\n", buffer));
368eb097431SAxel Dörfler 				TRACE(("Current length is %u\n", slNameSize));
369eb097431SAxel Dörfler 				//kernel_debugger("");
370eb097431SAxel Dörfler 				node->attr.slVer = *(uint8*)(buffer + bytePos++);
371eb097431SAxel Dörfler 				slFlags = *(uint8*)(buffer + bytePos++);
372eb097431SAxel Dörfler 
373eb097431SAxel Dörfler 				TRACE(("sl flags are %u\n", slFlags));
374eb097431SAxel Dörfler 				while (!slDone && bytePos < length) {
375eb097431SAxel Dörfler 					uint8 compFlag = *(uint8*)(buffer + bytePos++);
376eb097431SAxel Dörfler 					uint8 compLen = *(uint8*)(buffer + bytePos++);
377eb097431SAxel Dörfler 
378eb097431SAxel Dörfler 					if (slName == NULL)
379eb097431SAxel Dörfler 						useSeparator = false;
380eb097431SAxel Dörfler 
381eb097431SAxel Dörfler 					addPos = slNameSize;
382eb097431SAxel Dörfler 
383eb097431SAxel Dörfler 					TRACE(("sl comp flags are %u, length is %u\n", compFlag, compLen));
384eb097431SAxel Dörfler 					TRACE(("Current name size is %u\n", slNameSize));
385eb097431SAxel Dörfler 
386eb097431SAxel Dörfler 					switch (compFlag) {
387eb097431SAxel Dörfler 						case SLCP_CONTINUE:
388eb097431SAxel Dörfler 							useSeparator = false;
389eb097431SAxel Dörfler 						default:
390eb097431SAxel Dörfler 							// Add the component to the total path.
391eb097431SAxel Dörfler 							slNameSize += compLen;
392eb097431SAxel Dörfler 							if (useSeparator)
393eb097431SAxel Dörfler 								slNameSize++;
394eb097431SAxel Dörfler 							slName = (char*)realloc(slName,
395eb097431SAxel Dörfler 								slNameSize + 1);
396eb097431SAxel Dörfler 							if (slName == NULL)
397eb097431SAxel Dörfler 								return B_NO_MEMORY;
398eb097431SAxel Dörfler 
399eb097431SAxel Dörfler 							if (useSeparator) {
400eb097431SAxel Dörfler 								TRACE(("Adding separator\n"));
401eb097431SAxel Dörfler 								slName[addPos++] = '/';
402eb097431SAxel Dörfler 							}
403eb097431SAxel Dörfler 
404eb097431SAxel Dörfler 							TRACE(("doing memcopy of %u bytes at offset %d\n", compLen, addPos));
405eb097431SAxel Dörfler 							memcpy(slName + addPos, buffer + bytePos,
406eb097431SAxel Dörfler 								compLen);
407eb097431SAxel Dörfler 
408eb097431SAxel Dörfler 							addPos += compLen;
409eb097431SAxel Dörfler 							useSeparator = true;
410eb097431SAxel Dörfler 							break;
411eb097431SAxel Dörfler 
412eb097431SAxel Dörfler 						case SLCP_CURRENT:
413eb097431SAxel Dörfler 							TRACE(("InitNode - found link to current directory\n"));
414eb097431SAxel Dörfler 							slNameSize += 2;
415eb097431SAxel Dörfler 							slName = (char*)realloc(slName,
416eb097431SAxel Dörfler 								slNameSize + 1);
417eb097431SAxel Dörfler 							if (slName == NULL)
418eb097431SAxel Dörfler 								return B_NO_MEMORY;
419eb097431SAxel Dörfler 
420eb097431SAxel Dörfler 							memcpy(slName + addPos, "./", 2);
421eb097431SAxel Dörfler 							useSeparator = false;
422eb097431SAxel Dörfler 							break;
423eb097431SAxel Dörfler 
424eb097431SAxel Dörfler 						case SLCP_PARENT:
425eb097431SAxel Dörfler 							slNameSize += 3;
426eb097431SAxel Dörfler 							slName = (char*)realloc(slName,
427eb097431SAxel Dörfler 								slNameSize + 1);
428eb097431SAxel Dörfler 							if (slName == NULL)
429eb097431SAxel Dörfler 								return B_NO_MEMORY;
430eb097431SAxel Dörfler 
431eb097431SAxel Dörfler 							memcpy(slName + addPos, "../", 3);
432eb097431SAxel Dörfler 							useSeparator = false;
433eb097431SAxel Dörfler 							break;
434eb097431SAxel Dörfler 
435eb097431SAxel Dörfler 						case SLCP_ROOT:
436eb097431SAxel Dörfler 							TRACE(("InitNode - found link to root directory\n"));
437eb097431SAxel Dörfler 							slNameSize += 1;
438eb097431SAxel Dörfler 							slName = (char*)realloc(slName,
439eb097431SAxel Dörfler 								slNameSize + 1);
440eb097431SAxel Dörfler 							if (slName == NULL)
441eb097431SAxel Dörfler 								return B_NO_MEMORY;
442eb097431SAxel Dörfler 							memcpy(slName + addPos, "/", 1);
443eb097431SAxel Dörfler 							useSeparator = false;
444eb097431SAxel Dörfler 							break;
445eb097431SAxel Dörfler 
446eb097431SAxel Dörfler 						case SLCP_VOLROOT:
447eb097431SAxel Dörfler 							slDone = true;
448eb097431SAxel Dörfler 							break;
449eb097431SAxel Dörfler 
450eb097431SAxel Dörfler 						case SLCP_HOST:
451eb097431SAxel Dörfler 							slDone = true;
452eb097431SAxel Dörfler 							break;
453eb097431SAxel Dörfler 					}
454eb097431SAxel Dörfler 					slName[slNameSize] = '\0';
455eb097431SAxel Dörfler 					lastCompFlag = compFlag;
456eb097431SAxel Dörfler 					bytePos += compLen;
457eb097431SAxel Dörfler 					TRACE(("Current sl name is \'%s\'\n", slName));
458eb097431SAxel Dörfler 				}
459eb097431SAxel Dörfler 				node->attr.slName = slName;
460eb097431SAxel Dörfler 				TRACE(("InitNode = symlink name is \'%s\'\n", slName));
461eb097431SAxel Dörfler 				break;
462eb097431SAxel Dörfler 			}
463eb097431SAxel Dörfler 
464eb097431SAxel Dörfler 			// Altername name
465eb097431SAxel Dörfler 			case 'NM':
466eb097431SAxel Dörfler 			{
467eb097431SAxel Dörfler 				uint8 bytePos = 3;
468eb097431SAxel Dörfler 				uint8 flags = 0;
469eb097431SAxel Dörfler 				uint16 oldEnd = altNameSize;
470eb097431SAxel Dörfler 
471eb097431SAxel Dörfler 				altNameSize += length - 5;
472eb097431SAxel Dörfler 				altName = (char*)realloc(altName, altNameSize + 1);
473eb097431SAxel Dörfler 				if (altName == NULL)
474eb097431SAxel Dörfler 					return B_NO_MEMORY;
475eb097431SAxel Dörfler 
476eb097431SAxel Dörfler 				TRACE(("RR: found NM, length %u\n", length));
477eb097431SAxel Dörfler 				// Read flag and version.
478eb097431SAxel Dörfler 				node->attr.nmVer = *(uint8 *)(buffer + bytePos++);
479eb097431SAxel Dörfler 				flags = *(uint8 *)(buffer + bytePos++);
480eb097431SAxel Dörfler 
481eb097431SAxel Dörfler 				TRACE(("RR: nm buffer is %s, start at %p\n", (buffer + bytePos), buffer + bytePos));
482eb097431SAxel Dörfler 
483eb097431SAxel Dörfler 				// Build the file name.
484eb097431SAxel Dörfler 				memcpy(altName + oldEnd, buffer + bytePos, length - 5);
485eb097431SAxel Dörfler 				altName[altNameSize] = '\0';
486eb097431SAxel Dörfler 				TRACE(("RR: alt name is %s\n", altName));
487eb097431SAxel Dörfler 
488eb097431SAxel Dörfler 				// If the name is not continued in another record, update
489eb097431SAxel Dörfler 				// the record name.
490eb097431SAxel Dörfler 				if (!(flags & NM_CONTINUE)) {
491eb097431SAxel Dörfler 					// Get rid of the ISO name, replace with RR name.
492eb097431SAxel Dörfler 					if (node->name != NULL)
493eb097431SAxel Dörfler 						free(node->name);
494eb097431SAxel Dörfler 					node->name = altName;
495eb097431SAxel Dörfler 					node->name_length = altNameSize;
496eb097431SAxel Dörfler 				}
497eb097431SAxel Dörfler 				break;
498eb097431SAxel Dörfler 			}
499eb097431SAxel Dörfler 
500eb097431SAxel Dörfler 			// Deep directory record masquerading as a file.
501eb097431SAxel Dörfler 			case 'CL':
502*56b2febaSMichael Lotz 			{
503eb097431SAxel Dörfler 				TRACE(("RR: found CL, length %u\n", length));
504*56b2febaSMichael Lotz 				// Reinitialize the node with the information at the
505*56b2febaSMichael Lotz 				// "." entry of the pointed to directory data
506eb097431SAxel Dörfler 				node->startLBN[LSB_DATA] = *(uint32*)(buffer+4);
507eb097431SAxel Dörfler 				node->startLBN[MSB_DATA] = *(uint32*)(buffer+8);
508*56b2febaSMichael Lotz 
509*56b2febaSMichael Lotz 				char* buffer = (char*)block_cache_get(volume->fBlockCache,
510*56b2febaSMichael Lotz 					node->startLBN[FS_DATA_FORMAT]);
511*56b2febaSMichael Lotz 				if (buffer == NULL)
512eb097431SAxel Dörfler 					break;
513eb097431SAxel Dörfler 
514*56b2febaSMichael Lotz 				InitNode(volume, node, buffer, NULL, true);
515*56b2febaSMichael Lotz 				block_cache_put(volume->fBlockCache,
516*56b2febaSMichael Lotz 					node->startLBN[FS_DATA_FORMAT]);
517*56b2febaSMichael Lotz 				break;
518*56b2febaSMichael Lotz 			}
519*56b2febaSMichael Lotz 
520eb097431SAxel Dörfler 			case 'PL':
521eb097431SAxel Dörfler 				TRACE(("RR: found PL, length %u\n", length));
522eb097431SAxel Dörfler 				break;
523eb097431SAxel Dörfler 
524eb097431SAxel Dörfler 			case 'RE':
525eb097431SAxel Dörfler 				// Relocated directory, we should skip.
526eb097431SAxel Dörfler 				TRACE(("RR: found RE, length %u\n", length));
527*56b2febaSMichael Lotz 				if (!relocated)
52847a214deSAxel Dörfler 					return B_NOT_SUPPORTED;
529*56b2febaSMichael Lotz 				break;
530eb097431SAxel Dörfler 
531eb097431SAxel Dörfler 			case 'TF':
532eb097431SAxel Dörfler 				TRACE(("RR: found TF, length %u\n", length));
533eb097431SAxel Dörfler 				break;
534eb097431SAxel Dörfler 
535eb097431SAxel Dörfler 			case 'RR':
536eb097431SAxel Dörfler 				TRACE(("RR: found RR, length %u\n", length));
537eb097431SAxel Dörfler 				break;
538eb097431SAxel Dörfler 
53947a214deSAxel Dörfler 			case 'SF':
54047a214deSAxel Dörfler 				TRACE(("RR: found SF, sparse files not supported!\n"));
54147a214deSAxel Dörfler 				// TODO: support sparse files
54247a214deSAxel Dörfler 				return B_NOT_SUPPORTED;
54347a214deSAxel Dörfler 
544eb097431SAxel Dörfler 			default:
54547a214deSAxel Dörfler 				if (buffer[0] == '\0') {
54647a214deSAxel Dörfler 					TRACE(("RR: end of extensions\n"));
547eb097431SAxel Dörfler 					done = true;
54847a214deSAxel Dörfler 				} else
54947a214deSAxel Dörfler 					TRACE(("RR: Unknown tag %c%c\n", buffer[0], buffer[1]));
550eb097431SAxel Dörfler 				break;
551eb097431SAxel Dörfler 		}
552eb097431SAxel Dörfler 	}
553eb097431SAxel Dörfler 
554eb097431SAxel Dörfler 	return B_OK;
555eb097431SAxel Dörfler }
556eb097431SAxel Dörfler 
557eb097431SAxel Dörfler //	#pragma mark - ISO-9660 specific exported functions
558eb097431SAxel Dörfler 
559eb097431SAxel Dörfler 
560eb097431SAxel Dörfler status_t
561eb097431SAxel Dörfler ISOMount(const char *path, uint32 flags, iso9660_volume **_newVolume,
562eb097431SAxel Dörfler 	bool allowJoliet)
563eb097431SAxel Dörfler {
564eb097431SAxel Dörfler 	// path: 		path to device (eg, /dev/disk/scsi/030/raw)
565eb097431SAxel Dörfler 	// partition:	partition number on device ????
566eb097431SAxel Dörfler 	// flags:		currently unused
567eb097431SAxel Dörfler 
568eb097431SAxel Dörfler 	// determine if it is an ISO volume.
569eb097431SAxel Dörfler 	char buffer[ISO_PVD_SIZE];
570eb097431SAxel Dörfler 	bool done = false;
571eb097431SAxel Dörfler 	bool isISO = false;
572eb097431SAxel Dörfler 	off_t offset = 0x8000;
573eb097431SAxel Dörfler 	ssize_t retval;
574eb097431SAxel Dörfler 	partition_info partitionInfo;
575eb097431SAxel Dörfler 	int deviceBlockSize, multiplier;
576eb097431SAxel Dörfler 	iso9660_volume *volume;
577eb097431SAxel Dörfler 
578eb097431SAxel Dörfler 	(void)flags;
579eb097431SAxel Dörfler 
580eb097431SAxel Dörfler 	TRACE(("ISOMount - ENTER\n"));
581eb097431SAxel Dörfler 
582eb097431SAxel Dörfler 	volume = (iso9660_volume *)calloc(sizeof(iso9660_volume), 1);
583eb097431SAxel Dörfler 	if (volume == NULL) {
584eb097431SAxel Dörfler 		TRACE(("ISOMount - mem error \n"));
585eb097431SAxel Dörfler 		return B_NO_MEMORY;
586eb097431SAxel Dörfler 	}
587eb097431SAxel Dörfler 
588eb097431SAxel Dörfler 	memset(&partitionInfo, 0, sizeof(partition_info));
589eb097431SAxel Dörfler 
590eb097431SAxel Dörfler 	/* open and lock the device */
591eb097431SAxel Dörfler 	volume->fdOfSession = open(path, O_RDONLY);
592eb097431SAxel Dörfler 
593eb097431SAxel Dörfler 	/* try to open the raw device to get access to the other sessions as well */
594eb097431SAxel Dörfler 	if (volume->fdOfSession >= 0) {
595eb097431SAxel Dörfler 		if (ioctl(volume->fdOfSession, B_GET_PARTITION_INFO, &partitionInfo) < 0) {
596eb097431SAxel Dörfler 			TRACE(("B_GET_PARTITION_INFO: ioctl returned error\n"));
597eb097431SAxel Dörfler 			strcpy(partitionInfo.device, path);
598eb097431SAxel Dörfler 		}
599eb097431SAxel Dörfler 		TRACE(("ISOMount: open device/file \"%s\"\n", partitionInfo.device));
600eb097431SAxel Dörfler 
601eb097431SAxel Dörfler 		volume->fd = open(partitionInfo.device, O_RDONLY);
602eb097431SAxel Dörfler 	}
603eb097431SAxel Dörfler 
604eb097431SAxel Dörfler 	if (volume->fdOfSession < 0 || volume->fd < 0) {
605eb097431SAxel Dörfler 		close(volume->fd);
606eb097431SAxel Dörfler 		close(volume->fdOfSession);
607eb097431SAxel Dörfler 
608eb097431SAxel Dörfler 		TRACE(("ISO9660 ERROR - Unable to open <%s>\n", path));
609eb097431SAxel Dörfler 		free(volume);
610eb097431SAxel Dörfler 		return B_BAD_VALUE;
611eb097431SAxel Dörfler 	}
612eb097431SAxel Dörfler 
613eb097431SAxel Dörfler 	deviceBlockSize = get_device_block_size(volume->fdOfSession);
614eb097431SAxel Dörfler 	if (deviceBlockSize < 0)  {
615eb097431SAxel Dörfler 		TRACE(("ISO9660 ERROR - device block size is 0\n"));
616eb097431SAxel Dörfler 		close(volume->fd);
617eb097431SAxel Dörfler 		close(volume->fdOfSession);
618eb097431SAxel Dörfler 
619eb097431SAxel Dörfler 		free(volume);
620eb097431SAxel Dörfler 		return B_BAD_VALUE;
621eb097431SAxel Dörfler 	}
622eb097431SAxel Dörfler 
623eb097431SAxel Dörfler 	volume->joliet_level = 0;
624eb097431SAxel Dörfler 	while (!done && offset < 0x10000) {
625eb097431SAxel Dörfler 		retval = read_pos(volume->fdOfSession, offset, (void*)buffer,
626eb097431SAxel Dörfler 			ISO_PVD_SIZE);
627eb097431SAxel Dörfler 		if (retval < ISO_PVD_SIZE) {
628eb097431SAxel Dörfler 			isISO = false;
629eb097431SAxel Dörfler 			break;
630eb097431SAxel Dörfler 		}
631eb097431SAxel Dörfler 
632eb097431SAxel Dörfler 		if (strncmp(buffer + 1, kISO9660IDString, 5) == 0) {
633eb097431SAxel Dörfler 			if (*buffer == 0x01 && !isISO) {
634eb097431SAxel Dörfler 				// ISO_VD_PRIMARY
635eb097431SAxel Dörfler 				off_t maxBlocks;
636eb097431SAxel Dörfler 
637eb097431SAxel Dörfler 				TRACE(("ISOMount: Is an ISO9660 volume, initting rec\n"));
638eb097431SAxel Dörfler 
639eb097431SAxel Dörfler 				InitVolDesc(volume, buffer);
640eb097431SAxel Dörfler 				strncpy(volume->devicePath,path,127);
641eb097431SAxel Dörfler 				volume->id = ISO_ROOTNODE_ID;
642eb097431SAxel Dörfler 				TRACE(("ISO9660: volume->blockSize = %d\n", volume->logicalBlkSize[FS_DATA_FORMAT]));
643eb097431SAxel Dörfler 
644eb097431SAxel Dörfler 				multiplier = deviceBlockSize / volume->logicalBlkSize[FS_DATA_FORMAT];
645eb097431SAxel Dörfler 				TRACE(("ISOMount: block size multiplier is %d\n", multiplier));
646eb097431SAxel Dörfler 
647eb097431SAxel Dörfler 				// if the session is on a real device, size != 0
648eb097431SAxel Dörfler 				if (partitionInfo.size != 0) {
649eb097431SAxel Dörfler 					maxBlocks = (partitionInfo.size + partitionInfo.offset)
650eb097431SAxel Dörfler 						/ volume->logicalBlkSize[FS_DATA_FORMAT];
651eb097431SAxel Dörfler 				} else
652eb097431SAxel Dörfler 					maxBlocks = volume->volSpaceSize[FS_DATA_FORMAT];
653eb097431SAxel Dörfler 
654eb097431SAxel Dörfler 				/* Initialize access to the cache so that we can do cached i/o */
655eb097431SAxel Dörfler 				TRACE(("ISO9660: cache init: dev %d, max blocks %Ld\n", volume->fd, maxBlocks));
656eb097431SAxel Dörfler 				volume->fBlockCache = block_cache_create(volume->fd, maxBlocks,
657eb097431SAxel Dörfler 					volume->logicalBlkSize[FS_DATA_FORMAT], true);
658eb097431SAxel Dörfler 				isISO = true;
659eb097431SAxel Dörfler 			} else if (*buffer == 0x02 && isISO && allowJoliet) {
660eb097431SAxel Dörfler 				// ISO_VD_SUPPLEMENTARY
661eb097431SAxel Dörfler 
662eb097431SAxel Dörfler 				// JOLIET extension
663eb097431SAxel Dörfler 				// test escape sequence for level of UCS-2 characterset
664eb097431SAxel Dörfler 			    if (buffer[88] == 0x25 && buffer[89] == 0x2f) {
665eb097431SAxel Dörfler 					switch (buffer[90]) {
666eb097431SAxel Dörfler 						case 0x40: volume->joliet_level = 1; break;
667eb097431SAxel Dörfler 						case 0x43: volume->joliet_level = 2; break;
668eb097431SAxel Dörfler 						case 0x45: volume->joliet_level = 3; break;
669eb097431SAxel Dörfler 					}
670eb097431SAxel Dörfler 
671eb097431SAxel Dörfler 					TRACE(("ISO9660 Extensions: Microsoft Joliet Level %d\n", volume->joliet_level));
672eb097431SAxel Dörfler 
673eb097431SAxel Dörfler 					// Because Joliet-stuff starts at other sector,
674eb097431SAxel Dörfler 					// update root directory record.
675*56b2febaSMichael Lotz 					if (volume->joliet_level > 0) {
676*56b2febaSMichael Lotz 						InitNode(volume, &volume->rootDirRec, &buffer[156],
677*56b2febaSMichael Lotz 							NULL);
678*56b2febaSMichael Lotz 					}
679eb097431SAxel Dörfler 				}
680eb097431SAxel Dörfler 			} else if (*(unsigned char *)buffer == 0xff) {
681eb097431SAxel Dörfler 				// ISO_VD_END
682eb097431SAxel Dörfler 				done = true;
683eb097431SAxel Dörfler 			} else
684eb097431SAxel Dörfler 				TRACE(("found header %d\n",*buffer));
685eb097431SAxel Dörfler 		}
686eb097431SAxel Dörfler 		offset += 0x800;
687eb097431SAxel Dörfler 	}
688eb097431SAxel Dörfler 
689eb097431SAxel Dörfler 	if (!isISO) {
690eb097431SAxel Dörfler 		// It isn't an ISO disk.
691eb097431SAxel Dörfler 		close(volume->fdOfSession);
692eb097431SAxel Dörfler 		close(volume->fd);
693eb097431SAxel Dörfler 		free(volume);
694eb097431SAxel Dörfler 
695eb097431SAxel Dörfler 		TRACE(("ISOMount: Not an ISO9660 volume!\n"));
696eb097431SAxel Dörfler 		return B_BAD_VALUE;
697eb097431SAxel Dörfler 	}
698eb097431SAxel Dörfler 
699eb097431SAxel Dörfler 	TRACE(("ISOMount - EXIT, returning %p\n", volume));
700eb097431SAxel Dörfler 	*_newVolume = volume;
701eb097431SAxel Dörfler 	return B_OK;
702eb097431SAxel Dörfler }
703eb097431SAxel Dörfler 
704eb097431SAxel Dörfler 
705eb097431SAxel Dörfler /*!	Reads in a single directory entry and fills in the values in the
706eb097431SAxel Dörfler 	dirent struct. Uses the cookie to keep track of the current block
707eb097431SAxel Dörfler 	and position within the block. Also uses the cookie to determine when
708eb097431SAxel Dörfler 	it has reached the end of the directory file.
709eb097431SAxel Dörfler */
710eb097431SAxel Dörfler status_t
711eb097431SAxel Dörfler ISOReadDirEnt(iso9660_volume *volume, dircookie *cookie, struct dirent *dirent,
712eb097431SAxel Dörfler 	size_t bufferSize)
713eb097431SAxel Dörfler {
714eb097431SAxel Dörfler 	int	result = B_NO_ERROR;
71599d1bfb5SAxel Dörfler 	bool done = false;
716eb097431SAxel Dörfler 
717eb097431SAxel Dörfler 	TRACE(("ISOReadDirEnt - ENTER\n"));
718eb097431SAxel Dörfler 
71999d1bfb5SAxel Dörfler 	while (!done) {
72099d1bfb5SAxel Dörfler 		off_t totalRead = cookie->pos + (cookie->block - cookie->startBlock)
72199d1bfb5SAxel Dörfler 			* volume->logicalBlkSize[FS_DATA_FORMAT];
72299d1bfb5SAxel Dörfler 
723eb097431SAxel Dörfler 		// If we're at the end of the data in a block, move to the next block.
72499d1bfb5SAxel Dörfler 		char *blockData;
725eb097431SAxel Dörfler 		while (true) {
72699d1bfb5SAxel Dörfler 			blockData
72799d1bfb5SAxel Dörfler 				= (char*)block_cache_get(volume->fBlockCache, cookie->block);
728eb097431SAxel Dörfler 			if (blockData != NULL && *(blockData + cookie->pos) == 0) {
729eb097431SAxel Dörfler 				// NULL data, move to next block.
730eb097431SAxel Dörfler 				block_cache_put(volume->fBlockCache, cookie->block);
731eb097431SAxel Dörfler 				blockData = NULL;
73299d1bfb5SAxel Dörfler 				totalRead
73399d1bfb5SAxel Dörfler 					+= volume->logicalBlkSize[FS_DATA_FORMAT] - cookie->pos;
734eb097431SAxel Dörfler 				cookie->pos = 0;
735eb097431SAxel Dörfler 				cookie->block++;
736eb097431SAxel Dörfler 			} else
737eb097431SAxel Dörfler 				break;
738eb097431SAxel Dörfler 
739eb097431SAxel Dörfler 			if (totalRead >= cookie->totalSize)
740eb097431SAxel Dörfler 				break;
741eb097431SAxel Dörfler 		}
742eb097431SAxel Dörfler 
74399d1bfb5SAxel Dörfler 		off_t cacheBlock = cookie->block;
74499d1bfb5SAxel Dörfler 
745eb097431SAxel Dörfler 		if (blockData != NULL && totalRead < cookie->totalSize) {
746eb097431SAxel Dörfler 			iso9660_inode node;
74799d1bfb5SAxel Dörfler 			size_t bytesRead = 0;
748*56b2febaSMichael Lotz 			result = InitNode(volume, &node, blockData + cookie->pos,
749*56b2febaSMichael Lotz 				&bytesRead);
75043276e5bSMichael Lotz 
75143276e5bSMichael Lotz 			// if we hit an entry that we don't support, we just skip it
75243276e5bSMichael Lotz 			if (result != B_OK && result != B_NOT_SUPPORTED)
75347a214deSAxel Dörfler 				break;
75447a214deSAxel Dörfler 
75543276e5bSMichael Lotz 			if (result == B_OK && (node.flags & ISO_IS_ASSOCIATED_FILE) == 0) {
756eb097431SAxel Dörfler 				size_t nameBufferSize = bufferSize - sizeof(struct dirent);
757eb097431SAxel Dörfler 
758eb097431SAxel Dörfler 				dirent->d_dev = volume->id;
759eb097431SAxel Dörfler 				dirent->d_ino = ((ino_t)cookie->block << 30)
760eb097431SAxel Dörfler 					+ (cookie->pos & 0x3fffffff);
761eb097431SAxel Dörfler 				dirent->d_reclen = sizeof(struct dirent) + node.name_length + 1;
762eb097431SAxel Dörfler 
763eb097431SAxel Dörfler 				if (node.name_length <= nameBufferSize) {
764eb097431SAxel Dörfler 					// need to do some size checking here.
765eb097431SAxel Dörfler 					strlcpy(dirent->d_name, node.name, node.name_length + 1);
76699d1bfb5SAxel Dörfler 					TRACE(("ISOReadDirEnt  - success, name is %s, block %Ld, "
76799d1bfb5SAxel Dörfler 						"pos %Ld, inode id %Ld\n", dirent->d_name, cookie->block,
768eb097431SAxel Dörfler 						cookie->pos, dirent->d_ino));
769eb097431SAxel Dörfler 				} else {
770eb097431SAxel Dörfler 					// TODO: this can be just normal if we support reading more
771eb097431SAxel Dörfler 					// than one entry.
77299d1bfb5SAxel Dörfler 					TRACE(("ISOReadDirEnt - ERROR, name %s does not fit in "
77399d1bfb5SAxel Dörfler 						"buffer of size %d\n", node.name, (int)nameBufferSize));
774eb097431SAxel Dörfler 					result = B_BAD_VALUE;
775eb097431SAxel Dörfler 				}
77647a214deSAxel Dörfler 
77747a214deSAxel Dörfler 				done = true;
778eb097431SAxel Dörfler 			}
7792a64cb11SAxel Dörfler 
78047a214deSAxel Dörfler 			cookie->pos += bytesRead;
78147a214deSAxel Dörfler 
7822a64cb11SAxel Dörfler 			if (cookie->pos == volume->logicalBlkSize[FS_DATA_FORMAT]) {
7832a64cb11SAxel Dörfler 				cookie->pos = 0;
7842a64cb11SAxel Dörfler 				cookie->block++;
7852a64cb11SAxel Dörfler 			}
786eb097431SAxel Dörfler 		} else {
787eb097431SAxel Dörfler 			if (totalRead >= cookie->totalSize)
788eb097431SAxel Dörfler 				result = B_ENTRY_NOT_FOUND;
789eb097431SAxel Dörfler 			else
790eb097431SAxel Dörfler 				result = B_NO_MEMORY;
79199d1bfb5SAxel Dörfler 			done = true;
792eb097431SAxel Dörfler 		}
793eb097431SAxel Dörfler 
794eb097431SAxel Dörfler 		if (blockData != NULL)
795eb097431SAxel Dörfler 			block_cache_put(volume->fBlockCache, cacheBlock);
79699d1bfb5SAxel Dörfler 	}
797eb097431SAxel Dörfler 
798eb097431SAxel Dörfler 	TRACE(("ISOReadDirEnt - EXIT, result is %s, vnid is %Lu\n",
799eb097431SAxel Dörfler 		strerror(result), dirent->d_ino));
80099d1bfb5SAxel Dörfler 
801eb097431SAxel Dörfler 	return result;
802eb097431SAxel Dörfler }
803eb097431SAxel Dörfler 
804eb097431SAxel Dörfler 
805eb097431SAxel Dörfler status_t
806*56b2febaSMichael Lotz InitNode(iso9660_volume* volume, iso9660_inode* node, char* buffer,
807*56b2febaSMichael Lotz 	size_t* _bytesRead, bool relocated)
808eb097431SAxel Dörfler {
809eb097431SAxel Dörfler 	uint8 recordLength = *(uint8*)buffer++;
810eb097431SAxel Dörfler 	size_t nameLength;
811eb097431SAxel Dörfler 
812eb097431SAxel Dörfler 	TRACE(("InitNode - ENTER, bufstart is %p, record length is %d bytes\n",
813eb097431SAxel Dörfler 		buffer, recordLength));
814eb097431SAxel Dörfler 
815eb097431SAxel Dörfler 	if (_bytesRead != NULL)
816eb097431SAxel Dörfler 		*_bytesRead = recordLength;
817eb097431SAxel Dörfler 	if (recordLength == 0)
818eb097431SAxel Dörfler 		return B_ENTRY_NOT_FOUND;
819eb097431SAxel Dörfler 
820eb097431SAxel Dörfler 	char* end = buffer + recordLength;
821eb097431SAxel Dörfler 
822*56b2febaSMichael Lotz 	if (!relocated) {
823eb097431SAxel Dörfler 		node->cache = NULL;
824eb097431SAxel Dörfler 		node->name = NULL;
825eb097431SAxel Dörfler 		node->attr.slName = NULL;
826eb097431SAxel Dörfler 		memset(node->attr.stat, 0, sizeof(node->attr.stat));
827*56b2febaSMichael Lotz 	} else
828*56b2febaSMichael Lotz 		free(node->attr.slName);
829eb097431SAxel Dörfler 
830eb097431SAxel Dörfler 	node->extAttrRecLen = *(uint8*)buffer++;
83199d1bfb5SAxel Dörfler 	TRACE(("InitNode - ext attr length is %d\n", (int)node->extAttrRecLen));
832eb097431SAxel Dörfler 
833eb097431SAxel Dörfler 	node->startLBN[LSB_DATA] = *(uint32*)buffer;
834eb097431SAxel Dörfler 	buffer += 4;
835eb097431SAxel Dörfler 	node->startLBN[MSB_DATA] = *(uint32*)buffer;
836eb097431SAxel Dörfler 	buffer += 4;
83799d1bfb5SAxel Dörfler 	TRACE(("InitNode - data start LBN is %d\n",
83899d1bfb5SAxel Dörfler 		(int)node->startLBN[FS_DATA_FORMAT]));
839eb097431SAxel Dörfler 
840eb097431SAxel Dörfler 	node->dataLen[LSB_DATA] = *(uint32*)buffer;
841eb097431SAxel Dörfler 	buffer += 4;
842eb097431SAxel Dörfler 	node->dataLen[MSB_DATA] = *(uint32*)buffer;
843eb097431SAxel Dörfler 	buffer += 4;
84499d1bfb5SAxel Dörfler 	TRACE(("InitNode - data length is %d\n",
84599d1bfb5SAxel Dörfler 		(int)node->dataLen[FS_DATA_FORMAT]));
846eb097431SAxel Dörfler 
847eb097431SAxel Dörfler 	init_node_date(&node->recordDate, buffer);
848eb097431SAxel Dörfler 	buffer += 7;
849eb097431SAxel Dörfler 
850eb097431SAxel Dörfler 	node->flags = *(uint8*)buffer;
851eb097431SAxel Dörfler 	buffer++;
852eb097431SAxel Dörfler 	TRACE(("InitNode - flags are %d\n", node->flags));
853eb097431SAxel Dörfler 
854eb097431SAxel Dörfler 	node->fileUnitSize = *(uint8*)buffer;
855eb097431SAxel Dörfler 	buffer++;
856eb097431SAxel Dörfler 	TRACE(("InitNode - fileUnitSize is %d\n", node->fileUnitSize));
857eb097431SAxel Dörfler 
858eb097431SAxel Dörfler 	node->interleaveGapSize = *(uint8*)buffer;
859eb097431SAxel Dörfler 	buffer++;
860eb097431SAxel Dörfler 	TRACE(("InitNode - interleave gap size = %d\n", node->interleaveGapSize));
861eb097431SAxel Dörfler 
862eb097431SAxel Dörfler 	node->volSeqNum = *(uint32*)buffer;
863eb097431SAxel Dörfler 	buffer += 4;
86499d1bfb5SAxel Dörfler 	TRACE(("InitNode - volume seq num is %d\n", (int)node->volSeqNum));
865eb097431SAxel Dörfler 
866*56b2febaSMichael Lotz 	nameLength = *(uint8*)buffer;
867eb097431SAxel Dörfler 	buffer++;
868*56b2febaSMichael Lotz 
869*56b2febaSMichael Lotz 	// for relocated directories we take the name from the placeholder entry
870*56b2febaSMichael Lotz 	if (!relocated) {
871*56b2febaSMichael Lotz 		node->name_length = nameLength;
87299d1bfb5SAxel Dörfler 		TRACE(("InitNode - file id length is %u\n", node->name_length));
873*56b2febaSMichael Lotz 	}
874eb097431SAxel Dörfler 
875eb097431SAxel Dörfler 	// Set defaults, in case there is no RockRidge stuff.
87647a214deSAxel Dörfler 	node->attr.stat[FS_DATA_FORMAT].st_mode |= (node->flags & ISO_IS_DIR) != 0
877eb097431SAxel Dörfler 		? S_IFDIR | S_IXUSR | S_IRUSR | S_IXGRP | S_IRGRP | S_IXOTH | S_IROTH
878eb097431SAxel Dörfler 		: S_IFREG | S_IRUSR | S_IRGRP | S_IROTH;
879eb097431SAxel Dörfler 
880eb097431SAxel Dörfler 	if (node->name_length == 0) {
881eb097431SAxel Dörfler 		TRACE(("InitNode - File ID String is 0 length\n"));
882eb097431SAxel Dörfler 		return B_ENTRY_NOT_FOUND;
883eb097431SAxel Dörfler 	}
884eb097431SAxel Dörfler 
885*56b2febaSMichael Lotz 	if (!relocated) {
886eb097431SAxel Dörfler 		// JOLIET extension:
887eb097431SAxel Dörfler 		// on joliet discs, buffer[0] can be 0 for Unicoded filenames,
888eb097431SAxel Dörfler 		// so I've added a check here to test explicitely for
889eb097431SAxel Dörfler 		// directories (which have length 1)
890eb097431SAxel Dörfler 		// Take care of "." and "..", the first two dirents are
891eb097431SAxel Dörfler 		// these in iso.
8921dd3b2c7SAxel Dörfler 		if (node->name_length == 1 && buffer[0] == 0) {
893eb097431SAxel Dörfler 			node->name = strdup(".");
894eb097431SAxel Dörfler 			node->name_length = 1;
8951dd3b2c7SAxel Dörfler 		} else if (node->name_length == 1 && buffer[0] == 1) {
896eb097431SAxel Dörfler 			node->name = strdup("..");
897eb097431SAxel Dörfler 			node->name_length = 2;
898*56b2febaSMichael Lotz 		} else if (volume->joliet_level > 0) {
899eb097431SAxel Dörfler 			// JOLIET extension: convert Unicode16 string to UTF8
900eb097431SAxel Dörfler 			// Assume that the unicode->utf8 conversion produces 4 byte
901eb097431SAxel Dörfler 			// utf8 characters, and allocate that much space
902eb097431SAxel Dörfler 			node->name = (char*)malloc(node->name_length * 2 + 1);
903eb097431SAxel Dörfler 			if (node->name == NULL)
904eb097431SAxel Dörfler 				return B_NO_MEMORY;
905eb097431SAxel Dörfler 
906eb097431SAxel Dörfler 			int32 sourceLength = node->name_length;
907eb097431SAxel Dörfler 			int32 destLength = node->name_length * 2;
908eb097431SAxel Dörfler 
909eb097431SAxel Dörfler 			status_t status = unicode_to_utf8(buffer, &sourceLength,
910eb097431SAxel Dörfler 				node->name, &destLength);
911eb097431SAxel Dörfler 			if (status < B_OK) {
912eb097431SAxel Dörfler 				dprintf("iso9660: error converting unicode->utf8\n");
913eb097431SAxel Dörfler 				return status;
914eb097431SAxel Dörfler 			}
915eb097431SAxel Dörfler 
916eb097431SAxel Dörfler 			node->name[destLength] = '\0';
917eb097431SAxel Dörfler 			node->name_length = destLength;
918eb097431SAxel Dörfler 
919eb097431SAxel Dörfler 			sanitize_iso_name(node, false);
920eb097431SAxel Dörfler 		} else {
921eb097431SAxel Dörfler 			node->name = (char*)malloc(node->name_length + 1);
922eb097431SAxel Dörfler 			if (node->name == NULL)
923eb097431SAxel Dörfler 				return B_NO_MEMORY;
924eb097431SAxel Dörfler 
925eb097431SAxel Dörfler 			// convert all characters to lower case
926*56b2febaSMichael Lotz 			for (uint32 i = 0; i < node->name_length; i++)
927eb097431SAxel Dörfler 				node->name[i] = tolower(buffer[i]);
928*56b2febaSMichael Lotz 
929eb097431SAxel Dörfler 			node->name[node->name_length] = '\0';
930eb097431SAxel Dörfler 
931eb097431SAxel Dörfler 			sanitize_iso_name(node, true);
932eb097431SAxel Dörfler 		}
933eb097431SAxel Dörfler 
934eb097431SAxel Dörfler 		if (node->name == NULL) {
935eb097431SAxel Dörfler 			TRACE(("InitNode - unable to allocate memory!\n"));
936eb097431SAxel Dörfler 			return B_NO_MEMORY;
937eb097431SAxel Dörfler 		}
938*56b2febaSMichael Lotz 	}
939eb097431SAxel Dörfler 
940eb097431SAxel Dörfler 	buffer += nameLength;
941eb097431SAxel Dörfler 	if (nameLength % 2 == 0)
942eb097431SAxel Dörfler 		buffer++;
943eb097431SAxel Dörfler 
944eb097431SAxel Dörfler 	TRACE(("DirRec ID String is: %s\n", node->name));
945eb097431SAxel Dörfler 
946*56b2febaSMichael Lotz 	return parse_rock_ridge(volume, node, buffer, end, relocated);
947eb097431SAxel Dörfler }
948eb097431SAxel Dörfler 
949eb097431SAxel Dörfler 
950eb097431SAxel Dörfler status_t
951eb097431SAxel Dörfler ConvertRecDate(ISORecDate* inDate, time_t* outDate)
952eb097431SAxel Dörfler {
953eb097431SAxel Dörfler 	time_t	time;
954eb097431SAxel Dörfler 	int		days, i, year, tz;
955eb097431SAxel Dörfler 
956eb097431SAxel Dörfler 	year = inDate->year -70;
957eb097431SAxel Dörfler 	tz = inDate->offsetGMT;
958eb097431SAxel Dörfler 
959eb097431SAxel Dörfler 	if (year < 0) {
960eb097431SAxel Dörfler 		time = 0;
961eb097431SAxel Dörfler 	} else {
962eb097431SAxel Dörfler 		const int monlen[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
963eb097431SAxel Dörfler 
964eb097431SAxel Dörfler 		days = (year * 365);
965eb097431SAxel Dörfler 
966eb097431SAxel Dörfler 		if (year > 2)
967eb097431SAxel Dörfler 			days += (year + 1)/ 4;
968eb097431SAxel Dörfler 
969eb097431SAxel Dörfler 		for (i = 1; (i < inDate->month) && (i < 12); i++) {
970eb097431SAxel Dörfler 			days += monlen[i-1];
971eb097431SAxel Dörfler 		}
972eb097431SAxel Dörfler 
973eb097431SAxel Dörfler 		if (((year + 2) % 4) == 0 && inDate->month > 2)
974eb097431SAxel Dörfler 			days++;
975eb097431SAxel Dörfler 
976eb097431SAxel Dörfler 		days += inDate->date - 1;
977eb097431SAxel Dörfler 		time = ((((days*24) + inDate->hour) * 60 + inDate->minute) * 60)
978eb097431SAxel Dörfler 					+ inDate->second;
979eb097431SAxel Dörfler 		if (tz & 0x80)
980eb097431SAxel Dörfler 			tz |= (-1 << 8);
981eb097431SAxel Dörfler 
982eb097431SAxel Dörfler 		if (-48 <= tz && tz <= 52)
983eb097431SAxel Dörfler 			time += tz *15 * 60;
984eb097431SAxel Dörfler 	}
985eb097431SAxel Dörfler 	*outDate = time;
986eb097431SAxel Dörfler 	return 0;
987eb097431SAxel Dörfler }
988eb097431SAxel Dörfler 
989