1 /* 2 * Copyright 2002-2008, Haiku Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Tyler Dauwalder 7 * Ingo Weinhold, bonefish@users.sf.net 8 */ 9 10 11 #include <fcntl.h> 12 #include <unistd.h> 13 14 #include <Directory.h> 15 #include <Entry.h> 16 #include <File.h> 17 #include <fs_interface.h> 18 #include <NodeMonitor.h> 19 20 #include <syscalls.h> 21 22 23 extern mode_t __gUmask; 24 // declared in sys/umask.c 25 26 27 //! Creates an uninitialized BFile. 28 BFile::BFile() 29 : BNode(), 30 BPositionIO(), 31 fMode(0) 32 { 33 } 34 35 36 //! Creates a copy of the supplied BFile. 37 /*! If \a file is uninitialized, the newly constructed BFile will be, too. 38 \param file the BFile object to be copied 39 */ 40 BFile::BFile(const BFile &file) 41 : BNode(), 42 BPositionIO(), 43 fMode(0) 44 { 45 *this = file; 46 } 47 48 49 /*! \brief Creates a BFile and initializes it to the file referred to by 50 the supplied entry_ref and according to the specified open mode. 51 \param ref the entry_ref referring to the file 52 \param openMode the mode in which the file should be opened 53 \see SetTo() for values for \a openMode 54 */ 55 BFile::BFile(const entry_ref *ref, uint32 openMode) 56 : BNode(), 57 BPositionIO(), 58 fMode(0) 59 { 60 SetTo(ref, openMode); 61 } 62 63 64 /*! \brief Creates a BFile and initializes it to the file referred to by 65 the supplied BEntry and according to the specified open mode. 66 \param entry the BEntry referring to the file 67 \param openMode the mode in which the file should be opened 68 \see SetTo() for values for \a openMode 69 */ 70 BFile::BFile(const BEntry *entry, uint32 openMode) 71 : BNode(), 72 BPositionIO(), 73 fMode(0) 74 { 75 SetTo(entry, openMode); 76 } 77 78 79 /*! \brief Creates a BFile and initializes it to the file referred to by 80 the supplied path name and according to the specified open mode. 81 \param path the file's path name 82 \param openMode the mode in which the file should be opened 83 \see SetTo() for values for \a openMode 84 */ 85 BFile::BFile(const char *path, uint32 openMode) 86 : BNode(), 87 BPositionIO(), 88 fMode(0) 89 { 90 SetTo(path, openMode); 91 } 92 93 94 /*! \brief Creates a BFile and initializes it to the file referred to by 95 the supplied path name relative to the specified BDirectory and 96 according to the specified open mode. 97 \param dir the BDirectory, relative to which the file's path name is 98 given 99 \param path the file's path name relative to \a dir 100 \param openMode the mode in which the file should be opened 101 \see SetTo() for values for \a openMode 102 */ 103 BFile::BFile(const BDirectory *dir, const char *path, uint32 openMode) 104 : BNode(), 105 BPositionIO(), 106 fMode(0) 107 { 108 SetTo(dir, path, openMode); 109 } 110 111 112 /*! \brief Frees all allocated resources. 113 If the file is properly initialized, the file's file descriptor is closed. 114 */ 115 BFile::~BFile() 116 { 117 // Also called by the BNode destructor, but we rather try to avoid 118 // problems with calling virtual functions in the base class destructor. 119 // Depending on the compiler implementation an object may be degraded to 120 // an object of the base class after the destructor of the derived class 121 // has been executed. 122 close_fd(); 123 } 124 125 126 /*! \brief Re-initializes the BFile to the file referred to by the 127 supplied entry_ref and according to the specified open mode. 128 \param ref the entry_ref referring to the file 129 \param openMode the mode in which the file should be opened 130 \a openMode must be a bitwise or of exactly one of the flags 131 - \c B_READ_ONLY: The file is opened read only. 132 - \c B_WRITE_ONLY: The file is opened write only. 133 - \c B_READ_WRITE: The file is opened for random read/write access. 134 and any number of the flags 135 - \c B_CREATE_FILE: A new file will be created, if it does not already 136 exist. 137 - \c B_FAIL_IF_EXISTS: If the file does already exist and B_CREATE_FILE is 138 set, SetTo() fails. 139 - \c B_ERASE_FILE: An already existing file is truncated to zero size. 140 - \c B_OPEN_AT_END: Seek() to the end of the file after opening. 141 \return 142 - \c B_OK: Everything went fine. 143 - \c B_BAD_VALUE: \c NULL \a ref or bad \a openMode. 144 - \c B_ENTRY_NOT_FOUND: File not found or failed to create file. 145 - \c B_FILE_EXISTS: File exists and \c B_FAIL_IF_EXISTS was passed. 146 - \c B_PERMISSION_DENIED: File permissions didn't allow operation. 147 - \c B_NO_MEMORY: Insufficient memory for operation. 148 - \c B_LINK_LIMIT: Indicates a cyclic loop within the file system. 149 - \c B_BUSY: A node was busy. 150 - \c B_FILE_ERROR: A general file error. 151 - \c B_NO_MORE_FDS: The application has run out of file descriptors. 152 */ 153 status_t 154 BFile::SetTo(const entry_ref *ref, uint32 openMode) 155 { 156 Unset(); 157 158 if (!ref) 159 return (fCStatus = B_BAD_VALUE); 160 161 openMode |= O_CLOEXEC; 162 163 int fd = _kern_open_entry_ref(ref->device, ref->directory, ref->name, 164 openMode, DEFFILEMODE & ~__gUmask); 165 if (fd >= 0) { 166 set_fd(fd); 167 fMode = openMode; 168 fCStatus = B_OK; 169 } else 170 fCStatus = fd; 171 172 return fCStatus; 173 } 174 175 176 /*! \brief Re-initializes the BFile to the file referred to by the 177 supplied BEntry and according to the specified open mode. 178 \param entry the BEntry referring to the file 179 \param openMode the mode in which the file should be opened 180 \return 181 - \c B_OK: Everything went fine. 182 - \c B_BAD_VALUE: \c NULL \a entry or bad \a openMode. 183 - \c B_ENTRY_NOT_FOUND: File not found or failed to create file. 184 - \c B_FILE_EXISTS: File exists and \c B_FAIL_IF_EXISTS was passed. 185 - \c B_PERMISSION_DENIED: File permissions didn't allow operation. 186 - \c B_NO_MEMORY: Insufficient memory for operation. 187 - \c B_LINK_LIMIT: Indicates a cyclic loop within the file system. 188 - \c B_BUSY: A node was busy. 189 - \c B_FILE_ERROR: A general file error. 190 - \c B_NO_MORE_FDS: The application has run out of file descriptors. 191 \todo Implemented using SetTo(entry_ref*, uint32). Check, if necessary 192 to reimplement! 193 */ 194 status_t 195 BFile::SetTo(const BEntry *entry, uint32 openMode) 196 { 197 Unset(); 198 199 if (!entry) 200 return (fCStatus = B_BAD_VALUE); 201 if (entry->InitCheck() != B_OK) 202 return (fCStatus = entry->InitCheck()); 203 204 openMode |= O_CLOEXEC; 205 206 int fd = _kern_open(entry->fDirFd, entry->fName, openMode | O_CLOEXEC, 207 DEFFILEMODE & ~__gUmask); 208 if (fd >= 0) { 209 set_fd(fd); 210 fMode = openMode; 211 fCStatus = B_OK; 212 } else 213 fCStatus = fd; 214 215 return fCStatus; 216 } 217 218 219 /*! \brief Re-initializes the BFile to the file referred to by the 220 supplied path name and according to the specified open mode. 221 \param path the file's path name 222 \param openMode the mode in which the file should be opened 223 \return 224 - \c B_OK: Everything went fine. 225 - \c B_BAD_VALUE: \c NULL \a path or bad \a openMode. 226 - \c B_ENTRY_NOT_FOUND: File not found or failed to create file. 227 - \c B_FILE_EXISTS: File exists and \c B_FAIL_IF_EXISTS was passed. 228 - \c B_PERMISSION_DENIED: File permissions didn't allow operation. 229 - \c B_NO_MEMORY: Insufficient memory for operation. 230 - \c B_LINK_LIMIT: Indicates a cyclic loop within the file system. 231 - \c B_BUSY: A node was busy. 232 - \c B_FILE_ERROR: A general file error. 233 - \c B_NO_MORE_FDS: The application has run out of file descriptors. 234 */ 235 status_t 236 BFile::SetTo(const char *path, uint32 openMode) 237 { 238 Unset(); 239 240 if (!path) 241 return (fCStatus = B_BAD_VALUE); 242 243 openMode |= O_CLOEXEC; 244 245 int fd = _kern_open(-1, path, openMode, DEFFILEMODE & ~__gUmask); 246 if (fd >= 0) { 247 set_fd(fd); 248 fMode = openMode; 249 fCStatus = B_OK; 250 } else 251 fCStatus = fd; 252 253 return fCStatus; 254 } 255 256 257 /*! \brief Re-initializes the BFile to the file referred to by the 258 supplied path name relative to the specified BDirectory and 259 according to the specified open mode. 260 \param dir the BDirectory, relative to which the file's path name is 261 given 262 \param path the file's path name relative to \a dir 263 \param openMode the mode in which the file should be opened 264 - \c B_OK: Everything went fine. 265 - \c B_BAD_VALUE: \c NULL \a dir or \a path or bad \a openMode. 266 - \c B_ENTRY_NOT_FOUND: File not found or failed to create file. 267 - \c B_FILE_EXISTS: File exists and \c B_FAIL_IF_EXISTS was passed. 268 - \c B_PERMISSION_DENIED: File permissions didn't allow operation. 269 - \c B_NO_MEMORY: Insufficient memory for operation. 270 - \c B_LINK_LIMIT: Indicates a cyclic loop within the file system. 271 - \c B_BUSY: A node was busy. 272 - \c B_FILE_ERROR: A general file error. 273 - \c B_NO_MORE_FDS: The application has run out of file descriptors. 274 \todo Implemented using SetTo(BEntry*, uint32). Check, if necessary 275 to reimplement! 276 */ 277 status_t 278 BFile::SetTo(const BDirectory *dir, const char *path, uint32 openMode) 279 { 280 Unset(); 281 282 if (!dir) 283 return (fCStatus = B_BAD_VALUE); 284 285 openMode |= O_CLOEXEC; 286 287 int fd = _kern_open(dir->fDirFd, path, openMode, DEFFILEMODE & ~__gUmask); 288 if (fd >= 0) { 289 set_fd(fd); 290 fMode = openMode; 291 fCStatus = B_OK; 292 } else 293 fCStatus = fd; 294 295 return fCStatus; 296 } 297 298 299 /*! \brief Returns whether the file is readable. 300 \return 301 - \c true, if the BFile has been initialized properly and the file has 302 been been opened for reading, 303 - \c false, otherwise. 304 */ 305 bool 306 BFile::IsReadable() const 307 { 308 return InitCheck() == B_OK 309 && ((fMode & O_RWMASK) == O_RDONLY || (fMode & O_RWMASK) == O_RDWR); 310 } 311 312 313 /*! \brief Returns whether the file is writable. 314 \return 315 - \c true, if the BFile has been initialized properly and the file has 316 been opened for writing, 317 - \c false, otherwise. 318 */ 319 bool 320 BFile::IsWritable() const 321 { 322 return InitCheck() == B_OK 323 && ((fMode & O_RWMASK) == O_WRONLY || (fMode & O_RWMASK) == O_RDWR); 324 } 325 326 327 /*! \brief Reads a number of bytes from the file into a buffer. 328 \param buffer the buffer the data from the file shall be written to 329 \param size the number of bytes that shall be read 330 \return the number of bytes actually read or an error code 331 */ 332 ssize_t 333 BFile::Read(void *buffer, size_t size) 334 { 335 if (InitCheck() != B_OK) 336 return InitCheck(); 337 return _kern_read(get_fd(), -1, buffer, size); 338 } 339 340 341 /*! \brief Reads a number of bytes from a certain position within the file 342 into a buffer. 343 \param location the position (in bytes) within the file from which the 344 data shall be read 345 \param buffer the buffer the data from the file shall be written to 346 \param size the number of bytes that shall be read 347 \return the number of bytes actually read or an error code 348 */ 349 ssize_t 350 BFile::ReadAt(off_t location, void *buffer, size_t size) 351 { 352 if (InitCheck() != B_OK) 353 return InitCheck(); 354 if (location < 0) 355 return B_BAD_VALUE; 356 357 return _kern_read(get_fd(), location, buffer, size); 358 } 359 360 361 /*! \brief Writes a number of bytes from a buffer into the file. 362 \param buffer the buffer containing the data to be written to the file 363 \param size the number of bytes that shall be written 364 \return the number of bytes actually written or an error code 365 */ 366 ssize_t 367 BFile::Write(const void *buffer, size_t size) 368 { 369 if (InitCheck() != B_OK) 370 return InitCheck(); 371 return _kern_write(get_fd(), -1, buffer, size); 372 } 373 374 375 /*! \brief Writes a number of bytes from a buffer at a certain position 376 into the file. 377 \param location the position (in bytes) within the file at which the data 378 shall be written 379 \param buffer the buffer containing the data to be written to the file 380 \param size the number of bytes that shall be written 381 \return the number of bytes actually written or an error code 382 */ 383 ssize_t 384 BFile::WriteAt(off_t location, const void *buffer, size_t size) 385 { 386 if (InitCheck() != B_OK) 387 return InitCheck(); 388 if (location < 0) 389 return B_BAD_VALUE; 390 391 return _kern_write(get_fd(), location, buffer, size); 392 } 393 394 395 /*! \brief Seeks to another read/write position within the file. 396 It is allowed to seek past the end of the file. A subsequent call to 397 Write() will pad the file with undefined data. Seeking before the 398 beginning of the file will fail and the behavior of subsequent Read() 399 or Write() invocations will be undefined. 400 \param offset new read/write position, depending on \a seekMode relative 401 to the beginning or the end of the file or the current position 402 \param seekMode: 403 - \c SEEK_SET: move relative to the beginning of the file 404 - \c SEEK_CUR: move relative to the current position 405 - \c SEEK_END: move relative to the end of the file 406 \return 407 - the new read/write position relative to the beginning of the file 408 - \c B_ERROR when trying to seek before the beginning of the file 409 - \c B_FILE_ERROR, if the file is not properly initialized 410 */ 411 off_t 412 BFile::Seek(off_t offset, uint32 seekMode) 413 { 414 if (InitCheck() != B_OK) 415 return B_FILE_ERROR; 416 return _kern_seek(get_fd(), offset, seekMode); 417 } 418 419 420 /*! \brief Returns the current read/write position within the file. 421 \return 422 - the current read/write position relative to the beginning of the file 423 - \c B_ERROR, after a Seek() before the beginning of the file 424 - \c B_FILE_ERROR, if the file has not been initialized 425 */ 426 off_t 427 BFile::Position() const 428 { 429 if (InitCheck() != B_OK) 430 return B_FILE_ERROR; 431 return _kern_seek(get_fd(), 0, SEEK_CUR); 432 } 433 434 435 /*! \brief Sets the size of the file. 436 If the file is shorter than \a size bytes it will be padded with 437 unspecified data to the requested size. If it is larger, it will be 438 truncated. 439 Note: There's no problem with setting the size of a BFile opened in 440 \c B_READ_ONLY mode, unless the file resides on a read only volume. 441 \param size the new file size 442 \return 443 - \c B_OK, if everything went fine 444 - \c B_NOT_ALLOWED, if trying to set the size of a file on a read only 445 volume 446 - \c B_DEVICE_FULL, if there's not enough space left on the volume 447 */ 448 status_t 449 BFile::SetSize(off_t size) 450 { 451 if (InitCheck() != B_OK) 452 return InitCheck(); 453 if (size < 0) 454 return B_BAD_VALUE; 455 struct stat statData; 456 statData.st_size = size; 457 return set_stat(statData, B_STAT_SIZE | B_STAT_SIZE_INSECURE); 458 } 459 460 461 status_t 462 BFile::GetSize(off_t* size) const 463 { 464 return BStatable::GetSize(size); 465 } 466 467 468 /*! \brief Assigns another BFile to this BFile. 469 If the other BFile is uninitialized, this one will be too. Otherwise it 470 will refer to the same file using the same mode, unless an error occurs. 471 \param file the original BFile 472 \return a reference to this BFile 473 */ 474 BFile & 475 BFile::operator=(const BFile &file) 476 { 477 if (&file != this) { // no need to assign us to ourselves 478 Unset(); 479 if (file.InitCheck() == B_OK) { 480 // duplicate the file descriptor 481 int fd = _kern_dup(file.get_fd()); 482 // set it 483 if (fd >= 0) { 484 fFd = fd; 485 fMode = file.fMode; 486 fCStatus = B_OK; 487 } else 488 fCStatus = fd; 489 } 490 } 491 return *this; 492 } 493 494 495 // FBC 496 void BFile::_PhiloFile1() {} 497 void BFile::_PhiloFile2() {} 498 void BFile::_PhiloFile3() {} 499 void BFile::_PhiloFile4() {} 500 void BFile::_PhiloFile5() {} 501 void BFile::_PhiloFile6() {} 502 503 504 /*! Returns the file descriptor. 505 To be used instead of accessing the BNode's private \c fFd member directly. 506 \return the file descriptor, or -1, if not properly initialized. 507 */ 508 int 509 BFile::get_fd() const 510 { 511 return fFd; 512 } 513 514 515 /*! Overrides BNode::close_fd() solely for R5 binary compatibility. 516 */ 517 void 518 BFile::close_fd() 519 { 520 BNode::close_fd(); 521 } 522 523