1/* 2 * Copyright 2002-2009, 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#include <umask.h> 23 24 25// Creates an uninitialized BFile. 26BFile::BFile() 27 : 28 fMode(0) 29{ 30} 31 32 33// Creates a copy of the supplied BFile. 34BFile::BFile(const BFile& file) 35 : 36 fMode(0) 37{ 38 *this = file; 39} 40 41 42// Creates a BFile and initializes it to the file referred to by 43// the supplied entry_ref and according to the specified open mode. 44BFile::BFile(const entry_ref* ref, uint32 openMode) 45 : 46 fMode(0) 47{ 48 SetTo(ref, openMode); 49} 50 51 52// Creates a BFile and initializes it to the file referred to by 53// the supplied BEntry and according to the specified open mode. 54BFile::BFile(const BEntry* entry, uint32 openMode) 55 : 56 fMode(0) 57{ 58 SetTo(entry, openMode); 59} 60 61 62// Creates a BFile and initializes it to the file referred to by 63// the supplied path name and according to the specified open mode. 64BFile::BFile(const char* path, uint32 openMode) 65 : 66 fMode(0) 67{ 68 SetTo(path, openMode); 69} 70 71 72// Creates a BFile and initializes it to the file referred to by 73// the supplied path name relative to the specified BDirectory and 74// according to the specified open mode. 75BFile::BFile(const BDirectory *dir, const char* path, uint32 openMode) 76 : 77 fMode(0) 78{ 79 SetTo(dir, path, openMode); 80} 81 82 83// Frees all allocated resources. 84BFile::~BFile() 85{ 86 // Also called by the BNode destructor, but we rather try to avoid 87 // problems with calling virtual functions in the base class destructor. 88 // Depending on the compiler implementation an object may be degraded to 89 // an object of the base class after the destructor of the derived class 90 // has been executed. 91 close_fd(); 92} 93 94 95// Re-initializes the BFile to the file referred to by the 96// supplied entry_ref and according to the specified open mode. 97status_t 98BFile::SetTo(const entry_ref* ref, uint32 openMode) 99{ 100 Unset(); 101 102 if (!ref) 103 return (fCStatus = B_BAD_VALUE); 104 105 // if ref->name is absolute, let the path-only SetTo() do the job 106 if (BPrivate::Storage::is_absolute_path(ref->name)) 107 return SetTo(ref->name, openMode); 108 109 openMode |= O_CLOEXEC; 110 111 int fd = _kern_open_entry_ref(ref->device, ref->directory, ref->name, 112 openMode, DEFFILEMODE & ~__gUmask); 113 if (fd >= 0) { 114 set_fd(fd); 115 fMode = openMode; 116 fCStatus = B_OK; 117 } else 118 fCStatus = fd; 119 120 return fCStatus; 121} 122 123 124// Re-initializes the BFile to the file referred to by the 125// supplied BEntry and according to the specified open mode. 126status_t 127BFile::SetTo(const BEntry* entry, uint32 openMode) 128{ 129 Unset(); 130 131 if (!entry) 132 return (fCStatus = B_BAD_VALUE); 133 if (entry->InitCheck() != B_OK) 134 return (fCStatus = entry->InitCheck()); 135 136 openMode |= O_CLOEXEC; 137 138 int fd = _kern_open(entry->fDirFd, entry->fName, openMode | O_CLOEXEC, 139 DEFFILEMODE & ~__gUmask); 140 if (fd >= 0) { 141 set_fd(fd); 142 fMode = openMode; 143 fCStatus = B_OK; 144 } else 145 fCStatus = fd; 146 147 return fCStatus; 148} 149 150 151// Re-initializes the BFile to the file referred to by the 152// supplied path name and according to the specified open mode. 153status_t 154BFile::SetTo(const char* path, uint32 openMode) 155{ 156 Unset(); 157 158 if (!path) 159 return (fCStatus = B_BAD_VALUE); 160 161 openMode |= O_CLOEXEC; 162 163 int fd = _kern_open(-1, path, openMode, DEFFILEMODE & ~__gUmask); 164 if (fd >= 0) { 165 set_fd(fd); 166 fMode = openMode; 167 fCStatus = B_OK; 168 } else 169 fCStatus = fd; 170 171 return fCStatus; 172} 173 174 175// Re-initializes the BFile to the file referred to by the 176// supplied path name relative to the specified BDirectory and 177// according to the specified open mode. 178status_t 179BFile::SetTo(const BDirectory* dir, const char* path, uint32 openMode) 180{ 181 Unset(); 182 183 if (!dir) 184 return (fCStatus = B_BAD_VALUE); 185 186 openMode |= O_CLOEXEC; 187 188 int fd = _kern_open(dir->fDirFd, path, openMode, DEFFILEMODE & ~__gUmask); 189 if (fd >= 0) { 190 set_fd(fd); 191 fMode = openMode; 192 fCStatus = B_OK; 193 } else 194 fCStatus = fd; 195 196 return fCStatus; 197} 198 199 200// Reports whether or not the file is readable. 201bool 202BFile::IsReadable() const 203{ 204 return InitCheck() == B_OK 205 && ((fMode & O_RWMASK) == O_RDONLY || (fMode & O_RWMASK) == O_RDWR); 206} 207 208 209// Reports whether or not the file is writable. 210bool 211BFile::IsWritable() const 212{ 213 return InitCheck() == B_OK 214 && ((fMode & O_RWMASK) == O_WRONLY || (fMode & O_RWMASK) == O_RDWR); 215} 216 217 218// Reads a number of bytes from the file into a buffer. 219ssize_t 220BFile::Read(void* buffer, size_t size) 221{ 222 if (InitCheck() != B_OK) 223 return InitCheck(); 224 return _kern_read(get_fd(), -1, buffer, size); 225} 226 227 228// Reads a number of bytes from a certain position within the file 229// into a buffer. 230ssize_t 231BFile::ReadAt(off_t location, void* buffer, size_t size) 232{ 233 if (InitCheck() != B_OK) 234 return InitCheck(); 235 if (location < 0) 236 return B_BAD_VALUE; 237 238 return _kern_read(get_fd(), location, buffer, size); 239} 240 241 242// Writes a number of bytes from a buffer into the file. 243ssize_t 244BFile::Write(const void* buffer, size_t size) 245{ 246 if (InitCheck() != B_OK) 247 return InitCheck(); 248 return _kern_write(get_fd(), -1, buffer, size); 249} 250 251 252// Writes a number of bytes from a buffer at a certain position 253// into the file. 254ssize_t 255BFile::WriteAt(off_t location, const void* buffer, size_t size) 256{ 257 if (InitCheck() != B_OK) 258 return InitCheck(); 259 if (location < 0) 260 return B_BAD_VALUE; 261 262 return _kern_write(get_fd(), location, buffer, size); 263} 264 265 266// Seeks to another read/write position within the file. 267off_t 268BFile::Seek(off_t offset, uint32 seekMode) 269{ 270 if (InitCheck() != B_OK) 271 return B_FILE_ERROR; 272 return _kern_seek(get_fd(), offset, seekMode); 273} 274 275 276// Gets the current read/write position within the file. 277off_t 278BFile::Position() const 279{ 280 if (InitCheck() != B_OK) 281 return B_FILE_ERROR; 282 return _kern_seek(get_fd(), 0, SEEK_CUR); 283} 284 285 286// Sets the size of the file. 287status_t 288BFile::SetSize(off_t size) 289{ 290 if (InitCheck() != B_OK) 291 return InitCheck(); 292 if (size < 0) 293 return B_BAD_VALUE; 294 struct stat statData; 295 statData.st_size = size; 296 return set_stat(statData, B_STAT_SIZE | B_STAT_SIZE_INSECURE); 297} 298 299 300// Gets the size of the file. 301status_t 302BFile::GetSize(off_t* size) const 303{ 304 return BStatable::GetSize(size); 305} 306 307 308// Assigns another BFile to this BFile. 309BFile& 310BFile::operator=(const BFile &file) 311{ 312 if (&file != this) { 313 // no need to assign us to ourselves 314 Unset(); 315 if (file.InitCheck() == B_OK) { 316 // duplicate the file descriptor 317 int fd = _kern_dup(file.get_fd()); 318 // set it 319 if (fd >= 0) { 320 fFd = fd; 321 fMode = file.fMode; 322 fCStatus = B_OK; 323 } else 324 fCStatus = fd; 325 } 326 } 327 return *this; 328} 329 330 331// FBC 332void BFile::_PhiloFile1() {} 333void BFile::_PhiloFile2() {} 334void BFile::_PhiloFile3() {} 335void BFile::_PhiloFile4() {} 336void BFile::_PhiloFile5() {} 337void BFile::_PhiloFile6() {} 338 339 340/*! Gets the file descriptor of the BFile. 341 342 To be used instead of accessing the BNode's private \c fFd member directly. 343 344 \returns The file descriptor, or -1 if not properly initialized. 345*/ 346int 347BFile::get_fd() const 348{ 349 return fFd; 350} 351 352 353//! Overrides BNode::close_fd() for binary compatibility with BeOS R5. 354void 355BFile::close_fd() 356{ 357 BNode::close_fd(); 358} 359