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