Avoid using unions for LongDirEntry.
GCC still assumes that the dirent has no data past the end for some scenarios here and still mis-optimizes things. Therefore, drop the usages of unions altogether, and instead use a casted character array. Additionally, use B_FILE_NAME_LENGTH for the array, not B_PATH_NAME_LENGTH, and make sure to add 1 for the NULL terminator.
This commit is contained in:
@@ -25,9 +25,9 @@ namespace BPrivate {
|
||||
namespace Storage {
|
||||
|
||||
// For convenience:
|
||||
union LongDirEntry {
|
||||
struct dirent dirent;
|
||||
char _[sizeof(struct dirent) + B_PATH_NAME_LENGTH];
|
||||
struct LongDirEntry {
|
||||
char _[sizeof(struct dirent) + B_FILE_NAME_LENGTH + 1];
|
||||
struct dirent* dirent() { return (struct dirent*)_; }
|
||||
};
|
||||
|
||||
//! Returns whether the supplied path is absolute.
|
||||
@@ -73,9 +73,9 @@ void to_lower(const char *str, std::string &result);
|
||||
|
||||
/*! \brief Copies \c str into \c result, converting any uppercase alphabetics
|
||||
to lowercase.
|
||||
|
||||
|
||||
\a str and \a result may point to the same string. \a result is
|
||||
assumed to be as long as or longer than \a str.
|
||||
assumed to be as long as or longer than \a str.
|
||||
*/
|
||||
void to_lower(const char *str, char *result);
|
||||
|
||||
@@ -87,7 +87,7 @@ void to_lower(char *str);
|
||||
\a result must be large enough to accomodate the addition of
|
||||
escape sequences to \a str. \a str and \a result may *NOT* point to
|
||||
the same string.
|
||||
|
||||
|
||||
Note that this function was designed for use with the registrar's
|
||||
RecentEntries class, and may not create escapes exactly like you're
|
||||
hoping. Please double check the code for the function to see if this
|
||||
|
||||
@@ -333,7 +333,7 @@ BDirectory::GetNextRef(entry_ref* ref)
|
||||
return B_FILE_ERROR;
|
||||
|
||||
BPrivate::Storage::LongDirEntry longEntry;
|
||||
struct dirent* entry = &longEntry.dirent;
|
||||
struct dirent* entry = longEntry.dirent();
|
||||
bool next = true;
|
||||
while (next) {
|
||||
if (GetNextDirents(entry, sizeof(longEntry), 1) != 1)
|
||||
@@ -377,7 +377,7 @@ BDirectory::CountEntries()
|
||||
return error;
|
||||
int32 count = 0;
|
||||
BPrivate::Storage::LongDirEntry longEntry;
|
||||
struct dirent* entry = &longEntry.dirent;
|
||||
struct dirent* entry = longEntry.dirent();
|
||||
while (error == B_OK) {
|
||||
if (GetNextDirents(entry, sizeof(longEntry), 1) != 1)
|
||||
break;
|
||||
|
||||
@@ -110,7 +110,7 @@ status_t
|
||||
BMergedDirectory::GetNextRef(entry_ref* ref)
|
||||
{
|
||||
BPrivate::Storage::LongDirEntry longEntry;
|
||||
struct dirent* dirEntry = &longEntry.dirent;
|
||||
struct dirent* dirEntry = longEntry.dirent();
|
||||
int32 result = GetNextDirents(dirEntry, sizeof(longEntry), 1);
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
@@ -310,7 +310,7 @@ BNode::GetNextAttrName(char* buffer)
|
||||
return B_FILE_ERROR;
|
||||
|
||||
BPrivate::Storage::LongDirEntry longEntry;
|
||||
struct dirent* entry = &longEntry.dirent;
|
||||
struct dirent* entry = longEntry.dirent();
|
||||
ssize_t result = _kern_read_dir(fAttrFd, entry, sizeof(longEntry), 1);
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
@@ -129,10 +129,10 @@ class AttributeDirectory;
|
||||
typedef map<DIR*, AttributeDirectory*> AttrDirMap;
|
||||
static AttrDirMap sAttributeDirectories;
|
||||
|
||||
// LongDirent
|
||||
union LongDirent {
|
||||
struct dirent dirent;
|
||||
char _[sizeof(struct dirent) + B_FILE_NAME_LENGTH];
|
||||
// LongDirEntry
|
||||
struct LongDirEntry {
|
||||
char _[sizeof(struct dirent) + B_FILE_NAME_LENGTH + 1];
|
||||
struct dirent* dirent() { return (struct dirent*)_; }
|
||||
};
|
||||
|
||||
// AttributeHeader
|
||||
@@ -260,11 +260,11 @@ public:
|
||||
}
|
||||
|
||||
// prepare the dirent
|
||||
strcpy(fDirent.dirent.d_name, name);
|
||||
fDirent.dirent.d_ino = 0;
|
||||
strcpy(fDirent.dirent()->d_name, name);
|
||||
fDirent.dirent()->d_ino = 0;
|
||||
// TODO: We need the node ID!
|
||||
|
||||
*_entry = &fDirent.dirent;
|
||||
*_entry = fDirent.dirent();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -309,7 +309,7 @@ private:
|
||||
int fFileFD;
|
||||
string fPath;
|
||||
DIR* fFakeDir;
|
||||
LongDirent fDirent;
|
||||
LongDirEntry fDirent;
|
||||
char* fListing;
|
||||
int fListingLength;
|
||||
int fListingIndex;
|
||||
|
||||
@@ -353,7 +353,7 @@ BDirectory::GetNextRef(entry_ref* ref)
|
||||
return B_FILE_ERROR;
|
||||
|
||||
BPrivate::Storage::LongDirEntry longEntry;
|
||||
struct dirent* entry = &longEntry.dirent;
|
||||
struct dirent* entry = longEntry.dirent();
|
||||
bool next = true;
|
||||
while (next) {
|
||||
if (GetNextDirents(entry, sizeof(longEntry), 1) != 1)
|
||||
@@ -397,7 +397,7 @@ BDirectory::CountEntries()
|
||||
return error;
|
||||
int32 count = 0;
|
||||
BPrivate::Storage::LongDirEntry longEntry;
|
||||
struct dirent* entry = &longEntry.dirent;
|
||||
struct dirent* entry = longEntry.dirent();
|
||||
while (error == B_OK) {
|
||||
if (GetNextDirents(entry, sizeof(longEntry), 1) != 1)
|
||||
break;
|
||||
|
||||
@@ -112,7 +112,7 @@ status_t
|
||||
BMergedDirectory::GetNextRef(entry_ref* ref)
|
||||
{
|
||||
BPrivate::Storage::LongDirEntry longEntry;
|
||||
struct dirent* entry = &longEntry.dirent;
|
||||
struct dirent* entry = longEntry.dirent();
|
||||
int32 result = GetNextDirents(entry, sizeof(longEntry), 1);
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
@@ -320,7 +320,7 @@ BNode::GetNextAttrName(char* buffer)
|
||||
return B_FILE_ERROR;
|
||||
|
||||
BPrivate::Storage::LongDirEntry longEntry;
|
||||
struct dirent* entry = &longEntry.dirent;
|
||||
struct dirent* entry = longEntry.dirent();
|
||||
ssize_t result = _kern_read_dir(fAttrFd, entry, sizeof(longEntry), 1);
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
@@ -349,7 +349,7 @@ BQuery::GetNextRef(entry_ref* ref)
|
||||
error = B_FILE_ERROR;
|
||||
if (error == B_OK) {
|
||||
BPrivate::Storage::LongDirEntry longEntry;
|
||||
struct dirent* entry = &longEntry.dirent;
|
||||
struct dirent* entry = longEntry.dirent();
|
||||
bool next = true;
|
||||
while (error == B_OK && next) {
|
||||
if (GetNextDirents(entry, sizeof(longEntry), 1) != 1) {
|
||||
|
||||
@@ -83,7 +83,7 @@ status_t
|
||||
VirtualDirectoryEntryList::GetNextRef(entry_ref* ref)
|
||||
{
|
||||
BPrivate::Storage::LongDirEntry longEntry;
|
||||
struct dirent* entry = &longEntry.dirent;
|
||||
struct dirent* entry = longEntry.dirent();
|
||||
int32 result = GetNextDirents(entry, sizeof(longEntry), 1);
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
@@ -209,7 +209,7 @@ VirtualDirectoryPoseView::_EntryCreated(const BMessage* message)
|
||||
return true;
|
||||
|
||||
BPrivate::Storage::LongDirEntry longEntry;
|
||||
struct dirent* entry = &longEntry.dirent;
|
||||
struct dirent* entry = longEntry.dirent();
|
||||
while (directory.GetNextDirents(entry, sizeof(longEntry), 1) == 1) {
|
||||
if (strcmp(entry->d_name, ".") != 0
|
||||
&& strcmp(entry->d_name, "..") != 0) {
|
||||
|
||||
@@ -42,10 +42,9 @@ using namespace boot;
|
||||
struct __DIR {
|
||||
Directory* directory;
|
||||
void* cookie;
|
||||
union {
|
||||
dirent entry;
|
||||
char nameBuffer[sizeof(dirent) + B_FILE_NAME_LENGTH - 1];
|
||||
};
|
||||
|
||||
char _direntBuffer[sizeof(dirent) + B_FILE_NAME_LENGTH + 1];
|
||||
dirent* entry() { return (dirent*)_direntBuffer; }
|
||||
};
|
||||
|
||||
|
||||
@@ -1260,33 +1259,33 @@ readdir(DIR* dir)
|
||||
|
||||
for (;;) {
|
||||
status_t error = dir->directory->GetNextEntry(dir->cookie,
|
||||
dir->entry.d_name, B_FILE_NAME_LENGTH);
|
||||
dir->entry()->d_name, B_FILE_NAME_LENGTH);
|
||||
if (error != B_OK) {
|
||||
errno = error;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dir->entry.d_pdev = 0;
|
||||
dir->entry()->d_pdev = 0;
|
||||
// not supported
|
||||
dir->entry.d_pino = dir->directory->Inode();
|
||||
dir->entry.d_dev = dir->entry.d_pdev;
|
||||
dir->entry()->d_pino = dir->directory->Inode();
|
||||
dir->entry()->d_dev = dir->entry()->d_pdev;
|
||||
// not supported
|
||||
|
||||
if (strcmp(dir->entry.d_name, ".") == 0
|
||||
|| strcmp(dir->entry.d_name, "..") == 0) {
|
||||
if (strcmp(dir->entry()->d_name, ".") == 0
|
||||
|| strcmp(dir->entry()->d_name, "..") == 0) {
|
||||
// Note: That's obviously not correct for "..", but we can't
|
||||
// retrieve that information.
|
||||
dir->entry.d_ino = dir->entry.d_pino;
|
||||
dir->entry()->d_ino = dir->entry()->d_pino;
|
||||
} else {
|
||||
Node* node = dir->directory->Lookup(dir->entry.d_name, false);
|
||||
Node* node = dir->directory->Lookup(dir->entry()->d_name, false);
|
||||
if (node == NULL)
|
||||
continue;
|
||||
|
||||
dir->entry.d_ino = node->Inode();
|
||||
dir->entry()->d_ino = node->Inode();
|
||||
node->Release();
|
||||
}
|
||||
|
||||
return &dir->entry;
|
||||
return dir->entry();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user