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