From ce9fdaeae4e2465dfc3cd53954416e9567456ee9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Thu, 10 Feb 2011 19:49:12 +0000 Subject: [PATCH] * takes into account volume label * clean up * directories don't seem to have a valid contiguous flag, fixes directories with many files. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@40431 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../file_systems/exfat/DirectoryIterator.cpp | 3 +- .../kernel/file_systems/exfat/Inode.cpp | 23 ++++------ .../kernel/file_systems/exfat/Volume.cpp | 43 +++++++++++++++++-- .../kernel/file_systems/exfat/Volume.h | 7 ++- 4 files changed, 56 insertions(+), 20 deletions(-) diff --git a/src/add-ons/kernel/file_systems/exfat/DirectoryIterator.cpp b/src/add-ons/kernel/file_systems/exfat/DirectoryIterator.cpp index 8196dace37..ffeaff1bac 100644 --- a/src/add-ons/kernel/file_systems/exfat/DirectoryIterator.cpp +++ b/src/add-ons/kernel/file_systems/exfat/DirectoryIterator.cpp @@ -140,7 +140,8 @@ DirectoryIterator::Rewind() void DirectoryIterator::Iterate(EntryVisitor &visitor) { - Rewind(); + fOffset = 0; + fCluster = fInode->StartCluster(); while (_NextEntry() != B_ENTRY_NOT_FOUND) { switch (fCurrent->type) { diff --git a/src/add-ons/kernel/file_systems/exfat/Inode.cpp b/src/add-ons/kernel/file_systems/exfat/Inode.cpp index f6ba127bad..a03c13cceb 100644 --- a/src/add-ons/kernel/file_systems/exfat/Inode.cpp +++ b/src/add-ons/kernel/file_systems/exfat/Inode.cpp @@ -45,10 +45,9 @@ Inode::Inode(Volume* volume, cluster_t cluster, uint32 offset) fFileEntry.file.SetAttribs(EXFAT_ENTRY_ATTRIB_SUBDIR); fFileEntry.file_info.SetStartCluster(Cluster()); fFileInfoEntry.file_info.SetFlag(0); - } else + } else { fInitStatus = UpdateNodeFromDisk(); - if (fInitStatus == B_OK) { - if (!IsDirectory() && !IsSymLink()) { + if (fInitStatus == B_OK && !IsDirectory() && !IsSymLink()) { fCache = file_cache_create(fVolume->ID(), ID(), Size()); fMap = file_map_create(fVolume->ID(), ID(), Size()); } @@ -76,20 +75,17 @@ Inode::Inode(Volume* volume, ino_t ino) TRACE("Inode::Inode(%" B_PRIdINO ") cluster %ld\n", ID(), Cluster()); _Init(); - if (fInitStatus == B_OK && ID() != 1) - fInitStatus = UpdateNodeFromDisk(); - else if (fInitStatus == B_OK && ID() == 1) { - fFileEntry.file.SetAttribs(EXFAT_ENTRY_ATTRIB_SUBDIR); - fFileInfoEntry.file_info.SetStartCluster(Cluster()); - fFileInfoEntry.file_info.SetFlag(0); - } - if (fInitStatus == B_OK) { + if (fInitStatus == B_OK && ID() != 1) { + fInitStatus = UpdateNodeFromDisk(); if (!IsDirectory() && !IsSymLink()) { fCache = file_cache_create(fVolume->ID(), ID(), Size()); fMap = file_map_create(fVolume->ID(), ID(), Size()); } + } else if (fInitStatus == B_OK && ID() == 1) { + fFileEntry.file.SetAttribs(EXFAT_ENTRY_ATTRIB_SUBDIR); + fFileInfoEntry.file_info.SetStartCluster(Cluster()); + fFileInfoEntry.file_info.SetFlag(0); } - TRACE("Inode::Inode(%" B_PRIdINO ") end\n", ID()); } @@ -124,7 +120,6 @@ Inode::InitCheck() status_t Inode::UpdateNodeFromDisk() { - DirectoryIterator iterator(this); iterator.LookupEntry(this); return B_OK; @@ -134,7 +129,7 @@ Inode::UpdateNodeFromDisk() cluster_t Inode::NextCluster(cluster_t cluster) const { - if (!IsContiguous()) + if (!IsContiguous() || IsDirectory()) return GetVolume()->NextCluster(cluster); return cluster + 1; } diff --git a/src/add-ons/kernel/file_systems/exfat/Volume.cpp b/src/add-ons/kernel/file_systems/exfat/Volume.cpp index 876e2ec9eb..528ecb43cc 100644 --- a/src/add-ons/kernel/file_systems/exfat/Volume.cpp +++ b/src/add-ons/kernel/file_systems/exfat/Volume.cpp @@ -22,6 +22,7 @@ #include #include "CachedBlock.h" +#include "encodings.h" #include "Inode.h" @@ -198,6 +199,38 @@ DeviceOpener::GetSize(off_t* _size, uint32* _blockSize) // #pragma mark - +class LabelVisitor : public EntryVisitor { +public: + LabelVisitor(Volume* volume); + bool VisitLabel(struct exfat_entry*); +private: + Volume* fVolume; +}; + + +LabelVisitor::LabelVisitor(Volume* volume) + : + fVolume(volume) +{ +} + + +bool +LabelVisitor::VisitLabel(struct exfat_entry* entry) +{ + dprintf("LabelVisitor::VisitLabel()\n"); + char utfName[30]; + size_t utfLength = 30; + unicode_to_utf8((const uchar*)entry->name_label.name, + entry->name_label.length * 2, (uint8*)utfName, &utfLength); + fVolume->SetName(utfName); + return true; +} + + +// #pragma mark - + + bool exfat_super_block::IsValid() { @@ -228,6 +261,7 @@ Volume::Volume(fs_volume* volume) mutex_init(&fLock, "exfat volume"); fInodesClusterTree = new InodesClusterTree; fInodesInoTree = new InodesInoTree; + memset(fName, 0, sizeof(fName)); } @@ -249,7 +283,6 @@ Volume::IsValidSuperBlock() const char* Volume::Name() const { - /* TODO volume name is in the root directory */ return fName; } @@ -321,7 +354,11 @@ Volume::Mount(const char* deviceName, uint32 flags) // all went fine opener.Keep(); - /*if (!fSuperBlock.label[0]) {*/ + DirectoryIterator iterator(fRootNode); + LabelVisitor visitor(this); + iterator.Iterate(visitor); + + if (fName[0] == '\0') { // generate a more or less descriptive volume name off_t divisor = 1ULL << 40; char unit = 'T'; @@ -339,7 +376,7 @@ Volume::Mount(const char* deviceName, uint32 flags) snprintf(fName, sizeof(fName), "%g %cB ExFAT Volume", size / 10, unit); - //} + } return B_OK; } diff --git a/src/add-ons/kernel/file_systems/exfat/Volume.h b/src/add-ons/kernel/file_systems/exfat/Volume.h index d3590102f4..e177342db2 100644 --- a/src/add-ons/kernel/file_systems/exfat/Volume.h +++ b/src/add-ons/kernel/file_systems/exfat/Volume.h @@ -8,6 +8,7 @@ #include +#include #include "exfat.h" #include "SplayTree.h" @@ -108,6 +109,8 @@ public: { return fFSVolume ? fFSVolume->id : -1; } fs_volume* FSVolume() const { return fFSVolume; } const char* Name() const; + void SetName(const char* name) + { strlcpy(fName, name, sizeof(fName)); } uint32 BlockSize() const { return fBlockSize; } uint32 EntriesPerBlock() const @@ -149,8 +152,8 @@ private: ino_t fNextId; void* fBlockCache; - InodesInoTree* fInodesInoTree; - InodesClusterTree* fInodesClusterTree; + InodesInoTree* fInodesInoTree; + InodesClusterTree* fInodesClusterTree; NodeTree fNodeTree; InoTree fInoTree; };