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