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