xref: /haiku/src/kits/storage/File.cpp (revision 7c44680a3623191910d7fb6617ff897583f2ef60)
152a38012Sejakowatz //----------------------------------------------------------------------
252a38012Sejakowatz //  This software is part of the OpenBeOS distribution and is covered
352a38012Sejakowatz //  by the OpenBeOS license.
452a38012Sejakowatz //---------------------------------------------------------------------
552a38012Sejakowatz /*!
652a38012Sejakowatz 	\file File.cpp
752a38012Sejakowatz 	BFile implementation.
852a38012Sejakowatz */
952a38012Sejakowatz 
1052a38012Sejakowatz #include <fsproto.h>
1152a38012Sejakowatz 
1252a38012Sejakowatz #include <Entry.h>
1352a38012Sejakowatz #include <File.h>
1452a38012Sejakowatz #include "kernel_interface.h"
1552a38012Sejakowatz 
1652a38012Sejakowatz #ifdef USE_OPENBEOS_NAMESPACE
1752a38012Sejakowatz namespace OpenBeOS {
1852a38012Sejakowatz #endif
1952a38012Sejakowatz 
2052a38012Sejakowatz // constructor
2152a38012Sejakowatz //! Creates an uninitialized BFile.
2252a38012Sejakowatz BFile::BFile()
2352a38012Sejakowatz 	 : BNode(),
2452a38012Sejakowatz 	   BPositionIO(),
2552a38012Sejakowatz 	   fMode(0)
2652a38012Sejakowatz {
2752a38012Sejakowatz }
2852a38012Sejakowatz 
2952a38012Sejakowatz // copy constructor
3052a38012Sejakowatz //! Creates a copy of the supplied BFile.
3152a38012Sejakowatz /*! If \a file is uninitialized, the newly constructed BFile will be, too.
3252a38012Sejakowatz 	\param file the BFile object to be copied
3352a38012Sejakowatz */
3452a38012Sejakowatz BFile::BFile(const BFile &file)
3552a38012Sejakowatz 	 : BNode(),
3652a38012Sejakowatz 	   BPositionIO(),
3752a38012Sejakowatz 	   fMode(0)
3852a38012Sejakowatz {
3952a38012Sejakowatz 	*this = file;
4052a38012Sejakowatz }
4152a38012Sejakowatz 
4252a38012Sejakowatz // constructor
4352a38012Sejakowatz /*! \brief Creates a BFile and initializes it to the file referred to by
4452a38012Sejakowatz 		   the supplied entry_ref and according to the specified open mode.
4552a38012Sejakowatz 	\param ref the entry_ref referring to the file
4652a38012Sejakowatz 	\param openMode the mode in which the file should be opened
4752a38012Sejakowatz 	\see SetTo() for values for \a openMode
4852a38012Sejakowatz */
4952a38012Sejakowatz BFile::BFile(const entry_ref *ref, uint32 openMode)
5052a38012Sejakowatz 	 : BNode(),
5152a38012Sejakowatz 	   BPositionIO(),
5252a38012Sejakowatz 	   fMode(0)
5352a38012Sejakowatz {
5452a38012Sejakowatz 	SetTo(ref, openMode);
5552a38012Sejakowatz }
5652a38012Sejakowatz 
5752a38012Sejakowatz // constructor
5852a38012Sejakowatz /*! \brief Creates a BFile and initializes it to the file referred to by
5952a38012Sejakowatz 		   the supplied BEntry and according to the specified open mode.
6052a38012Sejakowatz 	\param entry the BEntry referring to the file
6152a38012Sejakowatz 	\param openMode the mode in which the file should be opened
6252a38012Sejakowatz 	\see SetTo() for values for \a openMode
6352a38012Sejakowatz */
6452a38012Sejakowatz BFile::BFile(const BEntry *entry, uint32 openMode)
6552a38012Sejakowatz 	 : BNode(),
6652a38012Sejakowatz 	   BPositionIO(),
6752a38012Sejakowatz 	   fMode(0)
6852a38012Sejakowatz {
6952a38012Sejakowatz 	SetTo(entry, openMode);
7052a38012Sejakowatz }
7152a38012Sejakowatz 
7252a38012Sejakowatz // constructor
7352a38012Sejakowatz /*! \brief Creates a BFile and initializes it to the file referred to by
7452a38012Sejakowatz 		   the supplied path name and according to the specified open mode.
7552a38012Sejakowatz 	\param path the file's path name
7652a38012Sejakowatz 	\param openMode the mode in which the file should be opened
7752a38012Sejakowatz 	\see SetTo() for values for \a openMode
7852a38012Sejakowatz */
7952a38012Sejakowatz BFile::BFile(const char *path, uint32 openMode)
8052a38012Sejakowatz 	 : BNode(),
8152a38012Sejakowatz 	   BPositionIO(),
8252a38012Sejakowatz 	   fMode(0)
8352a38012Sejakowatz {
8452a38012Sejakowatz 	SetTo(path, openMode);
8552a38012Sejakowatz }
8652a38012Sejakowatz 
8752a38012Sejakowatz // constructor
8852a38012Sejakowatz /*! \brief Creates a BFile and initializes it to the file referred to by
8952a38012Sejakowatz 		   the supplied path name relative to the specified BDirectory and
9052a38012Sejakowatz 		   according to the specified open mode.
9152a38012Sejakowatz 	\param dir the BDirectory, relative to which the file's path name is
9252a38012Sejakowatz 		   given
9352a38012Sejakowatz 	\param path the file's path name relative to \a dir
9452a38012Sejakowatz 	\param openMode the mode in which the file should be opened
9552a38012Sejakowatz 	\see SetTo() for values for \a openMode
9652a38012Sejakowatz */
9723d36867Sbeveloper BFile::BFile(const BDirectory *dir, const char *path, uint32 openMode)
9852a38012Sejakowatz 	 : BNode(),
9952a38012Sejakowatz 	   BPositionIO(),
10052a38012Sejakowatz 	   fMode(0)
10152a38012Sejakowatz {
10252a38012Sejakowatz 	SetTo(dir, path, openMode);
10352a38012Sejakowatz }
10452a38012Sejakowatz 
10552a38012Sejakowatz // destructor
10652a38012Sejakowatz //! Frees all allocated resources.
10752a38012Sejakowatz /*!	If the file is properly initialized, the file's file descriptor is closed.
10852a38012Sejakowatz */
10952a38012Sejakowatz BFile::~BFile()
11052a38012Sejakowatz {
11152a38012Sejakowatz 	// Also called by the BNode destructor, but we rather try to avoid
11252a38012Sejakowatz 	// problems with calling virtual functions in the base class destructor.
11352a38012Sejakowatz 	// Depending on the compiler implementation an object may be degraded to
11452a38012Sejakowatz 	// an object of the base class after the destructor of the derived class
11552a38012Sejakowatz 	// has been executed.
11652a38012Sejakowatz 	close_fd();
11752a38012Sejakowatz }
11852a38012Sejakowatz 
11952a38012Sejakowatz // SetTo
12052a38012Sejakowatz /*! \brief Re-initializes the BFile to the file referred to by the
12152a38012Sejakowatz 		   supplied entry_ref and according to the specified open mode.
12252a38012Sejakowatz 	\param ref the entry_ref referring to the file
12352a38012Sejakowatz 	\param openMode the mode in which the file should be opened
12452a38012Sejakowatz 	\a openMode must be a bitwise or of exactly one of the flags
12552a38012Sejakowatz 	- \c B_READ_ONLY: The file is opened read only.
12652a38012Sejakowatz 	- \c B_WRITE_ONLY: The file is opened write only.
12752a38012Sejakowatz 	- \c B_READ_WRITE: The file is opened for random read/write access.
12852a38012Sejakowatz 	and any number of the flags
12952a38012Sejakowatz 	- \c B_CREATE_FILE: A new file will be created, if it does not already
13052a38012Sejakowatz 	  exist.
13152a38012Sejakowatz 	- \c B_FAIL_IF_EXISTS: If the file does already exist and B_CREATE_FILE is
13252a38012Sejakowatz 	  set, SetTo() fails.
13352a38012Sejakowatz 	- \c B_ERASE_FILE: An already existing file is truncated to zero size.
13452a38012Sejakowatz 	- \c B_OPEN_AT_END: Seek() to the end of the file after opening.
13552a38012Sejakowatz 	\return
13652a38012Sejakowatz 	- \c B_OK: Everything went fine.
13752a38012Sejakowatz 	- \c B_BAD_VALUE: \c NULL \a ref or bad \a openMode.
13852a38012Sejakowatz 	- \c B_ENTRY_NOT_FOUND: File not found or failed to create file.
13952a38012Sejakowatz 	- \c B_FILE_EXISTS: File exists and \c B_FAIL_IF_EXISTS was passed.
14052a38012Sejakowatz 	- \c B_PERMISSION_DENIED: File permissions didn't allow operation.
14152a38012Sejakowatz 	- \c B_NO_MEMORY: Insufficient memory for operation.
14252a38012Sejakowatz 	- \c B_LINK_LIMIT: Indicates a cyclic loop within the file system.
14352a38012Sejakowatz 	- \c B_BUSY: A node was busy.
14452a38012Sejakowatz 	- \c B_FILE_ERROR: A general file error.
14552a38012Sejakowatz 	- \c B_NO_MORE_FDS: The application has run out of file descriptors.
14609d84e61STyler Dauwalder 	\todo Currently implemented using BPrivate::Storage::entry_ref_to_path().
14752a38012Sejakowatz 		  Reimplement!
14852a38012Sejakowatz */
14952a38012Sejakowatz status_t
15052a38012Sejakowatz BFile::SetTo(const entry_ref *ref, uint32 openMode)
15152a38012Sejakowatz {
15252a38012Sejakowatz 	Unset();
1539a17c3cfSIngo Weinhold 	char path[B_PATH_NAME_LENGTH];
15452a38012Sejakowatz 	status_t error = (ref ? B_OK : B_BAD_VALUE);
15552a38012Sejakowatz 	if (error == B_OK) {
15609d84e61STyler Dauwalder 		error = BPrivate::Storage::entry_ref_to_path(ref, path,
1579a17c3cfSIngo Weinhold 													 B_PATH_NAME_LENGTH);
15852a38012Sejakowatz 	}
15952a38012Sejakowatz 	if (error == B_OK)
16052a38012Sejakowatz 		error = SetTo(path, openMode);
16152a38012Sejakowatz 	set_status(error);
16252a38012Sejakowatz 	return error;
16352a38012Sejakowatz }
16452a38012Sejakowatz 
16552a38012Sejakowatz // SetTo
16652a38012Sejakowatz /*! \brief Re-initializes the BFile to the file referred to by the
16752a38012Sejakowatz 		   supplied BEntry and according to the specified open mode.
16852a38012Sejakowatz 	\param entry the BEntry referring to the file
16952a38012Sejakowatz 	\param openMode the mode in which the file should be opened
17052a38012Sejakowatz 	\return
17152a38012Sejakowatz 	- \c B_OK: Everything went fine.
17252a38012Sejakowatz 	- \c B_BAD_VALUE: \c NULL \a entry or bad \a openMode.
17352a38012Sejakowatz 	- \c B_ENTRY_NOT_FOUND: File not found or failed to create file.
17452a38012Sejakowatz 	- \c B_FILE_EXISTS: File exists and \c B_FAIL_IF_EXISTS was passed.
17552a38012Sejakowatz 	- \c B_PERMISSION_DENIED: File permissions didn't allow operation.
17652a38012Sejakowatz 	- \c B_NO_MEMORY: Insufficient memory for operation.
17752a38012Sejakowatz 	- \c B_LINK_LIMIT: Indicates a cyclic loop within the file system.
17852a38012Sejakowatz 	- \c B_BUSY: A node was busy.
17952a38012Sejakowatz 	- \c B_FILE_ERROR: A general file error.
18052a38012Sejakowatz 	- \c B_NO_MORE_FDS: The application has run out of file descriptors.
18152a38012Sejakowatz 	\todo Implemented using SetTo(entry_ref*, uint32). Check, if necessary
18252a38012Sejakowatz 		  to reimplement!
18352a38012Sejakowatz */
18452a38012Sejakowatz status_t
18552a38012Sejakowatz BFile::SetTo(const BEntry *entry, uint32 openMode)
18652a38012Sejakowatz {
18752a38012Sejakowatz 	Unset();
18852a38012Sejakowatz 	entry_ref ref;
18952a38012Sejakowatz 	status_t error = (entry ? B_OK : B_BAD_VALUE);
19052a38012Sejakowatz 	if (error == B_OK)
19152a38012Sejakowatz 		error = entry->GetRef(&ref);
19252a38012Sejakowatz 	if (error == B_OK)
19352a38012Sejakowatz 		error = SetTo(&ref, openMode);
19452a38012Sejakowatz 	set_status(error);
19552a38012Sejakowatz 	return error;
19652a38012Sejakowatz }
19752a38012Sejakowatz 
19852a38012Sejakowatz // SetTo
19952a38012Sejakowatz /*! \brief Re-initializes the BFile to the file referred to by the
20052a38012Sejakowatz 		   supplied path name and according to the specified open mode.
20152a38012Sejakowatz 	\param path the file's path name
20252a38012Sejakowatz 	\param openMode the mode in which the file should be opened
20352a38012Sejakowatz 	\return
20452a38012Sejakowatz 	- \c B_OK: Everything went fine.
20552a38012Sejakowatz 	- \c B_BAD_VALUE: \c NULL \a path or bad \a openMode.
20652a38012Sejakowatz 	- \c B_ENTRY_NOT_FOUND: File not found or failed to create file.
20752a38012Sejakowatz 	- \c B_FILE_EXISTS: File exists and \c B_FAIL_IF_EXISTS was passed.
20852a38012Sejakowatz 	- \c B_PERMISSION_DENIED: File permissions didn't allow operation.
20952a38012Sejakowatz 	- \c B_NO_MEMORY: Insufficient memory for operation.
21052a38012Sejakowatz 	- \c B_LINK_LIMIT: Indicates a cyclic loop within the file system.
21152a38012Sejakowatz 	- \c B_BUSY: A node was busy.
21252a38012Sejakowatz 	- \c B_FILE_ERROR: A general file error.
21352a38012Sejakowatz 	- \c B_NO_MORE_FDS: The application has run out of file descriptors.
21452a38012Sejakowatz */
21552a38012Sejakowatz status_t
21652a38012Sejakowatz BFile::SetTo(const char *path, uint32 openMode)
21752a38012Sejakowatz {
21852a38012Sejakowatz 	Unset();
21952a38012Sejakowatz 	status_t result = B_OK;
22009d84e61STyler Dauwalder 	BPrivate::Storage::FileDescriptor newFd = BPrivate::Storage::NullFd;
22152a38012Sejakowatz 	if (path) {
22252a38012Sejakowatz 		// analyze openMode
22352a38012Sejakowatz 		// Well, it's a bit schizophrenic to convert the B_* style openMode
22452a38012Sejakowatz 		// to POSIX style openFlags, but to use O_RWMASK to filter openMode.
225a04efc92SIngo Weinhold 		BPrivate::Storage::OpenFlags openFlags = 0;
22652a38012Sejakowatz 		switch (openMode & O_RWMASK) {
22752a38012Sejakowatz 			case B_READ_ONLY:
22852a38012Sejakowatz  				openFlags = O_RDONLY;
22952a38012Sejakowatz 				break;
23052a38012Sejakowatz 			case B_WRITE_ONLY:
23152a38012Sejakowatz  				openFlags = O_WRONLY;
23252a38012Sejakowatz 				break;
23352a38012Sejakowatz 			case B_READ_WRITE:
23452a38012Sejakowatz  				openFlags = O_RDWR;
23552a38012Sejakowatz 				break;
23652a38012Sejakowatz 			default:
23752a38012Sejakowatz 				result = B_BAD_VALUE;
23852a38012Sejakowatz 				break;
23952a38012Sejakowatz 		}
24052a38012Sejakowatz 		if (result == B_OK) {
24152a38012Sejakowatz 			if (openMode & B_ERASE_FILE)
24252a38012Sejakowatz 				openFlags |= O_TRUNC;
24352a38012Sejakowatz 			if (openMode & B_OPEN_AT_END)
24452a38012Sejakowatz 				openFlags |= O_APPEND;
24552a38012Sejakowatz 			if (openMode & B_CREATE_FILE) {
24652a38012Sejakowatz 				openFlags |= O_CREAT;
24752a38012Sejakowatz 				if (openMode & B_FAIL_IF_EXISTS)
24852a38012Sejakowatz 					openFlags |= O_EXCL;
24909d84e61STyler Dauwalder 				result = BPrivate::Storage::open(path, openFlags, S_IREAD | S_IWRITE,
25052a38012Sejakowatz 										  newFd);
25152a38012Sejakowatz 			} else
25209d84e61STyler Dauwalder 				result = BPrivate::Storage::open(path, openFlags, newFd);
25352a38012Sejakowatz 			if (result == B_OK)
25452a38012Sejakowatz 				fMode = openFlags;
25552a38012Sejakowatz 		}
25652a38012Sejakowatz 	} else
25752a38012Sejakowatz 		result = B_BAD_VALUE;
25852a38012Sejakowatz 	// set the new file descriptor
25952a38012Sejakowatz 	if (result == B_OK) {
26052a38012Sejakowatz 		result = set_fd(newFd);
26152a38012Sejakowatz 		if (result != B_OK)
26209d84e61STyler Dauwalder 			BPrivate::Storage::close(newFd);
26352a38012Sejakowatz 	}
26452a38012Sejakowatz 	// finally set the BNode status
26552a38012Sejakowatz 	set_status(result);
26652a38012Sejakowatz 	return result;
26752a38012Sejakowatz }
26852a38012Sejakowatz 
26952a38012Sejakowatz // SetTo
27052a38012Sejakowatz /*! \brief Re-initializes the BFile to the file referred to by the
27152a38012Sejakowatz 		   supplied path name relative to the specified BDirectory and
27252a38012Sejakowatz 		   according to the specified open mode.
27352a38012Sejakowatz 	\param dir the BDirectory, relative to which the file's path name is
27452a38012Sejakowatz 		   given
27552a38012Sejakowatz 	\param path the file's path name relative to \a dir
27652a38012Sejakowatz 	\param openMode the mode in which the file should be opened
27752a38012Sejakowatz 	- \c B_OK: Everything went fine.
27852a38012Sejakowatz 	- \c B_BAD_VALUE: \c NULL \a dir or \a path or bad \a openMode.
27952a38012Sejakowatz 	- \c B_ENTRY_NOT_FOUND: File not found or failed to create file.
28052a38012Sejakowatz 	- \c B_FILE_EXISTS: File exists and \c B_FAIL_IF_EXISTS was passed.
28152a38012Sejakowatz 	- \c B_PERMISSION_DENIED: File permissions didn't allow operation.
28252a38012Sejakowatz 	- \c B_NO_MEMORY: Insufficient memory for operation.
28352a38012Sejakowatz 	- \c B_LINK_LIMIT: Indicates a cyclic loop within the file system.
28452a38012Sejakowatz 	- \c B_BUSY: A node was busy.
28552a38012Sejakowatz 	- \c B_FILE_ERROR: A general file error.
28652a38012Sejakowatz 	- \c B_NO_MORE_FDS: The application has run out of file descriptors.
28752a38012Sejakowatz 	\todo Implemented using SetTo(BEntry*, uint32). Check, if necessary
28852a38012Sejakowatz 		  to reimplement!
28952a38012Sejakowatz */
29052a38012Sejakowatz status_t
29152a38012Sejakowatz BFile::SetTo(const BDirectory *dir, const char *path, uint32 openMode)
29252a38012Sejakowatz {
29352a38012Sejakowatz 	Unset();
29452a38012Sejakowatz 	status_t error = (dir && path ? B_OK : B_BAD_VALUE);
29552a38012Sejakowatz 	BEntry entry;
29652a38012Sejakowatz 	if (error == B_OK)
29752a38012Sejakowatz 		error = entry.SetTo(dir, path);
29852a38012Sejakowatz 	if (error == B_OK)
29952a38012Sejakowatz 		error = SetTo(&entry, openMode);
30052a38012Sejakowatz 	set_status(error);
30152a38012Sejakowatz 	return error;
30252a38012Sejakowatz }
30352a38012Sejakowatz 
30452a38012Sejakowatz // IsReadable
30552a38012Sejakowatz //! Returns whether the file is readable.
30652a38012Sejakowatz /*!	\return
30752a38012Sejakowatz 	- \c true, if the BFile has been initialized properly and the file has
30852a38012Sejakowatz 	  been been opened for reading,
30952a38012Sejakowatz 	- \c false, otherwise.
31052a38012Sejakowatz */
31152a38012Sejakowatz bool
31252a38012Sejakowatz BFile::IsReadable() const
31352a38012Sejakowatz {
31452a38012Sejakowatz 	return (InitCheck() == B_OK
31552a38012Sejakowatz 			&& ((fMode & O_RWMASK) == O_RDONLY
31652a38012Sejakowatz 				|| (fMode & O_RWMASK) == O_RDWR));
31752a38012Sejakowatz }
31852a38012Sejakowatz 
31952a38012Sejakowatz // IsWritable
32052a38012Sejakowatz //!	Returns whether the file is writable.
32152a38012Sejakowatz /*!	\return
32252a38012Sejakowatz 	- \c true, if the BFile has been initialized properly and the file has
32352a38012Sejakowatz 	  been opened for writing,
32452a38012Sejakowatz 	- \c false, otherwise.
32552a38012Sejakowatz */
32652a38012Sejakowatz bool
32752a38012Sejakowatz BFile::IsWritable() const
32852a38012Sejakowatz {
32952a38012Sejakowatz 	return (InitCheck() == B_OK
33052a38012Sejakowatz 			&& ((fMode & O_RWMASK) == O_WRONLY
33152a38012Sejakowatz 				|| (fMode & O_RWMASK) == O_RDWR));
33252a38012Sejakowatz }
33352a38012Sejakowatz 
33452a38012Sejakowatz // Read
33552a38012Sejakowatz //!	Reads a number of bytes from the file into a buffer.
33652a38012Sejakowatz /*!	\param buffer the buffer the data from the file shall be written to
33752a38012Sejakowatz 	\param size the number of bytes that shall be read
33852a38012Sejakowatz 	\return the number of bytes actually read or an error code
33952a38012Sejakowatz */
34052a38012Sejakowatz ssize_t
34152a38012Sejakowatz BFile::Read(void *buffer, size_t size)
34252a38012Sejakowatz {
34352a38012Sejakowatz 	ssize_t result = InitCheck();
34452a38012Sejakowatz 	if (result == B_OK)
34509d84e61STyler Dauwalder 		result = BPrivate::Storage::read(get_fd(), buffer, size);
34652a38012Sejakowatz 	return result;
34752a38012Sejakowatz }
34852a38012Sejakowatz 
34952a38012Sejakowatz // ReadAt
35052a38012Sejakowatz /*!	\brief Reads a number of bytes from a certain position within the file
35152a38012Sejakowatz 		   into a buffer.
35252a38012Sejakowatz 	\param location the position (in bytes) within the file from which the
35352a38012Sejakowatz 		   data shall be read
35452a38012Sejakowatz 	\param buffer the buffer the data from the file shall be written to
35552a38012Sejakowatz 	\param size the number of bytes that shall be read
35652a38012Sejakowatz 	\return the number of bytes actually read or an error code
35752a38012Sejakowatz */
35852a38012Sejakowatz ssize_t
35952a38012Sejakowatz BFile::ReadAt(off_t location, void *buffer, size_t size)
36052a38012Sejakowatz {
36152a38012Sejakowatz 	ssize_t result = InitCheck();
36252a38012Sejakowatz 	if (result == B_OK)
36309d84e61STyler Dauwalder 		result = BPrivate::Storage::read(get_fd(), buffer, location, size);
36452a38012Sejakowatz 	return result;
36552a38012Sejakowatz }
36652a38012Sejakowatz 
36752a38012Sejakowatz // Write
36852a38012Sejakowatz //!	Writes a number of bytes from a buffer into the file.
36952a38012Sejakowatz /*!	\param buffer the buffer containing the data to be written to the file
37052a38012Sejakowatz 	\param size the number of bytes that shall be written
37152a38012Sejakowatz 	\return the number of bytes actually written or an error code
37252a38012Sejakowatz */
37352a38012Sejakowatz ssize_t
37452a38012Sejakowatz BFile::Write(const void *buffer, size_t size)
37552a38012Sejakowatz {
37652a38012Sejakowatz 	ssize_t result = InitCheck();
37752a38012Sejakowatz 	if (result == B_OK)
37809d84e61STyler Dauwalder 		result = BPrivate::Storage::write(get_fd(), buffer, size);
37952a38012Sejakowatz 	return result;
38052a38012Sejakowatz }
38152a38012Sejakowatz 
38252a38012Sejakowatz // WriteAt
38352a38012Sejakowatz /*!	\brief Writes a number of bytes from a buffer at a certain position
38452a38012Sejakowatz 		   into the file.
38552a38012Sejakowatz 	\param location the position (in bytes) within the file at which the data
38652a38012Sejakowatz 		   shall be written
38752a38012Sejakowatz 	\param buffer the buffer containing the data to be written to the file
38852a38012Sejakowatz 	\param size the number of bytes that shall be written
38952a38012Sejakowatz 	\return the number of bytes actually written or an error code
39052a38012Sejakowatz */
39152a38012Sejakowatz ssize_t
39252a38012Sejakowatz BFile::WriteAt(off_t location, const void *buffer, size_t size)
39352a38012Sejakowatz {
39452a38012Sejakowatz 	ssize_t result = InitCheck();
39552a38012Sejakowatz 	if (result == B_OK)
39609d84e61STyler Dauwalder 		result = BPrivate::Storage::write(get_fd(), buffer, location, size);
39752a38012Sejakowatz 	return result;
39852a38012Sejakowatz }
39952a38012Sejakowatz 
40052a38012Sejakowatz // Seek
40152a38012Sejakowatz //!	Seeks to another read/write position within the file.
40252a38012Sejakowatz /*!	It is allowed to seek past the end of the file. A subsequent call to
40352a38012Sejakowatz 	Write() will pad the file with undefined data. Seeking before the
40452a38012Sejakowatz 	beginning of the file will fail and the behavior of subsequent Read()
40552a38012Sejakowatz 	or Write() invocations will be undefined.
40652a38012Sejakowatz 	\param offset new read/write position, depending on \a seekMode relative
40752a38012Sejakowatz 		   to the beginning or the end of the file or the current position
40852a38012Sejakowatz 	\param seekMode:
40952a38012Sejakowatz 		- \c SEEK_SET: move relative to the beginning of the file
41052a38012Sejakowatz 		- \c SEEK_CUR: move relative to the current position
41152a38012Sejakowatz 		- \c SEEK_END: move relative to the end of the file
41252a38012Sejakowatz 	\return
41352a38012Sejakowatz 	- the new read/write position relative to the beginning of the file
41452a38012Sejakowatz 	- \c B_ERROR when trying to seek before the beginning of the file
41552a38012Sejakowatz 	- \c B_FILE_ERROR, if the file is not properly initialized
41652a38012Sejakowatz */
41752a38012Sejakowatz off_t
41852a38012Sejakowatz BFile::Seek(off_t offset, uint32 seekMode)
41952a38012Sejakowatz {
42052a38012Sejakowatz 	off_t result = (InitCheck() == B_OK ? B_OK : B_FILE_ERROR);
42152a38012Sejakowatz 	if (result == B_OK)
42209d84e61STyler Dauwalder 		result = BPrivate::Storage::seek(get_fd(), offset, seekMode);
42352a38012Sejakowatz 	return result;
42452a38012Sejakowatz }
42552a38012Sejakowatz 
42652a38012Sejakowatz // Position
42752a38012Sejakowatz //!	Returns the current read/write position within the file.
42852a38012Sejakowatz /*!	\return
42952a38012Sejakowatz 	- the current read/write position relative to the beginning of the file
43052a38012Sejakowatz 	- \c B_ERROR, after a Seek() before the beginning of the file
43152a38012Sejakowatz 	- \c B_FILE_ERROR, if the file has not been initialized
43252a38012Sejakowatz */
43352a38012Sejakowatz off_t
43452a38012Sejakowatz BFile::Position() const
43552a38012Sejakowatz {
43652a38012Sejakowatz 	off_t result = (InitCheck() == B_OK ? B_OK : B_FILE_ERROR);
43752a38012Sejakowatz 	if (result == B_OK)
43809d84e61STyler Dauwalder 		result = BPrivate::Storage::get_position(get_fd());
43952a38012Sejakowatz 	return result;
44052a38012Sejakowatz }
44152a38012Sejakowatz 
44252a38012Sejakowatz // SetSize
44352a38012Sejakowatz //!	Sets the size of the file.
44452a38012Sejakowatz /*!	If the file is shorter than \a size bytes it will be padded with
44552a38012Sejakowatz 	unspecified data to the requested size. If it is larger, it will be
44652a38012Sejakowatz 	truncated.
44752a38012Sejakowatz 	Note: There's no problem with setting the size of a BFile opened in
44852a38012Sejakowatz 	\c B_READ_ONLY mode, unless the file resides on a read only volume.
44952a38012Sejakowatz 	\param size the new file size
45052a38012Sejakowatz 	\return
45152a38012Sejakowatz 	- \c B_OK, if everything went fine
45252a38012Sejakowatz 	- \c B_NOT_ALLOWED, if trying to set the size of a file on a read only
45352a38012Sejakowatz 	  volume
45452a38012Sejakowatz 	- \c B_DEVICE_FULL, if there's not enough space left on the volume
45552a38012Sejakowatz */
45652a38012Sejakowatz status_t
45752a38012Sejakowatz BFile::SetSize(off_t size)
45852a38012Sejakowatz {
45952a38012Sejakowatz 	status_t result = InitCheck();
46052a38012Sejakowatz 	if (result == B_OK && size < 0)
46152a38012Sejakowatz 		result = B_BAD_VALUE;
46252a38012Sejakowatz 	struct stat statData;
46352a38012Sejakowatz 	if (result == B_OK) {
46452a38012Sejakowatz 		statData.st_size = size;
46552a38012Sejakowatz 		result = set_stat(statData, WSTAT_SIZE);
46652a38012Sejakowatz 	}
46752a38012Sejakowatz 	return result;
46852a38012Sejakowatz }
46952a38012Sejakowatz 
47052a38012Sejakowatz // =
47152a38012Sejakowatz //!	Assigns another BFile to this BFile.
47252a38012Sejakowatz /*!	If the other BFile is uninitialized, this one will be too. Otherwise it
47352a38012Sejakowatz 	will refer to the same file using the same mode, unless an error occurs.
47452a38012Sejakowatz 	\param file the original BFile
47552a38012Sejakowatz 	\return a reference to this BFile
47652a38012Sejakowatz */
47752a38012Sejakowatz BFile &
47852a38012Sejakowatz BFile::operator=(const BFile &file)
47952a38012Sejakowatz {
48052a38012Sejakowatz 	if (&file != this) {	// no need to assign us to ourselves
48152a38012Sejakowatz 		Unset();
48252a38012Sejakowatz 		if (file.InitCheck() == B_OK) {
48352a38012Sejakowatz 			// duplicate the file descriptor
48409d84e61STyler Dauwalder 			BPrivate::Storage::FileDescriptor fd = -1;
48509d84e61STyler Dauwalder 			status_t status = BPrivate::Storage::dup(file.get_fd(), fd);
48652a38012Sejakowatz 			// set it
48752a38012Sejakowatz 			if (status == B_OK) {
48852a38012Sejakowatz 				status = set_fd(fd);
48952a38012Sejakowatz 				if (status == B_OK)
49052a38012Sejakowatz 					fMode = file.fMode;
49152a38012Sejakowatz 				else
49209d84e61STyler Dauwalder 					BPrivate::Storage::close(fd);
49352a38012Sejakowatz 			}
49452a38012Sejakowatz 			set_status(status);
49552a38012Sejakowatz 		}
49652a38012Sejakowatz 	}
49752a38012Sejakowatz 	return *this;
49852a38012Sejakowatz }
49952a38012Sejakowatz 
50052a38012Sejakowatz 
50152a38012Sejakowatz // FBC
502*7c44680aSIngo Weinhold void BFile::_PhiloFile1() {}
503*7c44680aSIngo Weinhold void BFile::_PhiloFile2() {}
504*7c44680aSIngo Weinhold void BFile::_PhiloFile3() {}
505*7c44680aSIngo Weinhold void BFile::_PhiloFile4() {}
506*7c44680aSIngo Weinhold void BFile::_PhiloFile5() {}
507*7c44680aSIngo Weinhold void BFile::_PhiloFile6() {}
50852a38012Sejakowatz 
50952a38012Sejakowatz 
51052a38012Sejakowatz // get_fd
51152a38012Sejakowatz /*!	Returns the file descriptor.
51252a38012Sejakowatz 	To be used instead of accessing the BNode's private \c fFd member directly.
51352a38012Sejakowatz 	\return the file descriptor, or -1, if not properly initialized.
51452a38012Sejakowatz */
51509d84e61STyler Dauwalder BPrivate::Storage::FileDescriptor
51652a38012Sejakowatz BFile::get_fd() const
51752a38012Sejakowatz {
51852a38012Sejakowatz 	return fFd;
51952a38012Sejakowatz }
52052a38012Sejakowatz 
52152a38012Sejakowatz 
52252a38012Sejakowatz #ifdef USE_OPENBEOS_NAMESPACE
52352a38012Sejakowatz };		// namespace OpenBeOS
52452a38012Sejakowatz #endif
52552a38012Sejakowatz 
52609d84e61STyler Dauwalder 
52709d84e61STyler Dauwalder 
52809d84e61STyler Dauwalder 
529