1 // NodeHandle.cpp 2 3 #include "NodeHandle.h" 4 5 #include <errno.h> 6 #include <fcntl.h> 7 #include <string.h> 8 #include <unistd.h> 9 #include <sys/stat.h> 10 11 #include <fs_attr.h> 12 13 #include "Compatibility.h" 14 #include "Directory.h" 15 #include "FDManager.h" 16 #include "Path.h" 17 18 // TODO: Do the FD creation via the FDManager. 19 20 // NodeHandle 21 22 // constructor 23 NodeHandle::NodeHandle() 24 : BReferenceable(true), 25 Lockable(), 26 fCookie(-1), 27 fNodeRef() 28 { 29 } 30 31 // destructor 32 NodeHandle::~NodeHandle() 33 { 34 } 35 36 // GetStat 37 status_t 38 NodeHandle::GetStat(struct stat* st) 39 { 40 int fd = GetFD(); 41 if (fd < 0) 42 return B_ENTRY_NOT_FOUND; 43 44 if (fstat(fd, st) < 0) 45 return errno; 46 47 return B_OK; 48 } 49 50 // SetCookie 51 void 52 NodeHandle::SetCookie(int32 cookie) 53 { 54 fCookie = cookie; 55 } 56 57 // GetCookie 58 int32 59 NodeHandle::GetCookie() const 60 { 61 return fCookie; 62 } 63 64 // GetNodeRef 65 const NodeRef& 66 NodeHandle::GetNodeRef() const 67 { 68 return fNodeRef; 69 } 70 71 // GetFD 72 int 73 NodeHandle::GetFD() const 74 { 75 return -1; 76 } 77 78 79 // #pragma mark - 80 81 // FileHandle 82 83 // constructor 84 FileHandle::FileHandle() 85 : fFD(-1) 86 { 87 } 88 89 // destructor 90 FileHandle::~FileHandle() 91 { 92 Close(); 93 } 94 95 // Open 96 status_t 97 FileHandle::Open(Node* node, int openMode) 98 { 99 if (!node) 100 return B_BAD_VALUE; 101 102 openMode &= O_RWMASK | O_TRUNC | O_APPEND; 103 104 // get a path 105 Path path; 106 status_t error = node->GetPath(&path); 107 if (error != B_OK) 108 return error; 109 110 // open the file 111 error = FDManager::Open(path.GetPath(), openMode | O_NOTRAVERSE, 0, fFD); 112 if (error != B_OK) 113 return error; 114 115 fNodeRef = node->GetNodeRef(); 116 117 return B_OK; 118 } 119 120 // Close 121 status_t 122 FileHandle::Close() 123 { 124 if (fFD < 0) 125 return B_BAD_VALUE; 126 127 status_t error = B_OK; 128 if (close(fFD) < 0) 129 error = errno; 130 fFD = -1; 131 132 return error; 133 } 134 135 // Read 136 status_t 137 FileHandle::Read(off_t pos, void* buffer, size_t size, size_t* _bytesRead) 138 { 139 if (fFD < 0) 140 return B_BAD_VALUE; 141 142 ssize_t bytesRead = read_pos(fFD, pos, buffer, size); 143 if (bytesRead < 0) 144 return errno; 145 146 *_bytesRead = bytesRead; 147 return B_OK; 148 } 149 150 // Write 151 status_t 152 FileHandle::Write(off_t pos, const void* buffer, size_t size, 153 size_t* _bytesWritten) 154 { 155 if (fFD < 0) 156 return B_BAD_VALUE; 157 158 ssize_t bytesWritten = write_pos(fFD, pos, buffer, size); 159 if (bytesWritten < 0) 160 return errno; 161 162 *_bytesWritten = bytesWritten; 163 return B_OK; 164 } 165 166 // ReadAttr 167 status_t 168 FileHandle::ReadAttr(const char* name, uint32 type, off_t pos, void* buffer, 169 size_t size, size_t* _bytesRead) 170 { 171 if (fFD < 0) 172 return B_BAD_VALUE; 173 174 ssize_t bytesRead = fs_read_attr(fFD, name, type, pos, buffer, size); 175 if (bytesRead < 0) 176 return errno; 177 178 *_bytesRead = bytesRead; 179 return B_OK; 180 } 181 182 // WriteAttr 183 status_t 184 FileHandle::WriteAttr(const char* name, uint32 type, off_t pos, 185 const void* buffer, size_t size, size_t* _bytesWritten) 186 { 187 if (fFD < 0) 188 return B_BAD_VALUE; 189 190 ssize_t bytesWritten = fs_write_attr(fFD, name, type, pos, buffer, size); 191 if (bytesWritten < 0) 192 return errno; 193 194 *_bytesWritten = bytesWritten; 195 return B_OK; 196 } 197 198 // RemoveAttr 199 status_t 200 FileHandle::RemoveAttr(const char* name) 201 { 202 if (fFD < 0) 203 return B_BAD_VALUE; 204 205 return (fs_remove_attr(fFD, name) == 0 ? B_OK : errno); 206 } 207 208 // StatAttr 209 status_t 210 FileHandle::StatAttr(const char* name, attr_info* info) 211 { 212 if (fFD < 0) 213 return B_BAD_VALUE; 214 215 return (fs_stat_attr(fFD, name, info) == 0 ? B_OK : errno); 216 } 217 218 // GetFD 219 int 220 FileHandle::GetFD() const 221 { 222 return fFD; 223 } 224 225 226 // #pragma mark - 227 228 // DirIterator 229 230 // constructor 231 DirIterator::DirIterator() 232 : fDirectory(NULL) 233 { 234 } 235 236 // destructor 237 DirIterator::~DirIterator() 238 { 239 if (fDirectory) 240 fDirectory->RemoveDirIterator(this); 241 } 242 243 // IsValid 244 bool 245 DirIterator::IsValid() const 246 { 247 return fDirectory; 248 } 249 250 251 // #pragma mark - 252 253 // AttrDirIterator 254 255 // constructor 256 AttrDirIterator::AttrDirIterator() 257 : NodeHandle(), 258 fDir(NULL) 259 { 260 } 261 262 // destructor 263 AttrDirIterator::~AttrDirIterator() 264 { 265 Close(); 266 } 267 268 // Open 269 status_t 270 AttrDirIterator::Open(Node* node) 271 { 272 if (!node) 273 return B_BAD_VALUE; 274 275 // get a path 276 Path path; 277 status_t error = node->GetPath(&path); 278 if (error != B_OK) 279 return error; 280 281 // open the attribute directory 282 error = FDManager::OpenAttrDir(path.GetPath(), fDir); 283 if (error != B_OK) 284 return errno; 285 286 fNodeRef = node->GetNodeRef(); 287 288 return B_OK; 289 } 290 291 // Close 292 status_t 293 AttrDirIterator::Close() 294 { 295 if (!fDir) 296 return B_BAD_VALUE; 297 298 status_t error = B_OK; 299 if (fs_close_attr_dir(fDir) < 0) 300 error = errno; 301 302 fDir = NULL; 303 return error; 304 } 305 306 // ReadDir 307 status_t 308 AttrDirIterator::ReadDir(dirent* _entry, int32 bufferSize, 309 int32 count, int32* countRead, bool* done) 310 { 311 // TODO: Burst read. 312 if (!fDir) 313 return B_ENTRY_NOT_FOUND; 314 315 *countRead = 0; 316 *done = false; 317 318 if (count == 0) 319 return B_OK; 320 321 if (struct dirent* entry = fs_read_attr_dir(fDir)) { 322 size_t entryLen = entry->d_name + strlen(entry->d_name) + 1 323 - (char*)entry; 324 memcpy(_entry, entry, entryLen); 325 *countRead = 1; 326 } else { 327 *countRead = 0; 328 *done = true; 329 } 330 return B_OK; 331 } 332 333 // RewindDir 334 status_t 335 AttrDirIterator::RewindDir() 336 { 337 if (!fDir) 338 return B_ENTRY_NOT_FOUND; 339 340 fs_rewind_attr_dir(fDir); 341 342 return B_OK; 343 } 344 345 // GetFD 346 int 347 AttrDirIterator::GetFD() const 348 { 349 return dirfd(fDir); 350 } 351 352 353 // #pragma mark - 354 355 // QueryListener 356 357 // constructor 358 QueryListener::QueryListener() 359 { 360 } 361 362 // destructor 363 QueryListener::~QueryListener() 364 { 365 } 366 367 368 // #pragma mark - 369 370 // QueryHandle 371 372 // constructor 373 QueryHandle::QueryHandle(port_id remotePort, int32 remoteToken) 374 : NodeHandle(), 375 fRemotePort(remotePort), 376 fRemoteToken(remoteToken), 377 fQueries(), 378 fCurrentQuery(NULL), 379 fListener(NULL), 380 fClosed(false) 381 { 382 } 383 384 // destructor 385 QueryHandle::~QueryHandle() 386 { 387 Close(); 388 } 389 390 // SetQueryListener 391 void 392 QueryHandle::SetQueryListener(QueryListener* listener) 393 { 394 fListener = listener; 395 } 396 397 // GetQueryListener 398 QueryListener* 399 QueryHandle::GetQueryListener() const 400 { 401 return fListener; 402 } 403 404 // AddQuery 405 void 406 QueryHandle::AddQuery(Query* query) 407 { 408 if (query) { 409 fQueries.Insert(query); 410 if (!fCurrentQuery) 411 fCurrentQuery = query; 412 } 413 } 414 415 // RemoveQuery 416 void 417 QueryHandle::RemoveQuery(Query* query) 418 { 419 if (query) { 420 if (query == fCurrentQuery) 421 fCurrentQuery = fQueries.GetNext(query); 422 fQueries.Remove(query); 423 } 424 } 425 426 // GetRemotePort 427 port_id 428 QueryHandle::GetRemotePort() const 429 { 430 return fRemotePort; 431 } 432 433 // GetRemoteToken 434 int32 435 QueryHandle::GetRemoteToken() const 436 { 437 return fRemoteToken; 438 } 439 440 // Close 441 status_t 442 QueryHandle::Close() 443 { 444 if (fClosed) 445 return B_OK; 446 447 fCurrentQuery = NULL; 448 449 // delete all queries 450 for (DoublyLinkedList<Query>::Iterator it = fQueries.GetIterator(); 451 it.HasNext();) { 452 Query* query = it.Next(); 453 it.Remove(); 454 delete query; 455 } 456 457 fClosed = true; 458 459 if (fListener) 460 fListener->QueryHandleClosed(this); 461 462 return B_OK; 463 } 464 465 // ReadDir 466 status_t 467 QueryHandle::ReadDir(dirent* entry, int32 count, int32* countRead) 468 { 469 if (count == 0) { 470 *countRead = 0; 471 return B_OK; 472 } 473 while (fCurrentQuery) { 474 int32 readEntries = fCurrentQuery->GetNextDirents(entry, 475 sizeof(struct dirent) + B_FILE_NAME_LENGTH, 1); 476 if (readEntries < 0) 477 return readEntries; 478 if (readEntries > 0) { 479 *countRead = 1; 480 return B_OK; 481 } 482 fCurrentQuery = fQueries.GetNext(fCurrentQuery); 483 } 484 *countRead = 0; 485 return B_OK; 486 } 487 488