file_systems & Tracker: Do not assume sizeof(dirent) contains 1 byte for the name.
At present, it does, but that is an oddity we have preserved from BeOS that the next commit is going to remove. (This commit thus wastes 1 byte without the following one.) Most changes are pretty straightforward: only a +1 is needed, and a few removed from sizing calculations. Some filesystems like UDF originally passed back the length with the \0 included, so they have been adjusted further. UFS2 had some other sizing problems which are also corrected in this commit.
This commit is contained in:
@@ -966,7 +966,7 @@ Equation<QueryPolicy>::GetNextMatching(Context* context,
|
||||
dirent->d_ino = QueryPolicy::EntryGetNodeID(entry);
|
||||
dirent->d_pdev = dirent->d_dev;
|
||||
dirent->d_pino = QueryPolicy::EntryGetParentID(entry);
|
||||
dirent->d_reclen = sizeof(struct dirent) + strlen(dirent->d_name);
|
||||
dirent->d_reclen = sizeof(struct dirent) + strlen(dirent->d_name) + 1;
|
||||
}
|
||||
|
||||
if (status == MATCH_OK)
|
||||
|
||||
@@ -673,7 +673,7 @@ Equation::GetNextMatching(Volume* volume, TreeIterator* iterator,
|
||||
FATAL(("inode %" B_PRIdOFF " in query has no name!\n",
|
||||
inode->BlockNumber()));
|
||||
} else {
|
||||
dirent->d_reclen += strlen(dirent->d_name);
|
||||
dirent->d_reclen += strlen(dirent->d_name) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1737,7 +1737,7 @@ bfs_read_dir(fs_volume* _volume, fs_vnode* _node, void* _cookie,
|
||||
while (count < maxCount && bufferSize > sizeof(struct dirent)) {
|
||||
ino_t id;
|
||||
uint16 length;
|
||||
size_t nameBufferSize = bufferSize - sizeof(struct dirent) + 1;
|
||||
size_t nameBufferSize = bufferSize - sizeof(struct dirent);
|
||||
|
||||
status_t status = iterator->GetNextEntry(dirent->d_name, &length,
|
||||
nameBufferSize, &id);
|
||||
@@ -1759,7 +1759,7 @@ bfs_read_dir(fs_volume* _volume, fs_vnode* _node, void* _cookie,
|
||||
|
||||
dirent->d_dev = volume->ID();
|
||||
dirent->d_ino = id;
|
||||
dirent->d_reclen = sizeof(struct dirent) + length;
|
||||
dirent->d_reclen = sizeof(struct dirent) + length + 1;
|
||||
|
||||
bufferSize -= dirent->d_reclen;
|
||||
dirent = (struct dirent*)((uint8*)dirent + dirent->d_reclen);
|
||||
@@ -1867,7 +1867,7 @@ bfs_read_attr_dir(fs_volume* _volume, fs_vnode* node, void* _cookie,
|
||||
Volume* volume = (Volume*)_volume->private_volume;
|
||||
|
||||
dirent->d_dev = volume->ID();
|
||||
dirent->d_reclen = sizeof(struct dirent) + length;
|
||||
dirent->d_reclen = sizeof(struct dirent) + length + 1;
|
||||
|
||||
*_num = 1;
|
||||
return B_OK;
|
||||
|
||||
@@ -814,7 +814,7 @@ btrfs_read_dir(fs_volume* _volume, fs_vnode* _node, void* _cookie,
|
||||
|
||||
while (count < maxCount && bufferSize > sizeof(struct dirent)) {
|
||||
ino_t id;
|
||||
size_t length = bufferSize - sizeof(struct dirent) + 1;
|
||||
size_t length = bufferSize - sizeof(struct dirent);
|
||||
|
||||
status_t status = iterator->GetNext(dirent->d_name, &length,
|
||||
&id);
|
||||
@@ -834,7 +834,7 @@ btrfs_read_dir(fs_volume* _volume, fs_vnode* _node, void* _cookie,
|
||||
|
||||
dirent->d_dev = volume->ID();
|
||||
dirent->d_ino = id;
|
||||
dirent->d_reclen = sizeof(struct dirent) + length;
|
||||
dirent->d_reclen = sizeof(struct dirent) + length + 1;
|
||||
|
||||
bufferSize -= dirent->d_reclen;
|
||||
dirent = (struct dirent*)((uint8*)dirent + dirent->d_reclen);
|
||||
@@ -928,7 +928,7 @@ btrfs_read_attr_dir(fs_volume* _volume, fs_vnode* _node,
|
||||
|
||||
Volume* volume = (Volume*)_volume->private_volume;
|
||||
dirent->d_dev = volume->ID();
|
||||
dirent->d_reclen = sizeof(struct dirent) + length;
|
||||
dirent->d_reclen = sizeof(struct dirent) + length + 1;
|
||||
*_num = 1;
|
||||
|
||||
return B_OK;
|
||||
|
||||
@@ -1907,7 +1907,7 @@ cdda_read_dir(fs_volume* _volume, fs_vnode* _node, void* _cookie,
|
||||
|
||||
buffer->d_dev = volume->FSVolume()->id;
|
||||
buffer->d_ino = childNode->ID();
|
||||
buffer->d_reclen = strlen(name) + sizeof(struct dirent);
|
||||
buffer->d_reclen = sizeof(struct dirent) + strlen(name) + 1;
|
||||
|
||||
if (buffer->d_reclen > bufferSize) {
|
||||
if (count == 0)
|
||||
@@ -2041,7 +2041,7 @@ cdda_read_attr_dir(fs_volume* _volume, fs_vnode* _node, void* _cookie,
|
||||
size_t length = strlcpy(dirent->d_name, attribute->Name(), bufferSize);
|
||||
dirent->d_dev = volume->FSVolume()->id;
|
||||
dirent->d_ino = inode->ID();
|
||||
dirent->d_reclen = sizeof(struct dirent) + length;
|
||||
dirent->d_reclen = sizeof(struct dirent) + length + 1;
|
||||
|
||||
cookie->current = attribute->GetDoublyLinkedListLink()->next;
|
||||
*_num = 1;
|
||||
|
||||
@@ -587,7 +587,7 @@ exfat_read_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie,
|
||||
|
||||
while (count < maxCount && bufferSize > sizeof(struct dirent)) {
|
||||
ino_t id;
|
||||
size_t length = bufferSize - sizeof(struct dirent) + 1;
|
||||
size_t length = bufferSize - sizeof(struct dirent);
|
||||
|
||||
status_t status = iterator->GetNext(dirent->d_name, &length, &id);
|
||||
if (status == B_ENTRY_NOT_FOUND)
|
||||
@@ -605,7 +605,7 @@ exfat_read_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie,
|
||||
|
||||
dirent->d_dev = volume->ID();
|
||||
dirent->d_ino = id;
|
||||
dirent->d_reclen = sizeof(struct dirent) + length;
|
||||
dirent->d_reclen = sizeof(struct dirent) + length + 1;
|
||||
|
||||
bufferSize -= dirent->d_reclen;
|
||||
dirent = (struct dirent*)((uint8*)dirent + dirent->d_reclen);
|
||||
|
||||
@@ -1442,7 +1442,7 @@ ext2_read_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie,
|
||||
|
||||
while (count < maxCount && bufferSize > sizeof(struct dirent)) {
|
||||
|
||||
size_t length = bufferSize - sizeof(struct dirent) + 1;
|
||||
size_t length = bufferSize - sizeof(struct dirent);
|
||||
ino_t id;
|
||||
|
||||
status_t status = iterator->GetNext(dirent->d_name, &length, &id);
|
||||
@@ -1465,7 +1465,7 @@ ext2_read_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie,
|
||||
|
||||
dirent->d_dev = volume->ID();
|
||||
dirent->d_ino = id;
|
||||
dirent->d_reclen = sizeof(struct dirent) + length;
|
||||
dirent->d_reclen = sizeof(struct dirent) + length + 1;
|
||||
|
||||
bufferSize -= dirent->d_reclen;
|
||||
dirent = (struct dirent*)((uint8*)dirent + dirent->d_reclen);
|
||||
@@ -1565,7 +1565,7 @@ ext2_read_attr_dir(fs_volume* _volume, fs_vnode* _node,
|
||||
|
||||
dirent->d_dev = volume->ID();
|
||||
dirent->d_ino = inode->ID();
|
||||
dirent->d_reclen = sizeof(struct dirent) + length;
|
||||
dirent->d_reclen = sizeof(struct dirent) + length + 1;
|
||||
|
||||
*_num = 1;
|
||||
*(int32*)_cookie = index + 1;
|
||||
|
||||
@@ -134,8 +134,8 @@ dosfs_read_attrdir(fs_volume *_vol, fs_vnode *_node, void *_cookie,
|
||||
|
||||
entry->d_ino = node->vnid;
|
||||
entry->d_dev = vol->id;
|
||||
entry->d_reclen = 10;
|
||||
strcpy(entry->d_name, "BEOS:TYPE");
|
||||
entry->d_reclen = sizeof(struct dirent) + strlen(entry->d_name) + 1;
|
||||
}
|
||||
|
||||
*cookie = 1;
|
||||
|
||||
@@ -1195,10 +1195,10 @@ dosfs_readdir(fs_volume *_vol, fs_vnode *_dir, void *_cookie,
|
||||
} else {
|
||||
if (cookie->current_index++ == 0) {
|
||||
strcpy(entry->d_name, ".");
|
||||
entry->d_reclen = sizeof(struct dirent) + 1;
|
||||
entry->d_reclen = sizeof(struct dirent) + 2;
|
||||
} else {
|
||||
strcpy(entry->d_name, "..");
|
||||
entry->d_reclen = sizeof(struct dirent) + 2;
|
||||
entry->d_reclen = sizeof(struct dirent) + 3;
|
||||
}
|
||||
*num = 1;
|
||||
entry->d_ino = vol->root_vnode.vnid;
|
||||
@@ -1229,7 +1229,7 @@ dosfs_readdir(fs_volume *_vol, fs_vnode *_dir, void *_cookie,
|
||||
if (result == B_NO_ERROR) {
|
||||
*num = 1;
|
||||
entry->d_dev = vol->id;
|
||||
entry->d_reclen = sizeof(struct dirent) + strlen(entry->d_name);
|
||||
entry->d_reclen = sizeof(struct dirent) + strlen(entry->d_name) + 1;
|
||||
DPRINTF(0, ("dosfs_readdir: found file %s\n", entry->d_name));
|
||||
} else if (result == ENOENT) {
|
||||
// When you get to the end, don't return an error, just return 0
|
||||
|
||||
@@ -1048,8 +1048,7 @@ fs_readdir(fs_volume *_volume, fs_vnode *_node, void *_cookie,
|
||||
buf->d_pdev = ns->nsid;
|
||||
buf->d_ino = vnid;
|
||||
buf->d_pino = node->vnid;
|
||||
buf->d_reclen = 2 * (sizeof(dev_t) + sizeof(ino_t))
|
||||
+ sizeof(unsigned short) + strlen(filename) + 1;
|
||||
buf->d_reclen = sizeof(struct dirent) + strlen(filename) + 1;
|
||||
strcpy (buf->d_name,filename);
|
||||
// if ((ns->rootid == node->vnid))//XXX:mmu_man:test
|
||||
// dprintf("nfs: dirent %d {d:%ld pd:%ld i:%lld pi:%lld '%s'}\n", *num, buf->d_dev, buf->d_pdev, buf->d_ino, buf->d_pino, buf->d_name);
|
||||
|
||||
@@ -1232,8 +1232,8 @@ fs_read_dir(fs_volume* _volume, fs_vnode* _node, void* _cookie,
|
||||
|
||||
dirent->d_dev = _volume->id;
|
||||
dirent->d_ino = cookie->current->inode;
|
||||
strlcpy(dirent->d_name, cookie->current->name, length + 1);
|
||||
dirent->d_reclen = sizeof(struct dirent) + length;
|
||||
strlcpy(dirent->d_name, cookie->current->name, length);
|
||||
dirent->d_reclen = sizeof(struct dirent) + length + 1;
|
||||
|
||||
bufferSize -= dirent->d_reclen;
|
||||
dirent = (struct dirent*)((uint8*)dirent + dirent->d_reclen);
|
||||
|
||||
@@ -30,7 +30,7 @@ DirectoryIterator::GetNextEntry(char *name, uint32 *length, ino_t *id)
|
||||
if (fAtBeginning) {
|
||||
TRACE(("DirectoryIterator::GetNextEntry: .\n"));
|
||||
sprintf(name, ".");
|
||||
*length = 2;
|
||||
*length = 1;
|
||||
*id = Parent()->Id();
|
||||
fAtBeginning = false;
|
||||
} else {
|
||||
@@ -58,7 +58,7 @@ DirectoryIterator::GetNextEntry(char *name, uint32 *length, ino_t *id)
|
||||
if (entry->is_parent()) {
|
||||
TRACE(("DirectoryIterator::GetNextEntry: ..\n"));
|
||||
sprintf(name, "..");
|
||||
*length = 3;
|
||||
*length = 2;
|
||||
} else {
|
||||
UdfString string(entry->id(), entry->id_length());
|
||||
TRACE(("DirectoryIterator::GetNextEntry: UfdString id == `%s', "
|
||||
|
||||
@@ -463,7 +463,7 @@ udf_read_dir(fs_volume *_volume, fs_vnode *vnode, void *cookie,
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
uint32 nameLength = bufferSize - sizeof(struct dirent) + 1;
|
||||
uint32 nameLength = bufferSize - sizeof(struct dirent);
|
||||
ino_t id;
|
||||
status_t status = iterator->GetNextEntry(dirent->d_name, &nameLength, &id);
|
||||
if (!status) {
|
||||
@@ -471,7 +471,7 @@ udf_read_dir(fs_volume *_volume, fs_vnode *vnode, void *cookie,
|
||||
*_num = 1;
|
||||
dirent->d_dev = volume->ID();
|
||||
dirent->d_ino = id;
|
||||
dirent->d_reclen = sizeof(struct dirent) + nameLength - 1;
|
||||
dirent->d_reclen = sizeof(struct dirent) + nameLength + 1;
|
||||
} else {
|
||||
*_num = 0;
|
||||
// Clear the status for end of directory
|
||||
|
||||
@@ -80,6 +80,8 @@ DirectoryIterator::GetNext(char* name, size_t* _nameLength, ino_t* _id)
|
||||
fOffset = fOffset + 8 + remainder;
|
||||
|
||||
if (direct.next_ino > 0) {
|
||||
if ((direct.namlen + 1) > *_nameLength)
|
||||
return B_BUFFER_OVERFLOW;
|
||||
strlcpy(name, direct.name, direct.namlen + 1);
|
||||
*_id = direct.next_ino;
|
||||
*_nameLength = direct.namlen;
|
||||
@@ -87,7 +89,6 @@ DirectoryIterator::GetNext(char* name, size_t* _nameLength, ino_t* _id)
|
||||
}
|
||||
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
}
|
||||
|
||||
return B_ERROR;
|
||||
|
||||
@@ -380,8 +380,8 @@ ufs2_read_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie,
|
||||
uint32 count = 0;
|
||||
|
||||
while (count < maxCount
|
||||
&& (bufferSize >= sizeof(struct dirent) + B_FILE_NAME_LENGTH)) {
|
||||
size_t length = bufferSize;
|
||||
&& (bufferSize >= sizeof(struct dirent) + B_FILE_NAME_LENGTH)) {
|
||||
size_t length = bufferSize - sizeof(struct dirent);
|
||||
ino_t iNodeNo;
|
||||
|
||||
status_t status = iterator->GetNext(dirent->d_name, &length, &iNodeNo);
|
||||
@@ -397,7 +397,7 @@ ufs2_read_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie,
|
||||
|
||||
dirent->d_dev = volume->ID();
|
||||
dirent->d_ino = iNodeNo;
|
||||
dirent->d_reclen = sizeof(struct dirent) + length;
|
||||
dirent->d_reclen = sizeof(struct dirent) + length + 1;
|
||||
bufferSize -= dirent->d_reclen;
|
||||
dirent = (struct dirent*)((uint8*)dirent + dirent->d_reclen);
|
||||
count++;
|
||||
|
||||
@@ -95,12 +95,6 @@ struct FUSEVolume::DirEntryCache {
|
||||
return fEntryCount;
|
||||
}
|
||||
|
||||
size_t DirentLength(uint32 index) const
|
||||
{
|
||||
const Entry& entry = fEntries[index];
|
||||
return sizeof(dirent) + entry.nameSize - 1;
|
||||
}
|
||||
|
||||
bool ReadDirent(uint32 index, dev_t volumeID, bool align, dirent* buffer,
|
||||
size_t bufferSize) const
|
||||
{
|
||||
@@ -110,7 +104,7 @@ struct FUSEVolume::DirEntryCache {
|
||||
const Entry& entry = fEntries[index];
|
||||
|
||||
// get and check the size
|
||||
size_t size = sizeof(dirent) + entry.nameSize - 1;
|
||||
size_t size = sizeof(dirent) + entry.nameSize;
|
||||
if (size > bufferSize)
|
||||
return false;
|
||||
|
||||
@@ -254,7 +248,7 @@ struct FUSEVolume::AttrDirCookie : RWLockable {
|
||||
size_t nameLen = strlen(name);
|
||||
|
||||
// get and check the size
|
||||
size_t size = sizeof(dirent) + nameLen;
|
||||
size_t size = sizeof(dirent) + nameLen + 1;
|
||||
if (size > bufferSize)
|
||||
return false;
|
||||
|
||||
@@ -2995,7 +2989,7 @@ FUSEVolume::_AddReadDirEntry(ReadDirBuffer* buffer, const char* name, int type,
|
||||
return 1;
|
||||
|
||||
// compute the entry length and check whether the entry still fits
|
||||
entryLen = sizeof(dirent) + strlen(name);
|
||||
entryLen = sizeof(dirent) + strlen(name) + 1;
|
||||
if (buffer->usedSize + entryLen > buffer->bufferSize)
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -428,7 +428,7 @@ xfs_read_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie,
|
||||
uint32 count = 0;
|
||||
|
||||
while (count < maxCount && (bufferSize > sizeof(struct dirent))) {
|
||||
size_t length = bufferSize - sizeof(struct dirent) + 1;
|
||||
size_t length = bufferSize - sizeof(struct dirent);
|
||||
xfs_ino_t ino;
|
||||
|
||||
status_t status = iterator->GetNext(buffer->d_name, &length, &ino);
|
||||
@@ -444,7 +444,7 @@ xfs_read_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie,
|
||||
|
||||
buffer->d_dev = volume->ID();
|
||||
buffer->d_ino = ino;
|
||||
buffer->d_reclen = sizeof(struct dirent) + length;
|
||||
buffer->d_reclen = sizeof(struct dirent) + length + 1;
|
||||
bufferSize -= buffer->d_reclen;
|
||||
buffer = (struct dirent*)((uint8*)buffer + buffer->d_reclen);
|
||||
count++;
|
||||
|
||||
@@ -397,7 +397,7 @@ build_dirent(const BEntry* source, struct dirent* ent,
|
||||
entry_ref ref;
|
||||
source->GetRef(&ref);
|
||||
|
||||
size_t recordLength = strlen(ref.name) + sizeof(dirent);
|
||||
size_t recordLength = strlen(ref.name) + 1 + sizeof(dirent);
|
||||
if (recordLength > size || count <= 0) {
|
||||
// can't fit in buffer, bail
|
||||
return 0;
|
||||
|
||||
@@ -1417,7 +1417,7 @@ devfs_read_dir(fs_volume* _volume, fs_vnode* _vnode, void* _cookie,
|
||||
|
||||
dirent->d_dev = fs->id;
|
||||
dirent->d_ino = childNode->id;
|
||||
dirent->d_reclen = strlen(name) + sizeof(struct dirent);
|
||||
dirent->d_reclen = strlen(name) + 1 + sizeof(struct dirent);
|
||||
|
||||
if (dirent->d_reclen > bufferSize)
|
||||
return ENOBUFS;
|
||||
|
||||
@@ -790,7 +790,7 @@ rootfs_read_dir(fs_volume* _volume, fs_vnode* _vnode, void* _cookie,
|
||||
|
||||
dirent->d_dev = fs->id;
|
||||
dirent->d_ino = childNode->id;
|
||||
dirent->d_reclen = strlen(name) + sizeof(struct dirent);
|
||||
dirent->d_reclen = strlen(name) + 1 + sizeof(struct dirent);
|
||||
|
||||
if (dirent->d_reclen > bufferSize)
|
||||
return ENOBUFS;
|
||||
|
||||
@@ -190,7 +190,7 @@ struct DirCookie {
|
||||
}
|
||||
}
|
||||
|
||||
size_t entrySize = sizeof(dirent) + nameLength;
|
||||
size_t entrySize = sizeof(dirent) + nameLength + 1;
|
||||
if (entrySize > size)
|
||||
return B_BUFFER_OVERFLOW;
|
||||
|
||||
@@ -2388,4 +2388,4 @@ fs_vnode_ops gCheckSumFSVnodeOps = {
|
||||
/* support for node and FS layers */
|
||||
NULL, // create_special_node
|
||||
NULL // get_super_vnode
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user