* Copyright 2008-2010, Axel DΓΆrfler, axeld@pinc-software.de.
* Copyright 2011, JΓ©rΓ΄me Duval, korli@users.berlios.de.
* Copyright 2014 Haiku, Inc. All rights reserved.
*
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel DΓΆrfler, axeld@pinc-software.de
* JΓ©rΓ΄me Duval, korli@users.berlios.de
* John Scipione, jscipione@gmail.com
*/
#ifndef VOLUME_H
#define VOLUME_H
#include <lock.h>
#include <string.h>
#include <StorageDefs.h>
#include <util/SplayTree.h>
#include "exfat.h"
struct node_key {
cluster_t cluster;
uint32 offset;
};
struct node {
struct node_key key;
ino_t ino;
ino_t parent;
SplayTreeLink<struct node> nodeTreeLink;
SplayTreeLink<struct node> inoTreeLink;
};
struct NodeTreeDefinition {
typedef struct node_key KeyType;
typedef struct node NodeType;
static KeyType GetKey(const NodeType* node)
{
return node->key;
}
static SplayTreeLink<NodeType>* GetLink(NodeType* node)
{
return &node->nodeTreeLink;
}
static int Compare(KeyType key, const NodeType* node)
{
if (key.cluster == node->key.cluster) {
if (key.offset == node->key.offset)
return 0;
return key.offset < node->key.offset ? -1 : 1;
}
return key.cluster < node->key.cluster ? -1 : 1;
}
};
struct InoTreeDefinition {
typedef ino_t KeyType;
typedef struct node NodeType;
static KeyType GetKey(const NodeType* node)
{
return node->ino;
}
static SplayTreeLink<NodeType>* GetLink(NodeType* node)
{
return &node->inoTreeLink;
}
static int Compare(KeyType key, const NodeType* node)
{
if (key != node->ino)
return key < node->ino ? -1 : 1;
return 0;
}
};
typedef SplayTree<NodeTreeDefinition> NodeTree;
typedef SplayTree<InoTreeDefinition> InoTree;
class Inode;
struct InodesInoTreeDefinition;
typedef IteratableSplayTree<InodesInoTreeDefinition> InodesInoTree;
struct InodesClusterTreeDefinition;
typedef IteratableSplayTree<InodesClusterTreeDefinition> InodesClusterTree;
enum volume_flags {
VOLUME_READ_ONLY = 0x0001
};
class Volume {
public:
Volume(fs_volume* volume);
~Volume();
status_t Mount(const char* device, uint32 flags);
status_t Unmount();
bool IsValidSuperBlock();
bool IsReadOnly() const
{ return (fFlags & VOLUME_READ_ONLY) != 0; }
Inode* RootNode() const { return fRootNode; }
int Device() const { return fDevice; }
dev_t ID() const
{ 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
{ return fEntriesPerBlock; }
uint32 EntriesPerCluster()
{ return fEntriesPerBlock
<< SuperBlock().BlocksPerClusterShift(); }
size_t ClusterSize() { return fBlockSize
<< SuperBlock().BlocksPerClusterShift(); }
exfat_super_block& SuperBlock() { return fSuperBlock; }
status_t LoadSuperBlock();
void* BlockCache() { return fBlockCache; }
static status_t Identify(int fd, exfat_super_block* superBlock);
status_t ClusterToBlock(cluster_t cluster,
fsblock_t &block);
Inode * FindInode(ino_t id);
Inode * FindInode(cluster_t cluster);
cluster_t NextCluster(cluster_t cluster);
ino_t GetIno(cluster_t cluster, uint32 offset,
ino_t parent);
struct node_key* GetNode(ino_t ino, ino_t &parent);
private:
ino_t _NextID() { return fNextId++; }
mutex fLock;
fs_volume* fFSVolume;
int fDevice;
exfat_super_block fSuperBlock;
char fName[B_FILE_NAME_LENGTH];
uint16 fFlags;
uint32 fBlockSize;
uint32 fEntriesPerBlock;
Inode* fRootNode;
ino_t fNextId;
void* fBlockCache;
InodesInoTree* fInodesInoTree;
InodesClusterTree* fInodesClusterTree;
NodeTree fNodeTree;
InoTree fInoTree;
};
#endif