diff --git a/src/add-ons/kernel/file_systems/iso9660/Jamfile b/src/add-ons/kernel/file_systems/iso9660/Jamfile index 80c68f0013..ced2516e0d 100644 --- a/src/add-ons/kernel/file_systems/iso9660/Jamfile +++ b/src/add-ons/kernel/file_systems/iso9660/Jamfile @@ -7,7 +7,7 @@ SubDirCcFlags -Wall -Wno-multichar ; SubDirC++Flags -Wall -Wno-multichar -fno-rtti ; KernelAddon iso9660 : - iso9660.c + iso9660.cpp iso9660_identify.cpp kernel_interface.cpp ; diff --git a/src/add-ons/kernel/file_systems/iso9660/iso9660.c b/src/add-ons/kernel/file_systems/iso9660/iso9660.c deleted file mode 100644 index fa0c5f385f..0000000000 --- a/src/add-ons/kernel/file_systems/iso9660/iso9660.c +++ /dev/null @@ -1,951 +0,0 @@ -/* - * Copyright 1999, Be Incorporated. All Rights Reserved. - * This file may be used under the terms of the Be Sample Code License. - * - * Copyright 2001, pinc Software. All Rights Reserved. - */ - - -#include "iso9660.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "rock_ridge.h" - -//#define TRACE_ISO9660 1 -#if TRACE_ISO9660 -# define TRACE(x) dprintf x -#else -# define TRACE(x) ; -#endif - - -// Just needed here -static status_t unicode_to_utf8(const char *src, int32 *srcLen, char *dst, int32 *dstLen); - - -// ISO9660 should start with this string -const char *kISO9660IDString = "CD001"; - -#if 0 -static int GetLogicalBlockSize(int fd); -static off_t GetNumDeviceBlocks(int fd, int block_size); -#endif -static int GetDeviceBlockSize(int fd); - -static int InitVolDate(ISOVolDate *date, char *buf); -static int InitRecDate(ISORecDate *date, char *buf); -static int InitVolDesc(nspace *vol, char *buf); - -#if 0 // currently unused -static int -GetLogicalBlockSize(int fd) -{ - partition_info p_info; - - if (ioctl(fd, B_GET_PARTITION_INFO, &p_info) == B_NO_ERROR) { - TRACE(("GetLogicalBlockSize: ioctl suceed\n")); - return p_info.logical_block_size; - } - TRACE(("GetLogicalBlockSize = ioctl returned error\n")); - - return 0; -} - - -static off_t -GetNumDeviceBlocks(int fd, int block_size) -{ - struct stat st; - device_geometry dg; - - if (ioctl(fd, B_GET_GEOMETRY, &dg) >= 0) { - return (off_t)dg.cylinder_count * - (off_t)dg.sectors_per_track * - (off_t)dg.head_count; - } - - /* if the ioctl fails, try just stat'ing in case it's a regular file */ - if (fstat(fd, &st) < 0) - return 0; - - return st.st_size / block_size; -} -#endif - -static int -GetDeviceBlockSize(int fd) -{ - struct stat st; - device_geometry dg; - - if (ioctl(fd, B_GET_GEOMETRY, &dg) < 0) { - if (fstat(fd, &st) < 0 || S_ISDIR(st.st_mode)) - return 0; - - return 512; /* just assume it's a plain old file or something */ - } - - return dg.bytes_per_sector; -} - - -// From EncodingComversions.cpp - -// Pierre's (modified) Uber Macro - -// NOTE: iso9660 seems to store the unicode text in big-endian form -#define u_to_utf8(str, uni_str)\ -{\ - if ((B_BENDIAN_TO_HOST_INT16(uni_str[0])&0xff80) == 0)\ - *str++ = B_BENDIAN_TO_HOST_INT16(*uni_str++);\ - else if ((B_BENDIAN_TO_HOST_INT16(uni_str[0])&0xf800) == 0) {\ - str[0] = 0xc0|(B_BENDIAN_TO_HOST_INT16(uni_str[0])>>6);\ - str[1] = 0x80|(B_BENDIAN_TO_HOST_INT16(*uni_str++)&0x3f);\ - str += 2;\ - } else if ((B_BENDIAN_TO_HOST_INT16(uni_str[0])&0xfc00) != 0xd800) {\ - str[0] = 0xe0|(B_BENDIAN_TO_HOST_INT16(uni_str[0])>>12);\ - str[1] = 0x80|((B_BENDIAN_TO_HOST_INT16(uni_str[0])>>6)&0x3f);\ - str[2] = 0x80|(B_BENDIAN_TO_HOST_INT16(*uni_str++)&0x3f);\ - str += 3;\ - } else {\ - int val;\ - val = ((B_BENDIAN_TO_HOST_INT16(uni_str[0])-0xd7c0)<<10) | (B_BENDIAN_TO_HOST_INT16(uni_str[1])&0x3ff);\ - str[0] = 0xf0 | (val>>18);\ - str[1] = 0x80 | ((val>>12)&0x3f);\ - str[2] = 0x80 | ((val>>6)&0x3f);\ - str[3] = 0x80 | (val&0x3f);\ - uni_str += 2; str += 4;\ - }\ -} - - -static status_t -unicode_to_utf8(const char *src, int32 *srcLen, char *dst, int32 *dstLen) -{ - int32 srcLimit = *srcLen; - int32 dstLimit = *dstLen; - int32 srcCount = 0; - int32 dstCount = 0; - - for (srcCount = 0; srcCount < srcLimit; srcCount += 2) { - uint16 *UNICODE = (uint16 *)&src[srcCount]; - uchar utf8[4]; - uchar *UTF8 = utf8; - int32 utf8Len; - int32 j; - - u_to_utf8(UTF8, UNICODE); - - utf8Len = UTF8 - utf8; - if ((dstCount + utf8Len) > dstLimit) - break; - - for (j = 0; j < utf8Len; j++) - dst[dstCount + j] = utf8[j]; - dstCount += utf8Len; - } - - *srcLen = srcCount; - *dstLen = dstCount; - - return dstCount > 0 ? B_NO_ERROR : B_ERROR; -} - - -// #pragma mark - -// Functions specific to iso driver. - - -int -ISOMount(const char *path, const int flags, nspace **newVol, bool allow_joliet) -{ - // path: path to device (eg, /dev/disk/scsi/030/raw) - // partition: partition number on device ???? - // flags: currently unused - - // determine if it is an ISO volume. - char buffer[ISO_PVD_SIZE]; - bool done = false; - bool is_iso = false; - off_t offset = 0x8000; - ssize_t retval; - partition_info partitionInfo; - int deviceBlockSize, multiplier; - nspace *vol; - int result = B_NO_ERROR; - - (void)flags; - - TRACE(("ISOMount - ENTER\n")); - - vol = (nspace *)calloc(sizeof(nspace), 1); - if (vol == NULL) { - TRACE(("ISOMount - mem error \n")); - return ENOMEM; - } - - memset(&partitionInfo, 0, sizeof(partition_info)); - - /* open and lock the device */ - vol->fdOfSession = open(path, O_RDONLY); - - /* try to open the raw device to get access to the other sessions as well */ - if (vol->fdOfSession >= 0) { - if (ioctl(vol->fdOfSession, B_GET_PARTITION_INFO, &partitionInfo) < B_NO_ERROR) { - TRACE(("B_GET_PARTITION_INFO: ioctl returned error\n")); - strcpy(partitionInfo.device, path); - } - TRACE(("ISOMount: open device/file \"%s\"\n", partitionInfo.device)); - - vol->fd = open(partitionInfo.device, O_RDONLY); - } - - if (vol->fdOfSession < 0 || vol->fd < 0) { - close(vol->fd); - close(vol->fdOfSession); - - TRACE(("ISO9660 ERROR - Unable to open <%s>\n", path)); - free(vol); - return EINVAL; - } - - deviceBlockSize = GetDeviceBlockSize(vol->fdOfSession); - if (deviceBlockSize < 0) { - TRACE(("ISO9660 ERROR - device block size is 0\n")); - close(vol->fd); - close(vol->fdOfSession); - - free(vol); - return EINVAL; - } - - vol->joliet_level = 0; - while ((!done) && (offset < 0x10000)) { - retval = read_pos (vol->fdOfSession, offset, (void *)buffer, ISO_PVD_SIZE); - if (retval < ISO_PVD_SIZE) { - is_iso = false; - break; - } - - if (strncmp(buffer + 1, kISO9660IDString, 5) == 0) { - if ((*buffer == 0x01) && (!is_iso)) { - // ISO_VD_PRIMARY - - off_t maxBlocks; - - TRACE(("ISOMount: Is an ISO9660 volume, initting rec\n")); - - InitVolDesc(vol, buffer); - strncpy(vol->devicePath,path,127); - vol->id = ISO_ROOTNODE_ID; - TRACE(("ISO9660: vol->blockSize = %d\n", vol->logicalBlkSize[FS_DATA_FORMAT])); - - multiplier = deviceBlockSize / vol->logicalBlkSize[FS_DATA_FORMAT]; - TRACE(("ISOMount: block size multiplier is %d\n", multiplier)); - - // if the session is on a real device, size != 0 - if (partitionInfo.size != 0) - maxBlocks = (partitionInfo.size+partitionInfo.offset) / vol->logicalBlkSize[FS_DATA_FORMAT]; - else - maxBlocks = vol->volSpaceSize[FS_DATA_FORMAT]; - - /* Initialize access to the cache so that we can do cached i/o */ - TRACE(("ISO9660: cache init: dev %d, max blocks %Ld\n", vol->fd, maxBlocks)); - vol->fBlockCache = block_cache_create(vol->fd, maxBlocks, - vol->logicalBlkSize[FS_DATA_FORMAT], true); - is_iso = true; - } else if ((*buffer == 0x02) && is_iso && allow_joliet) { - // ISO_VD_SUPPLEMENTARY - - // JOLIET extension - // test escape sequence for level of UCS-2 characterset - if (buffer[88] == 0x25 && buffer[89] == 0x2f) { - switch (buffer[90]) { - case 0x40: vol->joliet_level = 1; break; - case 0x43: vol->joliet_level = 2; break; - case 0x45: vol->joliet_level = 3; break; - } - - TRACE(("ISO9660 Extensions: Microsoft Joliet Level %d\n", vol->joliet_level)); - - // Because Joliet-stuff starts at other sector, - // update root directory record. - if (vol->joliet_level > 0) - InitNode(&(vol->rootDirRec), &buffer[156], NULL, 0); - } - } else if (*(unsigned char *)buffer == 0xff) { - // ISO_VD_END - done = true; - } else - TRACE(("found header %d\n",*buffer)); - } - offset += 0x800; - } - - if (!is_iso) { - // It isn't an ISO disk. - if (vol->fdOfSession >= 0) - close(vol->fdOfSession); - if (vol->fd >= 0) - close(vol->fd); - - free(vol); - vol = NULL; - result = EINVAL; - TRACE(("ISOMount: Not an ISO9660 volume!\n")); - } - - TRACE(("ISOMount - EXIT, result %s, returning %p\n", strerror(result), vol)); - *newVol = vol; - return result; -} - - -/*! Reads in a single directory entry and fills in the values in the - dirent struct. Uses the cookie to keep track of the current block - and position within the block. Also uses the cookie to determine when - it has reached the end of the directory file. -*/ -int -ISOReadDirEnt(nspace *ns, dircookie *cookie, struct dirent *dirent, - size_t bufsize) -{ - off_t totalRead = cookie->pos + ((cookie->block - cookie->startBlock) - * ns->logicalBlkSize[FS_DATA_FORMAT]); - off_t cacheBlock; - char *blockData; - int result = B_NO_ERROR; - int bytesRead = 0; - - TRACE(("ISOReadDirEnt - ENTER\n")); - - // If we're at the end of the data in a block, move to the next block. - while (true) { - blockData = (char *)block_cache_get_etc(ns->fBlockCache, cookie->block, - 0, ns->logicalBlkSize[FS_DATA_FORMAT]); - - if (blockData != NULL && *(blockData + cookie->pos) == 0) { - // NULL data, move to next block. - block_cache_put(ns->fBlockCache, cookie->block); - blockData = NULL; - totalRead += ns->logicalBlkSize[FS_DATA_FORMAT] - cookie->pos; - cookie->pos = 0; - cookie->block++; - } else - break; - - if (totalRead >= cookie->totalSize) - break; - } - - cacheBlock = cookie->block; - if (blockData != NULL && totalRead < cookie->totalSize) { - vnode node; - result = InitNode(&node, blockData + cookie->pos, &bytesRead, - ns->joliet_level); - if (result == B_NO_ERROR) { - int nameBufSize = (bufsize - (2 * sizeof(dev_t) + 2* sizeof(ino_t) - + sizeof(unsigned short))); - - dirent->d_ino = (cookie->block << 30) + (cookie->pos & 0xFFFFFFFF); - dirent->d_reclen = sizeof(struct dirent) + node.fileIDLen + 1; - - if (node.fileIDLen <= nameBufSize) { - // need to do some size checking here. - strlcpy(dirent->d_name, node.fileIDString, node.fileIDLen + 1); - TRACE(("ISOReadDirEnt - success, name is %s\n", - dirent->d_name)); - } else { - TRACE(("ISOReadDirEnt - ERROR, name %s does not fit in buffer " - "of size %d\n", node.fileIDString, nameBufSize)); - result = EINVAL; - } - cookie->pos += bytesRead; - } - } else { - if (totalRead >= cookie->totalSize) - result = ENOENT; - else - result = ENOMEM; - } - - if (blockData != NULL) - block_cache_put(ns->fBlockCache, cacheBlock); - - TRACE(("ISOReadDirEnt - EXIT, result is %s, vnid is %Lu\n", - strerror(result), dirent->d_ino)); - return result; -} - - -int -InitVolDesc(nspace *vol, char *buffer) -{ - TRACE(("InitVolDesc - ENTER\n")); - - vol->volDescType = *(uint8 *)buffer++; - - vol->stdIDString[5] = '\0'; - strncpy(vol->stdIDString, buffer, 5); - buffer += 5; - - vol->volDescVersion = *(uint8 *)buffer; - buffer += 2; // 8th byte unused - - vol->systemIDString[32] = '\0'; - strncpy(vol->systemIDString, buffer, 32); - buffer += 32; - TRACE(("InitVolDesc - system id string is %s\n", vol->systemIDString)); - - vol->volIDString[32] = '\0'; - strncpy(vol->volIDString, buffer, 32); - buffer += (32 + 80-73 + 1); // bytes 80-73 unused - TRACE(("InitVolDesc - volume id string is %s\n", vol->volIDString)); - - vol->volSpaceSize[LSB_DATA] = *(uint32 *)buffer; - buffer += 4; - vol->volSpaceSize[MSB_DATA] = *(uint32 *)buffer; - buffer+= (4 + 120-89 + 1); // bytes 120-89 unused - - vol->volSetSize[LSB_DATA] = *(uint16*)buffer; - buffer += 2; - vol->volSetSize[MSB_DATA] = *(uint16*)buffer; - buffer += 2; - - vol->volSeqNum[LSB_DATA] = *(uint16*)buffer; - buffer += 2; - vol->volSeqNum[MSB_DATA] = *(uint16*)buffer; - buffer += 2; - - vol->logicalBlkSize[LSB_DATA] = *(uint16*)buffer; - buffer += 2; - vol->logicalBlkSize[MSB_DATA] = *(uint16*)buffer; - buffer += 2; - - vol->pathTblSize[LSB_DATA] = *(uint32*)buffer; - buffer += 4; - vol->pathTblSize[MSB_DATA] = *(uint32*)buffer; - buffer += 4; - - vol->lPathTblLoc[LSB_DATA] = *(uint16*)buffer; - buffer += 2; - vol->lPathTblLoc[MSB_DATA] = *(uint16*)buffer; - buffer += 2; - - vol->optLPathTblLoc[LSB_DATA] = *(uint16*)buffer; - buffer += 2; - vol->optLPathTblLoc[MSB_DATA] = *(uint16*)buffer; - buffer += 2; - - vol->mPathTblLoc[LSB_DATA] = *(uint16*)buffer; - buffer += 2; - vol->mPathTblLoc[MSB_DATA] = *(uint16*)buffer; - buffer += 2; - - vol->optMPathTblLoc[LSB_DATA] = *(uint16*)buffer; - buffer += 2; - vol->optMPathTblLoc[MSB_DATA] = *(uint16*)buffer; - buffer += 2; - - // Fill in directory record. - InitNode(&(vol->rootDirRec), buffer, NULL, 0); - - vol->rootDirRec.id = ISO_ROOTNODE_ID; - buffer += 34; - - vol->volSetIDString[128] = '\0'; - strncpy(vol->volSetIDString, buffer, 128); - buffer += 128; - TRACE(("InitVolDesc - volume set id string is %s\n", vol->volSetIDString)); - - vol->pubIDString[128] = '\0'; - strncpy(vol->pubIDString, buffer, 128); - buffer += 128; - TRACE(("InitVolDesc - volume pub id string is %s\n", vol->pubIDString)); - - vol->dataPreparer[128] = '\0'; - strncpy(vol->dataPreparer, buffer, 128); - buffer += 128; - TRACE(("InitVolDesc - volume dataPreparer string is %s\n", vol->dataPreparer)); - - vol->appIDString[128] = '\0'; - strncpy(vol->appIDString, buffer, 128); - buffer += 128; - TRACE(("InitVolDesc - volume app id string is %s\n", vol->appIDString)); - - vol->copyright[38] = '\0'; - strncpy(vol->copyright, buffer, 38); - buffer += 38; - TRACE(("InitVolDesc - copyright is %s\n", vol->copyright)); - - vol->abstractFName[38] = '\0'; - strncpy(vol->abstractFName, buffer, 38); - buffer += 38; - - vol->biblioFName[38] = '\0'; - strncpy(vol->biblioFName, buffer, 38); - buffer += 38; - - InitVolDate(&(vol->createDate), buffer); - buffer += 17; - - InitVolDate(&(vol->modDate), buffer); - buffer += 17; - - InitVolDate(&(vol->expireDate), buffer); - buffer += 17; - - InitVolDate(&(vol->effectiveDate), buffer); - buffer += 17; - - vol->fileStructVers = *(uint8 *)buffer; - return 0; -} - - -int -InitNode(vnode *rec, char *buffer, int *_bytesRead, uint8 joliet_level) -{ - int result = B_NO_ERROR; - uint8 recLen = *(uint8 *)buffer++; - bool no_rock_ridge_stat_struct = TRUE; - - if (_bytesRead != NULL) - *_bytesRead = recLen; - - TRACE(("InitNode - ENTER, bufstart is %p, record length is %d bytes\n", buffer, recLen)); - - rec->cache = NULL; - - if (recLen > 0) { - rec->extAttrRecLen = *(uint8 *)buffer++; - - rec->startLBN[LSB_DATA] = *(uint32 *)buffer; - buffer += 4; - rec->startLBN[MSB_DATA] = *(uint32 *)buffer; - buffer += 4; - TRACE(("InitNode - data start LBN is %ld\n", rec->startLBN[FS_DATA_FORMAT])); - - rec->dataLen[LSB_DATA] = *(uint32 *)buffer; - buffer += 4; - rec->dataLen[MSB_DATA] = *(uint32 *)buffer; - buffer += 4; - TRACE(("InitNode - data length is %ld\n", rec->dataLen[FS_DATA_FORMAT])); - - InitRecDate(&(rec->recordDate), buffer); - buffer += 7; - - rec->flags = *(uint8 *)buffer; - buffer++; - TRACE(("InitNode - flags are %d\n", rec->flags)); - - rec->fileUnitSize = *(uint8 *)buffer; - buffer++; - TRACE(("InitNode - fileUnitSize is %d\n", rec->fileUnitSize)); - - rec->interleaveGapSize = *(uint8 *)buffer; - buffer++; - TRACE(("InitNode - interleave gap size = %d\n", rec->interleaveGapSize)); - - rec->volSeqNum = *(uint32 *)buffer; - buffer += 4; - TRACE(("InitNode - volume seq num is %ld\n", rec->volSeqNum)); - - rec->fileIDLen = *(uint8*)buffer; - buffer++; - TRACE(("InitNode - file id length is %d\n", rec->fileIDLen)); - - if (rec->fileIDLen > 0) { - // JOLIET extension: - // on joliet discs, buffer[0] can be 0 for Unicoded filenames, - // so I've added a check here to test explicitely for - // directories (which have length 1) - if (rec->fileIDLen == 1) { - // Take care of "." and "..", the first two dirents are - // these in iso. - if (buffer[0] == 0) { - rec->fileIDString = strdup("."); - rec->fileIDLen = 1; - } else if (buffer[0] == 1) { - rec->fileIDString = strdup(".."); - rec->fileIDLen = 2; - } - } else { - // JOLIET extension: - // convert Unicode16 string to UTF8 - if (joliet_level > 0) { - // Assume that the unicode->utf8 conversion produces 4 byte - // utf8 characters, and allocate that much space - rec->fileIDString = (char *)malloc(rec->fileIDLen * 2 + 1); - if (rec->fileIDString != NULL) { - status_t err; - int32 srcLen = rec->fileIDLen; - int32 dstLen = rec->fileIDLen * 2; - - err = unicode_to_utf8(buffer, &srcLen, rec->fileIDString, &dstLen); - if (err < B_NO_ERROR) { - dprintf("iso9660: error converting unicode->utf8\n"); - result = err; - } else { - rec->fileIDString[dstLen] = '\0'; - rec->fileIDLen = dstLen; - } - } else { - // Error - result = ENOMEM; - TRACE(("InitNode - unable to allocate memory!\n")); - } - } else { - rec->fileIDString = (char *)malloc((rec->fileIDLen) + 1); - - if (rec->fileIDString != NULL) { - strncpy(rec->fileIDString, buffer, rec->fileIDLen); - rec->fileIDString[rec->fileIDLen] = '\0'; - } else { - // Error - result = ENOMEM; - TRACE(("InitNode - unable to allocate memory!\n")); - } - } - } - - // Get rid of semicolons, which are used to delineate file versions.q - { - char *semi = NULL; - while ((semi = strchr(rec->fileIDString, ';')) != NULL) - semi[0] = '\0'; - } - TRACE(("DirRec ID String is: %s\n", rec->fileIDString)); - - if (result == B_NO_ERROR) { - buffer += rec->fileIDLen; - if (!(rec->fileIDLen % 2)) - buffer++; - - // Now we're at the start of the rock ridge stuff - { - char *altName = NULL; - char *slName = NULL; - uint16 altNameSize = 0; - uint16 slNameSize = 0; - uint8 slFlags = 0; - uint8 length = 0; - bool done = FALSE; - - TRACE(("RR: Start of extensions, but at %p\n", buffer)); - - memset(&(rec->attr.stat), 0, 2 * sizeof(struct stat)); - - // Set defaults, in case there is no RR stuff. - rec->attr.stat[FS_DATA_FORMAT].st_mode = (S_IRUSR | S_IRGRP | S_IROTH); - - while (!done) - { - buffer += length; - length = *(uint8 *)(buffer + 2); - switch (0x100 * buffer[0] + buffer[1]) - { - // Stat structure stuff - case 'PX': - { - uint8 bytePos = 3; - TRACE(("RR: found PX, length %u\n", length)); - rec->attr.pxVer = *(uint8*)(buffer + bytePos++); - no_rock_ridge_stat_struct = FALSE; - - // st_mode - rec->attr.stat[LSB_DATA].st_mode = *(mode_t*)(buffer + bytePos); - bytePos += 4; - rec->attr.stat[MSB_DATA].st_mode = *(mode_t*)(buffer + bytePos); - bytePos += 4; - - // st_nlink - rec->attr.stat[LSB_DATA].st_nlink = *(nlink_t*)(buffer+bytePos); - bytePos += 4; - rec->attr.stat[MSB_DATA].st_nlink = *(nlink_t*)(buffer + bytePos); - bytePos += 4; - - // st_uid - rec->attr.stat[LSB_DATA].st_uid = *(uid_t*)(buffer+bytePos); - bytePos += 4; - rec->attr.stat[MSB_DATA].st_uid = *(uid_t*)(buffer+bytePos); - bytePos += 4; - - // st_gid - rec->attr.stat[LSB_DATA].st_gid = *(gid_t*)(buffer+bytePos); - bytePos += 4; - rec->attr.stat[MSB_DATA].st_gid = *(gid_t*)(buffer+bytePos); - bytePos += 4; - break; - } - - case 'PN': - TRACE(("RR: found PN, length %u\n", length)); - break; - - // Symbolic link info - case 'SL': - { - uint8 bytePos = 3; - uint8 lastCompFlag = 0; - uint8 addPos = 0; - bool slDone = FALSE; - bool useSeparator = TRUE; - - TRACE(("RR: found SL, length %u\n", length)); - TRACE(("Buffer is at %p\n", buffer)); - TRACE(("Current length is %u\n", slNameSize)); - //kernel_debugger(""); - rec->attr.slVer = *(uint8*)(buffer + bytePos++); - slFlags = *(uint8*)(buffer + bytePos++); - - TRACE(("sl flags are %u\n", slFlags)); - while (!slDone && bytePos < length) - { - uint8 compFlag = *(uint8*)(buffer + bytePos++); - uint8 compLen = *(uint8*)(buffer + bytePos++); - - if (slName == NULL) useSeparator = FALSE; - - addPos = slNameSize; - - TRACE(("sl comp flags are %u, length is %u\n", compFlag, compLen)); - TRACE(("Current name size is %u\n", slNameSize)); - switch (compFlag) - { - case SLCP_CONTINUE: - useSeparator = FALSE; - default: - // Add the component to the total path. - slNameSize += compLen; - if ( useSeparator ) slNameSize++; - if (slName == NULL) - slName = (char*)malloc(slNameSize + 1); - else - slName = (char*)realloc(slName, slNameSize + 1); - - if (useSeparator) - { - TRACE(("Adding separator\n")); - slName[addPos++] = '/'; - } - - TRACE(("doing memcopy of %u bytes at offset %d\n", compLen, addPos)); - memcpy((slName + addPos), (buffer + bytePos), compLen); - - addPos += compLen; - useSeparator = TRUE; - break; - - case SLCP_CURRENT: - TRACE(("InitNode - found link to current directory\n")); - slNameSize += 2; - if (slName == NULL) - slName = (char*)malloc(slNameSize + 1); - else - slName = (char*)realloc(slName, slNameSize + 1); - memcpy(slName + addPos, "./", 2); - useSeparator = FALSE; - break; - - case SLCP_PARENT: - slNameSize += 3; - if (slName == NULL) - slName = (char*)malloc(slNameSize + 1); - else - slName = (char*)realloc(slName, slNameSize + 1); - memcpy(slName + addPos, "../", 3); - useSeparator = FALSE; - break; - - case SLCP_ROOT: - TRACE(("InitNode - found link to root directory\n")); - slNameSize += 1; - if (slName == NULL) - slName = (char*)malloc(slNameSize + 1); - else - slName = (char*)realloc(slName, slNameSize + 1); - memcpy(slName + addPos, "/", 1); - useSeparator = FALSE; - break; - - case SLCP_VOLROOT: - slDone = TRUE; - break; - - case SLCP_HOST: - slDone = TRUE; - break; - } - slName[slNameSize] = '\0'; - lastCompFlag = compFlag; - bytePos += compLen; - TRACE(("Current sl name is \'%s\'\n", slName)); - } - rec->attr.slName = slName; - TRACE(("InitNode = symlink name is \'%s\'\n", slName)); - break; - } - - // Altername name - case 'NM': - { - uint8 bytePos = 3; - uint8 flags = 0; - uint16 oldEnd = altNameSize; - - altNameSize += length - 5; - if (altName == NULL) - altName = (char *)malloc(altNameSize + 1); - else - altName = (char *)realloc(altName, altNameSize + 1); - - TRACE(("RR: found NM, length %u\n", length)); - // Read flag and version. - rec->attr.nmVer = *(uint8 *)(buffer + bytePos++); - flags = *(uint8 *)(buffer + bytePos++); - - TRACE(("RR: nm buffer is %s, start at %p\n", (buffer + bytePos), buffer + bytePos)); - - // Build the file name. - memcpy(altName + oldEnd, buffer + bytePos, length - 5); - altName[altNameSize] = '\0'; - TRACE(("RR: alt name is %s\n", altName)); - - // If the name is not continued in another record, update - // the record name. - if (!(flags & NM_CONTINUE)) - { - // Get rid of the ISO name, replace with RR name. - if (rec->fileIDString != NULL) - free(rec->fileIDString); - rec->fileIDString = altName; - rec->fileIDLen = altNameSize; - } - break; - } - - // Deep directory record masquerading as a file. - case 'CL': - TRACE(("RR: found CL, length %u\n", length)); - rec->flags |= ISO_ISDIR; - rec->startLBN[LSB_DATA] = *(uint32*)(buffer+4); - rec->startLBN[MSB_DATA] = *(uint32*)(buffer+8); - break; - - case 'PL': - TRACE(("RR: found PL, length %u\n", length)); - break; - - // Relocated directory, we should skip. - case 'RE': - result = EINVAL; - TRACE(("RR: found RE, length %u\n", length)); - break; - - case 'TF': - TRACE(("RR: found TF, length %u\n", length)); - break; - - case 'RR': - TRACE(("RR: found RR, length %u\n", length)); - break; - - default: - TRACE(("RR: %c%c (%d, %d)\n",buffer[0],buffer[1],buffer[0],buffer[1])); - TRACE(("RR: End of extensions.\n")); - done = TRUE; - break; - } - } - } - } - } else { - TRACE(("InitNode - File ID String is 0 length\n")); - result = ENOENT; - } - } else - result = ENOENT; - - TRACE(("InitNode - EXIT, result is %s name is \'%s\'\n", strerror(result), rec->fileIDString)); - - if (no_rock_ridge_stat_struct) { - if (rec->flags & ISO_ISDIR) - rec->attr.stat[FS_DATA_FORMAT].st_mode |= (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH); - else - rec->attr.stat[FS_DATA_FORMAT].st_mode |= (S_IFREG); - } - - return result; -} - - -static int -InitVolDate(ISOVolDate *date, char *buffer) -{ - memcpy(date, buffer, 17); - return 0; -} - - -static int -InitRecDate(ISORecDate *date, char *buffer) -{ - memcpy(date, buffer, 7); - return 0; -} - - -int -ConvertRecDate(ISORecDate* inDate, time_t* outDate) -{ - time_t time; - int days, i, year, tz; - - year = inDate->year -70; - tz = inDate->offsetGMT; - - if (year < 0) { - time = 0; - } else { - const int monlen[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - - days = (year * 365); - - if (year > 2) - days += (year + 1)/ 4; - - for (i = 1; (i < inDate->month) && (i < 12); i++) { - days += monlen[i-1]; - } - - if (((year + 2) % 4) == 0 && inDate->month > 2) - days++; - - days += inDate->date - 1; - time = ((((days*24) + inDate->hour) * 60 + inDate->minute) * 60) - + inDate->second; - if (tz & 0x80) - tz |= (-1 << 8); - - if (-48 <= tz && tz <= 52) - time += tz *15 * 60; - } - *outDate = time; - return 0; -} - diff --git a/src/add-ons/kernel/file_systems/iso9660/iso9660.cpp b/src/add-ons/kernel/file_systems/iso9660/iso9660.cpp new file mode 100644 index 0000000000..cb986809f1 --- /dev/null +++ b/src/add-ons/kernel/file_systems/iso9660/iso9660.cpp @@ -0,0 +1,930 @@ +/* + * Copyright 1999, Be Incorporated. All Rights Reserved. + * This file may be used under the terms of the Be Sample Code License. + * + * Copyright 2001, pinc Software. All Rights Reserved. + */ + + +#include "iso9660.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "rock_ridge.h" + +//#define TRACE_ISO9660 1 +#if TRACE_ISO9660 +# define TRACE(x) dprintf x +#else +# define TRACE(x) ; +#endif + + +// Just needed here +static status_t unicode_to_utf8(const char *src, int32 *srcLen, char *dst, + int32 *dstLen); + + +// ISO9660 should start with this string +const char *kISO9660IDString = "CD001"; + + +static int +get_device_block_size(int fd) +{ + device_geometry geometry; + + if (ioctl(fd, B_GET_GEOMETRY, &geometry) < 0) { + struct stat st; + if (fstat(fd, &st) < 0 || S_ISDIR(st.st_mode)) + return 0; + + return 512; /* just assume it's a plain old file or something */ + } + + return geometry.bytes_per_sector; +} + + +// From EncodingComversions.cpp + +// Pierre's (modified) Uber Macro + +// NOTE: iso9660 seems to store the unicode text in big-endian form +#define u_to_utf8(str, uni_str)\ +{\ + if ((B_BENDIAN_TO_HOST_INT16(uni_str[0])&0xff80) == 0)\ + *str++ = B_BENDIAN_TO_HOST_INT16(*uni_str++);\ + else if ((B_BENDIAN_TO_HOST_INT16(uni_str[0])&0xf800) == 0) {\ + str[0] = 0xc0|(B_BENDIAN_TO_HOST_INT16(uni_str[0])>>6);\ + str[1] = 0x80|(B_BENDIAN_TO_HOST_INT16(*uni_str++)&0x3f);\ + str += 2;\ + } else if ((B_BENDIAN_TO_HOST_INT16(uni_str[0])&0xfc00) != 0xd800) {\ + str[0] = 0xe0|(B_BENDIAN_TO_HOST_INT16(uni_str[0])>>12);\ + str[1] = 0x80|((B_BENDIAN_TO_HOST_INT16(uni_str[0])>>6)&0x3f);\ + str[2] = 0x80|(B_BENDIAN_TO_HOST_INT16(*uni_str++)&0x3f);\ + str += 3;\ + } else {\ + int val;\ + val = ((B_BENDIAN_TO_HOST_INT16(uni_str[0])-0xd7c0)<<10) | (B_BENDIAN_TO_HOST_INT16(uni_str[1])&0x3ff);\ + str[0] = 0xf0 | (val>>18);\ + str[1] = 0x80 | ((val>>12)&0x3f);\ + str[2] = 0x80 | ((val>>6)&0x3f);\ + str[3] = 0x80 | (val&0x3f);\ + uni_str += 2; str += 4;\ + }\ +} + + +static status_t +unicode_to_utf8(const char *src, int32 *srcLen, char *dst, int32 *dstLen) +{ + int32 srcLimit = *srcLen; + int32 dstLimit = *dstLen; + int32 srcCount = 0; + int32 dstCount = 0; + + for (srcCount = 0; srcCount < srcLimit; srcCount += 2) { + uint16 *UNICODE = (uint16 *)&src[srcCount]; + uchar utf8[4]; + uchar *UTF8 = utf8; + int32 utf8Len; + int32 j; + + u_to_utf8(UTF8, UNICODE); + + utf8Len = UTF8 - utf8; + if (dstCount + utf8Len > dstLimit) + break; + + for (j = 0; j < utf8Len; j++) + dst[dstCount + j] = utf8[j]; + dstCount += utf8Len; + } + + *srcLen = srcCount; + *dstLen = dstCount; + + return dstCount > 0 ? B_NO_ERROR : B_ERROR; +} + + +static void +sanitize_iso_name(iso9660_inode* node, bool removeTrailingPoints) +{ + // Get rid of semicolons, which are used to delineate file versions. + if (char* semi = strchr(node->name, ';')) { + semi[0] = '\0'; + node->name_length = semi - node->name; + } + + if (removeTrailingPoints) { + // Get rid of trailing points + if (node->name_length > 2 && node->name[node->name_length - 1] == '.') + node->name[--node->name_length] = '\0'; + } +} + + +static int +init_volume_date(ISOVolDate *date, char *buffer) +{ + memcpy(date, buffer, 17); + return 0; +} + + +static int +init_node_date(ISORecDate *date, char *buffer) +{ + memcpy(date, buffer, 7); + return 0; +} + + +static status_t +InitVolDesc(iso9660_volume *volume, char *buffer) +{ + TRACE(("InitVolDesc - ENTER\n")); + + volume->volDescType = *(uint8 *)buffer++; + + volume->stdIDString[5] = '\0'; + strncpy(volume->stdIDString, buffer, 5); + buffer += 5; + + volume->volDescVersion = *(uint8 *)buffer; + buffer += 2; // 8th byte unused + + volume->systemIDString[32] = '\0'; + strncpy(volume->systemIDString, buffer, 32); + buffer += 32; + TRACE(("InitVolDesc - system id string is %s\n", volume->systemIDString)); + + volume->volIDString[32] = '\0'; + strncpy(volume->volIDString, buffer, 32); + buffer += (32 + 80-73 + 1); // bytes 80-73 unused + TRACE(("InitVolDesc - volume id string is %s\n", volume->volIDString)); + + volume->volSpaceSize[LSB_DATA] = *(uint32 *)buffer; + buffer += 4; + volume->volSpaceSize[MSB_DATA] = *(uint32 *)buffer; + buffer+= (4 + 120-89 + 1); // bytes 120-89 unused + + volume->volSetSize[LSB_DATA] = *(uint16*)buffer; + buffer += 2; + volume->volSetSize[MSB_DATA] = *(uint16*)buffer; + buffer += 2; + + volume->volSeqNum[LSB_DATA] = *(uint16*)buffer; + buffer += 2; + volume->volSeqNum[MSB_DATA] = *(uint16*)buffer; + buffer += 2; + + volume->logicalBlkSize[LSB_DATA] = *(uint16*)buffer; + buffer += 2; + volume->logicalBlkSize[MSB_DATA] = *(uint16*)buffer; + buffer += 2; + + volume->pathTblSize[LSB_DATA] = *(uint32*)buffer; + buffer += 4; + volume->pathTblSize[MSB_DATA] = *(uint32*)buffer; + buffer += 4; + + volume->lPathTblLoc[LSB_DATA] = *(uint16*)buffer; + buffer += 2; + volume->lPathTblLoc[MSB_DATA] = *(uint16*)buffer; + buffer += 2; + + volume->optLPathTblLoc[LSB_DATA] = *(uint16*)buffer; + buffer += 2; + volume->optLPathTblLoc[MSB_DATA] = *(uint16*)buffer; + buffer += 2; + + volume->mPathTblLoc[LSB_DATA] = *(uint16*)buffer; + buffer += 2; + volume->mPathTblLoc[MSB_DATA] = *(uint16*)buffer; + buffer += 2; + + volume->optMPathTblLoc[LSB_DATA] = *(uint16*)buffer; + buffer += 2; + volume->optMPathTblLoc[MSB_DATA] = *(uint16*)buffer; + buffer += 2; + + // Fill in directory record. + InitNode(&volume->rootDirRec, buffer, NULL, 0); + + volume->rootDirRec.id = ISO_ROOTNODE_ID; + buffer += 34; + + volume->volSetIDString[128] = '\0'; + strncpy(volume->volSetIDString, buffer, 128); + buffer += 128; + TRACE(("InitVolDesc - volume set id string is %s\n", volume->volSetIDString)); + + volume->pubIDString[128] = '\0'; + strncpy(volume->pubIDString, buffer, 128); + buffer += 128; + TRACE(("InitVolDesc - volume pub id string is %s\n", volume->pubIDString)); + + volume->dataPreparer[128] = '\0'; + strncpy(volume->dataPreparer, buffer, 128); + buffer += 128; + TRACE(("InitVolDesc - volume dataPreparer string is %s\n", volume->dataPreparer)); + + volume->appIDString[128] = '\0'; + strncpy(volume->appIDString, buffer, 128); + buffer += 128; + TRACE(("InitVolDesc - volume app id string is %s\n", volume->appIDString)); + + volume->copyright[38] = '\0'; + strncpy(volume->copyright, buffer, 38); + buffer += 38; + TRACE(("InitVolDesc - copyright is %s\n", volume->copyright)); + + volume->abstractFName[38] = '\0'; + strncpy(volume->abstractFName, buffer, 38); + buffer += 38; + + volume->biblioFName[38] = '\0'; + strncpy(volume->biblioFName, buffer, 38); + buffer += 38; + + init_volume_date(&volume->createDate, buffer); + buffer += 17; + + init_volume_date(&volume->modDate, buffer); + buffer += 17; + + init_volume_date(&volume->expireDate, buffer); + buffer += 17; + + init_volume_date(&volume->effectiveDate, buffer); + buffer += 17; + + volume->fileStructVers = *(uint8*)buffer; + return B_OK; +} + + +static status_t +parse_rock_ridge(iso9660_inode* node, char* buffer, char* end) +{ + // Now we're at the start of the rock ridge stuff + char* altName = NULL; + char* slName = NULL; + uint16 altNameSize = 0; + uint16 slNameSize = 0; + uint8 slFlags = 0; + uint8 length = 0; + bool done = false; + + TRACE(("RR: Start of extensions at %p\n", buffer)); + + while (!done) { + buffer += length; + if (buffer + 2 >= end) + break; + length = *(uint8*)(buffer + 2); + if (buffer + length > end) + break; + + switch (((int)buffer[0] << 8) + buffer[1]) { + // Stat structure stuff + case 'PX': + { + uint8 bytePos = 3; + TRACE(("RR: found PX, length %u\n", length)); + node->attr.pxVer = *(uint8*)(buffer + bytePos++); + + // st_mode + node->attr.stat[LSB_DATA].st_mode + = *(mode_t*)(buffer + bytePos); + bytePos += 4; + node->attr.stat[MSB_DATA].st_mode + = *(mode_t*)(buffer + bytePos); + bytePos += 4; + + // st_nlink + node->attr.stat[LSB_DATA].st_nlink + = *(nlink_t*)(buffer+bytePos); + bytePos += 4; + node->attr.stat[MSB_DATA].st_nlink + = *(nlink_t*)(buffer + bytePos); + bytePos += 4; + + // st_uid + node->attr.stat[LSB_DATA].st_uid + = *(uid_t*)(buffer + bytePos); + bytePos += 4; + node->attr.stat[MSB_DATA].st_uid + = *(uid_t*)(buffer + bytePos); + bytePos += 4; + + // st_gid + node->attr.stat[LSB_DATA].st_gid + = *(gid_t*)(buffer + bytePos); + bytePos += 4; + node->attr.stat[MSB_DATA].st_gid + = *(gid_t*)(buffer + bytePos); + bytePos += 4; + break; + } + + case 'PN': + TRACE(("RR: found PN, length %u\n", length)); + break; + + // Symbolic link info + case 'SL': + { + uint8 bytePos = 3; + uint8 lastCompFlag = 0; + uint8 addPos = 0; + bool slDone = false; + bool useSeparator = true; + + TRACE(("RR: found SL, length %u\n", length)); + TRACE(("Buffer is at %p\n", buffer)); + TRACE(("Current length is %u\n", slNameSize)); + //kernel_debugger(""); + node->attr.slVer = *(uint8*)(buffer + bytePos++); + slFlags = *(uint8*)(buffer + bytePos++); + + TRACE(("sl flags are %u\n", slFlags)); + while (!slDone && bytePos < length) { + uint8 compFlag = *(uint8*)(buffer + bytePos++); + uint8 compLen = *(uint8*)(buffer + bytePos++); + + if (slName == NULL) + useSeparator = false; + + addPos = slNameSize; + + TRACE(("sl comp flags are %u, length is %u\n", compFlag, compLen)); + TRACE(("Current name size is %u\n", slNameSize)); + + switch (compFlag) { + case SLCP_CONTINUE: + useSeparator = false; + default: + // Add the component to the total path. + slNameSize += compLen; + if (useSeparator) + slNameSize++; + slName = (char*)realloc(slName, + slNameSize + 1); + if (slName == NULL) + return B_NO_MEMORY; + + if (useSeparator) { + TRACE(("Adding separator\n")); + slName[addPos++] = '/'; + } + + TRACE(("doing memcopy of %u bytes at offset %d\n", compLen, addPos)); + memcpy(slName + addPos, buffer + bytePos, + compLen); + + addPos += compLen; + useSeparator = true; + break; + + case SLCP_CURRENT: + TRACE(("InitNode - found link to current directory\n")); + slNameSize += 2; + slName = (char*)realloc(slName, + slNameSize + 1); + if (slName == NULL) + return B_NO_MEMORY; + + memcpy(slName + addPos, "./", 2); + useSeparator = false; + break; + + case SLCP_PARENT: + slNameSize += 3; + slName = (char*)realloc(slName, + slNameSize + 1); + if (slName == NULL) + return B_NO_MEMORY; + + memcpy(slName + addPos, "../", 3); + useSeparator = false; + break; + + case SLCP_ROOT: + TRACE(("InitNode - found link to root directory\n")); + slNameSize += 1; + slName = (char*)realloc(slName, + slNameSize + 1); + if (slName == NULL) + return B_NO_MEMORY; + memcpy(slName + addPos, "/", 1); + useSeparator = false; + break; + + case SLCP_VOLROOT: + slDone = true; + break; + + case SLCP_HOST: + slDone = true; + break; + } + slName[slNameSize] = '\0'; + lastCompFlag = compFlag; + bytePos += compLen; + TRACE(("Current sl name is \'%s\'\n", slName)); + } + node->attr.slName = slName; + TRACE(("InitNode = symlink name is \'%s\'\n", slName)); + break; + } + + // Altername name + case 'NM': + { + uint8 bytePos = 3; + uint8 flags = 0; + uint16 oldEnd = altNameSize; + + altNameSize += length - 5; + altName = (char*)realloc(altName, altNameSize + 1); + if (altName == NULL) + return B_NO_MEMORY; + + TRACE(("RR: found NM, length %u\n", length)); + // Read flag and version. + node->attr.nmVer = *(uint8 *)(buffer + bytePos++); + flags = *(uint8 *)(buffer + bytePos++); + + TRACE(("RR: nm buffer is %s, start at %p\n", (buffer + bytePos), buffer + bytePos)); + + // Build the file name. + memcpy(altName + oldEnd, buffer + bytePos, length - 5); + altName[altNameSize] = '\0'; + TRACE(("RR: alt name is %s\n", altName)); + + // If the name is not continued in another record, update + // the record name. + if (!(flags & NM_CONTINUE)) { + // Get rid of the ISO name, replace with RR name. + if (node->name != NULL) + free(node->name); + node->name = altName; + node->name_length = altNameSize; + } + break; + } + + // Deep directory record masquerading as a file. + case 'CL': + TRACE(("RR: found CL, length %u\n", length)); + node->flags |= ISO_ISDIR; + node->startLBN[LSB_DATA] = *(uint32*)(buffer+4); + node->startLBN[MSB_DATA] = *(uint32*)(buffer+8); + break; + + case 'PL': + TRACE(("RR: found PL, length %u\n", length)); + break; + + case 'RE': + // Relocated directory, we should skip. + TRACE(("RR: found RE, length %u\n", length)); + return B_BAD_VALUE; + + case 'TF': + TRACE(("RR: found TF, length %u\n", length)); + break; + + case 'RR': + TRACE(("RR: found RR, length %u\n", length)); + break; + + default: + TRACE(("RR: %x, %x, end of extensions.\n", + buffer[0], buffer[1])); + done = true; + break; + } + } + + return B_OK; +} + +// #pragma mark - ISO-9660 specific exported functions + + +status_t +ISOMount(const char *path, uint32 flags, iso9660_volume **_newVolume, + bool allowJoliet) +{ + // path: path to device (eg, /dev/disk/scsi/030/raw) + // partition: partition number on device ???? + // flags: currently unused + + // determine if it is an ISO volume. + char buffer[ISO_PVD_SIZE]; + bool done = false; + bool isISO = false; + off_t offset = 0x8000; + ssize_t retval; + partition_info partitionInfo; + int deviceBlockSize, multiplier; + iso9660_volume *volume; + + (void)flags; + + TRACE(("ISOMount - ENTER\n")); + + volume = (iso9660_volume *)calloc(sizeof(iso9660_volume), 1); + if (volume == NULL) { + TRACE(("ISOMount - mem error \n")); + return B_NO_MEMORY; + } + + memset(&partitionInfo, 0, sizeof(partition_info)); + + /* open and lock the device */ + volume->fdOfSession = open(path, O_RDONLY); + + /* try to open the raw device to get access to the other sessions as well */ + if (volume->fdOfSession >= 0) { + if (ioctl(volume->fdOfSession, B_GET_PARTITION_INFO, &partitionInfo) < 0) { + TRACE(("B_GET_PARTITION_INFO: ioctl returned error\n")); + strcpy(partitionInfo.device, path); + } + TRACE(("ISOMount: open device/file \"%s\"\n", partitionInfo.device)); + + volume->fd = open(partitionInfo.device, O_RDONLY); + } + + if (volume->fdOfSession < 0 || volume->fd < 0) { + close(volume->fd); + close(volume->fdOfSession); + + TRACE(("ISO9660 ERROR - Unable to open <%s>\n", path)); + free(volume); + return B_BAD_VALUE; + } + + deviceBlockSize = get_device_block_size(volume->fdOfSession); + if (deviceBlockSize < 0) { + TRACE(("ISO9660 ERROR - device block size is 0\n")); + close(volume->fd); + close(volume->fdOfSession); + + free(volume); + return B_BAD_VALUE; + } + + volume->joliet_level = 0; + while (!done && offset < 0x10000) { + retval = read_pos(volume->fdOfSession, offset, (void*)buffer, + ISO_PVD_SIZE); + if (retval < ISO_PVD_SIZE) { + isISO = false; + break; + } + + if (strncmp(buffer + 1, kISO9660IDString, 5) == 0) { + if (*buffer == 0x01 && !isISO) { + // ISO_VD_PRIMARY + off_t maxBlocks; + + TRACE(("ISOMount: Is an ISO9660 volume, initting rec\n")); + + InitVolDesc(volume, buffer); + strncpy(volume->devicePath,path,127); + volume->id = ISO_ROOTNODE_ID; + TRACE(("ISO9660: volume->blockSize = %d\n", volume->logicalBlkSize[FS_DATA_FORMAT])); + + multiplier = deviceBlockSize / volume->logicalBlkSize[FS_DATA_FORMAT]; + TRACE(("ISOMount: block size multiplier is %d\n", multiplier)); + + // if the session is on a real device, size != 0 + if (partitionInfo.size != 0) { + maxBlocks = (partitionInfo.size + partitionInfo.offset) + / volume->logicalBlkSize[FS_DATA_FORMAT]; + } else + maxBlocks = volume->volSpaceSize[FS_DATA_FORMAT]; + + /* Initialize access to the cache so that we can do cached i/o */ + TRACE(("ISO9660: cache init: dev %d, max blocks %Ld\n", volume->fd, maxBlocks)); + volume->fBlockCache = block_cache_create(volume->fd, maxBlocks, + volume->logicalBlkSize[FS_DATA_FORMAT], true); + isISO = true; + } else if (*buffer == 0x02 && isISO && allowJoliet) { + // ISO_VD_SUPPLEMENTARY + + // JOLIET extension + // test escape sequence for level of UCS-2 characterset + if (buffer[88] == 0x25 && buffer[89] == 0x2f) { + switch (buffer[90]) { + case 0x40: volume->joliet_level = 1; break; + case 0x43: volume->joliet_level = 2; break; + case 0x45: volume->joliet_level = 3; break; + } + + TRACE(("ISO9660 Extensions: Microsoft Joliet Level %d\n", volume->joliet_level)); + + // Because Joliet-stuff starts at other sector, + // update root directory record. + if (volume->joliet_level > 0) + InitNode(&volume->rootDirRec, &buffer[156], NULL, 0); + } + } else if (*(unsigned char *)buffer == 0xff) { + // ISO_VD_END + done = true; + } else + TRACE(("found header %d\n",*buffer)); + } + offset += 0x800; + } + + if (!isISO) { + // It isn't an ISO disk. + close(volume->fdOfSession); + close(volume->fd); + free(volume); + + TRACE(("ISOMount: Not an ISO9660 volume!\n")); + return B_BAD_VALUE; + } + + TRACE(("ISOMount - EXIT, returning %p\n", volume)); + *_newVolume = volume; + return B_OK; +} + + +/*! Reads in a single directory entry and fills in the values in the + dirent struct. Uses the cookie to keep track of the current block + and position within the block. Also uses the cookie to determine when + it has reached the end of the directory file. +*/ +status_t +ISOReadDirEnt(iso9660_volume *volume, dircookie *cookie, struct dirent *dirent, + size_t bufferSize) +{ + off_t totalRead = cookie->pos + (cookie->block - cookie->startBlock) + * volume->logicalBlkSize[FS_DATA_FORMAT]; + off_t cacheBlock; + char *blockData; + int result = B_NO_ERROR; + size_t bytesRead = 0; + + TRACE(("ISOReadDirEnt - ENTER\n")); + + // If we're at the end of the data in a block, move to the next block. + while (true) { + blockData = (char*)block_cache_get(volume->fBlockCache, cookie->block); + if (blockData != NULL && *(blockData + cookie->pos) == 0) { + // NULL data, move to next block. + block_cache_put(volume->fBlockCache, cookie->block); + blockData = NULL; + totalRead += volume->logicalBlkSize[FS_DATA_FORMAT] - cookie->pos; + cookie->pos = 0; + cookie->block++; + } else + break; + + if (totalRead >= cookie->totalSize) + break; + } + + cacheBlock = cookie->block; + if (blockData != NULL && totalRead < cookie->totalSize) { + iso9660_inode node; + result = InitNode(&node, blockData + cookie->pos, &bytesRead, + volume->joliet_level); + if (result == B_OK) { + size_t nameBufferSize = bufferSize - sizeof(struct dirent); + + dirent->d_dev = volume->id; + dirent->d_ino = ((ino_t)cookie->block << 30) + + (cookie->pos & 0x3fffffff); + dirent->d_reclen = sizeof(struct dirent) + node.name_length + 1; + + if (node.name_length <= nameBufferSize) { + // need to do some size checking here. + strlcpy(dirent->d_name, node.name, node.name_length + 1); + TRACE(("ISOReadDirEnt - success, name is %s, block %Ld, pos " + "%Ld, inode id %Ld\n", dirent->d_name, cookie->block, + cookie->pos, dirent->d_ino)); + } else { + // TODO: this can be just normal if we support reading more + // than one entry. + TRACE(("ISOReadDirEnt - ERROR, name %s does not fit in buffer " + "of size %lu\n", node.name, nameBufferSize)); + result = B_BAD_VALUE; + } + cookie->pos += bytesRead; + } + } else { + if (totalRead >= cookie->totalSize) + result = B_ENTRY_NOT_FOUND; + else + result = B_NO_MEMORY; + } + + if (blockData != NULL) + block_cache_put(volume->fBlockCache, cacheBlock); + + TRACE(("ISOReadDirEnt - EXIT, result is %s, vnid is %Lu\n", + strerror(result), dirent->d_ino)); + return result; +} + + +status_t +InitNode(iso9660_inode* node, char* buffer, size_t* _bytesRead, + uint8 jolietLevel) +{ + uint8 recordLength = *(uint8*)buffer++; + size_t nameLength; + + TRACE(("InitNode - ENTER, bufstart is %p, record length is %d bytes\n", + buffer, recordLength)); + + if (_bytesRead != NULL) + *_bytesRead = recordLength; + if (recordLength == 0) + return B_ENTRY_NOT_FOUND; + + char* end = buffer + recordLength; + + node->cache = NULL; + node->name = NULL; + node->attr.slName = NULL; + memset(node->attr.stat, 0, sizeof(node->attr.stat)); + + node->extAttrRecLen = *(uint8*)buffer++; + + node->startLBN[LSB_DATA] = *(uint32*)buffer; + buffer += 4; + node->startLBN[MSB_DATA] = *(uint32*)buffer; + buffer += 4; + TRACE(("InitNode - data start LBN is %ld\n", node->startLBN[FS_DATA_FORMAT])); + + node->dataLen[LSB_DATA] = *(uint32*)buffer; + buffer += 4; + node->dataLen[MSB_DATA] = *(uint32*)buffer; + buffer += 4; + TRACE(("InitNode - data length is %ld\n", node->dataLen[FS_DATA_FORMAT])); + + init_node_date(&node->recordDate, buffer); + buffer += 7; + + node->flags = *(uint8*)buffer; + buffer++; + TRACE(("InitNode - flags are %d\n", node->flags)); + + node->fileUnitSize = *(uint8*)buffer; + buffer++; + TRACE(("InitNode - fileUnitSize is %d\n", node->fileUnitSize)); + + node->interleaveGapSize = *(uint8*)buffer; + buffer++; + TRACE(("InitNode - interleave gap size = %d\n", node->interleaveGapSize)); + + node->volSeqNum = *(uint32*)buffer; + buffer += 4; + TRACE(("InitNode - volume seq num is %ld\n", node->volSeqNum)); + + node->name_length = *(uint8*)buffer; + buffer++; + TRACE(("InitNode - file id length is %lu\n", node->name_length)); + + // Set defaults, in case there is no RockRidge stuff. + node->attr.stat[FS_DATA_FORMAT].st_mode |= (node->flags & ISO_ISDIR) != 0 + ? S_IFDIR | S_IXUSR | S_IRUSR | S_IXGRP | S_IRGRP | S_IXOTH | S_IROTH + : S_IFREG | S_IRUSR | S_IRGRP | S_IROTH; + + if (node->name_length == 0) { + TRACE(("InitNode - File ID String is 0 length\n")); + return B_ENTRY_NOT_FOUND; + } + + nameLength = node->name_length; + + // JOLIET extension: + // on joliet discs, buffer[0] can be 0 for Unicoded filenames, + // so I've added a check here to test explicitely for + // directories (which have length 1) + if (node->name_length == 1) { + // Take care of "." and "..", the first two dirents are + // these in iso. + if (buffer[0] == 0) { + node->name = strdup("."); + node->name_length = 1; + } else if (buffer[0] == 1) { + node->name = strdup(".."); + node->name_length = 2; + } + } else { + if (jolietLevel > 0) { + // JOLIET extension: convert Unicode16 string to UTF8 + // Assume that the unicode->utf8 conversion produces 4 byte + // utf8 characters, and allocate that much space + node->name = (char*)malloc(node->name_length * 2 + 1); + if (node->name == NULL) + return B_NO_MEMORY; + + int32 sourceLength = node->name_length; + int32 destLength = node->name_length * 2; + + status_t status = unicode_to_utf8(buffer, &sourceLength, + node->name, &destLength); + if (status < B_OK) { + dprintf("iso9660: error converting unicode->utf8\n"); + return status; + } + + node->name[destLength] = '\0'; + node->name_length = destLength; + + sanitize_iso_name(node, false); + } else { + node->name = (char*)malloc(node->name_length + 1); + if (node->name == NULL) + return B_NO_MEMORY; + + // convert all characters to lower case + for (uint32 i = 0; i < node->name_length; i++) { + node->name[i] = tolower(buffer[i]); + } + node->name[node->name_length] = '\0'; + + sanitize_iso_name(node, true); + } + } + + if (node->name == NULL) { + TRACE(("InitNode - unable to allocate memory!\n")); + return B_NO_MEMORY; + } + + buffer += nameLength; + if (nameLength % 2 == 0) + buffer++; + + TRACE(("DirRec ID String is: %s\n", node->name)); + + return parse_rock_ridge(node, buffer, end); +} + + +status_t +ConvertRecDate(ISORecDate* inDate, time_t* outDate) +{ + time_t time; + int days, i, year, tz; + + year = inDate->year -70; + tz = inDate->offsetGMT; + + if (year < 0) { + time = 0; + } else { + const int monlen[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + + days = (year * 365); + + if (year > 2) + days += (year + 1)/ 4; + + for (i = 1; (i < inDate->month) && (i < 12); i++) { + days += monlen[i-1]; + } + + if (((year + 2) % 4) == 0 && inDate->month > 2) + days++; + + days += inDate->date - 1; + time = ((((days*24) + inDate->hour) * 60 + inDate->minute) * 60) + + inDate->second; + if (tz & 0x80) + tz |= (-1 << 8); + + if (-48 <= tz && tz <= 52) + time += tz *15 * 60; + } + *outDate = time; + return 0; +} + diff --git a/src/add-ons/kernel/file_systems/iso9660/iso9660.h b/src/add-ons/kernel/file_systems/iso9660/iso9660.h index 1aef617b83..0a7a56e8ad 100644 --- a/src/add-ons/kernel/file_systems/iso9660/iso9660.h +++ b/src/add-ons/kernel/file_systems/iso9660/iso9660.h @@ -22,7 +22,7 @@ // Size of primary volume descriptor for ISO9660 #define ISO_PVD_SIZE 882 -// ISO structure has both msb and lsb first data. These let you do a +// ISO structure has both msb and lsb first data. These let you do a // compile-time switch for different platforms. enum { @@ -62,34 +62,24 @@ typedef struct ISORecDate { int8 offsetGMT; } ISORecDate; -/* This next section is data structure to hold the data found in the rock ridge extensions. */ -typedef struct RRAttr { +// This next section is data structure to hold the data found in the +// rock ridge extensions. +struct rock_ridge_attributes { char* slName; struct stat stat[2]; uint8 nmVer; uint8 pxVer; uint8 slVer; -} RRAttr; +}; -/* For each item on the disk (directory, file, etc), your filesystem should allocate a vnode struct and - pass it back to the kernel when fs_read_vnode is called. This struct is then passed back in to - your file system by functions that reference an item on the disk. You'll need to be able to - create a vnode from a vnode id, either by hashing the id number or encoding the information needed - to create the vnode in the vnode id itself. Vnode ids are assigned by your file system when the - filesystem walk function is called. For this driver, the block number is encoded in the upper bits - of the vnode id, and the offset within the block in the lower, allowing me to just read the info - to fill in the vnode struct from the disk. When the kernel is done with a vnode, it will call - fs_write_vnode (somewhat of a misnomer) where you should deallocate the struct. -*/ - -typedef struct vnode { +struct iso9660_inode { /* Most drivers will probably want the first things defined here. */ - ino_t id; + ino_t id; ino_t parID; // parent vnode ID. void *cache; // for file cache - + // End of members other drivers will definitely want. - + /* The rest of this struct is very ISO-specific. You should replace the rest of this definition with the stuff your file system needs. */ @@ -97,7 +87,7 @@ typedef struct vnode { uint32 startLBN[2]; // Logical block # of start of file/directory data uint32 dataLen[2]; // Length of file section in bytes ISORecDate recordDate; // Date file was recorded. - + // BIT MEANING // --- ----------------------------- uint8 flags; // 0 - is hidden @@ -109,25 +99,25 @@ typedef struct vnode { // 5 - Reserved // 6 - Reserved // 7 - File has more that one directory record - + uint8 fileUnitSize; // Interleave only uint8 interleaveGapSize; // Interleave only uint32 volSeqNum; // Volume sequence number of volume - uint8 fileIDLen; // Length of volume "ID" (name) - char* fileIDString; // Volume "ID" (name) + char* name; + uint32 name_length; // The rest is Rock Ridge extensions. I suggest www.leo.org for spec info. - RRAttr attr; -} vnode; + rock_ridge_attributes attr; +}; -// These go with the flags member of the nspace struct. +// These go with the flags member of the iso9660_volume struct. enum { - ISO_ISHIDDEN = 0, + ISO_ISHIDDEN = 0, ISO_ISDIR = 2, - ISO_ISASSOCFILE = 4, - ISO_EXTATTR = 8, - ISO_EXTPERM = 16, - ISO_MOREDIRS = 128 + ISO_ISASSOCFILE = 4, + ISO_EXTATTR = 8, + ISO_EXTPERM = 16, + ISO_MOREDIRS = 128 }; @@ -137,7 +127,7 @@ enum { /* Structure used for directory "cookie". When you are asked to open a directory, you are asked to create a cookie for it and pass it back. The cookie should contain the information you - need to determine where you are at in reading the directory + need to determine where you are at in reading the directory entries, incremented every time readdir is called, until finally the end is reached, when readdir returns NULL. */ typedef struct dircookie { @@ -147,8 +137,8 @@ typedef struct dircookie { off_t totalSize; // Size of directory file off_t id; } dircookie; - -/* You may also need to define a cookie for files, which again is + +/* You may also need to define a cookie for files, which again is allocated every time a file is opened and freed when the free cookie function is called. For ISO, we didn't need one. */ @@ -158,12 +148,8 @@ typedef struct attrfilemap { off_t offset; } attrfilemap; -/* This is the global volume nspace struct. When mount is called , this struct should - be allocated. It is passed back into the functions so that you can get at any - global information you need. You'll need to change this struct to suit your purposes. -*/ - -typedef struct nspace { +// This is the global volume iso9660_volume struct. +struct iso9660_volume { // Start of members other drivers will definitely want. fs_volume *volume; // volume passed fo fs_mount dev_t id; @@ -171,10 +157,10 @@ typedef struct nspace { int fdOfSession; // File descriptor of the (mounted) session //unsigned int blockSize; // usually need this, but it's part of ISO void *fBlockCache; - + char devicePath[127]; //off_t numBlocks; // May need this, but it's part of ISO - + // End of members other drivers will definitely want. // attribute extensions @@ -204,7 +190,7 @@ typedef struct nspace { uint16 optLPathTblLoc[2]; // Loc (Logical block #) of optional Type L path tbl byte145-148 uint16 mPathTblLoc[2]; // Loc (Logical block #) of "Type M" path table byte149-152 uint16 optMPathTblLoc[2]; // Loc (Logical block #) of optional Type M path tbl byte153-156 - vnode rootDirRec; // Directory record for root directory byte157-190 + iso9660_inode rootDirRec; // Directory record for root directory byte157-190 char volSetIDString[29]; // Name of multi-volume set where vol is member byte191-318 char pubIDString[129]; // Name of publisher byte319-446 char dataPreparer[129]; // Name of data preparer byte447-574 @@ -217,23 +203,17 @@ typedef struct nspace { ISOVolDate modDate; // Modification date ISOVolDate expireDate; // Data expiration date ISOVolDate effectiveDate; // Data effective data - + uint8 fileStructVers; // File structure version byte882 -} nspace; +}; -#ifdef __cplusplus -extern "C" { -#endif -int ISOMount(const char *path, const int flags, nspace** newVolume, +status_t ISOMount(const char *path, uint32 flags, iso9660_volume** _newVolume, bool allowJoliet); -int ISOReadDirEnt(nspace* ns, dircookie* cookie, struct dirent* buffer, - size_t bufferSize); -int InitNode(vnode* rec, char* buf, int* bytesRead, uint8 jolietLevel); -int ConvertRecDate(ISORecDate* inDate, time_t* outDate); - -#ifdef __cplusplus -} -#endif +status_t ISOReadDirEnt(iso9660_volume* ns, dircookie* cookie, + struct dirent* buffer, size_t bufferSize); +status_t InitNode(iso9660_inode* rec, char* buf, size_t* bytesRead, + uint8 jolietLevel); +status_t ConvertRecDate(ISORecDate* inDate, time_t* outDate); #endif /* ISO_9660_H */ diff --git a/src/add-ons/kernel/file_systems/iso9660/kernel_interface.cpp b/src/add-ons/kernel/file_systems/iso9660/kernel_interface.cpp index 23c4868914..8b2bd3af51 100644 --- a/src/add-ons/kernel/file_systems/iso9660/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/iso9660/kernel_interface.cpp @@ -104,7 +104,7 @@ fs_mount(fs_volume *_volume, const char *device, uint32 flags, const char *args, ino_t *_rootID) { bool allowJoliet = true; - nspace *volume; + iso9660_volume *volume; // Check for a 'nojoliet' parm // all we check for is the existance of 'nojoliet' in the parms. @@ -152,7 +152,7 @@ static status_t fs_unmount(fs_volume *_vol) { status_t result = B_NO_ERROR; - nspace *ns = (nspace *)_vol->private_volume; + iso9660_volume *ns = (iso9660_volume *)_vol->private_volume; TRACE(("fs_unmount - ENTER\n")); @@ -173,7 +173,7 @@ fs_unmount(fs_volume *_vol) static status_t fs_read_fs_stat(fs_volume *_vol, struct fs_info *fss) { - nspace *ns = (nspace *)_vol->private_volume; + iso9660_volume *ns = (iso9660_volume *)_vol->private_volume; int i; fss->flags = B_FS_IS_PERSISTENT | B_FS_IS_READONLY; @@ -203,9 +203,9 @@ fs_read_fs_stat(fs_volume *_vol, struct fs_info *fss) static status_t fs_get_vnode_name(fs_volume *_vol, fs_vnode *_node, char *buffer, size_t bufferSize) { - vnode *node = (vnode*)_node->private_node; + iso9660_inode *node = (iso9660_inode*)_node->private_node; - strlcpy(buffer, node->fileIDString, bufferSize); + strlcpy(buffer, node->name, bufferSize); return B_OK; } @@ -213,11 +213,11 @@ fs_get_vnode_name(fs_volume *_vol, fs_vnode *_node, char *buffer, size_t bufferS static status_t fs_walk(fs_volume *_vol, fs_vnode *_base, const char *file, ino_t *_vnodeID) { - nspace *ns = (nspace *)_vol->private_volume; - vnode *baseNode = (vnode*)_base->private_node; - vnode *newNode = NULL; + iso9660_volume *ns = (iso9660_volume *)_vol->private_volume; + iso9660_inode *baseNode = (iso9660_inode*)_base->private_node; + iso9660_inode *newNode = NULL; - TRACE(("fs_walk - looking for %s in dir file of length %d\n", file, + TRACE(("fs_walk - looking for %s in dir file of length %ld\n", file, baseNode->dataLen[FS_DATA_FORMAT])); if (strcmp(file, ".") == 0) { @@ -235,39 +235,37 @@ fs_walk(fs_volume *_vol, fs_vnode *_base, const char *file, ino_t *_vnodeID) // look up file in the directory uint32 dataLength = baseNode->dataLen[FS_DATA_FORMAT]; status_t result = ENOENT; - uint32 totalRead = 0; + size_t totalRead = 0; off_t block = baseNode->startLBN[FS_DATA_FORMAT]; bool done = false; while (totalRead < dataLength && !done) { off_t cachedBlock = block; - char *blockData = (char *)block_cache_get_etc(ns->fBlockCache, block, 0, - ns->logicalBlkSize[FS_DATA_FORMAT]); + char* blockData = (char*)block_cache_get(ns->fBlockCache, block); if (blockData != NULL) { - int bytesRead = 0; + size_t bytesRead = 0; off_t blockBytesRead = 0; - vnode node; + iso9660_inode node; int initResult; - TRACE(("fs_walk - read buffer from disk at LBN %Ld into buffer 0x%x.\n", - block, blockData)); + TRACE(("fs_walk - read buffer from disk at LBN %Ld into buffer " + "%p.\n", block, blockData)); // Move to the next 2-block set if necessary // Don't go over end of buffer, if dir record sits on boundary. - node.fileIDString = NULL; - node.attr.slName = NULL; - while (blockBytesRead < 2 * ns->logicalBlkSize[FS_DATA_FORMAT] && totalRead + blockBytesRead < dataLength && blockData[0] != 0 && !done) { initResult = InitNode(&node, blockData, &bytesRead, ns->joliet_level); - TRACE(("fs_walk - InitNode returned %s, filename %s, %d bytes read\n", strerror(initResult), node.fileIDString, bytesRead)); + TRACE(("fs_walk - InitNode returned %s, filename %s, %lu bytes " + "read\n", strerror(initResult), node.name, + bytesRead)); if (initResult == B_OK) { - if (!strcmp(node.fileIDString, file)) { + if (!strcmp(node.name, file)) { TRACE(("fs_walk - success, found vnode at block %Ld, pos %Ld\n", block, blockBytesRead)); *_vnodeID = (block << 30) + (blockBytesRead & 0xffffffff); @@ -280,10 +278,8 @@ fs_walk(fs_volume *_vol, fs_vnode *_base, const char *file, ino_t *_vnodeID) done = true; } } else { - free(node.fileIDString); - node.fileIDString = NULL; + free(node.name); free(node.attr.slName); - node.attr.slName = NULL; } } else { result = initResult; @@ -293,13 +289,15 @@ fs_walk(fs_volume *_vol, fs_vnode *_base, const char *file, ino_t *_vnodeID) blockData += bytesRead; blockBytesRead += bytesRead; - TRACE(("fs_walk - Adding %d bytes to blockBytes read (total %Ld/%Ld).\n", - bytesRead, blockBytesRead, baseNode->dataLen[FS_DATA_FORMAT])); + TRACE(("fs_walk - Adding %lu bytes to blockBytes read (total " + "%Ld/%lu).\n", bytesRead, blockBytesRead, + baseNode->dataLen[FS_DATA_FORMAT])); } totalRead += ns->logicalBlkSize[FS_DATA_FORMAT]; block++; - TRACE(("fs_walk - moving to next block %Ld, total read %Ld\n", block, totalRead)); + TRACE(("fs_walk - moving to next block %Ld, total read %lu\n", + block, totalRead)); block_cache_put(ns->fBlockCache, cachedBlock); } else @@ -316,16 +314,16 @@ static status_t fs_read_vnode(fs_volume *_vol, ino_t vnodeID, fs_vnode *_node, int *_type, uint32 *_flags, bool reenter) { - nspace *ns = (nspace*)_vol->private_volume; + iso9660_volume *ns = (iso9660_volume*)_vol->private_volume; - vnode *newNode = (vnode*)calloc(sizeof(vnode), 1); + iso9660_inode *newNode = (iso9660_inode*)calloc(sizeof(iso9660_inode), 1); if (newNode == NULL) return B_NO_MEMORY; uint32 pos = vnodeID & 0x3fffffff; uint32 block = vnodeID >> 30; - TRACE(("fs_read_vnode - block = %ld, pos = %ld, raw = %Lu node 0x%x\n", + TRACE(("fs_read_vnode - block = %ld, pos = %ld, raw = %Lu node %p\n", block, pos, vnodeID, newNode)); if (pos > ns->logicalBlkSize[FS_DATA_FORMAT]) { @@ -333,8 +331,7 @@ fs_read_vnode(fs_volume *_vol, ino_t vnodeID, fs_vnode *_node, return B_BAD_VALUE; } - char *data = (char *)block_cache_get_etc(ns->fBlockCache, - block, 0, ns->logicalBlkSize[FS_DATA_FORMAT]); + char *data = (char *)block_cache_get(ns->fBlockCache, block); if (data == NULL) { free(newNode); return B_IO_ERROR; @@ -364,31 +361,24 @@ fs_read_vnode(fs_volume *_vol, ino_t vnodeID, fs_vnode *_node, static status_t -fs_release_vnode(fs_volume *_vol, fs_vnode *_node, bool reenter) +fs_release_vnode(fs_volume* /*_volume*/, fs_vnode* _node, bool /*reenter*/) { - status_t result = B_NO_ERROR; - vnode *node = (vnode*)_node->private_node; + iso9660_inode* node = (iso9660_inode*)_node->private_node; - (void)_vol; - (void)reenter; + TRACE(("fs_release_vnode - ENTER (%p)\n", node)); - TRACE(("fs_release_vnode - ENTER (0x%x)\n", node)); + if (node->id != ISO_ROOTNODE_ID) { + free(node->name); + free(node->attr.slName); - if (node != NULL) { - if (node->id != ISO_ROOTNODE_ID) { - if (node->fileIDString != NULL) - free (node->fileIDString); - if (node->attr.slName != NULL) - free (node->attr.slName); - if (node->cache != NULL) - file_cache_delete(node->cache); + if (node->cache != NULL) + file_cache_delete(node->cache); - free(node); - } + free(node); } TRACE(("fs_release_vnode - EXIT\n")); - return result; + return B_OK; } @@ -396,8 +386,8 @@ static status_t fs_read_pages(fs_volume *_vol, fs_vnode *_node, void * _cookie, off_t pos, const iovec *vecs, size_t count, size_t *_numBytes) { - nspace *ns = (nspace *)_vol->private_volume; - vnode *node = (vnode *)_node->private_node; + iso9660_volume *ns = (iso9660_volume *)_vol->private_volume; + iso9660_inode *node = (iso9660_inode *)_node->private_node; uint32 fileSize = node->dataLen[FS_DATA_FORMAT]; size_t bytesLeft = *_numBytes; @@ -426,8 +416,8 @@ fs_read_pages(fs_volume *_vol, fs_vnode *_node, void * _cookie, off_t pos, static status_t fs_read_stat(fs_volume *_vol, fs_vnode *_node, struct stat *st) { - nspace *ns = (nspace*)_vol->private_volume; - vnode *node = (vnode*)_node->private_node; + iso9660_volume *ns = (iso9660_volume*)_vol->private_volume; + iso9660_inode *node = (iso9660_inode*)_node->private_node; status_t result = B_NO_ERROR; time_t time; @@ -474,7 +464,7 @@ static status_t fs_read(fs_volume *_vol, fs_vnode *_node, void *cookie, off_t pos, void *buffer, size_t *_length) { - vnode *node = (vnode *)_node->private_node; + iso9660_inode *node = (iso9660_inode *)_node->private_node; if (node->flags & ISO_ISDIR) return EISDIR; @@ -529,7 +519,7 @@ fs_access(fs_volume *_vol, fs_vnode *_node, int mode) static status_t fs_read_link(fs_volume *_vol, fs_vnode *_node, char *buffer, size_t *_bufferSize) { - vnode *node = (vnode *)_node->private_node; + iso9660_inode *node = (iso9660_inode *)_node->private_node; if (!S_ISLNK(node->attr.stat[FS_DATA_FORMAT].st_mode)) return B_BAD_VALUE; @@ -547,16 +537,16 @@ fs_read_link(fs_volume *_vol, fs_vnode *_node, char *buffer, size_t *_bufferSize static status_t -fs_open_dir(fs_volume *_vol, fs_vnode *_node, void **cookie) +fs_open_dir(fs_volume* /*_volume*/, fs_vnode* _node, void** _cookie) { - vnode *node = (vnode *)_node->private_node; + iso9660_inode *node = (iso9660_inode *)_node->private_node; - TRACE(("fs_open_dir - node is 0x%x\n", _node)); + TRACE(("fs_open_dir - node is %p\n", node)); if (!(node->flags & ISO_ISDIR)) return B_NOT_A_DIRECTORY; - dircookie *dirCookie = (dircookie *)malloc(sizeof(dircookie)); + dircookie* dirCookie = (dircookie*)malloc(sizeof(dircookie)); if (dirCookie == NULL) return B_NO_MEMORY; @@ -565,7 +555,7 @@ fs_open_dir(fs_volume *_vol, fs_vnode *_node, void **cookie) dirCookie->totalSize = node->dataLen[FS_DATA_FORMAT]; dirCookie->pos = 0; dirCookie->id = node->id; - *cookie = (void *)dirCookie; + *_cookie = (void*)dirCookie; return B_OK; } @@ -575,7 +565,7 @@ static status_t fs_read_dir(fs_volume *_vol, fs_vnode *_node, void *_cookie, struct dirent *buffer, size_t bufferSize, uint32 *num) { - nspace *ns = (nspace *)_vol->private_volume; + iso9660_volume *ns = (iso9660_volume *)_vol->private_volume; dircookie *dirCookie = (dircookie *)_cookie; TRACE(("fs_read_dir - ENTER\n")); @@ -591,7 +581,7 @@ fs_read_dir(fs_volume *_vol, fs_vnode *_node, void *_cookie, // When you get to the end, don't return an error, just return // a zero in *num. - if (result == ENOENT) + if (result == B_ENTRY_NOT_FOUND) result = B_OK; TRACE(("fs_read_dir - EXIT, result is %s\n", strerror(result)));