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