xref: /haiku/src/add-ons/kernel/file_systems/iso9660/iso9660.cpp (revision 977f0426eebefaac4bcebc135b52c30d29e586e2)
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.
23056b2febaSMichael Lotz 	volume->joliet_level = 0;
23156b2febaSMichael 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
28756b2febaSMichael Lotz parse_rock_ridge(iso9660_volume* volume, iso9660_inode* node, char* buffer,
28856b2febaSMichael 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 					}
454*977f0426SAxel Dörfler 					if (slName != NULL)
455eb097431SAxel Dörfler 						slName[slNameSize] = '\0';
456eb097431SAxel Dörfler 					lastCompFlag = compFlag;
457eb097431SAxel Dörfler 					bytePos += compLen;
458eb097431SAxel Dörfler 					TRACE(("Current sl name is \'%s\'\n", slName));
459eb097431SAxel Dörfler 				}
460eb097431SAxel Dörfler 				node->attr.slName = slName;
461eb097431SAxel Dörfler 				TRACE(("InitNode = symlink name is \'%s\'\n", slName));
462eb097431SAxel Dörfler 				break;
463eb097431SAxel Dörfler 			}
464eb097431SAxel Dörfler 
465eb097431SAxel Dörfler 			// Altername name
466eb097431SAxel Dörfler 			case 'NM':
467eb097431SAxel Dörfler 			{
468eb097431SAxel Dörfler 				uint8 bytePos = 3;
469eb097431SAxel Dörfler 				uint8 flags = 0;
470eb097431SAxel Dörfler 				uint16 oldEnd = altNameSize;
471eb097431SAxel Dörfler 
472eb097431SAxel Dörfler 				altNameSize += length - 5;
473eb097431SAxel Dörfler 				altName = (char*)realloc(altName, altNameSize + 1);
474eb097431SAxel Dörfler 				if (altName == NULL)
475eb097431SAxel Dörfler 					return B_NO_MEMORY;
476eb097431SAxel Dörfler 
477eb097431SAxel Dörfler 				TRACE(("RR: found NM, length %u\n", length));
478eb097431SAxel Dörfler 				// Read flag and version.
479eb097431SAxel Dörfler 				node->attr.nmVer = *(uint8 *)(buffer + bytePos++);
480eb097431SAxel Dörfler 				flags = *(uint8 *)(buffer + bytePos++);
481eb097431SAxel Dörfler 
482eb097431SAxel Dörfler 				TRACE(("RR: nm buffer is %s, start at %p\n", (buffer + bytePos), buffer + bytePos));
483eb097431SAxel Dörfler 
484eb097431SAxel Dörfler 				// Build the file name.
485eb097431SAxel Dörfler 				memcpy(altName + oldEnd, buffer + bytePos, length - 5);
486eb097431SAxel Dörfler 				altName[altNameSize] = '\0';
487eb097431SAxel Dörfler 				TRACE(("RR: alt name is %s\n", altName));
488eb097431SAxel Dörfler 
489eb097431SAxel Dörfler 				// If the name is not continued in another record, update
490eb097431SAxel Dörfler 				// the record name.
491eb097431SAxel Dörfler 				if (!(flags & NM_CONTINUE)) {
492eb097431SAxel Dörfler 					// Get rid of the ISO name, replace with RR name.
493eb097431SAxel Dörfler 					if (node->name != NULL)
494eb097431SAxel Dörfler 						free(node->name);
495eb097431SAxel Dörfler 					node->name = altName;
496eb097431SAxel Dörfler 					node->name_length = altNameSize;
497eb097431SAxel Dörfler 				}
498eb097431SAxel Dörfler 				break;
499eb097431SAxel Dörfler 			}
500eb097431SAxel Dörfler 
501eb097431SAxel Dörfler 			// Deep directory record masquerading as a file.
502eb097431SAxel Dörfler 			case 'CL':
50356b2febaSMichael Lotz 			{
504eb097431SAxel Dörfler 				TRACE(("RR: found CL, length %u\n", length));
50556b2febaSMichael Lotz 				// Reinitialize the node with the information at the
50656b2febaSMichael Lotz 				// "." entry of the pointed to directory data
507eb097431SAxel Dörfler 				node->startLBN[LSB_DATA] = *(uint32*)(buffer+4);
508eb097431SAxel Dörfler 				node->startLBN[MSB_DATA] = *(uint32*)(buffer+8);
50956b2febaSMichael Lotz 
51056b2febaSMichael Lotz 				char* buffer = (char*)block_cache_get(volume->fBlockCache,
51156b2febaSMichael Lotz 					node->startLBN[FS_DATA_FORMAT]);
51256b2febaSMichael Lotz 				if (buffer == NULL)
513eb097431SAxel Dörfler 					break;
514eb097431SAxel Dörfler 
51556b2febaSMichael Lotz 				InitNode(volume, node, buffer, NULL, true);
51656b2febaSMichael Lotz 				block_cache_put(volume->fBlockCache,
51756b2febaSMichael Lotz 					node->startLBN[FS_DATA_FORMAT]);
51856b2febaSMichael Lotz 				break;
51956b2febaSMichael Lotz 			}
52056b2febaSMichael Lotz 
521eb097431SAxel Dörfler 			case 'PL':
522eb097431SAxel Dörfler 				TRACE(("RR: found PL, length %u\n", length));
523eb097431SAxel Dörfler 				break;
524eb097431SAxel Dörfler 
525eb097431SAxel Dörfler 			case 'RE':
526eb097431SAxel Dörfler 				// Relocated directory, we should skip.
527eb097431SAxel Dörfler 				TRACE(("RR: found RE, length %u\n", length));
52856b2febaSMichael Lotz 				if (!relocated)
52947a214deSAxel Dörfler 					return B_NOT_SUPPORTED;
53056b2febaSMichael Lotz 				break;
531eb097431SAxel Dörfler 
532eb097431SAxel Dörfler 			case 'TF':
533eb097431SAxel Dörfler 				TRACE(("RR: found TF, length %u\n", length));
534eb097431SAxel Dörfler 				break;
535eb097431SAxel Dörfler 
536eb097431SAxel Dörfler 			case 'RR':
537eb097431SAxel Dörfler 				TRACE(("RR: found RR, length %u\n", length));
538eb097431SAxel Dörfler 				break;
539eb097431SAxel Dörfler 
54047a214deSAxel Dörfler 			case 'SF':
54147a214deSAxel Dörfler 				TRACE(("RR: found SF, sparse files not supported!\n"));
54247a214deSAxel Dörfler 				// TODO: support sparse files
54347a214deSAxel Dörfler 				return B_NOT_SUPPORTED;
54447a214deSAxel Dörfler 
545eb097431SAxel Dörfler 			default:
54647a214deSAxel Dörfler 				if (buffer[0] == '\0') {
54747a214deSAxel Dörfler 					TRACE(("RR: end of extensions\n"));
548eb097431SAxel Dörfler 					done = true;
54947a214deSAxel Dörfler 				} else
55047a214deSAxel Dörfler 					TRACE(("RR: Unknown tag %c%c\n", buffer[0], buffer[1]));
551eb097431SAxel Dörfler 				break;
552eb097431SAxel Dörfler 		}
553eb097431SAxel Dörfler 	}
554eb097431SAxel Dörfler 
555eb097431SAxel Dörfler 	return B_OK;
556eb097431SAxel Dörfler }
557eb097431SAxel Dörfler 
558eb097431SAxel Dörfler //	#pragma mark - ISO-9660 specific exported functions
559eb097431SAxel Dörfler 
560eb097431SAxel Dörfler 
561eb097431SAxel Dörfler status_t
562eb097431SAxel Dörfler ISOMount(const char *path, uint32 flags, iso9660_volume **_newVolume,
563eb097431SAxel Dörfler 	bool allowJoliet)
564eb097431SAxel Dörfler {
565eb097431SAxel Dörfler 	// path: 		path to device (eg, /dev/disk/scsi/030/raw)
566eb097431SAxel Dörfler 	// partition:	partition number on device ????
567eb097431SAxel Dörfler 	// flags:		currently unused
568eb097431SAxel Dörfler 
569eb097431SAxel Dörfler 	// determine if it is an ISO volume.
570eb097431SAxel Dörfler 	char buffer[ISO_PVD_SIZE];
571eb097431SAxel Dörfler 	bool done = false;
572eb097431SAxel Dörfler 	bool isISO = false;
573eb097431SAxel Dörfler 	off_t offset = 0x8000;
574eb097431SAxel Dörfler 	ssize_t retval;
575eb097431SAxel Dörfler 	partition_info partitionInfo;
576eb097431SAxel Dörfler 	int deviceBlockSize, multiplier;
577eb097431SAxel Dörfler 	iso9660_volume *volume;
578eb097431SAxel Dörfler 
579eb097431SAxel Dörfler 	(void)flags;
580eb097431SAxel Dörfler 
581eb097431SAxel Dörfler 	TRACE(("ISOMount - ENTER\n"));
582eb097431SAxel Dörfler 
583eb097431SAxel Dörfler 	volume = (iso9660_volume *)calloc(sizeof(iso9660_volume), 1);
584eb097431SAxel Dörfler 	if (volume == NULL) {
585eb097431SAxel Dörfler 		TRACE(("ISOMount - mem error \n"));
586eb097431SAxel Dörfler 		return B_NO_MEMORY;
587eb097431SAxel Dörfler 	}
588eb097431SAxel Dörfler 
589eb097431SAxel Dörfler 	memset(&partitionInfo, 0, sizeof(partition_info));
590eb097431SAxel Dörfler 
591eb097431SAxel Dörfler 	/* open and lock the device */
592eb097431SAxel Dörfler 	volume->fdOfSession = open(path, O_RDONLY);
593eb097431SAxel Dörfler 
594eb097431SAxel Dörfler 	/* try to open the raw device to get access to the other sessions as well */
595eb097431SAxel Dörfler 	if (volume->fdOfSession >= 0) {
596eb097431SAxel Dörfler 		if (ioctl(volume->fdOfSession, B_GET_PARTITION_INFO, &partitionInfo) < 0) {
597eb097431SAxel Dörfler 			TRACE(("B_GET_PARTITION_INFO: ioctl returned error\n"));
598eb097431SAxel Dörfler 			strcpy(partitionInfo.device, path);
599eb097431SAxel Dörfler 		}
600eb097431SAxel Dörfler 		TRACE(("ISOMount: open device/file \"%s\"\n", partitionInfo.device));
601eb097431SAxel Dörfler 
602eb097431SAxel Dörfler 		volume->fd = open(partitionInfo.device, O_RDONLY);
603eb097431SAxel Dörfler 	}
604eb097431SAxel Dörfler 
605eb097431SAxel Dörfler 	if (volume->fdOfSession < 0 || volume->fd < 0) {
606eb097431SAxel Dörfler 		close(volume->fd);
607eb097431SAxel Dörfler 		close(volume->fdOfSession);
608eb097431SAxel Dörfler 
609eb097431SAxel Dörfler 		TRACE(("ISO9660 ERROR - Unable to open <%s>\n", path));
610eb097431SAxel Dörfler 		free(volume);
611eb097431SAxel Dörfler 		return B_BAD_VALUE;
612eb097431SAxel Dörfler 	}
613eb097431SAxel Dörfler 
614eb097431SAxel Dörfler 	deviceBlockSize = get_device_block_size(volume->fdOfSession);
615eb097431SAxel Dörfler 	if (deviceBlockSize < 0)  {
616eb097431SAxel Dörfler 		TRACE(("ISO9660 ERROR - device block size is 0\n"));
617eb097431SAxel Dörfler 		close(volume->fd);
618eb097431SAxel Dörfler 		close(volume->fdOfSession);
619eb097431SAxel Dörfler 
620eb097431SAxel Dörfler 		free(volume);
621eb097431SAxel Dörfler 		return B_BAD_VALUE;
622eb097431SAxel Dörfler 	}
623eb097431SAxel Dörfler 
624eb097431SAxel Dörfler 	volume->joliet_level = 0;
625eb097431SAxel Dörfler 	while (!done && offset < 0x10000) {
626eb097431SAxel Dörfler 		retval = read_pos(volume->fdOfSession, offset, (void*)buffer,
627eb097431SAxel Dörfler 			ISO_PVD_SIZE);
628eb097431SAxel Dörfler 		if (retval < ISO_PVD_SIZE) {
629eb097431SAxel Dörfler 			isISO = false;
630eb097431SAxel Dörfler 			break;
631eb097431SAxel Dörfler 		}
632eb097431SAxel Dörfler 
633eb097431SAxel Dörfler 		if (strncmp(buffer + 1, kISO9660IDString, 5) == 0) {
634eb097431SAxel Dörfler 			if (*buffer == 0x01 && !isISO) {
635eb097431SAxel Dörfler 				// ISO_VD_PRIMARY
636eb097431SAxel Dörfler 				off_t maxBlocks;
637eb097431SAxel Dörfler 
638eb097431SAxel Dörfler 				TRACE(("ISOMount: Is an ISO9660 volume, initting rec\n"));
639eb097431SAxel Dörfler 
640eb097431SAxel Dörfler 				InitVolDesc(volume, buffer);
641eb097431SAxel Dörfler 				strncpy(volume->devicePath,path,127);
642eb097431SAxel Dörfler 				volume->id = ISO_ROOTNODE_ID;
643eb097431SAxel Dörfler 				TRACE(("ISO9660: volume->blockSize = %d\n", volume->logicalBlkSize[FS_DATA_FORMAT]));
644eb097431SAxel Dörfler 
645eb097431SAxel Dörfler 				multiplier = deviceBlockSize / volume->logicalBlkSize[FS_DATA_FORMAT];
646eb097431SAxel Dörfler 				TRACE(("ISOMount: block size multiplier is %d\n", multiplier));
647eb097431SAxel Dörfler 
648eb097431SAxel Dörfler 				// if the session is on a real device, size != 0
649eb097431SAxel Dörfler 				if (partitionInfo.size != 0) {
650eb097431SAxel Dörfler 					maxBlocks = (partitionInfo.size + partitionInfo.offset)
651eb097431SAxel Dörfler 						/ volume->logicalBlkSize[FS_DATA_FORMAT];
652eb097431SAxel Dörfler 				} else
653eb097431SAxel Dörfler 					maxBlocks = volume->volSpaceSize[FS_DATA_FORMAT];
654eb097431SAxel Dörfler 
655eb097431SAxel Dörfler 				/* Initialize access to the cache so that we can do cached i/o */
656eb097431SAxel Dörfler 				TRACE(("ISO9660: cache init: dev %d, max blocks %Ld\n", volume->fd, maxBlocks));
657eb097431SAxel Dörfler 				volume->fBlockCache = block_cache_create(volume->fd, maxBlocks,
658eb097431SAxel Dörfler 					volume->logicalBlkSize[FS_DATA_FORMAT], true);
659eb097431SAxel Dörfler 				isISO = true;
660eb097431SAxel Dörfler 			} else if (*buffer == 0x02 && isISO && allowJoliet) {
661eb097431SAxel Dörfler 				// ISO_VD_SUPPLEMENTARY
662eb097431SAxel Dörfler 
663eb097431SAxel Dörfler 				// JOLIET extension
664eb097431SAxel Dörfler 				// test escape sequence for level of UCS-2 characterset
665eb097431SAxel Dörfler 			    if (buffer[88] == 0x25 && buffer[89] == 0x2f) {
666eb097431SAxel Dörfler 					switch (buffer[90]) {
667eb097431SAxel Dörfler 						case 0x40: volume->joliet_level = 1; break;
668eb097431SAxel Dörfler 						case 0x43: volume->joliet_level = 2; break;
669eb097431SAxel Dörfler 						case 0x45: volume->joliet_level = 3; break;
670eb097431SAxel Dörfler 					}
671eb097431SAxel Dörfler 
672eb097431SAxel Dörfler 					TRACE(("ISO9660 Extensions: Microsoft Joliet Level %d\n", volume->joliet_level));
673eb097431SAxel Dörfler 
674eb097431SAxel Dörfler 					// Because Joliet-stuff starts at other sector,
675eb097431SAxel Dörfler 					// update root directory record.
67656b2febaSMichael Lotz 					if (volume->joliet_level > 0) {
67756b2febaSMichael Lotz 						InitNode(volume, &volume->rootDirRec, &buffer[156],
67856b2febaSMichael Lotz 							NULL);
67956b2febaSMichael Lotz 					}
680eb097431SAxel Dörfler 				}
681eb097431SAxel Dörfler 			} else if (*(unsigned char *)buffer == 0xff) {
682eb097431SAxel Dörfler 				// ISO_VD_END
683eb097431SAxel Dörfler 				done = true;
684eb097431SAxel Dörfler 			} else
685eb097431SAxel Dörfler 				TRACE(("found header %d\n",*buffer));
686eb097431SAxel Dörfler 		}
687eb097431SAxel Dörfler 		offset += 0x800;
688eb097431SAxel Dörfler 	}
689eb097431SAxel Dörfler 
690eb097431SAxel Dörfler 	if (!isISO) {
691eb097431SAxel Dörfler 		// It isn't an ISO disk.
692eb097431SAxel Dörfler 		close(volume->fdOfSession);
693eb097431SAxel Dörfler 		close(volume->fd);
694eb097431SAxel Dörfler 		free(volume);
695eb097431SAxel Dörfler 
696eb097431SAxel Dörfler 		TRACE(("ISOMount: Not an ISO9660 volume!\n"));
697eb097431SAxel Dörfler 		return B_BAD_VALUE;
698eb097431SAxel Dörfler 	}
699eb097431SAxel Dörfler 
700eb097431SAxel Dörfler 	TRACE(("ISOMount - EXIT, returning %p\n", volume));
701eb097431SAxel Dörfler 	*_newVolume = volume;
702eb097431SAxel Dörfler 	return B_OK;
703eb097431SAxel Dörfler }
704eb097431SAxel Dörfler 
705eb097431SAxel Dörfler 
706eb097431SAxel Dörfler /*!	Reads in a single directory entry and fills in the values in the
707eb097431SAxel Dörfler 	dirent struct. Uses the cookie to keep track of the current block
708eb097431SAxel Dörfler 	and position within the block. Also uses the cookie to determine when
709eb097431SAxel Dörfler 	it has reached the end of the directory file.
710eb097431SAxel Dörfler */
711eb097431SAxel Dörfler status_t
712eb097431SAxel Dörfler ISOReadDirEnt(iso9660_volume *volume, dircookie *cookie, struct dirent *dirent,
713eb097431SAxel Dörfler 	size_t bufferSize)
714eb097431SAxel Dörfler {
715eb097431SAxel Dörfler 	int	result = B_NO_ERROR;
71699d1bfb5SAxel Dörfler 	bool done = false;
717eb097431SAxel Dörfler 
718eb097431SAxel Dörfler 	TRACE(("ISOReadDirEnt - ENTER\n"));
719eb097431SAxel Dörfler 
72099d1bfb5SAxel Dörfler 	while (!done) {
72199d1bfb5SAxel Dörfler 		off_t totalRead = cookie->pos + (cookie->block - cookie->startBlock)
72299d1bfb5SAxel Dörfler 			* volume->logicalBlkSize[FS_DATA_FORMAT];
72399d1bfb5SAxel Dörfler 
724eb097431SAxel Dörfler 		// If we're at the end of the data in a block, move to the next block.
72599d1bfb5SAxel Dörfler 		char *blockData;
726eb097431SAxel Dörfler 		while (true) {
72799d1bfb5SAxel Dörfler 			blockData
72899d1bfb5SAxel Dörfler 				= (char*)block_cache_get(volume->fBlockCache, cookie->block);
729eb097431SAxel Dörfler 			if (blockData != NULL && *(blockData + cookie->pos) == 0) {
730eb097431SAxel Dörfler 				// NULL data, move to next block.
731eb097431SAxel Dörfler 				block_cache_put(volume->fBlockCache, cookie->block);
732eb097431SAxel Dörfler 				blockData = NULL;
73399d1bfb5SAxel Dörfler 				totalRead
73499d1bfb5SAxel Dörfler 					+= volume->logicalBlkSize[FS_DATA_FORMAT] - cookie->pos;
735eb097431SAxel Dörfler 				cookie->pos = 0;
736eb097431SAxel Dörfler 				cookie->block++;
737eb097431SAxel Dörfler 			} else
738eb097431SAxel Dörfler 				break;
739eb097431SAxel Dörfler 
740eb097431SAxel Dörfler 			if (totalRead >= cookie->totalSize)
741eb097431SAxel Dörfler 				break;
742eb097431SAxel Dörfler 		}
743eb097431SAxel Dörfler 
74499d1bfb5SAxel Dörfler 		off_t cacheBlock = cookie->block;
74599d1bfb5SAxel Dörfler 
746eb097431SAxel Dörfler 		if (blockData != NULL && totalRead < cookie->totalSize) {
747eb097431SAxel Dörfler 			iso9660_inode node;
74899d1bfb5SAxel Dörfler 			size_t bytesRead = 0;
74956b2febaSMichael Lotz 			result = InitNode(volume, &node, blockData + cookie->pos,
75056b2febaSMichael Lotz 				&bytesRead);
75143276e5bSMichael Lotz 
75243276e5bSMichael Lotz 			// if we hit an entry that we don't support, we just skip it
75343276e5bSMichael Lotz 			if (result != B_OK && result != B_NOT_SUPPORTED)
75447a214deSAxel Dörfler 				break;
75547a214deSAxel Dörfler 
75643276e5bSMichael Lotz 			if (result == B_OK && (node.flags & ISO_IS_ASSOCIATED_FILE) == 0) {
757eb097431SAxel Dörfler 				size_t nameBufferSize = bufferSize - sizeof(struct dirent);
758eb097431SAxel Dörfler 
759eb097431SAxel Dörfler 				dirent->d_dev = volume->id;
760eb097431SAxel Dörfler 				dirent->d_ino = ((ino_t)cookie->block << 30)
761eb097431SAxel Dörfler 					+ (cookie->pos & 0x3fffffff);
762eb097431SAxel Dörfler 				dirent->d_reclen = sizeof(struct dirent) + node.name_length + 1;
763eb097431SAxel Dörfler 
764eb097431SAxel Dörfler 				if (node.name_length <= nameBufferSize) {
765eb097431SAxel Dörfler 					// need to do some size checking here.
766eb097431SAxel Dörfler 					strlcpy(dirent->d_name, node.name, node.name_length + 1);
76799d1bfb5SAxel Dörfler 					TRACE(("ISOReadDirEnt  - success, name is %s, block %Ld, "
76899d1bfb5SAxel Dörfler 						"pos %Ld, inode id %Ld\n", dirent->d_name, cookie->block,
769eb097431SAxel Dörfler 						cookie->pos, dirent->d_ino));
770eb097431SAxel Dörfler 				} else {
771eb097431SAxel Dörfler 					// TODO: this can be just normal if we support reading more
772eb097431SAxel Dörfler 					// than one entry.
77399d1bfb5SAxel Dörfler 					TRACE(("ISOReadDirEnt - ERROR, name %s does not fit in "
77499d1bfb5SAxel Dörfler 						"buffer of size %d\n", node.name, (int)nameBufferSize));
775eb097431SAxel Dörfler 					result = B_BAD_VALUE;
776eb097431SAxel Dörfler 				}
77747a214deSAxel Dörfler 
77847a214deSAxel Dörfler 				done = true;
779eb097431SAxel Dörfler 			}
7802a64cb11SAxel Dörfler 
78147a214deSAxel Dörfler 			cookie->pos += bytesRead;
78247a214deSAxel Dörfler 
7832a64cb11SAxel Dörfler 			if (cookie->pos == volume->logicalBlkSize[FS_DATA_FORMAT]) {
7842a64cb11SAxel Dörfler 				cookie->pos = 0;
7852a64cb11SAxel Dörfler 				cookie->block++;
7862a64cb11SAxel Dörfler 			}
787eb097431SAxel Dörfler 		} else {
788eb097431SAxel Dörfler 			if (totalRead >= cookie->totalSize)
789eb097431SAxel Dörfler 				result = B_ENTRY_NOT_FOUND;
790eb097431SAxel Dörfler 			else
791eb097431SAxel Dörfler 				result = B_NO_MEMORY;
79299d1bfb5SAxel Dörfler 			done = true;
793eb097431SAxel Dörfler 		}
794eb097431SAxel Dörfler 
795eb097431SAxel Dörfler 		if (blockData != NULL)
796eb097431SAxel Dörfler 			block_cache_put(volume->fBlockCache, cacheBlock);
79799d1bfb5SAxel Dörfler 	}
798eb097431SAxel Dörfler 
799eb097431SAxel Dörfler 	TRACE(("ISOReadDirEnt - EXIT, result is %s, vnid is %Lu\n",
800eb097431SAxel Dörfler 		strerror(result), dirent->d_ino));
80199d1bfb5SAxel Dörfler 
802eb097431SAxel Dörfler 	return result;
803eb097431SAxel Dörfler }
804eb097431SAxel Dörfler 
805eb097431SAxel Dörfler 
806eb097431SAxel Dörfler status_t
80756b2febaSMichael Lotz InitNode(iso9660_volume* volume, iso9660_inode* node, char* buffer,
80856b2febaSMichael Lotz 	size_t* _bytesRead, bool relocated)
809eb097431SAxel Dörfler {
810eb097431SAxel Dörfler 	uint8 recordLength = *(uint8*)buffer++;
811eb097431SAxel Dörfler 	size_t nameLength;
812eb097431SAxel Dörfler 
813eb097431SAxel Dörfler 	TRACE(("InitNode - ENTER, bufstart is %p, record length is %d bytes\n",
814eb097431SAxel Dörfler 		buffer, recordLength));
815eb097431SAxel Dörfler 
816eb097431SAxel Dörfler 	if (_bytesRead != NULL)
817eb097431SAxel Dörfler 		*_bytesRead = recordLength;
818eb097431SAxel Dörfler 	if (recordLength == 0)
819eb097431SAxel Dörfler 		return B_ENTRY_NOT_FOUND;
820eb097431SAxel Dörfler 
821eb097431SAxel Dörfler 	char* end = buffer + recordLength;
822eb097431SAxel Dörfler 
82356b2febaSMichael Lotz 	if (!relocated) {
824eb097431SAxel Dörfler 		node->cache = NULL;
825eb097431SAxel Dörfler 		node->name = NULL;
826eb097431SAxel Dörfler 		node->attr.slName = NULL;
827eb097431SAxel Dörfler 		memset(node->attr.stat, 0, sizeof(node->attr.stat));
82856b2febaSMichael Lotz 	} else
82956b2febaSMichael Lotz 		free(node->attr.slName);
830eb097431SAxel Dörfler 
831eb097431SAxel Dörfler 	node->extAttrRecLen = *(uint8*)buffer++;
83299d1bfb5SAxel Dörfler 	TRACE(("InitNode - ext attr length is %d\n", (int)node->extAttrRecLen));
833eb097431SAxel Dörfler 
834eb097431SAxel Dörfler 	node->startLBN[LSB_DATA] = *(uint32*)buffer;
835eb097431SAxel Dörfler 	buffer += 4;
836eb097431SAxel Dörfler 	node->startLBN[MSB_DATA] = *(uint32*)buffer;
837eb097431SAxel Dörfler 	buffer += 4;
83899d1bfb5SAxel Dörfler 	TRACE(("InitNode - data start LBN is %d\n",
83999d1bfb5SAxel Dörfler 		(int)node->startLBN[FS_DATA_FORMAT]));
840eb097431SAxel Dörfler 
841eb097431SAxel Dörfler 	node->dataLen[LSB_DATA] = *(uint32*)buffer;
842eb097431SAxel Dörfler 	buffer += 4;
843eb097431SAxel Dörfler 	node->dataLen[MSB_DATA] = *(uint32*)buffer;
844eb097431SAxel Dörfler 	buffer += 4;
84599d1bfb5SAxel Dörfler 	TRACE(("InitNode - data length is %d\n",
84699d1bfb5SAxel Dörfler 		(int)node->dataLen[FS_DATA_FORMAT]));
847eb097431SAxel Dörfler 
848eb097431SAxel Dörfler 	init_node_date(&node->recordDate, buffer);
849eb097431SAxel Dörfler 	buffer += 7;
850eb097431SAxel Dörfler 
851eb097431SAxel Dörfler 	node->flags = *(uint8*)buffer;
852eb097431SAxel Dörfler 	buffer++;
853eb097431SAxel Dörfler 	TRACE(("InitNode - flags are %d\n", node->flags));
854eb097431SAxel Dörfler 
855eb097431SAxel Dörfler 	node->fileUnitSize = *(uint8*)buffer;
856eb097431SAxel Dörfler 	buffer++;
857eb097431SAxel Dörfler 	TRACE(("InitNode - fileUnitSize is %d\n", node->fileUnitSize));
858eb097431SAxel Dörfler 
859eb097431SAxel Dörfler 	node->interleaveGapSize = *(uint8*)buffer;
860eb097431SAxel Dörfler 	buffer++;
861eb097431SAxel Dörfler 	TRACE(("InitNode - interleave gap size = %d\n", node->interleaveGapSize));
862eb097431SAxel Dörfler 
863eb097431SAxel Dörfler 	node->volSeqNum = *(uint32*)buffer;
864eb097431SAxel Dörfler 	buffer += 4;
86599d1bfb5SAxel Dörfler 	TRACE(("InitNode - volume seq num is %d\n", (int)node->volSeqNum));
866eb097431SAxel Dörfler 
86756b2febaSMichael Lotz 	nameLength = *(uint8*)buffer;
868eb097431SAxel Dörfler 	buffer++;
86956b2febaSMichael Lotz 
87056b2febaSMichael Lotz 	// for relocated directories we take the name from the placeholder entry
87156b2febaSMichael Lotz 	if (!relocated) {
87256b2febaSMichael Lotz 		node->name_length = nameLength;
87399d1bfb5SAxel Dörfler 		TRACE(("InitNode - file id length is %u\n", node->name_length));
87456b2febaSMichael Lotz 	}
875eb097431SAxel Dörfler 
876eb097431SAxel Dörfler 	// Set defaults, in case there is no RockRidge stuff.
87747a214deSAxel Dörfler 	node->attr.stat[FS_DATA_FORMAT].st_mode |= (node->flags & ISO_IS_DIR) != 0
878eb097431SAxel Dörfler 		? S_IFDIR | S_IXUSR | S_IRUSR | S_IXGRP | S_IRGRP | S_IXOTH | S_IROTH
879eb097431SAxel Dörfler 		: S_IFREG | S_IRUSR | S_IRGRP | S_IROTH;
880eb097431SAxel Dörfler 
881eb097431SAxel Dörfler 	if (node->name_length == 0) {
882eb097431SAxel Dörfler 		TRACE(("InitNode - File ID String is 0 length\n"));
883eb097431SAxel Dörfler 		return B_ENTRY_NOT_FOUND;
884eb097431SAxel Dörfler 	}
885eb097431SAxel Dörfler 
88656b2febaSMichael Lotz 	if (!relocated) {
887eb097431SAxel Dörfler 		// JOLIET extension:
888eb097431SAxel Dörfler 		// on joliet discs, buffer[0] can be 0 for Unicoded filenames,
889eb097431SAxel Dörfler 		// so I've added a check here to test explicitely for
890eb097431SAxel Dörfler 		// directories (which have length 1)
891eb097431SAxel Dörfler 		// Take care of "." and "..", the first two dirents are
892eb097431SAxel Dörfler 		// these in iso.
8931dd3b2c7SAxel Dörfler 		if (node->name_length == 1 && buffer[0] == 0) {
894eb097431SAxel Dörfler 			node->name = strdup(".");
895eb097431SAxel Dörfler 			node->name_length = 1;
8961dd3b2c7SAxel Dörfler 		} else if (node->name_length == 1 && buffer[0] == 1) {
897eb097431SAxel Dörfler 			node->name = strdup("..");
898eb097431SAxel Dörfler 			node->name_length = 2;
89956b2febaSMichael Lotz 		} else if (volume->joliet_level > 0) {
900eb097431SAxel Dörfler 			// JOLIET extension: convert Unicode16 string to UTF8
901eb097431SAxel Dörfler 			// Assume that the unicode->utf8 conversion produces 4 byte
902eb097431SAxel Dörfler 			// utf8 characters, and allocate that much space
903eb097431SAxel Dörfler 			node->name = (char*)malloc(node->name_length * 2 + 1);
904eb097431SAxel Dörfler 			if (node->name == NULL)
905eb097431SAxel Dörfler 				return B_NO_MEMORY;
906eb097431SAxel Dörfler 
907eb097431SAxel Dörfler 			int32 sourceLength = node->name_length;
908eb097431SAxel Dörfler 			int32 destLength = node->name_length * 2;
909eb097431SAxel Dörfler 
910eb097431SAxel Dörfler 			status_t status = unicode_to_utf8(buffer, &sourceLength,
911eb097431SAxel Dörfler 				node->name, &destLength);
912eb097431SAxel Dörfler 			if (status < B_OK) {
913eb097431SAxel Dörfler 				dprintf("iso9660: error converting unicode->utf8\n");
914eb097431SAxel Dörfler 				return status;
915eb097431SAxel Dörfler 			}
916eb097431SAxel Dörfler 
917eb097431SAxel Dörfler 			node->name[destLength] = '\0';
918eb097431SAxel Dörfler 			node->name_length = destLength;
919eb097431SAxel Dörfler 
920eb097431SAxel Dörfler 			sanitize_iso_name(node, false);
921eb097431SAxel Dörfler 		} else {
922eb097431SAxel Dörfler 			node->name = (char*)malloc(node->name_length + 1);
923eb097431SAxel Dörfler 			if (node->name == NULL)
924eb097431SAxel Dörfler 				return B_NO_MEMORY;
925eb097431SAxel Dörfler 
926eb097431SAxel Dörfler 			// convert all characters to lower case
92756b2febaSMichael Lotz 			for (uint32 i = 0; i < node->name_length; i++)
928eb097431SAxel Dörfler 				node->name[i] = tolower(buffer[i]);
92956b2febaSMichael Lotz 
930eb097431SAxel Dörfler 			node->name[node->name_length] = '\0';
931eb097431SAxel Dörfler 
932eb097431SAxel Dörfler 			sanitize_iso_name(node, true);
933eb097431SAxel Dörfler 		}
934eb097431SAxel Dörfler 
935eb097431SAxel Dörfler 		if (node->name == NULL) {
936eb097431SAxel Dörfler 			TRACE(("InitNode - unable to allocate memory!\n"));
937eb097431SAxel Dörfler 			return B_NO_MEMORY;
938eb097431SAxel Dörfler 		}
93956b2febaSMichael Lotz 	}
940eb097431SAxel Dörfler 
941eb097431SAxel Dörfler 	buffer += nameLength;
942eb097431SAxel Dörfler 	if (nameLength % 2 == 0)
943eb097431SAxel Dörfler 		buffer++;
944eb097431SAxel Dörfler 
945eb097431SAxel Dörfler 	TRACE(("DirRec ID String is: %s\n", node->name));
946eb097431SAxel Dörfler 
94756b2febaSMichael Lotz 	return parse_rock_ridge(volume, node, buffer, end, relocated);
948eb097431SAxel Dörfler }
949eb097431SAxel Dörfler 
950eb097431SAxel Dörfler 
951eb097431SAxel Dörfler status_t
952eb097431SAxel Dörfler ConvertRecDate(ISORecDate* inDate, time_t* outDate)
953eb097431SAxel Dörfler {
954eb097431SAxel Dörfler 	time_t	time;
955eb097431SAxel Dörfler 	int		days, i, year, tz;
956eb097431SAxel Dörfler 
957eb097431SAxel Dörfler 	year = inDate->year -70;
958eb097431SAxel Dörfler 	tz = inDate->offsetGMT;
959eb097431SAxel Dörfler 
960eb097431SAxel Dörfler 	if (year < 0) {
961eb097431SAxel Dörfler 		time = 0;
962eb097431SAxel Dörfler 	} else {
963eb097431SAxel Dörfler 		const int monlen[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
964eb097431SAxel Dörfler 
965eb097431SAxel Dörfler 		days = (year * 365);
966eb097431SAxel Dörfler 
967eb097431SAxel Dörfler 		if (year > 2)
968eb097431SAxel Dörfler 			days += (year + 1)/ 4;
969eb097431SAxel Dörfler 
970eb097431SAxel Dörfler 		for (i = 1; (i < inDate->month) && (i < 12); i++) {
971eb097431SAxel Dörfler 			days += monlen[i-1];
972eb097431SAxel Dörfler 		}
973eb097431SAxel Dörfler 
974eb097431SAxel Dörfler 		if (((year + 2) % 4) == 0 && inDate->month > 2)
975eb097431SAxel Dörfler 			days++;
976eb097431SAxel Dörfler 
977eb097431SAxel Dörfler 		days += inDate->date - 1;
978eb097431SAxel Dörfler 		time = ((((days*24) + inDate->hour) * 60 + inDate->minute) * 60)
979eb097431SAxel Dörfler 					+ inDate->second;
980eb097431SAxel Dörfler 		if (tz & 0x80)
981eb097431SAxel Dörfler 			tz |= (-1 << 8);
982eb097431SAxel Dörfler 
983eb097431SAxel Dörfler 		if (-48 <= tz && tz <= 52)
984eb097431SAxel Dörfler 			time += tz *15 * 60;
985eb097431SAxel Dörfler 	}
986eb097431SAxel Dörfler 	*outDate = time;
987eb097431SAxel Dörfler 	return 0;
988eb097431SAxel Dörfler }
989eb097431SAxel Dörfler 
990