⛏️ index : haiku.git

/*
 * Copyright 2017, ChαΊΏ VΕ© Gia Hy, cvghy116@gmail.com.
 * Copyright 2011, JΓ©rΓ΄me Duval, korli@users.berlios.de.
 * Copyright 2008, Axel DΓΆrfler, axeld@pinc-software.de.
 * This file may be used under the terms of the MIT License.
 */
#ifndef INODE_H
#define INODE_H


#include "btrfs.h"
#include "Volume.h"
#include "Journal.h"
#include "BTree.h"


//#define TRACE_BTRFS
#ifdef TRACE_BTRFS
#	define TRACEI(x...) dprintf("\33[34mbtrfs:\33[0m " x)
#else
#	define TRACEI(x...) ;
#endif


//! Class used for in-memory representation of inodes
class Inode {
public:
						Inode(Volume* volume, ino_t id);
						Inode(Volume* volume, ino_t id,
							const btrfs_inode& item);
						~Inode();

			status_t	InitCheck();

			ino_t		ID() const { return fID; }

			rw_lock*	Lock() { return& fLock; }

			status_t	UpdateNodeFromDisk();

			bool		IsDirectory() const
							{ return S_ISDIR(Mode()); }
			bool		IsFile() const
							{ return S_ISREG(Mode()); }
			bool		IsSymLink() const
							{ return S_ISLNK(Mode()); }
			status_t	CheckPermissions(int accessMode) const;

			btrfs_inode&	Node() { return fNode; }
			mode_t		Mode() const { return fNode.Mode(); }
			off_t		Size() const { return fNode.Size(); }
			uid_t		UserID() const { return fNode.UserID(); }
			gid_t		GroupID() const { return fNode.GroupID(); }
			void		GetChangeTime(struct timespec& timespec) const
							{ fNode.GetChangeTime(timespec); }
			void		GetModificationTime(struct timespec& timespec) const
							{ fNode.GetModificationTime(timespec); }
			void		GetCreationTime(struct timespec& timespec) const
							{ fNode.GetCreationTime(timespec); }
			void		GetAccessTime(struct timespec& timespec) const
							{ fNode.GetCreationTime(timespec); }

			Volume*		GetVolume() const { return fVolume; }

			status_t	FindBlock(off_t logical, off_t& physical,
							off_t* _length = NULL);
			status_t	ReadAt(off_t pos, uint8* buffer, size_t* length);
			status_t	FillGapWithZeros(off_t start, off_t end);

			void*		FileCache() const { return fCache; }
			void*		Map() const { return fMap; }

			status_t	FindParent(ino_t* id);
			uint64		FindNextIndex(BTree::Path* path) const;
	static	Inode*		Create(Transaction& transaction, ino_t id,
							Inode* parent, int32 mode, uint64 size = 0,
							uint64 flags = 0);
			status_t	Insert(Transaction& transaction, BTree::Path* path);
			status_t	Remove(Transaction& transaction, BTree::Path* path);
			status_t	MakeReference(Transaction& transaction, BTree::Path* path,
							Inode* parent, const char* name, int32 mode);
			status_t	Dereference(Transaction& transaction, BTree::Path* path,
							ino_t parentID, const char* name);
private:
						Inode(Volume* volume);
						Inode(const Inode&);
						Inode& operator=(const Inode&);
							// no implementation

			uint64		_NumBlocks();
private:

			rw_lock		fLock;
			::Volume*	fVolume;
			ino_t		fID;
			void*		fCache;
			void*		fMap;
			status_t	fInitStatus;
			btrfs_inode fNode;
};

/*!The Vnode class provides a convenience layer upon get_vnode(), so that
 * you don't have to call put_vnode() anymore, which may make code more
 * readable in some cases
 */
class Vnode {
public:
	Vnode(Volume* volume, ino_t id)
		:
		fInode(NULL)
	{
		SetTo(volume, id);
	}

	Vnode()
		:
		fStatus(B_NO_INIT),
		fInode(NULL)
	{
	}

	~Vnode()
	{
		Unset();
	}

	status_t InitCheck()
	{
		return fStatus;
	}

	void Unset()
	{
		if (fInode != NULL) {
			put_vnode(fInode->GetVolume()->FSVolume(), fInode->ID());
			fInode = NULL;
			fStatus = B_NO_INIT;
		}
	}

	status_t SetTo(Volume* volume, ino_t id)
	{
		Unset();

		return fStatus = get_vnode(volume->FSVolume(), id, (void**)&fInode);
	}

	status_t Get(Inode** _inode)
	{
		*_inode = fInode;
		return fStatus;
	}

	void Keep()
	{
		TRACEI("Vnode::Keep()\n");
		fInode = NULL;
	}

private:
	status_t	fStatus;
	Inode*		fInode;
};


#endif	// INODE_H