15905a0aeSAxel Dörfler /* 2160f2d10SAxel Dörfler * Copyright 2002-2009, Haiku Inc. 35905a0aeSAxel Dörfler * Distributed under the terms of the MIT License. 45905a0aeSAxel Dörfler * 55905a0aeSAxel Dörfler * Authors: 65905a0aeSAxel Dörfler * Tyler Dauwalder 75905a0aeSAxel Dörfler * Ingo Weinhold, bonefish@users.sf.net 852a38012Sejakowatz */ 952a38012Sejakowatz 105905a0aeSAxel Dörfler 11b06942c6SIngo Weinhold #include <fcntl.h> 12ca9e5772SIngo Weinhold #include <unistd.h> 1352a38012Sejakowatz 14db10640dSIngo Weinhold #include <Directory.h> 1552a38012Sejakowatz #include <Entry.h> 1652a38012Sejakowatz #include <File.h> 17a121b8c8SAxel Dörfler #include <fs_interface.h> 18b38c9e18SAxel Dörfler #include <NodeMonitor.h> 190af6bcebSOliver Tappe #include "storage_support.h" 20db10640dSIngo Weinhold 21db10640dSIngo Weinhold #include <syscalls.h> 22160f2d10SAxel Dörfler #include <umask.h> 233af4214aSAxel Dörfler 243af4214aSAxel Dörfler 25*e9191cc2SJohn Scipione // Creates an uninitialized BFile. 2652a38012Sejakowatz BFile::BFile() 27160f2d10SAxel Dörfler : 2852a38012Sejakowatz fMode(0) 2952a38012Sejakowatz { 3052a38012Sejakowatz } 3152a38012Sejakowatz 325905a0aeSAxel Dörfler 33*e9191cc2SJohn Scipione // Creates a copy of the supplied BFile. 3452a38012Sejakowatz BFile::BFile(const BFile& file) 35160f2d10SAxel Dörfler : 3652a38012Sejakowatz fMode(0) 3752a38012Sejakowatz { 3852a38012Sejakowatz *this = file; 3952a38012Sejakowatz } 4052a38012Sejakowatz 415905a0aeSAxel Dörfler 42*e9191cc2SJohn Scipione // Creates a BFile and initializes it to the file referred to by 43*e9191cc2SJohn Scipione // the supplied entry_ref and according to the specified open mode. 4452a38012Sejakowatz BFile::BFile(const entry_ref* ref, uint32 openMode) 45160f2d10SAxel Dörfler : 4652a38012Sejakowatz fMode(0) 4752a38012Sejakowatz { 4852a38012Sejakowatz SetTo(ref, openMode); 4952a38012Sejakowatz } 5052a38012Sejakowatz 515905a0aeSAxel Dörfler 52*e9191cc2SJohn Scipione // Creates a BFile and initializes it to the file referred to by 53*e9191cc2SJohn Scipione // the supplied BEntry and according to the specified open mode. 5452a38012Sejakowatz BFile::BFile(const BEntry* entry, uint32 openMode) 55160f2d10SAxel Dörfler : 5652a38012Sejakowatz fMode(0) 5752a38012Sejakowatz { 5852a38012Sejakowatz SetTo(entry, openMode); 5952a38012Sejakowatz } 6052a38012Sejakowatz 615905a0aeSAxel Dörfler 62*e9191cc2SJohn Scipione // Creates a BFile and initializes it to the file referred to by 63*e9191cc2SJohn Scipione // the supplied path name and according to the specified open mode. 6452a38012Sejakowatz BFile::BFile(const char* path, uint32 openMode) 65160f2d10SAxel Dörfler : 6652a38012Sejakowatz fMode(0) 6752a38012Sejakowatz { 6852a38012Sejakowatz SetTo(path, openMode); 6952a38012Sejakowatz } 7052a38012Sejakowatz 715905a0aeSAxel Dörfler 72*e9191cc2SJohn Scipione // Creates a BFile and initializes it to the file referred to by 73*e9191cc2SJohn Scipione // the supplied path name relative to the specified BDirectory and 74*e9191cc2SJohn Scipione // according to the specified open mode. 7523d36867Sbeveloper BFile::BFile(const BDirectory *dir, const char* path, uint32 openMode) 76160f2d10SAxel Dörfler : 7752a38012Sejakowatz fMode(0) 7852a38012Sejakowatz { 7952a38012Sejakowatz SetTo(dir, path, openMode); 8052a38012Sejakowatz } 8152a38012Sejakowatz 825905a0aeSAxel Dörfler 83*e9191cc2SJohn Scipione // Frees all allocated resources. 8452a38012Sejakowatz BFile::~BFile() 8552a38012Sejakowatz { 8652a38012Sejakowatz // Also called by the BNode destructor, but we rather try to avoid 8752a38012Sejakowatz // problems with calling virtual functions in the base class destructor. 8852a38012Sejakowatz // Depending on the compiler implementation an object may be degraded to 8952a38012Sejakowatz // an object of the base class after the destructor of the derived class 9052a38012Sejakowatz // has been executed. 9152a38012Sejakowatz close_fd(); 9252a38012Sejakowatz } 9352a38012Sejakowatz 945905a0aeSAxel Dörfler 95*e9191cc2SJohn Scipione // Re-initializes the BFile to the file referred to by the 96*e9191cc2SJohn Scipione // supplied entry_ref and according to the specified open mode. 9752a38012Sejakowatz status_t 9852a38012Sejakowatz BFile::SetTo(const entry_ref* ref, uint32 openMode) 9952a38012Sejakowatz { 10052a38012Sejakowatz Unset(); 101b06942c6SIngo Weinhold 102db10640dSIngo Weinhold if (!ref) 103db10640dSIngo Weinhold return (fCStatus = B_BAD_VALUE); 104b06942c6SIngo Weinhold 1050af6bcebSOliver Tappe // if ref->name is absolute, let the path-only SetTo() do the job 1060af6bcebSOliver Tappe if (BPrivate::Storage::is_absolute_path(ref->name)) 1070af6bcebSOliver Tappe return SetTo(ref->name, openMode); 1080af6bcebSOliver Tappe 109b06942c6SIngo Weinhold openMode |= O_CLOEXEC; 110b06942c6SIngo Weinhold 111db10640dSIngo Weinhold int fd = _kern_open_entry_ref(ref->device, ref->directory, ref->name, 1123af4214aSAxel Dörfler openMode, DEFFILEMODE & ~__gUmask); 113db10640dSIngo Weinhold if (fd >= 0) { 114db10640dSIngo Weinhold set_fd(fd); 115db10640dSIngo Weinhold fMode = openMode; 116db10640dSIngo Weinhold fCStatus = B_OK; 117db10640dSIngo Weinhold } else 118db10640dSIngo Weinhold fCStatus = fd; 119b06942c6SIngo Weinhold 120db10640dSIngo Weinhold return fCStatus; 12152a38012Sejakowatz } 12252a38012Sejakowatz 1235905a0aeSAxel Dörfler 124*e9191cc2SJohn Scipione // Re-initializes the BFile to the file referred to by the 125*e9191cc2SJohn Scipione // supplied BEntry and according to the specified open mode. 12652a38012Sejakowatz status_t 12752a38012Sejakowatz BFile::SetTo(const BEntry* entry, uint32 openMode) 12852a38012Sejakowatz { 12952a38012Sejakowatz Unset(); 130b06942c6SIngo Weinhold 131db10640dSIngo Weinhold if (!entry) 132db10640dSIngo Weinhold return (fCStatus = B_BAD_VALUE); 133db10640dSIngo Weinhold if (entry->InitCheck() != B_OK) 134db10640dSIngo Weinhold return (fCStatus = entry->InitCheck()); 135b06942c6SIngo Weinhold 136b06942c6SIngo Weinhold openMode |= O_CLOEXEC; 137b06942c6SIngo Weinhold 1383af4214aSAxel Dörfler int fd = _kern_open(entry->fDirFd, entry->fName, openMode | O_CLOEXEC, 1393af4214aSAxel Dörfler DEFFILEMODE & ~__gUmask); 140db10640dSIngo Weinhold if (fd >= 0) { 141db10640dSIngo Weinhold set_fd(fd); 142db10640dSIngo Weinhold fMode = openMode; 143db10640dSIngo Weinhold fCStatus = B_OK; 144db10640dSIngo Weinhold } else 145db10640dSIngo Weinhold fCStatus = fd; 146b06942c6SIngo Weinhold 147db10640dSIngo Weinhold return fCStatus; 14852a38012Sejakowatz } 14952a38012Sejakowatz 1505905a0aeSAxel Dörfler 151*e9191cc2SJohn Scipione // Re-initializes the BFile to the file referred to by the 152*e9191cc2SJohn Scipione // supplied path name and according to the specified open mode. 15352a38012Sejakowatz status_t 15452a38012Sejakowatz BFile::SetTo(const char* path, uint32 openMode) 15552a38012Sejakowatz { 15652a38012Sejakowatz Unset(); 157b06942c6SIngo Weinhold 158db10640dSIngo Weinhold if (!path) 159db10640dSIngo Weinhold return (fCStatus = B_BAD_VALUE); 160b06942c6SIngo Weinhold 161b06942c6SIngo Weinhold openMode |= O_CLOEXEC; 162b06942c6SIngo Weinhold 1633af4214aSAxel Dörfler int fd = _kern_open(-1, path, openMode, DEFFILEMODE & ~__gUmask); 164db10640dSIngo Weinhold if (fd >= 0) { 165db10640dSIngo Weinhold set_fd(fd); 166db10640dSIngo Weinhold fMode = openMode; 167db10640dSIngo Weinhold fCStatus = B_OK; 16852a38012Sejakowatz } else 169db10640dSIngo Weinhold fCStatus = fd; 170b06942c6SIngo Weinhold 171db10640dSIngo Weinhold return fCStatus; 17252a38012Sejakowatz } 17352a38012Sejakowatz 1745905a0aeSAxel Dörfler 175*e9191cc2SJohn Scipione // Re-initializes the BFile to the file referred to by the 176*e9191cc2SJohn Scipione // supplied path name relative to the specified BDirectory and 177*e9191cc2SJohn Scipione // according to the specified open mode. 17852a38012Sejakowatz status_t 17952a38012Sejakowatz BFile::SetTo(const BDirectory* dir, const char* path, uint32 openMode) 18052a38012Sejakowatz { 18152a38012Sejakowatz Unset(); 182b06942c6SIngo Weinhold 183db10640dSIngo Weinhold if (!dir) 184db10640dSIngo Weinhold return (fCStatus = B_BAD_VALUE); 185b06942c6SIngo Weinhold 186b06942c6SIngo Weinhold openMode |= O_CLOEXEC; 187b06942c6SIngo Weinhold 1883af4214aSAxel Dörfler int fd = _kern_open(dir->fDirFd, path, openMode, DEFFILEMODE & ~__gUmask); 189db10640dSIngo Weinhold if (fd >= 0) { 190db10640dSIngo Weinhold set_fd(fd); 191db10640dSIngo Weinhold fMode = openMode; 192db10640dSIngo Weinhold fCStatus = B_OK; 193db10640dSIngo Weinhold } else 194db10640dSIngo Weinhold fCStatus = fd; 195b06942c6SIngo Weinhold 196db10640dSIngo Weinhold return fCStatus; 19752a38012Sejakowatz } 19852a38012Sejakowatz 1995905a0aeSAxel Dörfler 200*e9191cc2SJohn Scipione // Reports whether or not the file is readable. 20152a38012Sejakowatz bool 20252a38012Sejakowatz BFile::IsReadable() const 20352a38012Sejakowatz { 2045905a0aeSAxel Dörfler return InitCheck() == B_OK 2055905a0aeSAxel Dörfler && ((fMode & O_RWMASK) == O_RDONLY || (fMode & O_RWMASK) == O_RDWR); 20652a38012Sejakowatz } 20752a38012Sejakowatz 2085905a0aeSAxel Dörfler 209*e9191cc2SJohn Scipione // Reports whether or not the file is writable. 21052a38012Sejakowatz bool 21152a38012Sejakowatz BFile::IsWritable() const 21252a38012Sejakowatz { 2135905a0aeSAxel Dörfler return InitCheck() == B_OK 2145905a0aeSAxel Dörfler && ((fMode & O_RWMASK) == O_WRONLY || (fMode & O_RWMASK) == O_RDWR); 21552a38012Sejakowatz } 21652a38012Sejakowatz 2175905a0aeSAxel Dörfler 218*e9191cc2SJohn Scipione // Reads a number of bytes from the file into a buffer. 21952a38012Sejakowatz ssize_t 22052a38012Sejakowatz BFile::Read(void* buffer, size_t size) 22152a38012Sejakowatz { 222db10640dSIngo Weinhold if (InitCheck() != B_OK) 223db10640dSIngo Weinhold return InitCheck(); 224db10640dSIngo Weinhold return _kern_read(get_fd(), -1, buffer, size); 22552a38012Sejakowatz } 22652a38012Sejakowatz 2275905a0aeSAxel Dörfler 228*e9191cc2SJohn Scipione // Reads a number of bytes from a certain position within the file 229*e9191cc2SJohn Scipione // into a buffer. 23052a38012Sejakowatz ssize_t 23152a38012Sejakowatz BFile::ReadAt(off_t location, void* buffer, size_t size) 23252a38012Sejakowatz { 233db10640dSIngo Weinhold if (InitCheck() != B_OK) 234db10640dSIngo Weinhold return InitCheck(); 235db10640dSIngo Weinhold if (location < 0) 236db10640dSIngo Weinhold return B_BAD_VALUE; 2373debfe51SBruno G. Albuquerque 2385905a0aeSAxel Dörfler return _kern_read(get_fd(), location, buffer, size); 23952a38012Sejakowatz } 24052a38012Sejakowatz 2415905a0aeSAxel Dörfler 242*e9191cc2SJohn Scipione // Writes a number of bytes from a buffer into the file. 24352a38012Sejakowatz ssize_t 24452a38012Sejakowatz BFile::Write(const void* buffer, size_t size) 24552a38012Sejakowatz { 246db10640dSIngo Weinhold if (InitCheck() != B_OK) 247db10640dSIngo Weinhold return InitCheck(); 248db10640dSIngo Weinhold return _kern_write(get_fd(), -1, buffer, size); 24952a38012Sejakowatz } 25052a38012Sejakowatz 2515905a0aeSAxel Dörfler 252*e9191cc2SJohn Scipione // Writes a number of bytes from a buffer at a certain position 253*e9191cc2SJohn Scipione // into the file. 25452a38012Sejakowatz ssize_t 25552a38012Sejakowatz BFile::WriteAt(off_t location, const void* buffer, size_t size) 25652a38012Sejakowatz { 257db10640dSIngo Weinhold if (InitCheck() != B_OK) 258db10640dSIngo Weinhold return InitCheck(); 259db10640dSIngo Weinhold if (location < 0) 260db10640dSIngo Weinhold return B_BAD_VALUE; 26140da55c3SStephan Aßmus 2625905a0aeSAxel Dörfler return _kern_write(get_fd(), location, buffer, size); 26352a38012Sejakowatz } 26452a38012Sejakowatz 2655905a0aeSAxel Dörfler 266*e9191cc2SJohn Scipione // Seeks to another read/write position within the file. 26752a38012Sejakowatz off_t 26852a38012Sejakowatz BFile::Seek(off_t offset, uint32 seekMode) 26952a38012Sejakowatz { 270db10640dSIngo Weinhold if (InitCheck() != B_OK) 271db10640dSIngo Weinhold return B_FILE_ERROR; 272db10640dSIngo Weinhold return _kern_seek(get_fd(), offset, seekMode); 27352a38012Sejakowatz } 27452a38012Sejakowatz 2755905a0aeSAxel Dörfler 276*e9191cc2SJohn Scipione // Gets the current read/write position within the file. 27752a38012Sejakowatz off_t 27852a38012Sejakowatz BFile::Position() const 27952a38012Sejakowatz { 280db10640dSIngo Weinhold if (InitCheck() != B_OK) 281db10640dSIngo Weinhold return B_FILE_ERROR; 282db10640dSIngo Weinhold return _kern_seek(get_fd(), 0, SEEK_CUR); 28352a38012Sejakowatz } 28452a38012Sejakowatz 2855905a0aeSAxel Dörfler 286*e9191cc2SJohn Scipione // Sets the size of the file. 28752a38012Sejakowatz status_t 28852a38012Sejakowatz BFile::SetSize(off_t size) 28952a38012Sejakowatz { 290db10640dSIngo Weinhold if (InitCheck() != B_OK) 291db10640dSIngo Weinhold return InitCheck(); 292db10640dSIngo Weinhold if (size < 0) 293db10640dSIngo Weinhold return B_BAD_VALUE; 29452a38012Sejakowatz struct stat statData; 29552a38012Sejakowatz statData.st_size = size; 296a121b8c8SAxel Dörfler return set_stat(statData, B_STAT_SIZE | B_STAT_SIZE_INSECURE); 29752a38012Sejakowatz } 29852a38012Sejakowatz 2995905a0aeSAxel Dörfler 300*e9191cc2SJohn Scipione // Gets the size of the file. 30139c991c0SStephan Aßmus status_t 30239c991c0SStephan Aßmus BFile::GetSize(off_t* size) const 30339c991c0SStephan Aßmus { 30439c991c0SStephan Aßmus return BStatable::GetSize(size); 30539c991c0SStephan Aßmus } 30639c991c0SStephan Aßmus 3075905a0aeSAxel Dörfler 308*e9191cc2SJohn Scipione // Assigns another BFile to this BFile. 30952a38012Sejakowatz BFile& 31052a38012Sejakowatz BFile::operator=(const BFile &file) 31152a38012Sejakowatz { 312*e9191cc2SJohn Scipione if (&file != this) { 313*e9191cc2SJohn Scipione // no need to assign us to ourselves 31452a38012Sejakowatz Unset(); 31552a38012Sejakowatz if (file.InitCheck() == B_OK) { 31652a38012Sejakowatz // duplicate the file descriptor 317db10640dSIngo Weinhold int fd = _kern_dup(file.get_fd()); 31852a38012Sejakowatz // set it 319db10640dSIngo Weinhold if (fd >= 0) { 320db10640dSIngo Weinhold fFd = fd; 32152a38012Sejakowatz fMode = file.fMode; 322db10640dSIngo Weinhold fCStatus = B_OK; 323db10640dSIngo Weinhold } else 324db10640dSIngo Weinhold fCStatus = fd; 32552a38012Sejakowatz } 32652a38012Sejakowatz } 32752a38012Sejakowatz return *this; 32852a38012Sejakowatz } 32952a38012Sejakowatz 33052a38012Sejakowatz 33152a38012Sejakowatz // FBC 3327c44680aSIngo Weinhold void BFile::_PhiloFile1() {} 3337c44680aSIngo Weinhold void BFile::_PhiloFile2() {} 3347c44680aSIngo Weinhold void BFile::_PhiloFile3() {} 3357c44680aSIngo Weinhold void BFile::_PhiloFile4() {} 3367c44680aSIngo Weinhold void BFile::_PhiloFile5() {} 3377c44680aSIngo Weinhold void BFile::_PhiloFile6() {} 33852a38012Sejakowatz 33952a38012Sejakowatz 340*e9191cc2SJohn Scipione // Gets the file descriptor of the BFile. 341db10640dSIngo Weinhold int 34252a38012Sejakowatz BFile::get_fd() const 34352a38012Sejakowatz { 34452a38012Sejakowatz return fFd; 34552a38012Sejakowatz } 34652a38012Sejakowatz 3475905a0aeSAxel Dörfler 348*e9191cc2SJohn Scipione // Overrides BNode::close_fd() for binary compatibility with BeOS R5. 3494b9ec73eSIngo Weinhold void 3504b9ec73eSIngo Weinhold BFile::close_fd() 3514b9ec73eSIngo Weinhold { 3524b9ec73eSIngo Weinhold BNode::close_fd(); 3534b9ec73eSIngo Weinhold } 354