xref: /haiku/src/add-ons/kernel/file_systems/reiserfs/StatItem.h (revision 8195a5a835117ab2da405e0d477153570b75d921)
1 // StatItem.h
2 //
3 // Copyright (c) 2003, Ingo Weinhold (bonefish@cs.tu-berlin.de)
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 //
19 // You can alternatively use *this file* under the terms of the the MIT
20 // license included in this package.
21 
22 #ifndef STAT_ITEM_H
23 #define STAT_ITEM_H
24 
25 #include <sys/stat.h>
26 
27 #include <SupportDefs.h>
28 
29 #include "Block.h"
30 #include "Debug.h"
31 #include "endianess.h"
32 #include "Item.h"
33 #include "reiserfs.h"
34 
35 // StatData
36 /*!
37 	\class StatData
38 	\brief Represents the on-disk structure for stat data (stat item contents).
39 
40 	There are two different formats for stat data. This class hides this
41 	fact and provides convenient access to the fields.
42 */
43 class StatData {
44 public:
45 	StatData() : fCurrentData(NULL), fVersion(STAT_DATA_V2) {}
46 	StatData(const StatData &data)
47 		: fCurrentData(NULL), fVersion(STAT_DATA_V2) { *this = data; }
48 	StatData(stat_data_v1 *data, bool clone = false)
49 		: fCurrentData(NULL), fVersion(STAT_DATA_V2) { SetTo(data, clone); }
50 	StatData(stat_data *data, bool clone = false)
51 		: fCurrentData(NULL), fVersion(STAT_DATA_V2) { SetTo(data, clone); }
52 	~StatData() { Unset(); }
53 
54 	status_t SetTo(stat_data_v1 *data, bool clone = false)
55 	{
56 		Unset();
57 		status_t error = B_OK;
58 		fVersion = STAT_DATA_V1;
59 		if (clone && data) {
60 			fOldData = new(nothrow) stat_data_v1;
61 			if (fOldData) {
62 				*fOldData = *data;
63 				fVersion |= ALLOCATED;
64 			} else
65 				error = B_NO_MEMORY;
66 		} else
67 			fOldData = data;
68 		return error;
69 	}
70 
71 	status_t SetTo(stat_data *data, bool clone = false)
72 	{
73 		Unset();
74 		status_t error = B_OK;
75 		fVersion = STAT_DATA_V2;
76 		if (clone && data) {
77 			fCurrentData = new(nothrow) stat_data;
78 			if (fCurrentData) {
79 				*fCurrentData = *data;
80 				fVersion |= ALLOCATED;
81 			} else
82 				error = B_NO_MEMORY;
83 		} else
84 			fCurrentData = data;
85 		return error;
86 	}
87 
88 	void Unset()
89 	{
90 		if (fVersion & ALLOCATED) {
91 			if (GetVersion() == STAT_DATA_V2) {
92 				delete fCurrentData;
93 				fCurrentData = NULL;
94 			} else {
95 				delete fOldData;
96 				fOldData = NULL;
97 			}
98 		}
99 	}
100 
101 	uint32 GetVersion() const { return (fVersion & VERSION_MASK); }
102 
103 	uint16 GetMode() const
104 	{
105 		return (GetVersion() == STAT_DATA_V2 ? le2h(fCurrentData->sd_mode)
106 											 : le2h(fOldData->sd_mode));
107 	}
108 
109 	uint32 GetNLink() const
110 	{
111 		return (GetVersion() == STAT_DATA_V2 ? le2h(fCurrentData->sd_nlink)
112 											 : le2h(fOldData->sd_nlink));
113 	}
114 
115 	uint32 GetUID() const
116 	{
117 		return (GetVersion() == STAT_DATA_V2 ? le2h(fCurrentData->sd_uid)
118 											 : le2h(fOldData->sd_uid));
119 	}
120 
121 	uint32 GetGID() const
122 	{
123 		return (GetVersion() == STAT_DATA_V2 ? le2h(fCurrentData->sd_gid)
124 											 : le2h(fOldData->sd_gid));
125 	}
126 
127 	uint64 GetSize() const
128 	{
129 		return (GetVersion() == STAT_DATA_V2 ? le2h(fCurrentData->sd_size)
130 											 : le2h(fOldData->sd_size));
131 	}
132 
133 	uint32 GetATime() const
134 	{
135 		return (GetVersion() == STAT_DATA_V2 ? le2h(fCurrentData->sd_atime)
136 											 : le2h(fOldData->sd_atime));
137 	}
138 
139 	uint32 GetMTime() const
140 	{
141 		return (GetVersion() == STAT_DATA_V2 ? le2h(fCurrentData->sd_mtime)
142 											 : le2h(fOldData->sd_mtime));
143 	}
144 
145 	uint32 GetCTime() const
146 	{
147 		return (GetVersion() == STAT_DATA_V2 ? le2h(fCurrentData->sd_ctime)
148 											 : le2h(fOldData->sd_ctime));
149 	}
150 
151 	uint32 GetBlocks() const
152 	{
153 		return (GetVersion() == STAT_DATA_V2 ? le2h(fCurrentData->sd_blocks)
154 											 : le2h(fOldData->u.sd_blocks));
155 	}
156 
157 	uint32 GetRDev() const
158 	{
159 		return (GetVersion() == STAT_DATA_V2 ? le2h(fCurrentData->u.sd_rdev)
160 											 : le2h(fOldData->u.sd_rdev));
161 	}
162 
163 	uint32 GetGeneration() const
164 	{
165 		return (GetVersion() == STAT_DATA_V2
166 			? le2h(fCurrentData->u.sd_generation) : 0);
167 	}
168 
169 	bool IsDir() const { return S_ISDIR(GetMode()); }
170 	bool IsFile() const { return S_ISREG(GetMode()); }
171 	bool IsSymlink() const { return S_ISLNK(GetMode()); }
172 	bool IsEsoteric() const { return (!IsDir() && !IsFile() && !IsSymlink()); }
173 
174 
175 	void Dump()
176 	{
177 		PRINT(("StatData:\n"));
178 		PRINT(("  mode:       %hx\n", GetMode()));
179 		PRINT(("  nlink:      %lu\n", GetNLink()));
180 		PRINT(("  uid:        %lx\n", GetUID()));
181 		PRINT(("  gid:        %lx\n", GetGID()));
182 		PRINT(("  size:       %Lu\n", GetSize()));
183 		PRINT(("  atime:      %lu\n", GetATime()));
184 		PRINT(("  mtime:      %lu\n", GetMTime()));
185 		PRINT(("  ctime:      %lu\n", GetCTime()));
186 		PRINT(("  blocks:     %lu\n", GetBlocks()));
187 		PRINT(("  rdev:       %lu\n", GetRDev()));
188 		PRINT(("  generation: %lu\n", GetGeneration()));
189 	}
190 
191 	StatData &operator=(const StatData &data)
192 	{
193 		if (&data != this) {
194 			if (data.GetVersion() == STAT_DATA_V2)
195 				SetTo(data.fCurrentData, true);
196 			else
197 				SetTo(data.fOldData, true);
198 		}
199 		return *this;
200 	}
201 
202 private:
203 	enum {
204 		VERSION_MASK	= STAT_DATA_V1 | STAT_DATA_V2,
205 		ALLOCATED		= 0x8000
206 	};
207 
208 private:
209 	union {
210 		stat_data_v1	*fOldData;
211 		stat_data		*fCurrentData;
212 	};
213 	uint16	fVersion;
214 };
215 
216 // StatItem
217 /*!
218 	\class StatItem
219 	\brief Provides access to the on-disk stat item structure.
220 
221 	A stat item simply consists of StatData. This is only a convenience
222 	class to get hold of it.
223 */
224 class StatItem : public Item {
225 public:
226 	StatItem() : Item() {}
227 	StatItem(LeafNode *node, ItemHeader *header)
228 		: Item(node, header) {}
229 
230 	status_t GetStatData(StatData *statData, bool clone = false) const
231 	{
232 		status_t error = B_OK;
233 		if (GetLen() == sizeof(stat_data)) {
234 			stat_data *data = (stat_data*)GetData();
235 			statData->SetTo(data, clone);
236 		} else if (GetLen() == sizeof(stat_data_v1)) {
237 			stat_data_v1 *data = (stat_data_v1*)GetData();
238 			statData->SetTo(data, clone);
239 		} else {
240 			FATAL(("WARNING: bad stat item %ld on node %Ld: the item len "
241 				   "(%u) does not match the len of any stat data format!\n",
242 				   GetIndex(), fNode->GetNumber(), GetLen()));
243 			error = B_BAD_DATA;
244 		}
245 		return error;
246 	}
247 };
248 
249 #endif	// STAT_ITEM_H
250