Add actual support for relocated directories. In case we hit a placeholder file
pointing to a relocated directory, we now re-initialize the node we are initializing with the first entry of the pointed at directory. This ought to be the "." entry containing the proper flags, start block number and data length. As per the specs we do only keep the file id or alternate name of the placeholder and take everything else from the relocated directory. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30886 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -227,7 +227,8 @@ InitVolDesc(iso9660_volume *volume, char *buffer)
|
|||||||
buffer += 2;
|
buffer += 2;
|
||||||
|
|
||||||
// Fill in directory record.
|
// Fill in directory record.
|
||||||
InitNode(&volume->rootDirRec, buffer, NULL, 0);
|
volume->joliet_level = 0;
|
||||||
|
InitNode(volume, &volume->rootDirRec, buffer, NULL);
|
||||||
|
|
||||||
volume->rootDirRec.id = ISO_ROOTNODE_ID;
|
volume->rootDirRec.id = ISO_ROOTNODE_ID;
|
||||||
buffer += 34;
|
buffer += 34;
|
||||||
@@ -283,7 +284,8 @@ InitVolDesc(iso9660_volume *volume, char *buffer)
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
parse_rock_ridge(iso9660_inode* node, char* buffer, char* end)
|
parse_rock_ridge(iso9660_volume* volume, iso9660_inode* node, char* buffer,
|
||||||
|
char* end, bool relocated)
|
||||||
{
|
{
|
||||||
// Now we're at the start of the rock ridge stuff
|
// Now we're at the start of the rock ridge stuff
|
||||||
char* altName = NULL;
|
char* altName = NULL;
|
||||||
@@ -497,11 +499,23 @@ parse_rock_ridge(iso9660_inode* node, char* buffer, char* end)
|
|||||||
|
|
||||||
// Deep directory record masquerading as a file.
|
// Deep directory record masquerading as a file.
|
||||||
case 'CL':
|
case 'CL':
|
||||||
|
{
|
||||||
TRACE(("RR: found CL, length %u\n", length));
|
TRACE(("RR: found CL, length %u\n", length));
|
||||||
node->flags |= ISO_IS_DIR;
|
// Reinitialize the node with the information at the
|
||||||
|
// "." entry of the pointed to directory data
|
||||||
node->startLBN[LSB_DATA] = *(uint32*)(buffer+4);
|
node->startLBN[LSB_DATA] = *(uint32*)(buffer+4);
|
||||||
node->startLBN[MSB_DATA] = *(uint32*)(buffer+8);
|
node->startLBN[MSB_DATA] = *(uint32*)(buffer+8);
|
||||||
|
|
||||||
|
char* buffer = (char*)block_cache_get(volume->fBlockCache,
|
||||||
|
node->startLBN[FS_DATA_FORMAT]);
|
||||||
|
if (buffer == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
InitNode(volume, node, buffer, NULL, true);
|
||||||
|
block_cache_put(volume->fBlockCache,
|
||||||
|
node->startLBN[FS_DATA_FORMAT]);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case 'PL':
|
case 'PL':
|
||||||
TRACE(("RR: found PL, length %u\n", length));
|
TRACE(("RR: found PL, length %u\n", length));
|
||||||
@@ -510,8 +524,9 @@ parse_rock_ridge(iso9660_inode* node, char* buffer, char* end)
|
|||||||
case 'RE':
|
case 'RE':
|
||||||
// Relocated directory, we should skip.
|
// Relocated directory, we should skip.
|
||||||
TRACE(("RR: found RE, length %u\n", length));
|
TRACE(("RR: found RE, length %u\n", length));
|
||||||
// TODO: support relocated directories
|
if (!relocated)
|
||||||
return B_NOT_SUPPORTED;
|
return B_NOT_SUPPORTED;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'TF':
|
case 'TF':
|
||||||
TRACE(("RR: found TF, length %u\n", length));
|
TRACE(("RR: found TF, length %u\n", length));
|
||||||
@@ -657,8 +672,10 @@ ISOMount(const char *path, uint32 flags, iso9660_volume **_newVolume,
|
|||||||
|
|
||||||
// Because Joliet-stuff starts at other sector,
|
// Because Joliet-stuff starts at other sector,
|
||||||
// update root directory record.
|
// update root directory record.
|
||||||
if (volume->joliet_level > 0)
|
if (volume->joliet_level > 0) {
|
||||||
InitNode(&volume->rootDirRec, &buffer[156], NULL, 0);
|
InitNode(volume, &volume->rootDirRec, &buffer[156],
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (*(unsigned char *)buffer == 0xff) {
|
} else if (*(unsigned char *)buffer == 0xff) {
|
||||||
// ISO_VD_END
|
// ISO_VD_END
|
||||||
@@ -728,8 +745,8 @@ ISOReadDirEnt(iso9660_volume *volume, dircookie *cookie, struct dirent *dirent,
|
|||||||
if (blockData != NULL && totalRead < cookie->totalSize) {
|
if (blockData != NULL && totalRead < cookie->totalSize) {
|
||||||
iso9660_inode node;
|
iso9660_inode node;
|
||||||
size_t bytesRead = 0;
|
size_t bytesRead = 0;
|
||||||
result = InitNode(&node, blockData + cookie->pos, &bytesRead,
|
result = InitNode(volume, &node, blockData + cookie->pos,
|
||||||
volume->joliet_level);
|
&bytesRead);
|
||||||
|
|
||||||
// if we hit an entry that we don't support, we just skip it
|
// if we hit an entry that we don't support, we just skip it
|
||||||
if (result != B_OK && result != B_NOT_SUPPORTED)
|
if (result != B_OK && result != B_NOT_SUPPORTED)
|
||||||
@@ -786,8 +803,8 @@ ISOReadDirEnt(iso9660_volume *volume, dircookie *cookie, struct dirent *dirent,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
InitNode(iso9660_inode* node, char* buffer, size_t* _bytesRead,
|
InitNode(iso9660_volume* volume, iso9660_inode* node, char* buffer,
|
||||||
uint8 jolietLevel)
|
size_t* _bytesRead, bool relocated)
|
||||||
{
|
{
|
||||||
uint8 recordLength = *(uint8*)buffer++;
|
uint8 recordLength = *(uint8*)buffer++;
|
||||||
size_t nameLength;
|
size_t nameLength;
|
||||||
@@ -802,10 +819,13 @@ InitNode(iso9660_inode* node, char* buffer, size_t* _bytesRead,
|
|||||||
|
|
||||||
char* end = buffer + recordLength;
|
char* end = buffer + recordLength;
|
||||||
|
|
||||||
node->cache = NULL;
|
if (!relocated) {
|
||||||
node->name = NULL;
|
node->cache = NULL;
|
||||||
node->attr.slName = NULL;
|
node->name = NULL;
|
||||||
memset(node->attr.stat, 0, sizeof(node->attr.stat));
|
node->attr.slName = NULL;
|
||||||
|
memset(node->attr.stat, 0, sizeof(node->attr.stat));
|
||||||
|
} else
|
||||||
|
free(node->attr.slName);
|
||||||
|
|
||||||
node->extAttrRecLen = *(uint8*)buffer++;
|
node->extAttrRecLen = *(uint8*)buffer++;
|
||||||
TRACE(("InitNode - ext attr length is %d\n", (int)node->extAttrRecLen));
|
TRACE(("InitNode - ext attr length is %d\n", (int)node->extAttrRecLen));
|
||||||
@@ -843,9 +863,14 @@ InitNode(iso9660_inode* node, char* buffer, size_t* _bytesRead,
|
|||||||
buffer += 4;
|
buffer += 4;
|
||||||
TRACE(("InitNode - volume seq num is %d\n", (int)node->volSeqNum));
|
TRACE(("InitNode - volume seq num is %d\n", (int)node->volSeqNum));
|
||||||
|
|
||||||
node->name_length = *(uint8*)buffer;
|
nameLength = *(uint8*)buffer;
|
||||||
buffer++;
|
buffer++;
|
||||||
TRACE(("InitNode - file id length is %u\n", node->name_length));
|
|
||||||
|
// for relocated directories we take the name from the placeholder entry
|
||||||
|
if (!relocated) {
|
||||||
|
node->name_length = nameLength;
|
||||||
|
TRACE(("InitNode - file id length is %u\n", node->name_length));
|
||||||
|
}
|
||||||
|
|
||||||
// Set defaults, in case there is no RockRidge stuff.
|
// Set defaults, in case there is no RockRidge stuff.
|
||||||
node->attr.stat[FS_DATA_FORMAT].st_mode |= (node->flags & ISO_IS_DIR) != 0
|
node->attr.stat[FS_DATA_FORMAT].st_mode |= (node->flags & ISO_IS_DIR) != 0
|
||||||
@@ -857,59 +882,59 @@ InitNode(iso9660_inode* node, char* buffer, size_t* _bytesRead,
|
|||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
nameLength = node->name_length;
|
if (!relocated) {
|
||||||
|
// 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)
|
||||||
|
// Take care of "." and "..", the first two dirents are
|
||||||
|
// these in iso.
|
||||||
|
if (node->name_length == 1 && buffer[0] == 0) {
|
||||||
|
node->name = strdup(".");
|
||||||
|
node->name_length = 1;
|
||||||
|
} else if (node->name_length == 1 && buffer[0] == 1) {
|
||||||
|
node->name = strdup("..");
|
||||||
|
node->name_length = 2;
|
||||||
|
} else if (volume->joliet_level > 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;
|
||||||
|
|
||||||
// JOLIET extension:
|
int32 sourceLength = node->name_length;
|
||||||
// on joliet discs, buffer[0] can be 0 for Unicoded filenames,
|
int32 destLength = node->name_length * 2;
|
||||||
// so I've added a check here to test explicitely for
|
|
||||||
// directories (which have length 1)
|
|
||||||
// Take care of "." and "..", the first two dirents are
|
|
||||||
// these in iso.
|
|
||||||
if (node->name_length == 1 && buffer[0] == 0) {
|
|
||||||
node->name = strdup(".");
|
|
||||||
node->name_length = 1;
|
|
||||||
} else if (node->name_length == 1 && 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;
|
status_t status = unicode_to_utf8(buffer, &sourceLength,
|
||||||
int32 destLength = node->name_length * 2;
|
node->name, &destLength);
|
||||||
|
if (status < B_OK) {
|
||||||
|
dprintf("iso9660: error converting unicode->utf8\n");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
status_t status = unicode_to_utf8(buffer, &sourceLength,
|
node->name[destLength] = '\0';
|
||||||
node->name, &destLength);
|
node->name_length = destLength;
|
||||||
if (status < B_OK) {
|
|
||||||
dprintf("iso9660: error converting unicode->utf8\n");
|
sanitize_iso_name(node, false);
|
||||||
return status;
|
} 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
node->name[destLength] = '\0';
|
if (node->name == NULL) {
|
||||||
node->name_length = destLength;
|
TRACE(("InitNode - unable to allocate memory!\n"));
|
||||||
|
|
||||||
sanitize_iso_name(node, false);
|
|
||||||
} else {
|
|
||||||
node->name = (char*)malloc(node->name_length + 1);
|
|
||||||
if (node->name == NULL)
|
|
||||||
return B_NO_MEMORY;
|
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;
|
buffer += nameLength;
|
||||||
@@ -918,7 +943,7 @@ InitNode(iso9660_inode* node, char* buffer, size_t* _bytesRead,
|
|||||||
|
|
||||||
TRACE(("DirRec ID String is: %s\n", node->name));
|
TRACE(("DirRec ID String is: %s\n", node->name));
|
||||||
|
|
||||||
return parse_rock_ridge(node, buffer, end);
|
return parse_rock_ridge(volume, node, buffer, end, relocated);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -216,8 +216,8 @@ status_t ISOMount(const char *path, uint32 flags, iso9660_volume** _newVolume,
|
|||||||
bool allowJoliet);
|
bool allowJoliet);
|
||||||
status_t ISOReadDirEnt(iso9660_volume* ns, dircookie* cookie,
|
status_t ISOReadDirEnt(iso9660_volume* ns, dircookie* cookie,
|
||||||
struct dirent* buffer, size_t bufferSize);
|
struct dirent* buffer, size_t bufferSize);
|
||||||
status_t InitNode(iso9660_inode* rec, char* buf, size_t* bytesRead,
|
status_t InitNode(iso9660_volume* volume, iso9660_inode* rec, char* buf,
|
||||||
uint8 jolietLevel);
|
size_t* bytesRead, bool relocated = false);
|
||||||
status_t ConvertRecDate(ISORecDate* inDate, time_t* outDate);
|
status_t ConvertRecDate(ISORecDate* inDate, time_t* outDate);
|
||||||
|
|
||||||
#endif /* ISO_9660_H */
|
#endif /* ISO_9660_H */
|
||||||
|
|||||||
@@ -264,8 +264,7 @@ fs_walk(fs_volume *_vol, fs_vnode *_base, const char *file, ino_t *_vnodeID)
|
|||||||
&& totalRead + blockBytesRead < dataLength
|
&& totalRead + blockBytesRead < dataLength
|
||||||
&& blockData[0] != 0
|
&& blockData[0] != 0
|
||||||
&& !done) {
|
&& !done) {
|
||||||
initResult = InitNode(&node, blockData, &bytesRead,
|
initResult = InitNode(ns, &node, blockData, &bytesRead);
|
||||||
ns->joliet_level);
|
|
||||||
TRACE(("fs_walk - InitNode returned %s, filename %s, %u bytes "
|
TRACE(("fs_walk - InitNode returned %s, filename %s, %u bytes "
|
||||||
"read\n", strerror(initResult), node.name, (unsigned)bytesRead));
|
"read\n", strerror(initResult), node.name, (unsigned)bytesRead));
|
||||||
|
|
||||||
@@ -341,7 +340,7 @@ fs_read_vnode(fs_volume *_vol, ino_t vnodeID, fs_vnode *_node,
|
|||||||
return B_IO_ERROR;
|
return B_IO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t result = InitNode(newNode, data + pos, NULL, ns->joliet_level);
|
status_t result = InitNode(ns, newNode, data + pos, NULL);
|
||||||
block_cache_put(ns->fBlockCache, block);
|
block_cache_put(ns->fBlockCache, block);
|
||||||
|
|
||||||
if (result < B_OK) {
|
if (result < B_OK) {
|
||||||
|
|||||||
Reference in New Issue
Block a user