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
get_device_block_size(int fd)48eb097431SAxel Dörfler get_device_block_size(int fd)
49eb097431SAxel Dörfler {
50eb097431SAxel Dörfler device_geometry geometry;
51eb097431SAxel Dörfler
521418cadeSAugustin Cavalier if (ioctl(fd, B_GET_GEOMETRY, &geometry, sizeof(device_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
unicode_to_utf8(const char * src,int32 * srcLen,char * dst,int32 * dstLen)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
sanitize_iso_name(iso9660_inode * node,bool removeTrailingPoints)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
init_volume_date(ISOVolDate * date,char * buffer)145eb097431SAxel Dörfler init_volume_date(ISOVolDate *date, char *buffer)
146eb097431SAxel Dörfler {
147723f4b6aSGediminas Jarulaitis memcpy(date, buffer, ISO_VOL_DATE_SIZE);
148eb097431SAxel Dörfler return 0;
149eb097431SAxel Dörfler }
150eb097431SAxel Dörfler
151eb097431SAxel Dörfler
152eb097431SAxel Dörfler static int
init_node_date(ISORecDate * date,char * buffer)153eb097431SAxel Dörfler init_node_date(ISORecDate *date, char *buffer)
154eb097431SAxel Dörfler {
155723f4b6aSGediminas Jarulaitis memcpy(date, buffer, sizeof(struct ISORecDate));
156eb097431SAxel Dörfler return 0;
157eb097431SAxel Dörfler }
158eb097431SAxel Dörfler
159eb097431SAxel Dörfler
160eb097431SAxel Dörfler static status_t
InitVolDesc(iso9660_volume * volume,char * buffer)161eb097431SAxel Dörfler InitVolDesc(iso9660_volume *volume, char *buffer)
162eb097431SAxel Dörfler {
163eb097431SAxel Dörfler TRACE(("InitVolDesc - ENTER\n"));
164eb097431SAxel Dörfler
165723f4b6aSGediminas Jarulaitis volume->volDescType = *(uint8 *)buffer;
166723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->volDescType);
167eb097431SAxel Dörfler
168723f4b6aSGediminas Jarulaitis const size_t kStdIDStringLen = sizeof(volume->stdIDString) - 1;
169723f4b6aSGediminas Jarulaitis volume->stdIDString[kStdIDStringLen] = '\0';
170723f4b6aSGediminas Jarulaitis strncpy(volume->stdIDString, buffer, kStdIDStringLen);
171723f4b6aSGediminas Jarulaitis buffer += kStdIDStringLen;
172eb097431SAxel Dörfler
173eb097431SAxel Dörfler volume->volDescVersion = *(uint8 *)buffer;
174723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->volDescVersion);
175eb097431SAxel Dörfler
176723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->unused1); // skip unused 8th byte
177723f4b6aSGediminas Jarulaitis
178723f4b6aSGediminas Jarulaitis const size_t kSystemIDStringLen = sizeof(volume->systemIDString) - 1;
179723f4b6aSGediminas Jarulaitis volume->systemIDString[kSystemIDStringLen] = '\0';
180723f4b6aSGediminas Jarulaitis strncpy(volume->systemIDString, buffer, kSystemIDStringLen);
181723f4b6aSGediminas Jarulaitis buffer += kSystemIDStringLen;
182eb097431SAxel Dörfler TRACE(("InitVolDesc - system id string is %s\n", volume->systemIDString));
183eb097431SAxel Dörfler
184723f4b6aSGediminas Jarulaitis const size_t kVolIDStringLen = sizeof(volume->volIDString) - 1;
185723f4b6aSGediminas Jarulaitis volume->volIDString[kVolIDStringLen] = '\0';
186723f4b6aSGediminas Jarulaitis strncpy(volume->volIDString, buffer, kVolIDStringLen);
187723f4b6aSGediminas Jarulaitis buffer += kVolIDStringLen;
188eb097431SAxel Dörfler TRACE(("InitVolDesc - volume id string is %s\n", volume->volIDString));
189eb097431SAxel Dörfler
190723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->unused2) - 1; // skip unused 73-80 bytes
191723f4b6aSGediminas Jarulaitis
192eb097431SAxel Dörfler volume->volSpaceSize[LSB_DATA] = *(uint32 *)buffer;
193723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->volSpaceSize[LSB_DATA]);
194eb097431SAxel Dörfler volume->volSpaceSize[MSB_DATA] = *(uint32 *)buffer;
195723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->volSpaceSize[MSB_DATA]);
196723f4b6aSGediminas Jarulaitis
197723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->unused3) - 1; // skip unused 89-120 bytes
198eb097431SAxel Dörfler
199eb097431SAxel Dörfler volume->volSetSize[LSB_DATA] = *(uint16*)buffer;
200723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->volSetSize[LSB_DATA]);
201eb097431SAxel Dörfler volume->volSetSize[MSB_DATA] = *(uint16*)buffer;
202723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->volSetSize[MSB_DATA]);
203eb097431SAxel Dörfler
204eb097431SAxel Dörfler volume->volSeqNum[LSB_DATA] = *(uint16*)buffer;
205723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->volSeqNum[LSB_DATA]);
206eb097431SAxel Dörfler volume->volSeqNum[MSB_DATA] = *(uint16*)buffer;
207723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->volSeqNum[MSB_DATA]);
208eb097431SAxel Dörfler
209eb097431SAxel Dörfler volume->logicalBlkSize[LSB_DATA] = *(uint16*)buffer;
210723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->logicalBlkSize[LSB_DATA]);
211eb097431SAxel Dörfler volume->logicalBlkSize[MSB_DATA] = *(uint16*)buffer;
212723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->logicalBlkSize[MSB_DATA]);
213eb097431SAxel Dörfler
214eb097431SAxel Dörfler volume->pathTblSize[LSB_DATA] = *(uint32*)buffer;
215723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->pathTblSize[LSB_DATA]);
216eb097431SAxel Dörfler volume->pathTblSize[MSB_DATA] = *(uint32*)buffer;
217723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->pathTblSize[MSB_DATA]);
218eb097431SAxel Dörfler
219eb097431SAxel Dörfler volume->lPathTblLoc[LSB_DATA] = *(uint16*)buffer;
220723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->lPathTblLoc[LSB_DATA]);
221eb097431SAxel Dörfler volume->lPathTblLoc[MSB_DATA] = *(uint16*)buffer;
222723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->lPathTblLoc[MSB_DATA]);
223eb097431SAxel Dörfler
224eb097431SAxel Dörfler volume->optLPathTblLoc[LSB_DATA] = *(uint16*)buffer;
225723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->optLPathTblLoc[LSB_DATA]);
226eb097431SAxel Dörfler volume->optLPathTblLoc[MSB_DATA] = *(uint16*)buffer;
227723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->optLPathTblLoc[MSB_DATA]);
228eb097431SAxel Dörfler
229eb097431SAxel Dörfler volume->mPathTblLoc[LSB_DATA] = *(uint16*)buffer;
230723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->mPathTblLoc[LSB_DATA]);
231eb097431SAxel Dörfler volume->mPathTblLoc[MSB_DATA] = *(uint16*)buffer;
232723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->mPathTblLoc[MSB_DATA]);
233eb097431SAxel Dörfler
234eb097431SAxel Dörfler volume->optMPathTblLoc[LSB_DATA] = *(uint16*)buffer;
235723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->optMPathTblLoc[LSB_DATA]);
236eb097431SAxel Dörfler volume->optMPathTblLoc[MSB_DATA] = *(uint16*)buffer;
237723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->optMPathTblLoc[MSB_DATA]);
238eb097431SAxel Dörfler
239eb097431SAxel Dörfler // Fill in directory record.
24056b2febaSMichael Lotz volume->joliet_level = 0;
24156b2febaSMichael Lotz InitNode(volume, &volume->rootDirRec, buffer, NULL);
242eb097431SAxel Dörfler
243eb097431SAxel Dörfler volume->rootDirRec.id = ISO_ROOTNODE_ID;
244723f4b6aSGediminas Jarulaitis buffer += ISO_ROOT_DIR_REC_SIZE;
245eb097431SAxel Dörfler
246723f4b6aSGediminas Jarulaitis const size_t kVolSetIDStringLen = sizeof(volume->volSetIDString) - 1;
247723f4b6aSGediminas Jarulaitis volume->volSetIDString[kVolSetIDStringLen] = '\0';
248723f4b6aSGediminas Jarulaitis strncpy(volume->volSetIDString, buffer, kVolSetIDStringLen);
249723f4b6aSGediminas Jarulaitis buffer += kVolSetIDStringLen;
250eb097431SAxel Dörfler TRACE(("InitVolDesc - volume set id string is %s\n", volume->volSetIDString));
251eb097431SAxel Dörfler
252723f4b6aSGediminas Jarulaitis const size_t kPubIDStringLen = sizeof(volume->pubIDString) - 1;
253723f4b6aSGediminas Jarulaitis volume->pubIDString[kPubIDStringLen] = '\0';
254723f4b6aSGediminas Jarulaitis strncpy(volume->pubIDString, buffer, kPubIDStringLen);
255723f4b6aSGediminas Jarulaitis buffer += kPubIDStringLen;
256eb097431SAxel Dörfler TRACE(("InitVolDesc - volume pub id string is %s\n", volume->pubIDString));
257eb097431SAxel Dörfler
258723f4b6aSGediminas Jarulaitis const size_t kDataPreparerLen = sizeof(volume->dataPreparer) - 1;
259723f4b6aSGediminas Jarulaitis volume->dataPreparer[kDataPreparerLen] = '\0';
260723f4b6aSGediminas Jarulaitis strncpy(volume->dataPreparer, buffer, kDataPreparerLen);
261723f4b6aSGediminas Jarulaitis buffer += kDataPreparerLen;
262eb097431SAxel Dörfler TRACE(("InitVolDesc - volume dataPreparer string is %s\n", volume->dataPreparer));
263eb097431SAxel Dörfler
264723f4b6aSGediminas Jarulaitis const size_t kAppIDStringLen = sizeof(volume->appIDString) - 1;
265723f4b6aSGediminas Jarulaitis volume->appIDString[kAppIDStringLen] = '\0';
266723f4b6aSGediminas Jarulaitis strncpy(volume->appIDString, buffer, kAppIDStringLen);
267723f4b6aSGediminas Jarulaitis buffer += kAppIDStringLen;
268eb097431SAxel Dörfler TRACE(("InitVolDesc - volume app id string is %s\n", volume->appIDString));
269eb097431SAxel Dörfler
270723f4b6aSGediminas Jarulaitis const size_t kCopyrightLen = sizeof(volume->copyright) - 1;
271723f4b6aSGediminas Jarulaitis volume->copyright[kCopyrightLen] = '\0';
272723f4b6aSGediminas Jarulaitis strncpy(volume->copyright, buffer, kCopyrightLen);
273723f4b6aSGediminas Jarulaitis buffer += kCopyrightLen;
274eb097431SAxel Dörfler TRACE(("InitVolDesc - copyright is %s\n", volume->copyright));
275eb097431SAxel Dörfler
276723f4b6aSGediminas Jarulaitis const size_t kAbstractFNameLen = sizeof(volume->abstractFName) - 1;
277723f4b6aSGediminas Jarulaitis volume->abstractFName[kAbstractFNameLen] = '\0';
278723f4b6aSGediminas Jarulaitis strncpy(volume->abstractFName, buffer, kAbstractFNameLen);
279723f4b6aSGediminas Jarulaitis buffer += kAbstractFNameLen;
280eb097431SAxel Dörfler
281723f4b6aSGediminas Jarulaitis const size_t kBiblioFNameLen = sizeof(volume->biblioFName) - 1;
282723f4b6aSGediminas Jarulaitis volume->biblioFName[kBiblioFNameLen] = '\0';
283723f4b6aSGediminas Jarulaitis strncpy(volume->biblioFName, buffer, kBiblioFNameLen);
284723f4b6aSGediminas Jarulaitis buffer += kBiblioFNameLen;
285eb097431SAxel Dörfler
286eb097431SAxel Dörfler init_volume_date(&volume->createDate, buffer);
287723f4b6aSGediminas Jarulaitis buffer += ISO_VOL_DATE_SIZE;
288eb097431SAxel Dörfler
289eb097431SAxel Dörfler init_volume_date(&volume->modDate, buffer);
290723f4b6aSGediminas Jarulaitis buffer += ISO_VOL_DATE_SIZE;
291eb097431SAxel Dörfler
292eb097431SAxel Dörfler init_volume_date(&volume->expireDate, buffer);
293723f4b6aSGediminas Jarulaitis buffer += ISO_VOL_DATE_SIZE;
294eb097431SAxel Dörfler
295eb097431SAxel Dörfler init_volume_date(&volume->effectiveDate, buffer);
296723f4b6aSGediminas Jarulaitis buffer += ISO_VOL_DATE_SIZE;
297eb097431SAxel Dörfler
298eb097431SAxel Dörfler volume->fileStructVers = *(uint8*)buffer;
299eb097431SAxel Dörfler return B_OK;
300eb097431SAxel Dörfler }
301eb097431SAxel Dörfler
302eb097431SAxel Dörfler
303eb097431SAxel Dörfler static status_t
parse_rock_ridge(iso9660_volume * volume,iso9660_inode * node,char * buffer,char * end,bool relocated)30456b2febaSMichael Lotz parse_rock_ridge(iso9660_volume* volume, iso9660_inode* node, char* buffer,
30556b2febaSMichael Lotz char* end, bool relocated)
306eb097431SAxel Dörfler {
307eb097431SAxel Dörfler // Now we're at the start of the rock ridge stuff
308eb097431SAxel Dörfler char* altName = NULL;
309eb097431SAxel Dörfler char* slName = NULL;
3107dc68bfbSAdrien Destugues char* newSlName = NULL;
311eb097431SAxel Dörfler uint16 altNameSize = 0;
312eb097431SAxel Dörfler uint16 slNameSize = 0;
313eb097431SAxel Dörfler uint8 length = 0;
314eb097431SAxel Dörfler bool done = false;
315eb097431SAxel Dörfler
316eb097431SAxel Dörfler TRACE(("RR: Start of extensions at %p\n", buffer));
317eb097431SAxel Dörfler
318eb097431SAxel Dörfler while (!done) {
319eb097431SAxel Dörfler buffer += length;
320eb097431SAxel Dörfler if (buffer + 2 >= end)
321eb097431SAxel Dörfler break;
322eb097431SAxel Dörfler length = *(uint8*)(buffer + 2);
323eb097431SAxel Dörfler if (buffer + length > end)
324eb097431SAxel Dörfler break;
32547a214deSAxel Dörfler if (length == 0)
32647a214deSAxel Dörfler break;
327eb097431SAxel Dörfler
328eb097431SAxel Dörfler switch (((int)buffer[0] << 8) + buffer[1]) {
329eb097431SAxel Dörfler // Stat structure stuff
330eb097431SAxel Dörfler case 'PX':
331eb097431SAxel Dörfler {
332eb097431SAxel Dörfler uint8 bytePos = 3;
333eb097431SAxel Dörfler TRACE(("RR: found PX, length %u\n", length));
334eb097431SAxel Dörfler node->attr.pxVer = *(uint8*)(buffer + bytePos++);
335eb097431SAxel Dörfler
336eb097431SAxel Dörfler // st_mode
337eb097431SAxel Dörfler node->attr.stat[LSB_DATA].st_mode
338eb097431SAxel Dörfler = *(mode_t*)(buffer + bytePos);
339eb097431SAxel Dörfler bytePos += 4;
340eb097431SAxel Dörfler node->attr.stat[MSB_DATA].st_mode
341eb097431SAxel Dörfler = *(mode_t*)(buffer + bytePos);
342eb097431SAxel Dörfler bytePos += 4;
343eb097431SAxel Dörfler
344eb097431SAxel Dörfler // st_nlink
345eb097431SAxel Dörfler node->attr.stat[LSB_DATA].st_nlink
346eb097431SAxel Dörfler = *(nlink_t*)(buffer+bytePos);
347eb097431SAxel Dörfler bytePos += 4;
348eb097431SAxel Dörfler node->attr.stat[MSB_DATA].st_nlink
349eb097431SAxel Dörfler = *(nlink_t*)(buffer + bytePos);
350eb097431SAxel Dörfler bytePos += 4;
351eb097431SAxel Dörfler
352eb097431SAxel Dörfler // st_uid
353eb097431SAxel Dörfler node->attr.stat[LSB_DATA].st_uid
354eb097431SAxel Dörfler = *(uid_t*)(buffer + bytePos);
355eb097431SAxel Dörfler bytePos += 4;
356eb097431SAxel Dörfler node->attr.stat[MSB_DATA].st_uid
357eb097431SAxel Dörfler = *(uid_t*)(buffer + bytePos);
358eb097431SAxel Dörfler bytePos += 4;
359eb097431SAxel Dörfler
360eb097431SAxel Dörfler // st_gid
361eb097431SAxel Dörfler node->attr.stat[LSB_DATA].st_gid
362eb097431SAxel Dörfler = *(gid_t*)(buffer + bytePos);
363eb097431SAxel Dörfler bytePos += 4;
364eb097431SAxel Dörfler node->attr.stat[MSB_DATA].st_gid
365eb097431SAxel Dörfler = *(gid_t*)(buffer + bytePos);
366eb097431SAxel Dörfler bytePos += 4;
367eb097431SAxel Dörfler break;
368eb097431SAxel Dörfler }
369eb097431SAxel Dörfler
370eb097431SAxel Dörfler case 'PN':
371eb097431SAxel Dörfler TRACE(("RR: found PN, length %u\n", length));
372eb097431SAxel Dörfler break;
373eb097431SAxel Dörfler
374eb097431SAxel Dörfler // Symbolic link info
375eb097431SAxel Dörfler case 'SL':
376eb097431SAxel Dörfler {
377eb097431SAxel Dörfler uint8 bytePos = 3;
378eb097431SAxel Dörfler uint8 addPos = 0;
379eb097431SAxel Dörfler bool slDone = false;
380eb097431SAxel Dörfler bool useSeparator = true;
381eb097431SAxel Dörfler
382eb097431SAxel Dörfler TRACE(("RR: found SL, length %u\n", length));
383eb097431SAxel Dörfler TRACE(("Buffer is at %p\n", buffer));
384eb097431SAxel Dörfler TRACE(("Current length is %u\n", slNameSize));
385eb097431SAxel Dörfler //kernel_debugger("");
386eb097431SAxel Dörfler node->attr.slVer = *(uint8*)(buffer + bytePos++);
387eb5f3639SJerome Duval #if TRACE_ISO9660
388eb5f3639SJerome Duval uint8 slFlags = *(uint8*)(buffer + bytePos++);
389eb097431SAxel Dörfler TRACE(("sl flags are %u\n", slFlags));
390e766bb9eSRene Gollent #else
391e766bb9eSRene Gollent // skip symlink flags
392e766bb9eSRene Gollent ++bytePos;
393eb5f3639SJerome Duval #endif
394eb097431SAxel Dörfler while (!slDone && bytePos < length) {
395eb097431SAxel Dörfler uint8 compFlag = *(uint8*)(buffer + bytePos++);
396eb097431SAxel Dörfler uint8 compLen = *(uint8*)(buffer + bytePos++);
397eb097431SAxel Dörfler
398eb097431SAxel Dörfler if (slName == NULL)
399eb097431SAxel Dörfler useSeparator = false;
400eb097431SAxel Dörfler
401eb097431SAxel Dörfler addPos = slNameSize;
402eb097431SAxel Dörfler
403eb097431SAxel Dörfler TRACE(("sl comp flags are %u, length is %u\n", compFlag, compLen));
404eb097431SAxel Dörfler TRACE(("Current name size is %u\n", slNameSize));
405eb097431SAxel Dörfler
406eb097431SAxel Dörfler switch (compFlag) {
407eb097431SAxel Dörfler case SLCP_CONTINUE:
408eb097431SAxel Dörfler useSeparator = false;
409eb097431SAxel Dörfler default:
410eb097431SAxel Dörfler // Add the component to the total path.
411eb097431SAxel Dörfler slNameSize += compLen;
412eb097431SAxel Dörfler if (useSeparator)
413eb097431SAxel Dörfler slNameSize++;
4147dc68bfbSAdrien Destugues newSlName = (char*)realloc(slName,
415eb097431SAxel Dörfler slNameSize + 1);
4167dc68bfbSAdrien Destugues if (newSlName == NULL) {
4177dc68bfbSAdrien Destugues free(slName);
418eb097431SAxel Dörfler return B_NO_MEMORY;
4197dc68bfbSAdrien Destugues }
4207dc68bfbSAdrien Destugues slName = newSlName;
421eb097431SAxel Dörfler
422eb097431SAxel Dörfler if (useSeparator) {
423eb097431SAxel Dörfler TRACE(("Adding separator\n"));
424eb097431SAxel Dörfler slName[addPos++] = '/';
425eb097431SAxel Dörfler }
426eb097431SAxel Dörfler
427eb097431SAxel Dörfler TRACE(("doing memcopy of %u bytes at offset %d\n", compLen, addPos));
428eb097431SAxel Dörfler memcpy(slName + addPos, buffer + bytePos,
429eb097431SAxel Dörfler compLen);
430eb097431SAxel Dörfler
431eb097431SAxel Dörfler addPos += compLen;
432eb097431SAxel Dörfler useSeparator = true;
433eb097431SAxel Dörfler break;
434eb097431SAxel Dörfler
435eb097431SAxel Dörfler case SLCP_CURRENT:
436eb097431SAxel Dörfler TRACE(("InitNode - found link to current directory\n"));
437eb097431SAxel Dörfler slNameSize += 2;
4387dc68bfbSAdrien Destugues newSlName = (char*)realloc(slName,
439eb097431SAxel Dörfler slNameSize + 1);
4407dc68bfbSAdrien Destugues if (newSlName == NULL) {
4417dc68bfbSAdrien Destugues free(slName);
442eb097431SAxel Dörfler return B_NO_MEMORY;
4437dc68bfbSAdrien Destugues }
4447dc68bfbSAdrien Destugues slName = newSlName;
445eb097431SAxel Dörfler
446eb097431SAxel Dörfler memcpy(slName + addPos, "./", 2);
447eb097431SAxel Dörfler useSeparator = false;
448eb097431SAxel Dörfler break;
449eb097431SAxel Dörfler
450eb097431SAxel Dörfler case SLCP_PARENT:
451eb097431SAxel Dörfler slNameSize += 3;
4527dc68bfbSAdrien Destugues newSlName = (char*)realloc(slName,
453eb097431SAxel Dörfler slNameSize + 1);
4547dc68bfbSAdrien Destugues if (newSlName == NULL) {
4557dc68bfbSAdrien Destugues free(slName);
456eb097431SAxel Dörfler return B_NO_MEMORY;
4577dc68bfbSAdrien Destugues }
4587dc68bfbSAdrien Destugues slName = newSlName;
459eb097431SAxel Dörfler
460eb097431SAxel Dörfler memcpy(slName + addPos, "../", 3);
461eb097431SAxel Dörfler useSeparator = false;
462eb097431SAxel Dörfler break;
463eb097431SAxel Dörfler
464eb097431SAxel Dörfler case SLCP_ROOT:
465eb097431SAxel Dörfler TRACE(("InitNode - found link to root directory\n"));
466eb097431SAxel Dörfler slNameSize += 1;
4677dc68bfbSAdrien Destugues newSlName = (char*)realloc(slName,
468eb097431SAxel Dörfler slNameSize + 1);
4697dc68bfbSAdrien Destugues if (newSlName == NULL) {
4707dc68bfbSAdrien Destugues free(slName);
471eb097431SAxel Dörfler return B_NO_MEMORY;
4727dc68bfbSAdrien Destugues }
4737dc68bfbSAdrien Destugues slName = newSlName;
474eb097431SAxel Dörfler memcpy(slName + addPos, "/", 1);
475eb097431SAxel Dörfler useSeparator = false;
476eb097431SAxel Dörfler break;
477eb097431SAxel Dörfler
478eb097431SAxel Dörfler case SLCP_VOLROOT:
479eb097431SAxel Dörfler slDone = true;
480eb097431SAxel Dörfler break;
481eb097431SAxel Dörfler
482eb097431SAxel Dörfler case SLCP_HOST:
483eb097431SAxel Dörfler slDone = true;
484eb097431SAxel Dörfler break;
485eb097431SAxel Dörfler }
486977f0426SAxel Dörfler if (slName != NULL)
487eb097431SAxel Dörfler slName[slNameSize] = '\0';
488eb097431SAxel Dörfler bytePos += compLen;
489eb097431SAxel Dörfler TRACE(("Current sl name is \'%s\'\n", slName));
490eb097431SAxel Dörfler }
491eb097431SAxel Dörfler node->attr.slName = slName;
492eb097431SAxel Dörfler TRACE(("InitNode = symlink name is \'%s\'\n", slName));
493eb097431SAxel Dörfler break;
494eb097431SAxel Dörfler }
495eb097431SAxel Dörfler
496eb097431SAxel Dörfler // Altername name
497eb097431SAxel Dörfler case 'NM':
498eb097431SAxel Dörfler {
499eb097431SAxel Dörfler uint8 bytePos = 3;
500eb097431SAxel Dörfler uint8 flags = 0;
501eb097431SAxel Dörfler uint16 oldEnd = altNameSize;
502eb097431SAxel Dörfler
503eb097431SAxel Dörfler altNameSize += length - 5;
5047dc68bfbSAdrien Destugues char* newAltName = (char*)realloc(altName, altNameSize + 1);
5057dc68bfbSAdrien Destugues if (newAltName == NULL) {
5067dc68bfbSAdrien Destugues free(altName);
507eb097431SAxel Dörfler return B_NO_MEMORY;
5087dc68bfbSAdrien Destugues }
5097dc68bfbSAdrien Destugues altName = newAltName;
510eb097431SAxel Dörfler
511eb097431SAxel Dörfler TRACE(("RR: found NM, length %u\n", length));
512eb097431SAxel Dörfler // Read flag and version.
513eb097431SAxel Dörfler node->attr.nmVer = *(uint8 *)(buffer + bytePos++);
514eb097431SAxel Dörfler flags = *(uint8 *)(buffer + bytePos++);
515eb097431SAxel Dörfler
5167dc68bfbSAdrien Destugues TRACE(("RR: nm buffer is %s, start at %p\n", (buffer + bytePos),
5177dc68bfbSAdrien Destugues buffer + bytePos));
518eb097431SAxel Dörfler
519eb097431SAxel Dörfler // Build the file name.
520eb097431SAxel Dörfler memcpy(altName + oldEnd, buffer + bytePos, length - 5);
521eb097431SAxel Dörfler altName[altNameSize] = '\0';
522eb097431SAxel Dörfler TRACE(("RR: alt name is %s\n", altName));
523eb097431SAxel Dörfler
524eb097431SAxel Dörfler // If the name is not continued in another record, update
525eb097431SAxel Dörfler // the record name.
526eb097431SAxel Dörfler if (!(flags & NM_CONTINUE)) {
527eb097431SAxel Dörfler // Get rid of the ISO name, replace with RR name.
528eb097431SAxel Dörfler if (node->name != NULL)
529eb097431SAxel Dörfler free(node->name);
530eb097431SAxel Dörfler node->name = altName;
531eb097431SAxel Dörfler node->name_length = altNameSize;
532eb097431SAxel Dörfler }
533eb097431SAxel Dörfler break;
534eb097431SAxel Dörfler }
535eb097431SAxel Dörfler
536eb097431SAxel Dörfler // Deep directory record masquerading as a file.
537eb097431SAxel Dörfler case 'CL':
53856b2febaSMichael Lotz {
539eb097431SAxel Dörfler TRACE(("RR: found CL, length %u\n", length));
54056b2febaSMichael Lotz // Reinitialize the node with the information at the
54156b2febaSMichael Lotz // "." entry of the pointed to directory data
542eb097431SAxel Dörfler node->startLBN[LSB_DATA] = *(uint32*)(buffer+4);
543eb097431SAxel Dörfler node->startLBN[MSB_DATA] = *(uint32*)(buffer+8);
54456b2febaSMichael Lotz
54556b2febaSMichael Lotz char* buffer = (char*)block_cache_get(volume->fBlockCache,
54656b2febaSMichael Lotz node->startLBN[FS_DATA_FORMAT]);
54756b2febaSMichael Lotz if (buffer == NULL)
548eb097431SAxel Dörfler break;
549eb097431SAxel Dörfler
55056b2febaSMichael Lotz InitNode(volume, node, buffer, NULL, true);
55156b2febaSMichael Lotz block_cache_put(volume->fBlockCache,
55256b2febaSMichael Lotz node->startLBN[FS_DATA_FORMAT]);
55356b2febaSMichael Lotz break;
55456b2febaSMichael Lotz }
55556b2febaSMichael Lotz
556eb097431SAxel Dörfler case 'PL':
557eb097431SAxel Dörfler TRACE(("RR: found PL, length %u\n", length));
558eb097431SAxel Dörfler break;
559eb097431SAxel Dörfler
560eb097431SAxel Dörfler case 'RE':
561eb097431SAxel Dörfler // Relocated directory, we should skip.
562eb097431SAxel Dörfler TRACE(("RR: found RE, length %u\n", length));
56356b2febaSMichael Lotz if (!relocated)
564a735bdebSMichael Lotz return B_UNSUPPORTED;
56556b2febaSMichael Lotz break;
566eb097431SAxel Dörfler
567eb097431SAxel Dörfler case 'TF':
568eb097431SAxel Dörfler TRACE(("RR: found TF, length %u\n", length));
569eb097431SAxel Dörfler break;
570eb097431SAxel Dörfler
571eb097431SAxel Dörfler case 'RR':
572eb097431SAxel Dörfler TRACE(("RR: found RR, length %u\n", length));
573eb097431SAxel Dörfler break;
574eb097431SAxel Dörfler
57547a214deSAxel Dörfler case 'SF':
57647a214deSAxel Dörfler TRACE(("RR: found SF, sparse files not supported!\n"));
57747a214deSAxel Dörfler // TODO: support sparse files
578a735bdebSMichael Lotz return B_UNSUPPORTED;
57947a214deSAxel Dörfler
580eb097431SAxel Dörfler default:
58147a214deSAxel Dörfler if (buffer[0] == '\0') {
58247a214deSAxel Dörfler TRACE(("RR: end of extensions\n"));
583eb097431SAxel Dörfler done = true;
58447a214deSAxel Dörfler } else
58547a214deSAxel Dörfler TRACE(("RR: Unknown tag %c%c\n", buffer[0], buffer[1]));
586eb097431SAxel Dörfler break;
587eb097431SAxel Dörfler }
588eb097431SAxel Dörfler }
589eb097431SAxel Dörfler
590eb097431SAxel Dörfler return B_OK;
591eb097431SAxel Dörfler }
592eb097431SAxel Dörfler
593eb097431SAxel Dörfler // #pragma mark - ISO-9660 specific exported functions
594eb097431SAxel Dörfler
595eb097431SAxel Dörfler
596eb097431SAxel Dörfler status_t
ISOMount(const char * path,uint32 flags,iso9660_volume ** _newVolume,bool allowJoliet)597eb097431SAxel Dörfler ISOMount(const char *path, uint32 flags, iso9660_volume **_newVolume,
598eb097431SAxel Dörfler bool allowJoliet)
599eb097431SAxel Dörfler {
600eb097431SAxel Dörfler // path: path to device (eg, /dev/disk/scsi/030/raw)
601eb097431SAxel Dörfler // partition: partition number on device ????
602eb097431SAxel Dörfler // flags: currently unused
603eb097431SAxel Dörfler
604eb097431SAxel Dörfler // determine if it is an ISO volume.
605eb097431SAxel Dörfler char buffer[ISO_PVD_SIZE];
606eb097431SAxel Dörfler bool done = false;
607eb097431SAxel Dörfler bool isISO = false;
608eb097431SAxel Dörfler off_t offset = 0x8000;
609eb097431SAxel Dörfler ssize_t retval;
610eb097431SAxel Dörfler partition_info partitionInfo;
611eb5f3639SJerome Duval int deviceBlockSize;
612eb097431SAxel Dörfler iso9660_volume *volume;
613eb097431SAxel Dörfler
614eb097431SAxel Dörfler (void)flags;
615eb097431SAxel Dörfler
616eb097431SAxel Dörfler TRACE(("ISOMount - ENTER\n"));
617eb097431SAxel Dörfler
618eb097431SAxel Dörfler volume = (iso9660_volume *)calloc(sizeof(iso9660_volume), 1);
619eb097431SAxel Dörfler if (volume == NULL) {
620eb097431SAxel Dörfler TRACE(("ISOMount - mem error \n"));
621eb097431SAxel Dörfler return B_NO_MEMORY;
622eb097431SAxel Dörfler }
623eb097431SAxel Dörfler
624eb097431SAxel Dörfler memset(&partitionInfo, 0, sizeof(partition_info));
625eb097431SAxel Dörfler
626eb097431SAxel Dörfler /* open and lock the device */
627eb097431SAxel Dörfler volume->fdOfSession = open(path, O_RDONLY);
628eb097431SAxel Dörfler
629eb097431SAxel Dörfler /* try to open the raw device to get access to the other sessions as well */
630eb097431SAxel Dörfler if (volume->fdOfSession >= 0) {
6311418cadeSAugustin Cavalier if (ioctl(volume->fdOfSession, B_GET_PARTITION_INFO, &partitionInfo,
6321418cadeSAugustin Cavalier sizeof(partition_info)) < 0) {
633eb097431SAxel Dörfler TRACE(("B_GET_PARTITION_INFO: ioctl returned error\n"));
634eb097431SAxel Dörfler strcpy(partitionInfo.device, path);
635eb097431SAxel Dörfler }
636eb097431SAxel Dörfler TRACE(("ISOMount: open device/file \"%s\"\n", partitionInfo.device));
637eb097431SAxel Dörfler
638eb097431SAxel Dörfler volume->fd = open(partitionInfo.device, O_RDONLY);
639eb097431SAxel Dörfler }
640eb097431SAxel Dörfler
641eb097431SAxel Dörfler if (volume->fdOfSession < 0 || volume->fd < 0) {
642eb097431SAxel Dörfler close(volume->fd);
643eb097431SAxel Dörfler close(volume->fdOfSession);
644eb097431SAxel Dörfler
645eb097431SAxel Dörfler TRACE(("ISO9660 ERROR - Unable to open <%s>\n", path));
646eb097431SAxel Dörfler free(volume);
647eb097431SAxel Dörfler return B_BAD_VALUE;
648eb097431SAxel Dörfler }
649eb097431SAxel Dörfler
650eb097431SAxel Dörfler deviceBlockSize = get_device_block_size(volume->fdOfSession);
651eb097431SAxel Dörfler if (deviceBlockSize < 0) {
652eb097431SAxel Dörfler TRACE(("ISO9660 ERROR - device block size is 0\n"));
653eb097431SAxel Dörfler close(volume->fd);
654eb097431SAxel Dörfler close(volume->fdOfSession);
655eb097431SAxel Dörfler
656eb097431SAxel Dörfler free(volume);
657eb097431SAxel Dörfler return B_BAD_VALUE;
658eb097431SAxel Dörfler }
659eb097431SAxel Dörfler
660eb097431SAxel Dörfler volume->joliet_level = 0;
661eb097431SAxel Dörfler while (!done && offset < 0x10000) {
662eb097431SAxel Dörfler retval = read_pos(volume->fdOfSession, offset, (void*)buffer,
663eb097431SAxel Dörfler ISO_PVD_SIZE);
664eb097431SAxel Dörfler if (retval < ISO_PVD_SIZE) {
665eb097431SAxel Dörfler isISO = false;
666eb097431SAxel Dörfler break;
667eb097431SAxel Dörfler }
668eb097431SAxel Dörfler
669eb097431SAxel Dörfler if (strncmp(buffer + 1, kISO9660IDString, 5) == 0) {
670eb097431SAxel Dörfler if (*buffer == 0x01 && !isISO) {
671eb097431SAxel Dörfler // ISO_VD_PRIMARY
672eb097431SAxel Dörfler off_t maxBlocks;
673eb097431SAxel Dörfler
674eb097431SAxel Dörfler TRACE(("ISOMount: Is an ISO9660 volume, initting rec\n"));
675eb097431SAxel Dörfler
676eb097431SAxel Dörfler InitVolDesc(volume, buffer);
677eb097431SAxel Dörfler strncpy(volume->devicePath,path,127);
678eb097431SAxel Dörfler volume->id = ISO_ROOTNODE_ID;
679eb097431SAxel Dörfler TRACE(("ISO9660: volume->blockSize = %d\n", volume->logicalBlkSize[FS_DATA_FORMAT]));
680eb097431SAxel Dörfler
681eb5f3639SJerome Duval #if TRACE_ISO9660
682eb5f3639SJerome Duval int multiplier = deviceBlockSize / volume->logicalBlkSize[FS_DATA_FORMAT];
683eb097431SAxel Dörfler TRACE(("ISOMount: block size multiplier is %d\n", multiplier));
684eb5f3639SJerome Duval #endif
685eb097431SAxel Dörfler
686eb097431SAxel Dörfler // if the session is on a real device, size != 0
687eb097431SAxel Dörfler if (partitionInfo.size != 0) {
688eb097431SAxel Dörfler maxBlocks = (partitionInfo.size + partitionInfo.offset)
689eb097431SAxel Dörfler / volume->logicalBlkSize[FS_DATA_FORMAT];
690eb097431SAxel Dörfler } else
691eb097431SAxel Dörfler maxBlocks = volume->volSpaceSize[FS_DATA_FORMAT];
692eb097431SAxel Dörfler
693eb097431SAxel Dörfler /* Initialize access to the cache so that we can do cached i/o */
694*425ac1b6SAlexander von Gluck IV TRACE(("ISO9660: cache init: dev %d, max blocks %lld\n", volume->fd, maxBlocks));
695eb097431SAxel Dörfler volume->fBlockCache = block_cache_create(volume->fd, maxBlocks,
696eb097431SAxel Dörfler volume->logicalBlkSize[FS_DATA_FORMAT], true);
697eb097431SAxel Dörfler isISO = true;
698eb097431SAxel Dörfler } else if (*buffer == 0x02 && isISO && allowJoliet) {
699eb097431SAxel Dörfler // ISO_VD_SUPPLEMENTARY
700eb097431SAxel Dörfler
701eb097431SAxel Dörfler // JOLIET extension
702eb097431SAxel Dörfler // test escape sequence for level of UCS-2 characterset
703eb097431SAxel Dörfler if (buffer[88] == 0x25 && buffer[89] == 0x2f) {
704eb097431SAxel Dörfler switch (buffer[90]) {
705eb097431SAxel Dörfler case 0x40: volume->joliet_level = 1; break;
706eb097431SAxel Dörfler case 0x43: volume->joliet_level = 2; break;
707eb097431SAxel Dörfler case 0x45: volume->joliet_level = 3; break;
708eb097431SAxel Dörfler }
709eb097431SAxel Dörfler
710eb097431SAxel Dörfler TRACE(("ISO9660 Extensions: Microsoft Joliet Level %d\n", volume->joliet_level));
711eb097431SAxel Dörfler
712eb097431SAxel Dörfler // Because Joliet-stuff starts at other sector,
713eb097431SAxel Dörfler // update root directory record.
71456b2febaSMichael Lotz if (volume->joliet_level > 0) {
71556b2febaSMichael Lotz InitNode(volume, &volume->rootDirRec, &buffer[156],
71656b2febaSMichael Lotz NULL);
71756b2febaSMichael Lotz }
718eb097431SAxel Dörfler }
719eb097431SAxel Dörfler } else if (*(unsigned char *)buffer == 0xff) {
720eb097431SAxel Dörfler // ISO_VD_END
721eb097431SAxel Dörfler done = true;
722eb097431SAxel Dörfler } else
723eb097431SAxel Dörfler TRACE(("found header %d\n",*buffer));
724eb097431SAxel Dörfler }
725eb097431SAxel Dörfler offset += 0x800;
726eb097431SAxel Dörfler }
727eb097431SAxel Dörfler
728eb097431SAxel Dörfler if (!isISO) {
729eb097431SAxel Dörfler // It isn't an ISO disk.
730eb097431SAxel Dörfler close(volume->fdOfSession);
731eb097431SAxel Dörfler close(volume->fd);
732eb097431SAxel Dörfler free(volume);
733eb097431SAxel Dörfler
734eb097431SAxel Dörfler TRACE(("ISOMount: Not an ISO9660 volume!\n"));
735eb097431SAxel Dörfler return B_BAD_VALUE;
736eb097431SAxel Dörfler }
737eb097431SAxel Dörfler
738eb097431SAxel Dörfler TRACE(("ISOMount - EXIT, returning %p\n", volume));
739eb097431SAxel Dörfler *_newVolume = volume;
740eb097431SAxel Dörfler return B_OK;
741eb097431SAxel Dörfler }
742eb097431SAxel Dörfler
743eb097431SAxel Dörfler
744eb097431SAxel Dörfler /*! Reads in a single directory entry and fills in the values in the
745eb097431SAxel Dörfler dirent struct. Uses the cookie to keep track of the current block
746eb097431SAxel Dörfler and position within the block. Also uses the cookie to determine when
747eb097431SAxel Dörfler it has reached the end of the directory file.
748eb097431SAxel Dörfler */
749eb097431SAxel Dörfler status_t
ISOReadDirEnt(iso9660_volume * volume,dircookie * cookie,struct dirent * dirent,size_t bufferSize)750eb097431SAxel Dörfler ISOReadDirEnt(iso9660_volume *volume, dircookie *cookie, struct dirent *dirent,
751eb097431SAxel Dörfler size_t bufferSize)
752eb097431SAxel Dörfler {
753eb097431SAxel Dörfler int result = B_NO_ERROR;
75499d1bfb5SAxel Dörfler bool done = false;
755eb097431SAxel Dörfler
756eb097431SAxel Dörfler TRACE(("ISOReadDirEnt - ENTER\n"));
757eb097431SAxel Dörfler
75899d1bfb5SAxel Dörfler while (!done) {
75999d1bfb5SAxel Dörfler off_t totalRead = cookie->pos + (cookie->block - cookie->startBlock)
76099d1bfb5SAxel Dörfler * volume->logicalBlkSize[FS_DATA_FORMAT];
76199d1bfb5SAxel Dörfler
762eb097431SAxel Dörfler // If we're at the end of the data in a block, move to the next block.
76399d1bfb5SAxel Dörfler char *blockData;
764eb097431SAxel Dörfler while (true) {
76599d1bfb5SAxel Dörfler blockData
76699d1bfb5SAxel Dörfler = (char*)block_cache_get(volume->fBlockCache, cookie->block);
767eb097431SAxel Dörfler if (blockData != NULL && *(blockData + cookie->pos) == 0) {
768eb097431SAxel Dörfler // NULL data, move to next block.
769eb097431SAxel Dörfler block_cache_put(volume->fBlockCache, cookie->block);
770eb097431SAxel Dörfler blockData = NULL;
77199d1bfb5SAxel Dörfler totalRead
77299d1bfb5SAxel Dörfler += volume->logicalBlkSize[FS_DATA_FORMAT] - cookie->pos;
773eb097431SAxel Dörfler cookie->pos = 0;
774eb097431SAxel Dörfler cookie->block++;
775eb097431SAxel Dörfler } else
776eb097431SAxel Dörfler break;
777eb097431SAxel Dörfler
778eb097431SAxel Dörfler if (totalRead >= cookie->totalSize)
779eb097431SAxel Dörfler break;
780eb097431SAxel Dörfler }
781eb097431SAxel Dörfler
78299d1bfb5SAxel Dörfler off_t cacheBlock = cookie->block;
78399d1bfb5SAxel Dörfler
784eb097431SAxel Dörfler if (blockData != NULL && totalRead < cookie->totalSize) {
785eb097431SAxel Dörfler iso9660_inode node;
78699d1bfb5SAxel Dörfler size_t bytesRead = 0;
78756b2febaSMichael Lotz result = InitNode(volume, &node, blockData + cookie->pos,
78856b2febaSMichael Lotz &bytesRead);
78943276e5bSMichael Lotz
79043276e5bSMichael Lotz // if we hit an entry that we don't support, we just skip it
791a735bdebSMichael Lotz if (result != B_OK && result != B_UNSUPPORTED)
79247a214deSAxel Dörfler break;
79347a214deSAxel Dörfler
79443276e5bSMichael Lotz if (result == B_OK && (node.flags & ISO_IS_ASSOCIATED_FILE) == 0) {
795711e2dc0SAugustin Cavalier size_t nameBufferSize = bufferSize - offsetof(struct dirent, d_name);
796eb097431SAxel Dörfler
797eb097431SAxel Dörfler dirent->d_dev = volume->id;
798eb097431SAxel Dörfler dirent->d_ino = ((ino_t)cookie->block << 30)
799eb097431SAxel Dörfler + (cookie->pos & 0x3fffffff);
800711e2dc0SAugustin Cavalier dirent->d_reclen = offsetof(struct dirent, d_name) + node.name_length + 1;
801eb097431SAxel Dörfler
802eb097431SAxel Dörfler if (node.name_length <= nameBufferSize) {
803eb097431SAxel Dörfler // need to do some size checking here.
804eb097431SAxel Dörfler strlcpy(dirent->d_name, node.name, node.name_length + 1);
805*425ac1b6SAlexander von Gluck IV TRACE(("ISOReadDirEnt - success, name is %s, block %lld, "
806*425ac1b6SAlexander von Gluck IV "pos %lld, inode id %lld\n", dirent->d_name, cookie->block,
807eb097431SAxel Dörfler cookie->pos, dirent->d_ino));
808eb097431SAxel Dörfler } else {
809eb097431SAxel Dörfler // TODO: this can be just normal if we support reading more
810eb097431SAxel Dörfler // than one entry.
81199d1bfb5SAxel Dörfler TRACE(("ISOReadDirEnt - ERROR, name %s does not fit in "
81299d1bfb5SAxel Dörfler "buffer of size %d\n", node.name, (int)nameBufferSize));
813eb097431SAxel Dörfler result = B_BAD_VALUE;
814eb097431SAxel Dörfler }
81547a214deSAxel Dörfler
81647a214deSAxel Dörfler done = true;
817eb097431SAxel Dörfler }
8182a64cb11SAxel Dörfler
81947a214deSAxel Dörfler cookie->pos += bytesRead;
82047a214deSAxel Dörfler
8212a64cb11SAxel Dörfler if (cookie->pos == volume->logicalBlkSize[FS_DATA_FORMAT]) {
8222a64cb11SAxel Dörfler cookie->pos = 0;
8232a64cb11SAxel Dörfler cookie->block++;
8242a64cb11SAxel Dörfler }
825eb097431SAxel Dörfler } else {
826eb097431SAxel Dörfler if (totalRead >= cookie->totalSize)
827eb097431SAxel Dörfler result = B_ENTRY_NOT_FOUND;
828eb097431SAxel Dörfler else
829eb097431SAxel Dörfler result = B_NO_MEMORY;
83099d1bfb5SAxel Dörfler done = true;
831eb097431SAxel Dörfler }
832eb097431SAxel Dörfler
833eb097431SAxel Dörfler if (blockData != NULL)
834eb097431SAxel Dörfler block_cache_put(volume->fBlockCache, cacheBlock);
83599d1bfb5SAxel Dörfler }
836eb097431SAxel Dörfler
837eb097431SAxel Dörfler TRACE(("ISOReadDirEnt - EXIT, result is %s, vnid is %Lu\n",
838eb097431SAxel Dörfler strerror(result), dirent->d_ino));
83999d1bfb5SAxel Dörfler
840eb097431SAxel Dörfler return result;
841eb097431SAxel Dörfler }
842eb097431SAxel Dörfler
843eb097431SAxel Dörfler
844eb097431SAxel Dörfler status_t
InitNode(iso9660_volume * volume,iso9660_inode * node,char * buffer,size_t * _bytesRead,bool relocated)84556b2febaSMichael Lotz InitNode(iso9660_volume* volume, iso9660_inode* node, char* buffer,
84656b2febaSMichael Lotz size_t* _bytesRead, bool relocated)
847eb097431SAxel Dörfler {
848eb097431SAxel Dörfler uint8 recordLength = *(uint8*)buffer++;
849eb097431SAxel Dörfler size_t nameLength;
850eb097431SAxel Dörfler
851eb097431SAxel Dörfler TRACE(("InitNode - ENTER, bufstart is %p, record length is %d bytes\n",
852eb097431SAxel Dörfler buffer, recordLength));
853eb097431SAxel Dörfler
854eb097431SAxel Dörfler if (_bytesRead != NULL)
855eb097431SAxel Dörfler *_bytesRead = recordLength;
856eb097431SAxel Dörfler if (recordLength == 0)
857eb097431SAxel Dörfler return B_ENTRY_NOT_FOUND;
858eb097431SAxel Dörfler
859eb097431SAxel Dörfler char* end = buffer + recordLength;
860eb097431SAxel Dörfler
86156b2febaSMichael Lotz if (!relocated) {
862eb097431SAxel Dörfler node->cache = NULL;
863eb097431SAxel Dörfler node->name = NULL;
864eb097431SAxel Dörfler node->attr.slName = NULL;
865eb097431SAxel Dörfler memset(node->attr.stat, 0, sizeof(node->attr.stat));
86656b2febaSMichael Lotz } else
86756b2febaSMichael Lotz free(node->attr.slName);
868eb097431SAxel Dörfler
869eb097431SAxel Dörfler node->extAttrRecLen = *(uint8*)buffer++;
87099d1bfb5SAxel Dörfler TRACE(("InitNode - ext attr length is %d\n", (int)node->extAttrRecLen));
871eb097431SAxel Dörfler
872eb097431SAxel Dörfler node->startLBN[LSB_DATA] = *(uint32*)buffer;
873eb097431SAxel Dörfler buffer += 4;
874eb097431SAxel Dörfler node->startLBN[MSB_DATA] = *(uint32*)buffer;
875eb097431SAxel Dörfler buffer += 4;
87699d1bfb5SAxel Dörfler TRACE(("InitNode - data start LBN is %d\n",
87799d1bfb5SAxel Dörfler (int)node->startLBN[FS_DATA_FORMAT]));
878eb097431SAxel Dörfler
879eb097431SAxel Dörfler node->dataLen[LSB_DATA] = *(uint32*)buffer;
880eb097431SAxel Dörfler buffer += 4;
881eb097431SAxel Dörfler node->dataLen[MSB_DATA] = *(uint32*)buffer;
882eb097431SAxel Dörfler buffer += 4;
88399d1bfb5SAxel Dörfler TRACE(("InitNode - data length is %d\n",
88499d1bfb5SAxel Dörfler (int)node->dataLen[FS_DATA_FORMAT]));
885eb097431SAxel Dörfler
886eb097431SAxel Dörfler init_node_date(&node->recordDate, buffer);
887eb097431SAxel Dörfler buffer += 7;
888eb097431SAxel Dörfler
889eb097431SAxel Dörfler node->flags = *(uint8*)buffer;
890eb097431SAxel Dörfler buffer++;
891eb097431SAxel Dörfler TRACE(("InitNode - flags are %d\n", node->flags));
892eb097431SAxel Dörfler
893eb097431SAxel Dörfler node->fileUnitSize = *(uint8*)buffer;
894eb097431SAxel Dörfler buffer++;
895eb097431SAxel Dörfler TRACE(("InitNode - fileUnitSize is %d\n", node->fileUnitSize));
896eb097431SAxel Dörfler
897eb097431SAxel Dörfler node->interleaveGapSize = *(uint8*)buffer;
898eb097431SAxel Dörfler buffer++;
899eb097431SAxel Dörfler TRACE(("InitNode - interleave gap size = %d\n", node->interleaveGapSize));
900eb097431SAxel Dörfler
901eb097431SAxel Dörfler node->volSeqNum = *(uint32*)buffer;
902eb097431SAxel Dörfler buffer += 4;
90399d1bfb5SAxel Dörfler TRACE(("InitNode - volume seq num is %d\n", (int)node->volSeqNum));
904eb097431SAxel Dörfler
90556b2febaSMichael Lotz nameLength = *(uint8*)buffer;
906eb097431SAxel Dörfler buffer++;
90756b2febaSMichael Lotz
90856b2febaSMichael Lotz // for relocated directories we take the name from the placeholder entry
90956b2febaSMichael Lotz if (!relocated) {
91056b2febaSMichael Lotz node->name_length = nameLength;
9115348fbe6SAlexander von Gluck IV TRACE(("InitNode - file id length is %" B_PRIu32 "\n",
9125348fbe6SAlexander von Gluck IV node->name_length));
91356b2febaSMichael Lotz }
914eb097431SAxel Dörfler
915eb097431SAxel Dörfler // Set defaults, in case there is no RockRidge stuff.
91647a214deSAxel Dörfler node->attr.stat[FS_DATA_FORMAT].st_mode |= (node->flags & ISO_IS_DIR) != 0
917eb097431SAxel Dörfler ? S_IFDIR | S_IXUSR | S_IRUSR | S_IXGRP | S_IRGRP | S_IXOTH | S_IROTH
918eb097431SAxel Dörfler : S_IFREG | S_IRUSR | S_IRGRP | S_IROTH;
919eb097431SAxel Dörfler
920eb097431SAxel Dörfler if (node->name_length == 0) {
921eb097431SAxel Dörfler TRACE(("InitNode - File ID String is 0 length\n"));
922eb097431SAxel Dörfler return B_ENTRY_NOT_FOUND;
923eb097431SAxel Dörfler }
924eb097431SAxel Dörfler
92556b2febaSMichael Lotz if (!relocated) {
926eb097431SAxel Dörfler // JOLIET extension:
927eb097431SAxel Dörfler // on joliet discs, buffer[0] can be 0 for Unicoded filenames,
928eb097431SAxel Dörfler // so I've added a check here to test explicitely for
929eb097431SAxel Dörfler // directories (which have length 1)
930eb097431SAxel Dörfler // Take care of "." and "..", the first two dirents are
931eb097431SAxel Dörfler // these in iso.
9321dd3b2c7SAxel Dörfler if (node->name_length == 1 && buffer[0] == 0) {
933eb097431SAxel Dörfler node->name = strdup(".");
934eb097431SAxel Dörfler node->name_length = 1;
9351dd3b2c7SAxel Dörfler } else if (node->name_length == 1 && buffer[0] == 1) {
936eb097431SAxel Dörfler node->name = strdup("..");
937eb097431SAxel Dörfler node->name_length = 2;
93856b2febaSMichael Lotz } else if (volume->joliet_level > 0) {
939eb097431SAxel Dörfler // JOLIET extension: convert Unicode16 string to UTF8
940eb097431SAxel Dörfler // Assume that the unicode->utf8 conversion produces 4 byte
941eb097431SAxel Dörfler // utf8 characters, and allocate that much space
942eb097431SAxel Dörfler node->name = (char*)malloc(node->name_length * 2 + 1);
943eb097431SAxel Dörfler if (node->name == NULL)
944eb097431SAxel Dörfler return B_NO_MEMORY;
945eb097431SAxel Dörfler
946eb097431SAxel Dörfler int32 sourceLength = node->name_length;
947eb097431SAxel Dörfler int32 destLength = node->name_length * 2;
948eb097431SAxel Dörfler
949eb097431SAxel Dörfler status_t status = unicode_to_utf8(buffer, &sourceLength,
950eb097431SAxel Dörfler node->name, &destLength);
951eb097431SAxel Dörfler if (status < B_OK) {
952eb097431SAxel Dörfler dprintf("iso9660: error converting unicode->utf8\n");
953eb097431SAxel Dörfler return status;
954eb097431SAxel Dörfler }
955eb097431SAxel Dörfler
956eb097431SAxel Dörfler node->name[destLength] = '\0';
957eb097431SAxel Dörfler node->name_length = destLength;
958eb097431SAxel Dörfler
959eb097431SAxel Dörfler sanitize_iso_name(node, false);
960eb097431SAxel Dörfler } else {
961eb097431SAxel Dörfler node->name = (char*)malloc(node->name_length + 1);
962eb097431SAxel Dörfler if (node->name == NULL)
963eb097431SAxel Dörfler return B_NO_MEMORY;
964eb097431SAxel Dörfler
965eb097431SAxel Dörfler // convert all characters to lower case
96656b2febaSMichael Lotz for (uint32 i = 0; i < node->name_length; i++)
967eb097431SAxel Dörfler node->name[i] = tolower(buffer[i]);
96856b2febaSMichael Lotz
969eb097431SAxel Dörfler node->name[node->name_length] = '\0';
970eb097431SAxel Dörfler
971eb097431SAxel Dörfler sanitize_iso_name(node, true);
972eb097431SAxel Dörfler }
973eb097431SAxel Dörfler
974eb097431SAxel Dörfler if (node->name == NULL) {
975eb097431SAxel Dörfler TRACE(("InitNode - unable to allocate memory!\n"));
976eb097431SAxel Dörfler return B_NO_MEMORY;
977eb097431SAxel Dörfler }
97856b2febaSMichael Lotz }
979eb097431SAxel Dörfler
980eb097431SAxel Dörfler buffer += nameLength;
981eb097431SAxel Dörfler if (nameLength % 2 == 0)
982eb097431SAxel Dörfler buffer++;
983eb097431SAxel Dörfler
984eb097431SAxel Dörfler TRACE(("DirRec ID String is: %s\n", node->name));
985eb097431SAxel Dörfler
98656b2febaSMichael Lotz return parse_rock_ridge(volume, node, buffer, end, relocated);
987eb097431SAxel Dörfler }
988eb097431SAxel Dörfler
989eb097431SAxel Dörfler
990eb097431SAxel Dörfler status_t
ConvertRecDate(ISORecDate * inDate,time_t * outDate)991eb097431SAxel Dörfler ConvertRecDate(ISORecDate* inDate, time_t* outDate)
992eb097431SAxel Dörfler {
993eb097431SAxel Dörfler time_t time;
9947dc68bfbSAdrien Destugues int days, i, year;
9957dc68bfbSAdrien Destugues int8_t tz;
996eb097431SAxel Dörfler
997eb097431SAxel Dörfler year = inDate->year - 70;
998eb097431SAxel Dörfler tz = inDate->offsetGMT;
999eb097431SAxel Dörfler
1000eb097431SAxel Dörfler if (year < 0) {
1001eb097431SAxel Dörfler time = 0;
1002eb097431SAxel Dörfler } else {
1003eb097431SAxel Dörfler const int monlen[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1004eb097431SAxel Dörfler
1005eb097431SAxel Dörfler days = (year * 365);
1006eb097431SAxel Dörfler
1007eb097431SAxel Dörfler if (year > 2)
1008eb097431SAxel Dörfler days += (year + 1)/ 4;
1009eb097431SAxel Dörfler
1010eb097431SAxel Dörfler for (i = 1; (i < inDate->month) && (i < 12); i++) {
1011eb097431SAxel Dörfler days += monlen[i-1];
1012eb097431SAxel Dörfler }
1013eb097431SAxel Dörfler
1014eb097431SAxel Dörfler if (((year + 2) % 4) == 0 && inDate->month > 2)
1015eb097431SAxel Dörfler days++;
1016eb097431SAxel Dörfler
1017eb097431SAxel Dörfler days += inDate->date - 1;
1018eb097431SAxel Dörfler time = ((((days*24) + inDate->hour) * 60 + inDate->minute) * 60)
1019eb097431SAxel Dörfler + inDate->second;
1020eb097431SAxel Dörfler
1021eb097431SAxel Dörfler if (-48 <= tz && tz <= 52)
1022a3fdd62cSGediminas Jarulaitis time -= tz * 15 * 60;
1023eb097431SAxel Dörfler }
1024eb097431SAxel Dörfler *outDate = time;
1025eb097431SAxel Dörfler return 0;
1026eb097431SAxel Dörfler }
1027eb097431SAxel Dörfler
1028