1 2 #ifdef BUILDING_FS_SHELL 3 # include "compat.h" 4 # define B_OK 0 5 # define B_FILE_ERROR EBADF 6 #else 7 # include <BeOSBuildCompatibility.h> 8 #endif 9 10 #include "fs_descriptors.h" 11 12 #include <map> 13 14 #include <stdio.h> 15 #include <unistd.h> 16 17 #include <fs_attr.h> 18 19 #include "fs_impl.h" 20 21 using std::map; 22 23 static const int kVirtualDescriptorStart = 10000; 24 25 typedef map<int, BPrivate::Descriptor*> DescriptorMap; 26 static DescriptorMap *sDescriptors; 27 28 namespace BPrivate { 29 30 31 // #pragma mark - Descriptor 32 33 34 // constructor 35 Descriptor::~Descriptor() 36 { 37 } 38 39 // IsSystemFD 40 bool 41 Descriptor::IsSystemFD() const 42 { 43 return false; 44 } 45 46 // GetPath 47 status_t 48 Descriptor::GetPath(string& path) const 49 { 50 return get_path(fd, NULL, path); 51 } 52 53 // GetNodeRef 54 status_t 55 Descriptor::GetNodeRef(NodeRef &ref) 56 { 57 struct stat st; 58 status_t error = GetStat(false, &st); 59 if (error != B_OK) 60 return error; 61 62 ref = NodeRef(st); 63 64 return B_OK; 65 } 66 67 68 // #pragma mark - FileDescriptor 69 70 71 // constructor 72 FileDescriptor::FileDescriptor(int fd) 73 { 74 this->fd = fd; 75 } 76 77 // destructor 78 FileDescriptor::~FileDescriptor() 79 { 80 Close(); 81 } 82 83 // Close 84 status_t 85 FileDescriptor::Close() 86 { 87 if (fd >= 0) { 88 int oldFD = fd; 89 fd = -1; 90 if (close(oldFD) < 0) 91 return errno; 92 } 93 94 return B_OK; 95 } 96 97 // Dup 98 status_t 99 FileDescriptor::Dup(Descriptor *&clone) 100 { 101 int dupFD = dup(fd); 102 if (dupFD < 0) 103 return errno; 104 105 clone = new FileDescriptor(dupFD); 106 return B_OK; 107 } 108 109 // GetStat 110 status_t 111 FileDescriptor::GetStat(bool traverseLink, struct stat *st) 112 { 113 if (fstat(fd, st) < 0) 114 return errno; 115 return B_OK; 116 } 117 118 // IsSystemFD 119 bool 120 FileDescriptor::IsSystemFD() const 121 { 122 return true; 123 } 124 125 126 // #pragma mark - DirectoryDescriptor 127 128 129 // constructor 130 DirectoryDescriptor::DirectoryDescriptor(DIR *dir, const NodeRef &ref) 131 { 132 this->dir = dir; 133 this->ref = ref; 134 } 135 136 // destructor 137 DirectoryDescriptor::~DirectoryDescriptor() 138 { 139 Close(); 140 } 141 142 // Close 143 status_t 144 DirectoryDescriptor::Close() 145 { 146 if (dir) { 147 DIR *oldDir = dir; 148 dir = NULL; 149 if (closedir(oldDir) < 0) 150 return errno; 151 } 152 153 return B_OK; 154 } 155 156 // Dup 157 status_t 158 DirectoryDescriptor::Dup(Descriptor *&clone) 159 { 160 string path; 161 status_t error = get_path(fd, NULL, path); 162 if (error != B_OK) 163 return error; 164 165 DIR *dupDir = opendir(path.c_str()); 166 if (!dupDir) 167 return errno; 168 169 clone = new DirectoryDescriptor(dupDir, ref); 170 return B_OK; 171 } 172 173 // GetStat 174 status_t 175 DirectoryDescriptor::GetStat(bool traverseLink, struct stat *st) 176 { 177 // get a usable path 178 string realPath; 179 status_t error = get_path(fd, NULL, realPath); 180 if (error != B_OK) 181 return error; 182 183 // stat 184 int result; 185 result = stat(realPath.c_str(), st); 186 187 if (result < 0) 188 return errno; 189 190 return B_OK; 191 } 192 193 // GetNodeRef 194 status_t 195 DirectoryDescriptor::GetNodeRef(NodeRef &ref) 196 { 197 ref = this->ref; 198 199 return B_OK; 200 } 201 202 203 // #pragma mark - SymlinkDescriptor 204 205 206 // constructor 207 SymlinkDescriptor::SymlinkDescriptor(const char *path) 208 { 209 this->path = path; 210 } 211 212 // Close 213 status_t 214 SymlinkDescriptor::Close() 215 { 216 return B_OK; 217 } 218 219 // Dup 220 status_t 221 SymlinkDescriptor::Dup(Descriptor *&clone) 222 { 223 clone = new SymlinkDescriptor(path.c_str()); 224 return B_OK; 225 } 226 227 // GetStat 228 status_t 229 SymlinkDescriptor::GetStat(bool traverseLink, struct stat *st) 230 { 231 // stat 232 int result; 233 if (traverseLink) 234 result = stat(path.c_str(), st); 235 else 236 result = lstat(path.c_str(), st); 237 238 if (result < 0) 239 return errno; 240 241 return B_OK; 242 } 243 244 // GetPath 245 status_t 246 SymlinkDescriptor::GetPath(string& path) const 247 { 248 path = this->path; 249 return B_OK; 250 } 251 252 253 // #pragma mark - AttrDirDescriptor 254 255 256 // constructor 257 AttrDirDescriptor::AttrDirDescriptor(DIR *dir, const NodeRef &ref) 258 : DirectoryDescriptor(dir, ref) 259 { 260 } 261 262 // destructor 263 AttrDirDescriptor::~AttrDirDescriptor() 264 { 265 Close(); 266 } 267 268 // Close 269 status_t 270 AttrDirDescriptor::Close() 271 { 272 if (dir) { 273 DIR *oldDir = dir; 274 dir = NULL; 275 if (fs_close_attr_dir(oldDir) < 0) 276 return errno; 277 } 278 279 return B_OK; 280 } 281 282 // Dup 283 status_t 284 AttrDirDescriptor::Dup(Descriptor *&clone) 285 { 286 // we don't allow dup()int attr dir descriptors 287 return B_FILE_ERROR; 288 } 289 290 // GetStat 291 status_t 292 AttrDirDescriptor::GetStat(bool traverseLink, struct stat *st) 293 { 294 // we don't allow stat()int attr dir descriptors 295 return B_FILE_ERROR; 296 } 297 298 // GetNodeRef 299 status_t 300 AttrDirDescriptor::GetNodeRef(NodeRef &ref) 301 { 302 ref = this->ref; 303 304 return B_OK; 305 } 306 307 308 // get_descriptor 309 Descriptor * 310 get_descriptor(int fd) 311 { 312 if (!sDescriptors) 313 return NULL; 314 DescriptorMap::iterator it = sDescriptors->find(fd); 315 if (it == sDescriptors->end()) 316 return NULL; 317 return it->second; 318 } 319 320 // add_descriptor 321 int 322 add_descriptor(Descriptor *descriptor) 323 { 324 if (!sDescriptors) 325 sDescriptors = new DescriptorMap; 326 327 int fd = -1; 328 if (FileDescriptor *file = dynamic_cast<FileDescriptor*>(descriptor)) { 329 fd = file->fd; 330 } else { 331 // find a free slot 332 for (fd = kVirtualDescriptorStart; 333 sDescriptors->find(fd) != sDescriptors->end(); 334 fd++) { 335 } 336 } 337 338 (*sDescriptors)[fd] = descriptor; 339 descriptor->fd = fd; 340 341 return fd; 342 } 343 344 // delete_descriptor 345 status_t 346 delete_descriptor(int fd) 347 { 348 DescriptorMap::iterator it = sDescriptors->find(fd); 349 if (it == sDescriptors->end()) 350 return B_FILE_ERROR; 351 352 status_t error = it->second->Close(); 353 delete it->second; 354 sDescriptors->erase(it); 355 356 if (sDescriptors->size() == 0) { 357 delete sDescriptors; 358 sDescriptors = NULL; 359 } 360 return error; 361 } 362 363 } // namespace BPrivate 364