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 { 147723f4b6aSGediminas Jarulaitis memcpy(date, buffer, ISO_VOL_DATE_SIZE); 148eb097431SAxel Dörfler return 0; 149eb097431SAxel Dörfler } 150eb097431SAxel Dörfler 151eb097431SAxel Dörfler 152eb097431SAxel Dörfler static int 153eb097431SAxel Dörfler init_node_date(ISORecDate *date, char *buffer) 154eb097431SAxel Dörfler { 155723f4b6aSGediminas Jarulaitis memcpy(date, buffer, sizeof(struct ISORecDate)); 156eb097431SAxel Dörfler return 0; 157eb097431SAxel Dörfler } 158eb097431SAxel Dörfler 159eb097431SAxel Dörfler 160eb097431SAxel Dörfler static status_t 161eb097431SAxel Dörfler InitVolDesc(iso9660_volume *volume, char *buffer) 162eb097431SAxel Dörfler { 163eb097431SAxel Dörfler TRACE(("InitVolDesc - ENTER\n")); 164eb097431SAxel Dörfler 165723f4b6aSGediminas Jarulaitis volume->volDescType = *(uint8 *)buffer; 166723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->volDescType); 167eb097431SAxel Dörfler 168723f4b6aSGediminas Jarulaitis const size_t kStdIDStringLen = sizeof(volume->stdIDString) - 1; 169723f4b6aSGediminas Jarulaitis volume->stdIDString[kStdIDStringLen] = '\0'; 170723f4b6aSGediminas Jarulaitis strncpy(volume->stdIDString, buffer, kStdIDStringLen); 171723f4b6aSGediminas Jarulaitis buffer += kStdIDStringLen; 172eb097431SAxel Dörfler 173eb097431SAxel Dörfler volume->volDescVersion = *(uint8 *)buffer; 174723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->volDescVersion); 175eb097431SAxel Dörfler 176723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->unused1); // skip unused 8th byte 177723f4b6aSGediminas Jarulaitis 178723f4b6aSGediminas Jarulaitis const size_t kSystemIDStringLen = sizeof(volume->systemIDString) - 1; 179723f4b6aSGediminas Jarulaitis volume->systemIDString[kSystemIDStringLen] = '\0'; 180723f4b6aSGediminas Jarulaitis strncpy(volume->systemIDString, buffer, kSystemIDStringLen); 181723f4b6aSGediminas Jarulaitis buffer += kSystemIDStringLen; 182eb097431SAxel Dörfler TRACE(("InitVolDesc - system id string is %s\n", volume->systemIDString)); 183eb097431SAxel Dörfler 184723f4b6aSGediminas Jarulaitis const size_t kVolIDStringLen = sizeof(volume->volIDString) - 1; 185723f4b6aSGediminas Jarulaitis volume->volIDString[kVolIDStringLen] = '\0'; 186723f4b6aSGediminas Jarulaitis strncpy(volume->volIDString, buffer, kVolIDStringLen); 187723f4b6aSGediminas Jarulaitis buffer += kVolIDStringLen; 188eb097431SAxel Dörfler TRACE(("InitVolDesc - volume id string is %s\n", volume->volIDString)); 189eb097431SAxel Dörfler 190723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->unused2) - 1; // skip unused 73-80 bytes 191723f4b6aSGediminas Jarulaitis 192eb097431SAxel Dörfler volume->volSpaceSize[LSB_DATA] = *(uint32 *)buffer; 193723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->volSpaceSize[LSB_DATA]); 194eb097431SAxel Dörfler volume->volSpaceSize[MSB_DATA] = *(uint32 *)buffer; 195723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->volSpaceSize[MSB_DATA]); 196723f4b6aSGediminas Jarulaitis 197723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->unused3) - 1; // skip unused 89-120 bytes 198eb097431SAxel Dörfler 199eb097431SAxel Dörfler volume->volSetSize[LSB_DATA] = *(uint16*)buffer; 200723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->volSetSize[LSB_DATA]); 201eb097431SAxel Dörfler volume->volSetSize[MSB_DATA] = *(uint16*)buffer; 202723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->volSetSize[MSB_DATA]); 203eb097431SAxel Dörfler 204eb097431SAxel Dörfler volume->volSeqNum[LSB_DATA] = *(uint16*)buffer; 205723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->volSeqNum[LSB_DATA]); 206eb097431SAxel Dörfler volume->volSeqNum[MSB_DATA] = *(uint16*)buffer; 207723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->volSeqNum[MSB_DATA]); 208eb097431SAxel Dörfler 209eb097431SAxel Dörfler volume->logicalBlkSize[LSB_DATA] = *(uint16*)buffer; 210723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->logicalBlkSize[LSB_DATA]); 211eb097431SAxel Dörfler volume->logicalBlkSize[MSB_DATA] = *(uint16*)buffer; 212723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->logicalBlkSize[MSB_DATA]); 213eb097431SAxel Dörfler 214eb097431SAxel Dörfler volume->pathTblSize[LSB_DATA] = *(uint32*)buffer; 215723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->pathTblSize[LSB_DATA]); 216eb097431SAxel Dörfler volume->pathTblSize[MSB_DATA] = *(uint32*)buffer; 217723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->pathTblSize[MSB_DATA]); 218eb097431SAxel Dörfler 219eb097431SAxel Dörfler volume->lPathTblLoc[LSB_DATA] = *(uint16*)buffer; 220723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->lPathTblLoc[LSB_DATA]); 221eb097431SAxel Dörfler volume->lPathTblLoc[MSB_DATA] = *(uint16*)buffer; 222723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->lPathTblLoc[MSB_DATA]); 223eb097431SAxel Dörfler 224eb097431SAxel Dörfler volume->optLPathTblLoc[LSB_DATA] = *(uint16*)buffer; 225723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->optLPathTblLoc[LSB_DATA]); 226eb097431SAxel Dörfler volume->optLPathTblLoc[MSB_DATA] = *(uint16*)buffer; 227723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->optLPathTblLoc[MSB_DATA]); 228eb097431SAxel Dörfler 229eb097431SAxel Dörfler volume->mPathTblLoc[LSB_DATA] = *(uint16*)buffer; 230723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->mPathTblLoc[LSB_DATA]); 231eb097431SAxel Dörfler volume->mPathTblLoc[MSB_DATA] = *(uint16*)buffer; 232723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->mPathTblLoc[MSB_DATA]); 233eb097431SAxel Dörfler 234eb097431SAxel Dörfler volume->optMPathTblLoc[LSB_DATA] = *(uint16*)buffer; 235723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->optMPathTblLoc[LSB_DATA]); 236eb097431SAxel Dörfler volume->optMPathTblLoc[MSB_DATA] = *(uint16*)buffer; 237723f4b6aSGediminas Jarulaitis buffer += sizeof(volume->optMPathTblLoc[MSB_DATA]); 238eb097431SAxel Dörfler 239eb097431SAxel Dörfler // Fill in directory record. 24056b2febaSMichael Lotz volume->joliet_level = 0; 24156b2febaSMichael Lotz InitNode(volume, &volume->rootDirRec, buffer, NULL); 242eb097431SAxel Dörfler 243eb097431SAxel Dörfler volume->rootDirRec.id = ISO_ROOTNODE_ID; 244723f4b6aSGediminas Jarulaitis buffer += ISO_ROOT_DIR_REC_SIZE; 245eb097431SAxel Dörfler 246723f4b6aSGediminas Jarulaitis const size_t kVolSetIDStringLen = sizeof(volume->volSetIDString) - 1; 247723f4b6aSGediminas Jarulaitis volume->volSetIDString[kVolSetIDStringLen] = '\0'; 248723f4b6aSGediminas Jarulaitis strncpy(volume->volSetIDString, buffer, kVolSetIDStringLen); 249723f4b6aSGediminas Jarulaitis buffer += kVolSetIDStringLen; 250eb097431SAxel Dörfler TRACE(("InitVolDesc - volume set id string is %s\n", volume->volSetIDString)); 251eb097431SAxel Dörfler 252723f4b6aSGediminas Jarulaitis const size_t kPubIDStringLen = sizeof(volume->pubIDString) - 1; 253723f4b6aSGediminas Jarulaitis volume->pubIDString[kPubIDStringLen] = '\0'; 254723f4b6aSGediminas Jarulaitis strncpy(volume->pubIDString, buffer, kPubIDStringLen); 255723f4b6aSGediminas Jarulaitis buffer += kPubIDStringLen; 256eb097431SAxel Dörfler TRACE(("InitVolDesc - volume pub id string is %s\n", volume->pubIDString)); 257eb097431SAxel Dörfler 258723f4b6aSGediminas Jarulaitis const size_t kDataPreparerLen = sizeof(volume->dataPreparer) - 1; 259723f4b6aSGediminas Jarulaitis volume->dataPreparer[kDataPreparerLen] = '\0'; 260723f4b6aSGediminas Jarulaitis strncpy(volume->dataPreparer, buffer, kDataPreparerLen); 261723f4b6aSGediminas Jarulaitis buffer += kDataPreparerLen; 262eb097431SAxel Dörfler TRACE(("InitVolDesc - volume dataPreparer string is %s\n", volume->dataPreparer)); 263eb097431SAxel Dörfler 264723f4b6aSGediminas Jarulaitis const size_t kAppIDStringLen = sizeof(volume->appIDString) - 1; 265723f4b6aSGediminas Jarulaitis volume->appIDString[kAppIDStringLen] = '\0'; 266723f4b6aSGediminas Jarulaitis strncpy(volume->appIDString, buffer, kAppIDStringLen); 267723f4b6aSGediminas Jarulaitis buffer += kAppIDStringLen; 268eb097431SAxel Dörfler TRACE(("InitVolDesc - volume app id string is %s\n", volume->appIDString)); 269eb097431SAxel Dörfler 270723f4b6aSGediminas Jarulaitis const size_t kCopyrightLen = sizeof(volume->copyright) - 1; 271723f4b6aSGediminas Jarulaitis volume->copyright[kCopyrightLen] = '\0'; 272723f4b6aSGediminas Jarulaitis strncpy(volume->copyright, buffer, kCopyrightLen); 273723f4b6aSGediminas Jarulaitis buffer += kCopyrightLen; 274eb097431SAxel Dörfler TRACE(("InitVolDesc - copyright is %s\n", volume->copyright)); 275eb097431SAxel Dörfler 276723f4b6aSGediminas Jarulaitis const size_t kAbstractFNameLen = sizeof(volume->abstractFName) - 1; 277723f4b6aSGediminas Jarulaitis volume->abstractFName[kAbstractFNameLen] = '\0'; 278723f4b6aSGediminas Jarulaitis strncpy(volume->abstractFName, buffer, kAbstractFNameLen); 279723f4b6aSGediminas Jarulaitis buffer += kAbstractFNameLen; 280eb097431SAxel Dörfler 281723f4b6aSGediminas Jarulaitis const size_t kBiblioFNameLen = sizeof(volume->biblioFName) - 1; 282723f4b6aSGediminas Jarulaitis volume->biblioFName[kBiblioFNameLen] = '\0'; 283723f4b6aSGediminas Jarulaitis strncpy(volume->biblioFName, buffer, kBiblioFNameLen); 284723f4b6aSGediminas Jarulaitis buffer += kBiblioFNameLen; 285eb097431SAxel Dörfler 286eb097431SAxel Dörfler init_volume_date(&volume->createDate, buffer); 287723f4b6aSGediminas Jarulaitis buffer += ISO_VOL_DATE_SIZE; 288eb097431SAxel Dörfler 289eb097431SAxel Dörfler init_volume_date(&volume->modDate, buffer); 290723f4b6aSGediminas Jarulaitis buffer += ISO_VOL_DATE_SIZE; 291eb097431SAxel Dörfler 292eb097431SAxel Dörfler init_volume_date(&volume->expireDate, buffer); 293723f4b6aSGediminas Jarulaitis buffer += ISO_VOL_DATE_SIZE; 294eb097431SAxel Dörfler 295eb097431SAxel Dörfler init_volume_date(&volume->effectiveDate, buffer); 296723f4b6aSGediminas Jarulaitis buffer += ISO_VOL_DATE_SIZE; 297eb097431SAxel Dörfler 298eb097431SAxel Dörfler volume->fileStructVers = *(uint8*)buffer; 299eb097431SAxel Dörfler return B_OK; 300eb097431SAxel Dörfler } 301eb097431SAxel Dörfler 302eb097431SAxel Dörfler 303eb097431SAxel Dörfler static status_t 30456b2febaSMichael Lotz parse_rock_ridge(iso9660_volume* volume, iso9660_inode* node, char* buffer, 30556b2febaSMichael Lotz char* end, bool relocated) 306eb097431SAxel Dörfler { 307eb097431SAxel Dörfler // Now we're at the start of the rock ridge stuff 308eb097431SAxel Dörfler char* altName = NULL; 309eb097431SAxel Dörfler char* slName = NULL; 310eb097431SAxel Dörfler uint16 altNameSize = 0; 311eb097431SAxel Dörfler uint16 slNameSize = 0; 312eb097431SAxel Dörfler uint8 length = 0; 313eb097431SAxel Dörfler bool done = false; 314eb097431SAxel Dörfler 315eb097431SAxel Dörfler TRACE(("RR: Start of extensions at %p\n", buffer)); 316eb097431SAxel Dörfler 317eb097431SAxel Dörfler while (!done) { 318eb097431SAxel Dörfler buffer += length; 319eb097431SAxel Dörfler if (buffer + 2 >= end) 320eb097431SAxel Dörfler break; 321eb097431SAxel Dörfler length = *(uint8*)(buffer + 2); 322eb097431SAxel Dörfler if (buffer + length > end) 323eb097431SAxel Dörfler break; 32447a214deSAxel Dörfler if (length == 0) 32547a214deSAxel Dörfler break; 326eb097431SAxel Dörfler 327eb097431SAxel Dörfler switch (((int)buffer[0] << 8) + buffer[1]) { 328eb097431SAxel Dörfler // Stat structure stuff 329eb097431SAxel Dörfler case 'PX': 330eb097431SAxel Dörfler { 331eb097431SAxel Dörfler uint8 bytePos = 3; 332eb097431SAxel Dörfler TRACE(("RR: found PX, length %u\n", length)); 333eb097431SAxel Dörfler node->attr.pxVer = *(uint8*)(buffer + bytePos++); 334eb097431SAxel Dörfler 335eb097431SAxel Dörfler // st_mode 336eb097431SAxel Dörfler node->attr.stat[LSB_DATA].st_mode 337eb097431SAxel Dörfler = *(mode_t*)(buffer + bytePos); 338eb097431SAxel Dörfler bytePos += 4; 339eb097431SAxel Dörfler node->attr.stat[MSB_DATA].st_mode 340eb097431SAxel Dörfler = *(mode_t*)(buffer + bytePos); 341eb097431SAxel Dörfler bytePos += 4; 342eb097431SAxel Dörfler 343eb097431SAxel Dörfler // st_nlink 344eb097431SAxel Dörfler node->attr.stat[LSB_DATA].st_nlink 345eb097431SAxel Dörfler = *(nlink_t*)(buffer+bytePos); 346eb097431SAxel Dörfler bytePos += 4; 347eb097431SAxel Dörfler node->attr.stat[MSB_DATA].st_nlink 348eb097431SAxel Dörfler = *(nlink_t*)(buffer + bytePos); 349eb097431SAxel Dörfler bytePos += 4; 350eb097431SAxel Dörfler 351eb097431SAxel Dörfler // st_uid 352eb097431SAxel Dörfler node->attr.stat[LSB_DATA].st_uid 353eb097431SAxel Dörfler = *(uid_t*)(buffer + bytePos); 354eb097431SAxel Dörfler bytePos += 4; 355eb097431SAxel Dörfler node->attr.stat[MSB_DATA].st_uid 356eb097431SAxel Dörfler = *(uid_t*)(buffer + bytePos); 357eb097431SAxel Dörfler bytePos += 4; 358eb097431SAxel Dörfler 359eb097431SAxel Dörfler // st_gid 360eb097431SAxel Dörfler node->attr.stat[LSB_DATA].st_gid 361eb097431SAxel Dörfler = *(gid_t*)(buffer + bytePos); 362eb097431SAxel Dörfler bytePos += 4; 363eb097431SAxel Dörfler node->attr.stat[MSB_DATA].st_gid 364eb097431SAxel Dörfler = *(gid_t*)(buffer + bytePos); 365eb097431SAxel Dörfler bytePos += 4; 366eb097431SAxel Dörfler break; 367eb097431SAxel Dörfler } 368eb097431SAxel Dörfler 369eb097431SAxel Dörfler case 'PN': 370eb097431SAxel Dörfler TRACE(("RR: found PN, length %u\n", length)); 371eb097431SAxel Dörfler break; 372eb097431SAxel Dörfler 373eb097431SAxel Dörfler // Symbolic link info 374eb097431SAxel Dörfler case 'SL': 375eb097431SAxel Dörfler { 376eb097431SAxel Dörfler uint8 bytePos = 3; 377eb097431SAxel Dörfler uint8 addPos = 0; 378eb097431SAxel Dörfler bool slDone = false; 379eb097431SAxel Dörfler bool useSeparator = true; 380eb097431SAxel Dörfler 381eb097431SAxel Dörfler TRACE(("RR: found SL, length %u\n", length)); 382eb097431SAxel Dörfler TRACE(("Buffer is at %p\n", buffer)); 383eb097431SAxel Dörfler TRACE(("Current length is %u\n", slNameSize)); 384eb097431SAxel Dörfler //kernel_debugger(""); 385eb097431SAxel Dörfler node->attr.slVer = *(uint8*)(buffer + bytePos++); 386eb5f3639SJerome Duval #if TRACE_ISO9660 387eb5f3639SJerome Duval uint8 slFlags = *(uint8*)(buffer + bytePos++); 388eb097431SAxel Dörfler TRACE(("sl flags are %u\n", slFlags)); 389e766bb9eSRene Gollent #else 390e766bb9eSRene Gollent // skip symlink flags 391e766bb9eSRene Gollent ++bytePos; 392eb5f3639SJerome Duval #endif 393eb097431SAxel Dörfler while (!slDone && bytePos < length) { 394eb097431SAxel Dörfler uint8 compFlag = *(uint8*)(buffer + bytePos++); 395eb097431SAxel Dörfler uint8 compLen = *(uint8*)(buffer + bytePos++); 396eb097431SAxel Dörfler 397eb097431SAxel Dörfler if (slName == NULL) 398eb097431SAxel Dörfler useSeparator = false; 399eb097431SAxel Dörfler 400eb097431SAxel Dörfler addPos = slNameSize; 401eb097431SAxel Dörfler 402eb097431SAxel Dörfler TRACE(("sl comp flags are %u, length is %u\n", compFlag, compLen)); 403eb097431SAxel Dörfler TRACE(("Current name size is %u\n", slNameSize)); 404eb097431SAxel Dörfler 405eb097431SAxel Dörfler switch (compFlag) { 406eb097431SAxel Dörfler case SLCP_CONTINUE: 407eb097431SAxel Dörfler useSeparator = false; 408eb097431SAxel Dörfler default: 409eb097431SAxel Dörfler // Add the component to the total path. 410eb097431SAxel Dörfler slNameSize += compLen; 411eb097431SAxel Dörfler if (useSeparator) 412eb097431SAxel Dörfler slNameSize++; 413eb097431SAxel Dörfler slName = (char*)realloc(slName, 414eb097431SAxel Dörfler slNameSize + 1); 415eb097431SAxel Dörfler if (slName == NULL) 416eb097431SAxel Dörfler return B_NO_MEMORY; 417eb097431SAxel Dörfler 418eb097431SAxel Dörfler if (useSeparator) { 419eb097431SAxel Dörfler TRACE(("Adding separator\n")); 420eb097431SAxel Dörfler slName[addPos++] = '/'; 421eb097431SAxel Dörfler } 422eb097431SAxel Dörfler 423eb097431SAxel Dörfler TRACE(("doing memcopy of %u bytes at offset %d\n", compLen, addPos)); 424eb097431SAxel Dörfler memcpy(slName + addPos, buffer + bytePos, 425eb097431SAxel Dörfler compLen); 426eb097431SAxel Dörfler 427eb097431SAxel Dörfler addPos += compLen; 428eb097431SAxel Dörfler useSeparator = true; 429eb097431SAxel Dörfler break; 430eb097431SAxel Dörfler 431eb097431SAxel Dörfler case SLCP_CURRENT: 432eb097431SAxel Dörfler TRACE(("InitNode - found link to current directory\n")); 433eb097431SAxel Dörfler slNameSize += 2; 434eb097431SAxel Dörfler slName = (char*)realloc(slName, 435eb097431SAxel Dörfler slNameSize + 1); 436eb097431SAxel Dörfler if (slName == NULL) 437eb097431SAxel Dörfler return B_NO_MEMORY; 438eb097431SAxel Dörfler 439eb097431SAxel Dörfler memcpy(slName + addPos, "./", 2); 440eb097431SAxel Dörfler useSeparator = false; 441eb097431SAxel Dörfler break; 442eb097431SAxel Dörfler 443eb097431SAxel Dörfler case SLCP_PARENT: 444eb097431SAxel Dörfler slNameSize += 3; 445eb097431SAxel Dörfler slName = (char*)realloc(slName, 446eb097431SAxel Dörfler slNameSize + 1); 447eb097431SAxel Dörfler if (slName == NULL) 448eb097431SAxel Dörfler return B_NO_MEMORY; 449eb097431SAxel Dörfler 450eb097431SAxel Dörfler memcpy(slName + addPos, "../", 3); 451eb097431SAxel Dörfler useSeparator = false; 452eb097431SAxel Dörfler break; 453eb097431SAxel Dörfler 454eb097431SAxel Dörfler case SLCP_ROOT: 455eb097431SAxel Dörfler TRACE(("InitNode - found link to root directory\n")); 456eb097431SAxel Dörfler slNameSize += 1; 457eb097431SAxel Dörfler slName = (char*)realloc(slName, 458eb097431SAxel Dörfler slNameSize + 1); 459eb097431SAxel Dörfler if (slName == NULL) 460eb097431SAxel Dörfler return B_NO_MEMORY; 461eb097431SAxel Dörfler memcpy(slName + addPos, "/", 1); 462eb097431SAxel Dörfler useSeparator = false; 463eb097431SAxel Dörfler break; 464eb097431SAxel Dörfler 465eb097431SAxel Dörfler case SLCP_VOLROOT: 466eb097431SAxel Dörfler slDone = true; 467eb097431SAxel Dörfler break; 468eb097431SAxel Dörfler 469eb097431SAxel Dörfler case SLCP_HOST: 470eb097431SAxel Dörfler slDone = true; 471eb097431SAxel Dörfler break; 472eb097431SAxel Dörfler } 473977f0426SAxel Dörfler if (slName != NULL) 474eb097431SAxel Dörfler slName[slNameSize] = '\0'; 475eb097431SAxel Dörfler bytePos += compLen; 476eb097431SAxel Dörfler TRACE(("Current sl name is \'%s\'\n", slName)); 477eb097431SAxel Dörfler } 478eb097431SAxel Dörfler node->attr.slName = slName; 479eb097431SAxel Dörfler TRACE(("InitNode = symlink name is \'%s\'\n", slName)); 480eb097431SAxel Dörfler break; 481eb097431SAxel Dörfler } 482eb097431SAxel Dörfler 483eb097431SAxel Dörfler // Altername name 484eb097431SAxel Dörfler case 'NM': 485eb097431SAxel Dörfler { 486eb097431SAxel Dörfler uint8 bytePos = 3; 487eb097431SAxel Dörfler uint8 flags = 0; 488eb097431SAxel Dörfler uint16 oldEnd = altNameSize; 489eb097431SAxel Dörfler 490eb097431SAxel Dörfler altNameSize += length - 5; 491eb097431SAxel Dörfler altName = (char*)realloc(altName, altNameSize + 1); 492eb097431SAxel Dörfler if (altName == NULL) 493eb097431SAxel Dörfler return B_NO_MEMORY; 494eb097431SAxel Dörfler 495eb097431SAxel Dörfler TRACE(("RR: found NM, length %u\n", length)); 496eb097431SAxel Dörfler // Read flag and version. 497eb097431SAxel Dörfler node->attr.nmVer = *(uint8 *)(buffer + bytePos++); 498eb097431SAxel Dörfler flags = *(uint8 *)(buffer + bytePos++); 499eb097431SAxel Dörfler 500eb097431SAxel Dörfler TRACE(("RR: nm buffer is %s, start at %p\n", (buffer + bytePos), buffer + bytePos)); 501eb097431SAxel Dörfler 502eb097431SAxel Dörfler // Build the file name. 503eb097431SAxel Dörfler memcpy(altName + oldEnd, buffer + bytePos, length - 5); 504eb097431SAxel Dörfler altName[altNameSize] = '\0'; 505eb097431SAxel Dörfler TRACE(("RR: alt name is %s\n", altName)); 506eb097431SAxel Dörfler 507eb097431SAxel Dörfler // If the name is not continued in another record, update 508eb097431SAxel Dörfler // the record name. 509eb097431SAxel Dörfler if (!(flags & NM_CONTINUE)) { 510eb097431SAxel Dörfler // Get rid of the ISO name, replace with RR name. 511eb097431SAxel Dörfler if (node->name != NULL) 512eb097431SAxel Dörfler free(node->name); 513eb097431SAxel Dörfler node->name = altName; 514eb097431SAxel Dörfler node->name_length = altNameSize; 515eb097431SAxel Dörfler } 516eb097431SAxel Dörfler break; 517eb097431SAxel Dörfler } 518eb097431SAxel Dörfler 519eb097431SAxel Dörfler // Deep directory record masquerading as a file. 520eb097431SAxel Dörfler case 'CL': 52156b2febaSMichael Lotz { 522eb097431SAxel Dörfler TRACE(("RR: found CL, length %u\n", length)); 52356b2febaSMichael Lotz // Reinitialize the node with the information at the 52456b2febaSMichael Lotz // "." entry of the pointed to directory data 525eb097431SAxel Dörfler node->startLBN[LSB_DATA] = *(uint32*)(buffer+4); 526eb097431SAxel Dörfler node->startLBN[MSB_DATA] = *(uint32*)(buffer+8); 52756b2febaSMichael Lotz 52856b2febaSMichael Lotz char* buffer = (char*)block_cache_get(volume->fBlockCache, 52956b2febaSMichael Lotz node->startLBN[FS_DATA_FORMAT]); 53056b2febaSMichael Lotz if (buffer == NULL) 531eb097431SAxel Dörfler break; 532eb097431SAxel Dörfler 53356b2febaSMichael Lotz InitNode(volume, node, buffer, NULL, true); 53456b2febaSMichael Lotz block_cache_put(volume->fBlockCache, 53556b2febaSMichael Lotz node->startLBN[FS_DATA_FORMAT]); 53656b2febaSMichael Lotz break; 53756b2febaSMichael Lotz } 53856b2febaSMichael Lotz 539eb097431SAxel Dörfler case 'PL': 540eb097431SAxel Dörfler TRACE(("RR: found PL, length %u\n", length)); 541eb097431SAxel Dörfler break; 542eb097431SAxel Dörfler 543eb097431SAxel Dörfler case 'RE': 544eb097431SAxel Dörfler // Relocated directory, we should skip. 545eb097431SAxel Dörfler TRACE(("RR: found RE, length %u\n", length)); 54656b2febaSMichael Lotz if (!relocated) 547a735bdebSMichael Lotz return B_UNSUPPORTED; 54856b2febaSMichael Lotz break; 549eb097431SAxel Dörfler 550eb097431SAxel Dörfler case 'TF': 551eb097431SAxel Dörfler TRACE(("RR: found TF, length %u\n", length)); 552eb097431SAxel Dörfler break; 553eb097431SAxel Dörfler 554eb097431SAxel Dörfler case 'RR': 555eb097431SAxel Dörfler TRACE(("RR: found RR, length %u\n", length)); 556eb097431SAxel Dörfler break; 557eb097431SAxel Dörfler 55847a214deSAxel Dörfler case 'SF': 55947a214deSAxel Dörfler TRACE(("RR: found SF, sparse files not supported!\n")); 56047a214deSAxel Dörfler // TODO: support sparse files 561a735bdebSMichael Lotz return B_UNSUPPORTED; 56247a214deSAxel Dörfler 563eb097431SAxel Dörfler default: 56447a214deSAxel Dörfler if (buffer[0] == '\0') { 56547a214deSAxel Dörfler TRACE(("RR: end of extensions\n")); 566eb097431SAxel Dörfler done = true; 56747a214deSAxel Dörfler } else 56847a214deSAxel Dörfler TRACE(("RR: Unknown tag %c%c\n", buffer[0], buffer[1])); 569eb097431SAxel Dörfler break; 570eb097431SAxel Dörfler } 571eb097431SAxel Dörfler } 572eb097431SAxel Dörfler 573eb097431SAxel Dörfler return B_OK; 574eb097431SAxel Dörfler } 575eb097431SAxel Dörfler 576eb097431SAxel Dörfler // #pragma mark - ISO-9660 specific exported functions 577eb097431SAxel Dörfler 578eb097431SAxel Dörfler 579eb097431SAxel Dörfler status_t 580eb097431SAxel Dörfler ISOMount(const char *path, uint32 flags, iso9660_volume **_newVolume, 581eb097431SAxel Dörfler bool allowJoliet) 582eb097431SAxel Dörfler { 583eb097431SAxel Dörfler // path: path to device (eg, /dev/disk/scsi/030/raw) 584eb097431SAxel Dörfler // partition: partition number on device ???? 585eb097431SAxel Dörfler // flags: currently unused 586eb097431SAxel Dörfler 587eb097431SAxel Dörfler // determine if it is an ISO volume. 588eb097431SAxel Dörfler char buffer[ISO_PVD_SIZE]; 589eb097431SAxel Dörfler bool done = false; 590eb097431SAxel Dörfler bool isISO = false; 591eb097431SAxel Dörfler off_t offset = 0x8000; 592eb097431SAxel Dörfler ssize_t retval; 593eb097431SAxel Dörfler partition_info partitionInfo; 594eb5f3639SJerome Duval int deviceBlockSize; 595eb097431SAxel Dörfler iso9660_volume *volume; 596eb097431SAxel Dörfler 597eb097431SAxel Dörfler (void)flags; 598eb097431SAxel Dörfler 599eb097431SAxel Dörfler TRACE(("ISOMount - ENTER\n")); 600eb097431SAxel Dörfler 601eb097431SAxel Dörfler volume = (iso9660_volume *)calloc(sizeof(iso9660_volume), 1); 602eb097431SAxel Dörfler if (volume == NULL) { 603eb097431SAxel Dörfler TRACE(("ISOMount - mem error \n")); 604eb097431SAxel Dörfler return B_NO_MEMORY; 605eb097431SAxel Dörfler } 606eb097431SAxel Dörfler 607eb097431SAxel Dörfler memset(&partitionInfo, 0, sizeof(partition_info)); 608eb097431SAxel Dörfler 609eb097431SAxel Dörfler /* open and lock the device */ 610eb097431SAxel Dörfler volume->fdOfSession = open(path, O_RDONLY); 611eb097431SAxel Dörfler 612eb097431SAxel Dörfler /* try to open the raw device to get access to the other sessions as well */ 613eb097431SAxel Dörfler if (volume->fdOfSession >= 0) { 614eb097431SAxel Dörfler if (ioctl(volume->fdOfSession, B_GET_PARTITION_INFO, &partitionInfo) < 0) { 615eb097431SAxel Dörfler TRACE(("B_GET_PARTITION_INFO: ioctl returned error\n")); 616eb097431SAxel Dörfler strcpy(partitionInfo.device, path); 617eb097431SAxel Dörfler } 618eb097431SAxel Dörfler TRACE(("ISOMount: open device/file \"%s\"\n", partitionInfo.device)); 619eb097431SAxel Dörfler 620eb097431SAxel Dörfler volume->fd = open(partitionInfo.device, O_RDONLY); 621eb097431SAxel Dörfler } 622eb097431SAxel Dörfler 623eb097431SAxel Dörfler if (volume->fdOfSession < 0 || volume->fd < 0) { 624eb097431SAxel Dörfler close(volume->fd); 625eb097431SAxel Dörfler close(volume->fdOfSession); 626eb097431SAxel Dörfler 627eb097431SAxel Dörfler TRACE(("ISO9660 ERROR - Unable to open <%s>\n", path)); 628eb097431SAxel Dörfler free(volume); 629eb097431SAxel Dörfler return B_BAD_VALUE; 630eb097431SAxel Dörfler } 631eb097431SAxel Dörfler 632eb097431SAxel Dörfler deviceBlockSize = get_device_block_size(volume->fdOfSession); 633eb097431SAxel Dörfler if (deviceBlockSize < 0) { 634eb097431SAxel Dörfler TRACE(("ISO9660 ERROR - device block size is 0\n")); 635eb097431SAxel Dörfler close(volume->fd); 636eb097431SAxel Dörfler close(volume->fdOfSession); 637eb097431SAxel Dörfler 638eb097431SAxel Dörfler free(volume); 639eb097431SAxel Dörfler return B_BAD_VALUE; 640eb097431SAxel Dörfler } 641eb097431SAxel Dörfler 642eb097431SAxel Dörfler volume->joliet_level = 0; 643eb097431SAxel Dörfler while (!done && offset < 0x10000) { 644eb097431SAxel Dörfler retval = read_pos(volume->fdOfSession, offset, (void*)buffer, 645eb097431SAxel Dörfler ISO_PVD_SIZE); 646eb097431SAxel Dörfler if (retval < ISO_PVD_SIZE) { 647eb097431SAxel Dörfler isISO = false; 648eb097431SAxel Dörfler break; 649eb097431SAxel Dörfler } 650eb097431SAxel Dörfler 651eb097431SAxel Dörfler if (strncmp(buffer + 1, kISO9660IDString, 5) == 0) { 652eb097431SAxel Dörfler if (*buffer == 0x01 && !isISO) { 653eb097431SAxel Dörfler // ISO_VD_PRIMARY 654eb097431SAxel Dörfler off_t maxBlocks; 655eb097431SAxel Dörfler 656eb097431SAxel Dörfler TRACE(("ISOMount: Is an ISO9660 volume, initting rec\n")); 657eb097431SAxel Dörfler 658eb097431SAxel Dörfler InitVolDesc(volume, buffer); 659eb097431SAxel Dörfler strncpy(volume->devicePath,path,127); 660eb097431SAxel Dörfler volume->id = ISO_ROOTNODE_ID; 661eb097431SAxel Dörfler TRACE(("ISO9660: volume->blockSize = %d\n", volume->logicalBlkSize[FS_DATA_FORMAT])); 662eb097431SAxel Dörfler 663eb5f3639SJerome Duval #if TRACE_ISO9660 664eb5f3639SJerome Duval int multiplier = deviceBlockSize / volume->logicalBlkSize[FS_DATA_FORMAT]; 665eb097431SAxel Dörfler TRACE(("ISOMount: block size multiplier is %d\n", multiplier)); 666eb5f3639SJerome Duval #endif 667eb097431SAxel Dörfler 668eb097431SAxel Dörfler // if the session is on a real device, size != 0 669eb097431SAxel Dörfler if (partitionInfo.size != 0) { 670eb097431SAxel Dörfler maxBlocks = (partitionInfo.size + partitionInfo.offset) 671eb097431SAxel Dörfler / volume->logicalBlkSize[FS_DATA_FORMAT]; 672eb097431SAxel Dörfler } else 673eb097431SAxel Dörfler maxBlocks = volume->volSpaceSize[FS_DATA_FORMAT]; 674eb097431SAxel Dörfler 675eb097431SAxel Dörfler /* Initialize access to the cache so that we can do cached i/o */ 676eb097431SAxel Dörfler TRACE(("ISO9660: cache init: dev %d, max blocks %Ld\n", volume->fd, maxBlocks)); 677eb097431SAxel Dörfler volume->fBlockCache = block_cache_create(volume->fd, maxBlocks, 678eb097431SAxel Dörfler volume->logicalBlkSize[FS_DATA_FORMAT], true); 679eb097431SAxel Dörfler isISO = true; 680eb097431SAxel Dörfler } else if (*buffer == 0x02 && isISO && allowJoliet) { 681eb097431SAxel Dörfler // ISO_VD_SUPPLEMENTARY 682eb097431SAxel Dörfler 683eb097431SAxel Dörfler // JOLIET extension 684eb097431SAxel Dörfler // test escape sequence for level of UCS-2 characterset 685eb097431SAxel Dörfler if (buffer[88] == 0x25 && buffer[89] == 0x2f) { 686eb097431SAxel Dörfler switch (buffer[90]) { 687eb097431SAxel Dörfler case 0x40: volume->joliet_level = 1; break; 688eb097431SAxel Dörfler case 0x43: volume->joliet_level = 2; break; 689eb097431SAxel Dörfler case 0x45: volume->joliet_level = 3; break; 690eb097431SAxel Dörfler } 691eb097431SAxel Dörfler 692eb097431SAxel Dörfler TRACE(("ISO9660 Extensions: Microsoft Joliet Level %d\n", volume->joliet_level)); 693eb097431SAxel Dörfler 694eb097431SAxel Dörfler // Because Joliet-stuff starts at other sector, 695eb097431SAxel Dörfler // update root directory record. 69656b2febaSMichael Lotz if (volume->joliet_level > 0) { 69756b2febaSMichael Lotz InitNode(volume, &volume->rootDirRec, &buffer[156], 69856b2febaSMichael Lotz NULL); 69956b2febaSMichael Lotz } 700eb097431SAxel Dörfler } 701eb097431SAxel Dörfler } else if (*(unsigned char *)buffer == 0xff) { 702eb097431SAxel Dörfler // ISO_VD_END 703eb097431SAxel Dörfler done = true; 704eb097431SAxel Dörfler } else 705eb097431SAxel Dörfler TRACE(("found header %d\n",*buffer)); 706eb097431SAxel Dörfler } 707eb097431SAxel Dörfler offset += 0x800; 708eb097431SAxel Dörfler } 709eb097431SAxel Dörfler 710eb097431SAxel Dörfler if (!isISO) { 711eb097431SAxel Dörfler // It isn't an ISO disk. 712eb097431SAxel Dörfler close(volume->fdOfSession); 713eb097431SAxel Dörfler close(volume->fd); 714eb097431SAxel Dörfler free(volume); 715eb097431SAxel Dörfler 716eb097431SAxel Dörfler TRACE(("ISOMount: Not an ISO9660 volume!\n")); 717eb097431SAxel Dörfler return B_BAD_VALUE; 718eb097431SAxel Dörfler } 719eb097431SAxel Dörfler 720eb097431SAxel Dörfler TRACE(("ISOMount - EXIT, returning %p\n", volume)); 721eb097431SAxel Dörfler *_newVolume = volume; 722eb097431SAxel Dörfler return B_OK; 723eb097431SAxel Dörfler } 724eb097431SAxel Dörfler 725eb097431SAxel Dörfler 726eb097431SAxel Dörfler /*! Reads in a single directory entry and fills in the values in the 727eb097431SAxel Dörfler dirent struct. Uses the cookie to keep track of the current block 728eb097431SAxel Dörfler and position within the block. Also uses the cookie to determine when 729eb097431SAxel Dörfler it has reached the end of the directory file. 730eb097431SAxel Dörfler */ 731eb097431SAxel Dörfler status_t 732eb097431SAxel Dörfler ISOReadDirEnt(iso9660_volume *volume, dircookie *cookie, struct dirent *dirent, 733eb097431SAxel Dörfler size_t bufferSize) 734eb097431SAxel Dörfler { 735eb097431SAxel Dörfler int result = B_NO_ERROR; 73699d1bfb5SAxel Dörfler bool done = false; 737eb097431SAxel Dörfler 738eb097431SAxel Dörfler TRACE(("ISOReadDirEnt - ENTER\n")); 739eb097431SAxel Dörfler 74099d1bfb5SAxel Dörfler while (!done) { 74199d1bfb5SAxel Dörfler off_t totalRead = cookie->pos + (cookie->block - cookie->startBlock) 74299d1bfb5SAxel Dörfler * volume->logicalBlkSize[FS_DATA_FORMAT]; 74399d1bfb5SAxel Dörfler 744eb097431SAxel Dörfler // If we're at the end of the data in a block, move to the next block. 74599d1bfb5SAxel Dörfler char *blockData; 746eb097431SAxel Dörfler while (true) { 74799d1bfb5SAxel Dörfler blockData 74899d1bfb5SAxel Dörfler = (char*)block_cache_get(volume->fBlockCache, cookie->block); 749eb097431SAxel Dörfler if (blockData != NULL && *(blockData + cookie->pos) == 0) { 750eb097431SAxel Dörfler // NULL data, move to next block. 751eb097431SAxel Dörfler block_cache_put(volume->fBlockCache, cookie->block); 752eb097431SAxel Dörfler blockData = NULL; 75399d1bfb5SAxel Dörfler totalRead 75499d1bfb5SAxel Dörfler += volume->logicalBlkSize[FS_DATA_FORMAT] - cookie->pos; 755eb097431SAxel Dörfler cookie->pos = 0; 756eb097431SAxel Dörfler cookie->block++; 757eb097431SAxel Dörfler } else 758eb097431SAxel Dörfler break; 759eb097431SAxel Dörfler 760eb097431SAxel Dörfler if (totalRead >= cookie->totalSize) 761eb097431SAxel Dörfler break; 762eb097431SAxel Dörfler } 763eb097431SAxel Dörfler 76499d1bfb5SAxel Dörfler off_t cacheBlock = cookie->block; 76599d1bfb5SAxel Dörfler 766eb097431SAxel Dörfler if (blockData != NULL && totalRead < cookie->totalSize) { 767eb097431SAxel Dörfler iso9660_inode node; 76899d1bfb5SAxel Dörfler size_t bytesRead = 0; 76956b2febaSMichael Lotz result = InitNode(volume, &node, blockData + cookie->pos, 77056b2febaSMichael Lotz &bytesRead); 77143276e5bSMichael Lotz 77243276e5bSMichael Lotz // if we hit an entry that we don't support, we just skip it 773a735bdebSMichael Lotz if (result != B_OK && result != B_UNSUPPORTED) 77447a214deSAxel Dörfler break; 77547a214deSAxel Dörfler 77643276e5bSMichael Lotz if (result == B_OK && (node.flags & ISO_IS_ASSOCIATED_FILE) == 0) { 777eb097431SAxel Dörfler size_t nameBufferSize = bufferSize - sizeof(struct dirent); 778eb097431SAxel Dörfler 779eb097431SAxel Dörfler dirent->d_dev = volume->id; 780eb097431SAxel Dörfler dirent->d_ino = ((ino_t)cookie->block << 30) 781eb097431SAxel Dörfler + (cookie->pos & 0x3fffffff); 782eb097431SAxel Dörfler dirent->d_reclen = sizeof(struct dirent) + node.name_length + 1; 783eb097431SAxel Dörfler 784eb097431SAxel Dörfler if (node.name_length <= nameBufferSize) { 785eb097431SAxel Dörfler // need to do some size checking here. 786eb097431SAxel Dörfler strlcpy(dirent->d_name, node.name, node.name_length + 1); 78799d1bfb5SAxel Dörfler TRACE(("ISOReadDirEnt - success, name is %s, block %Ld, " 78899d1bfb5SAxel Dörfler "pos %Ld, inode id %Ld\n", dirent->d_name, cookie->block, 789eb097431SAxel Dörfler cookie->pos, dirent->d_ino)); 790eb097431SAxel Dörfler } else { 791eb097431SAxel Dörfler // TODO: this can be just normal if we support reading more 792eb097431SAxel Dörfler // than one entry. 79399d1bfb5SAxel Dörfler TRACE(("ISOReadDirEnt - ERROR, name %s does not fit in " 79499d1bfb5SAxel Dörfler "buffer of size %d\n", node.name, (int)nameBufferSize)); 795eb097431SAxel Dörfler result = B_BAD_VALUE; 796eb097431SAxel Dörfler } 79747a214deSAxel Dörfler 79847a214deSAxel Dörfler done = true; 799eb097431SAxel Dörfler } 8002a64cb11SAxel Dörfler 80147a214deSAxel Dörfler cookie->pos += bytesRead; 80247a214deSAxel Dörfler 8032a64cb11SAxel Dörfler if (cookie->pos == volume->logicalBlkSize[FS_DATA_FORMAT]) { 8042a64cb11SAxel Dörfler cookie->pos = 0; 8052a64cb11SAxel Dörfler cookie->block++; 8062a64cb11SAxel Dörfler } 807eb097431SAxel Dörfler } else { 808eb097431SAxel Dörfler if (totalRead >= cookie->totalSize) 809eb097431SAxel Dörfler result = B_ENTRY_NOT_FOUND; 810eb097431SAxel Dörfler else 811eb097431SAxel Dörfler result = B_NO_MEMORY; 81299d1bfb5SAxel Dörfler done = true; 813eb097431SAxel Dörfler } 814eb097431SAxel Dörfler 815eb097431SAxel Dörfler if (blockData != NULL) 816eb097431SAxel Dörfler block_cache_put(volume->fBlockCache, cacheBlock); 81799d1bfb5SAxel Dörfler } 818eb097431SAxel Dörfler 819eb097431SAxel Dörfler TRACE(("ISOReadDirEnt - EXIT, result is %s, vnid is %Lu\n", 820eb097431SAxel Dörfler strerror(result), dirent->d_ino)); 82199d1bfb5SAxel Dörfler 822eb097431SAxel Dörfler return result; 823eb097431SAxel Dörfler } 824eb097431SAxel Dörfler 825eb097431SAxel Dörfler 826eb097431SAxel Dörfler status_t 82756b2febaSMichael Lotz InitNode(iso9660_volume* volume, iso9660_inode* node, char* buffer, 82856b2febaSMichael Lotz size_t* _bytesRead, bool relocated) 829eb097431SAxel Dörfler { 830eb097431SAxel Dörfler uint8 recordLength = *(uint8*)buffer++; 831eb097431SAxel Dörfler size_t nameLength; 832eb097431SAxel Dörfler 833eb097431SAxel Dörfler TRACE(("InitNode - ENTER, bufstart is %p, record length is %d bytes\n", 834eb097431SAxel Dörfler buffer, recordLength)); 835eb097431SAxel Dörfler 836eb097431SAxel Dörfler if (_bytesRead != NULL) 837eb097431SAxel Dörfler *_bytesRead = recordLength; 838eb097431SAxel Dörfler if (recordLength == 0) 839eb097431SAxel Dörfler return B_ENTRY_NOT_FOUND; 840eb097431SAxel Dörfler 841eb097431SAxel Dörfler char* end = buffer + recordLength; 842eb097431SAxel Dörfler 84356b2febaSMichael Lotz if (!relocated) { 844eb097431SAxel Dörfler node->cache = NULL; 845eb097431SAxel Dörfler node->name = NULL; 846eb097431SAxel Dörfler node->attr.slName = NULL; 847eb097431SAxel Dörfler memset(node->attr.stat, 0, sizeof(node->attr.stat)); 84856b2febaSMichael Lotz } else 84956b2febaSMichael Lotz free(node->attr.slName); 850eb097431SAxel Dörfler 851eb097431SAxel Dörfler node->extAttrRecLen = *(uint8*)buffer++; 85299d1bfb5SAxel Dörfler TRACE(("InitNode - ext attr length is %d\n", (int)node->extAttrRecLen)); 853eb097431SAxel Dörfler 854eb097431SAxel Dörfler node->startLBN[LSB_DATA] = *(uint32*)buffer; 855eb097431SAxel Dörfler buffer += 4; 856eb097431SAxel Dörfler node->startLBN[MSB_DATA] = *(uint32*)buffer; 857eb097431SAxel Dörfler buffer += 4; 85899d1bfb5SAxel Dörfler TRACE(("InitNode - data start LBN is %d\n", 85999d1bfb5SAxel Dörfler (int)node->startLBN[FS_DATA_FORMAT])); 860eb097431SAxel Dörfler 861eb097431SAxel Dörfler node->dataLen[LSB_DATA] = *(uint32*)buffer; 862eb097431SAxel Dörfler buffer += 4; 863eb097431SAxel Dörfler node->dataLen[MSB_DATA] = *(uint32*)buffer; 864eb097431SAxel Dörfler buffer += 4; 86599d1bfb5SAxel Dörfler TRACE(("InitNode - data length is %d\n", 86699d1bfb5SAxel Dörfler (int)node->dataLen[FS_DATA_FORMAT])); 867eb097431SAxel Dörfler 868eb097431SAxel Dörfler init_node_date(&node->recordDate, buffer); 869eb097431SAxel Dörfler buffer += 7; 870eb097431SAxel Dörfler 871eb097431SAxel Dörfler node->flags = *(uint8*)buffer; 872eb097431SAxel Dörfler buffer++; 873eb097431SAxel Dörfler TRACE(("InitNode - flags are %d\n", node->flags)); 874eb097431SAxel Dörfler 875eb097431SAxel Dörfler node->fileUnitSize = *(uint8*)buffer; 876eb097431SAxel Dörfler buffer++; 877eb097431SAxel Dörfler TRACE(("InitNode - fileUnitSize is %d\n", node->fileUnitSize)); 878eb097431SAxel Dörfler 879eb097431SAxel Dörfler node->interleaveGapSize = *(uint8*)buffer; 880eb097431SAxel Dörfler buffer++; 881eb097431SAxel Dörfler TRACE(("InitNode - interleave gap size = %d\n", node->interleaveGapSize)); 882eb097431SAxel Dörfler 883eb097431SAxel Dörfler node->volSeqNum = *(uint32*)buffer; 884eb097431SAxel Dörfler buffer += 4; 88599d1bfb5SAxel Dörfler TRACE(("InitNode - volume seq num is %d\n", (int)node->volSeqNum)); 886eb097431SAxel Dörfler 88756b2febaSMichael Lotz nameLength = *(uint8*)buffer; 888eb097431SAxel Dörfler buffer++; 88956b2febaSMichael Lotz 89056b2febaSMichael Lotz // for relocated directories we take the name from the placeholder entry 89156b2febaSMichael Lotz if (!relocated) { 89256b2febaSMichael Lotz node->name_length = nameLength; 8935348fbe6SAlexander von Gluck IV TRACE(("InitNode - file id length is %" B_PRIu32 "\n", 8945348fbe6SAlexander von Gluck IV node->name_length)); 89556b2febaSMichael Lotz } 896eb097431SAxel Dörfler 897eb097431SAxel Dörfler // Set defaults, in case there is no RockRidge stuff. 89847a214deSAxel Dörfler node->attr.stat[FS_DATA_FORMAT].st_mode |= (node->flags & ISO_IS_DIR) != 0 899eb097431SAxel Dörfler ? S_IFDIR | S_IXUSR | S_IRUSR | S_IXGRP | S_IRGRP | S_IXOTH | S_IROTH 900eb097431SAxel Dörfler : S_IFREG | S_IRUSR | S_IRGRP | S_IROTH; 901eb097431SAxel Dörfler 902eb097431SAxel Dörfler if (node->name_length == 0) { 903eb097431SAxel Dörfler TRACE(("InitNode - File ID String is 0 length\n")); 904eb097431SAxel Dörfler return B_ENTRY_NOT_FOUND; 905eb097431SAxel Dörfler } 906eb097431SAxel Dörfler 90756b2febaSMichael Lotz if (!relocated) { 908eb097431SAxel Dörfler // JOLIET extension: 909eb097431SAxel Dörfler // on joliet discs, buffer[0] can be 0 for Unicoded filenames, 910eb097431SAxel Dörfler // so I've added a check here to test explicitely for 911eb097431SAxel Dörfler // directories (which have length 1) 912eb097431SAxel Dörfler // Take care of "." and "..", the first two dirents are 913eb097431SAxel Dörfler // these in iso. 9141dd3b2c7SAxel Dörfler if (node->name_length == 1 && buffer[0] == 0) { 915eb097431SAxel Dörfler node->name = strdup("."); 916eb097431SAxel Dörfler node->name_length = 1; 9171dd3b2c7SAxel Dörfler } else if (node->name_length == 1 && buffer[0] == 1) { 918eb097431SAxel Dörfler node->name = strdup(".."); 919eb097431SAxel Dörfler node->name_length = 2; 92056b2febaSMichael Lotz } else if (volume->joliet_level > 0) { 921eb097431SAxel Dörfler // JOLIET extension: convert Unicode16 string to UTF8 922eb097431SAxel Dörfler // Assume that the unicode->utf8 conversion produces 4 byte 923eb097431SAxel Dörfler // utf8 characters, and allocate that much space 924eb097431SAxel Dörfler node->name = (char*)malloc(node->name_length * 2 + 1); 925eb097431SAxel Dörfler if (node->name == NULL) 926eb097431SAxel Dörfler return B_NO_MEMORY; 927eb097431SAxel Dörfler 928eb097431SAxel Dörfler int32 sourceLength = node->name_length; 929eb097431SAxel Dörfler int32 destLength = node->name_length * 2; 930eb097431SAxel Dörfler 931eb097431SAxel Dörfler status_t status = unicode_to_utf8(buffer, &sourceLength, 932eb097431SAxel Dörfler node->name, &destLength); 933eb097431SAxel Dörfler if (status < B_OK) { 934eb097431SAxel Dörfler dprintf("iso9660: error converting unicode->utf8\n"); 935eb097431SAxel Dörfler return status; 936eb097431SAxel Dörfler } 937eb097431SAxel Dörfler 938eb097431SAxel Dörfler node->name[destLength] = '\0'; 939eb097431SAxel Dörfler node->name_length = destLength; 940eb097431SAxel Dörfler 941eb097431SAxel Dörfler sanitize_iso_name(node, false); 942eb097431SAxel Dörfler } else { 943eb097431SAxel Dörfler node->name = (char*)malloc(node->name_length + 1); 944eb097431SAxel Dörfler if (node->name == NULL) 945eb097431SAxel Dörfler return B_NO_MEMORY; 946eb097431SAxel Dörfler 947eb097431SAxel Dörfler // convert all characters to lower case 94856b2febaSMichael Lotz for (uint32 i = 0; i < node->name_length; i++) 949eb097431SAxel Dörfler node->name[i] = tolower(buffer[i]); 95056b2febaSMichael Lotz 951eb097431SAxel Dörfler node->name[node->name_length] = '\0'; 952eb097431SAxel Dörfler 953eb097431SAxel Dörfler sanitize_iso_name(node, true); 954eb097431SAxel Dörfler } 955eb097431SAxel Dörfler 956eb097431SAxel Dörfler if (node->name == NULL) { 957eb097431SAxel Dörfler TRACE(("InitNode - unable to allocate memory!\n")); 958eb097431SAxel Dörfler return B_NO_MEMORY; 959eb097431SAxel Dörfler } 96056b2febaSMichael Lotz } 961eb097431SAxel Dörfler 962eb097431SAxel Dörfler buffer += nameLength; 963eb097431SAxel Dörfler if (nameLength % 2 == 0) 964eb097431SAxel Dörfler buffer++; 965eb097431SAxel Dörfler 966eb097431SAxel Dörfler TRACE(("DirRec ID String is: %s\n", node->name)); 967eb097431SAxel Dörfler 96856b2febaSMichael Lotz return parse_rock_ridge(volume, node, buffer, end, relocated); 969eb097431SAxel Dörfler } 970eb097431SAxel Dörfler 971eb097431SAxel Dörfler 972eb097431SAxel Dörfler status_t 973eb097431SAxel Dörfler ConvertRecDate(ISORecDate* inDate, time_t* outDate) 974eb097431SAxel Dörfler { 975eb097431SAxel Dörfler time_t time; 976eb097431SAxel Dörfler int days, i, year, tz; 977eb097431SAxel Dörfler 978eb097431SAxel Dörfler year = inDate->year - 70; 979eb097431SAxel Dörfler tz = inDate->offsetGMT; 980eb097431SAxel Dörfler 981eb097431SAxel Dörfler if (year < 0) { 982eb097431SAxel Dörfler time = 0; 983eb097431SAxel Dörfler } else { 984eb097431SAxel Dörfler const int monlen[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 985eb097431SAxel Dörfler 986eb097431SAxel Dörfler days = (year * 365); 987eb097431SAxel Dörfler 988eb097431SAxel Dörfler if (year > 2) 989eb097431SAxel Dörfler days += (year + 1)/ 4; 990eb097431SAxel Dörfler 991eb097431SAxel Dörfler for (i = 1; (i < inDate->month) && (i < 12); i++) { 992eb097431SAxel Dörfler days += monlen[i-1]; 993eb097431SAxel Dörfler } 994eb097431SAxel Dörfler 995eb097431SAxel Dörfler if (((year + 2) % 4) == 0 && inDate->month > 2) 996eb097431SAxel Dörfler days++; 997eb097431SAxel Dörfler 998eb097431SAxel Dörfler days += inDate->date - 1; 999eb097431SAxel Dörfler time = ((((days*24) + inDate->hour) * 60 + inDate->minute) * 60) 1000eb097431SAxel Dörfler + inDate->second; 1001eb097431SAxel Dörfler if (tz & 0x80) 1002eb097431SAxel Dörfler tz |= (-1 << 8); 1003eb097431SAxel Dörfler 1004eb097431SAxel Dörfler if (-48 <= tz && tz <= 52) 1005*a3fdd62cSGediminas Jarulaitis time -= tz * 15 * 60; 1006eb097431SAxel Dörfler } 1007eb097431SAxel Dörfler *outDate = time; 1008eb097431SAxel Dörfler return 0; 1009eb097431SAxel Dörfler } 1010eb097431SAxel Dörfler 1011