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 23NodeHandle::NodeHandle() 24 : BReferenceable(), 25 Lockable(), 26 fCookie(-1), 27 fNodeRef() 28{ 29} 30 31// destructor 32NodeHandle::~NodeHandle() 33{ 34} 35 36// GetStat 37status_t 38NodeHandle::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 51void 52NodeHandle::SetCookie(int32 cookie) 53{ 54 fCookie = cookie; 55} 56 57// GetCookie 58int32 59NodeHandle::GetCookie() const 60{ 61 return fCookie; 62} 63 64// GetNodeRef 65const NodeRef& 66NodeHandle::GetNodeRef() const 67{ 68 return fNodeRef; 69} 70 71// GetFD 72int 73NodeHandle::GetFD() const 74{ 75 return -1; 76} 77 78 79// #pragma mark - 80 81// FileHandle 82 83// constructor 84FileHandle::FileHandle() 85 : fFD(-1) 86{ 87} 88 89// destructor 90FileHandle::~FileHandle() 91{ 92 Close(); 93} 94 95// Open 96status_t 97FileHandle::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 121status_t 122FileHandle::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 136status_t 137FileHandle::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 151status_t 152FileHandle::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 167status_t 168FileHandle::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 183status_t 184FileHandle::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 199status_t 200FileHandle::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 209status_t 210FileHandle::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 219int 220FileHandle::GetFD() const 221{ 222 return fFD; 223} 224 225 226// #pragma mark - 227 228// DirIterator 229 230// constructor 231DirIterator::DirIterator() 232 : fDirectory(NULL) 233{ 234} 235 236// destructor 237DirIterator::~DirIterator() 238{ 239 if (fDirectory) 240 fDirectory->RemoveDirIterator(this); 241} 242 243// IsValid 244bool 245DirIterator::IsValid() const 246{ 247 return fDirectory; 248} 249 250 251// #pragma mark - 252 253// AttrDirIterator 254 255// constructor 256AttrDirIterator::AttrDirIterator() 257 : NodeHandle(), 258 fDir(NULL) 259{ 260} 261 262// destructor 263AttrDirIterator::~AttrDirIterator() 264{ 265 Close(); 266} 267 268// Open 269status_t 270AttrDirIterator::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 292status_t 293AttrDirIterator::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 307status_t 308AttrDirIterator::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 334status_t 335AttrDirIterator::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 346int 347AttrDirIterator::GetFD() const 348{ 349 return dirfd(fDir); 350} 351 352 353// #pragma mark - 354 355// QueryListener 356 357// constructor 358QueryListener::QueryListener() 359{ 360} 361 362// destructor 363QueryListener::~QueryListener() 364{ 365} 366 367 368// #pragma mark - 369 370// QueryHandle 371 372// constructor 373QueryHandle::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 385QueryHandle::~QueryHandle() 386{ 387 Close(); 388} 389 390// SetQueryListener 391void 392QueryHandle::SetQueryListener(QueryListener* listener) 393{ 394 fListener = listener; 395} 396 397// GetQueryListener 398QueryListener* 399QueryHandle::GetQueryListener() const 400{ 401 return fListener; 402} 403 404// AddQuery 405void 406QueryHandle::AddQuery(Query* query) 407{ 408 if (query) { 409 fQueries.Insert(query); 410 if (!fCurrentQuery) 411 fCurrentQuery = query; 412 } 413} 414 415// RemoveQuery 416void 417QueryHandle::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 427port_id 428QueryHandle::GetRemotePort() const 429{ 430 return fRemotePort; 431} 432 433// GetRemoteToken 434int32 435QueryHandle::GetRemoteToken() const 436{ 437 return fRemoteToken; 438} 439 440// Close 441status_t 442QueryHandle::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 466status_t 467QueryHandle::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