1/*
2 * Copyright 2020 Suhel Mehta, mehtasuhel@gmail.com
3 * Copyright 2008-2010, Axel D��rfler, axeld@pinc-software.de.
4 * All rights reserved. Distributed under the terms of the MIT License.
5 */
6
7#ifndef INODE_H
8#define INODE_H
9
10#include "ufs2.h"
11#include "Volume.h"
12
13#define	UFS2_ROOT	((ino_t)2)
14
15
16struct timeval32
17{
18	int tv_sec, tv_usec;
19};
20
21
22struct ufs2_inode {
23	u_int16_t	fileMode;
24	int16_t		linkCount;
25	int32_t		userId;
26	int32_t		groupId;
27	int32_t		inodeBlockSize;
28	int64_t		size;
29	int64_t		inodeBlocks;
30	struct		timeval32	accessTime;
31	struct		timeval32	modifiedTime;
32	struct		timeval32	changeTime;
33	struct		timeval32	createTime;
34	/* time in nano seconds */
35	int32_t		nsModifiedTime;
36	int32_t		nsAccessTime;
37	int32_t		nsChangeTime;
38	int32_t		nsCreateTime;
39	int32_t		generationNumber;
40	int32_t		kernelFlags;
41	int32_t		statusFlags;
42	int32_t		extendedAttSize; /* Extended attribute size */
43	/* 2 Direct extended attribute block pointers */
44	int64_t		extendedBklPtr1;
45	int64_t		extendedBklPtr2;
46
47	union {
48		struct {
49			int64_t		directBlockPointer[12];
50			int64_t		indirectBlockPointer;
51			int64_t		doubleIndriectBlockPointer;
52			int64_t		tripleIndriectBlockPointer;
53		};
54		char	symlinkpath[120];
55	};
56	/* Unused but need to figure out what are they */
57	int64_t		unused1;
58	int64_t		unused2;
59	int64_t		unused3;
60
61
62	static void _DecodeTime(struct timespec& timespec, timeval32 time)
63	{
64		timespec.tv_sec = time.tv_sec;
65		timespec.tv_nsec = time.tv_usec * 1000;
66	}
67	void GetAccessTime(struct timespec& timespec) const
68		{ _DecodeTime(timespec, accessTime); }
69	void GetChangeTime(struct timespec& timespec) const
70		{ _DecodeTime(timespec, changeTime); }
71	void GetModificationTime(struct timespec& timespec) const
72		{ _DecodeTime(timespec, modifiedTime); }
73	void GetCreationTime(struct timespec& timespec) const
74		{ _DecodeTime(timespec, createTime); }
75};
76
77class Inode {
78	public:
79						Inode(Volume* volume, ino_t id);
80						Inode(Volume* volume, ino_t id,
81							const ufs2_inode& item);
82						~Inode();
83
84			status_t	InitCheck();
85
86			ino_t		ID() const { return fID; }
87//
88			rw_lock*	Lock() { return& fLock; }
89//
90//			status_t	UpdateNodeFromDisk();
91
92			bool		IsDirectory() const
93							{ return S_ISDIR(Mode()); }
94			bool		IsFile() const
95							{ return S_ISREG(Mode()); }
96			bool		IsSymLink() const
97							{ return S_ISLNK(Mode()); }
98//			status_t	CheckPermissions(int accessMode) const;
99
100			mode_t		Mode() const { return fNode.fileMode; }
101			off_t		Size() const { return fNode.size; }
102			uid_t		UserID() const { return fNode.userId; }
103			gid_t		GroupID() const { return fNode.groupId; }
104			int16_t		LinkCount() const { return fNode.linkCount; }
105			uint64_t	NumBlocks() const
106							{ return fNode.inodeBlocks * (fNode.inodeBlockSize >> 9); }
107			void		GetChangeTime(struct timespec& timespec) const
108							{ fNode.GetChangeTime(timespec); }
109			void		GetModificationTime(struct timespec& timespec) const
110							{ fNode.GetModificationTime(timespec); }
111			void		GetCreationTime(struct timespec& timespec) const
112							{ fNode.GetCreationTime(timespec); }
113			void		GetAccessTime(struct timespec& timespec) const
114							{ fNode.GetAccessTime(timespec); }
115			status_t	CheckPermissions(int accessMode) const;
116
117			Volume*		GetVolume() const { return fVolume; }
118
119			ino_t		Parent();
120
121			off_t   	FindBlock(off_t block_number, off_t block_offset);
122			status_t	ReadAt(off_t pos, uint8* buffer, size_t* length);
123			status_t	ReadLink(char* buffer, size_t *_bufferSize);
124//			status_t	FillGapWithZeros(off_t start, off_t end);
125
126			void*		FileCache() const { return fCache; }
127			void*		Map() const { return fMap; }
128
129//			status_t	FindParent(ino_t* id);
130	//static	Inode*		Create(Transaction& transaction, ino_t id, Inode* parent, int32 mode, uint64 size = 0, uint64 flags = 0);
131private:
132						Inode(Volume* volume);
133						Inode(const Inode&);
134						Inode& operator=(const Inode&);
135			int64_t		GetBlockPointer(int ptrNumber) {
136						return fNode.directBlockPointer[ptrNumber]; }
137
138			int64_t 	GetIndirectBlockPointer() {
139						return fNode.indirectBlockPointer; }
140
141			int64_t 	GetDoubleIndirectBlockPtr() {
142						return fNode.doubleIndriectBlockPointer; }
143
144			int64_t 	GetTripleIndirectBlockPtr() {
145						return fNode.tripleIndriectBlockPointer; }
146
147//			uint64		_NumBlocks();
148private:
149
150			rw_lock		fLock;
151			::Volume*	fVolume;
152			ino_t		fID;
153			void*		fCache;
154			void*		fMap;
155			status_t	fInitStatus;
156			ufs2_inode	fNode;
157};
158
159#endif	// INODE_H
160