xref: /haiku/src/kits/storage/File.cpp (revision 0ab7cc6d6005b22804b9a7b7c742bf0debab4542)
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 
25e9191cc2SJohn Scipione // Creates an uninitialized BFile.
BFile()2652a38012Sejakowatz BFile::BFile()
27160f2d10SAxel Dörfler 	:
2852a38012Sejakowatz 	fMode(0)
2952a38012Sejakowatz {
3052a38012Sejakowatz }
3152a38012Sejakowatz 
325905a0aeSAxel Dörfler 
33e9191cc2SJohn Scipione // Creates a copy of the supplied BFile.
BFile(const BFile & file)3452a38012Sejakowatz BFile::BFile(const BFile& file)
35160f2d10SAxel Dörfler 	:
3652a38012Sejakowatz 	fMode(0)
3752a38012Sejakowatz {
3852a38012Sejakowatz 	*this = file;
3952a38012Sejakowatz }
4052a38012Sejakowatz 
415905a0aeSAxel Dörfler 
42e9191cc2SJohn Scipione // Creates a BFile and initializes it to the file referred to by
43e9191cc2SJohn Scipione // the supplied entry_ref and according to the specified open mode.
BFile(const entry_ref * ref,uint32 openMode)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 
52e9191cc2SJohn Scipione // Creates a BFile and initializes it to the file referred to by
53e9191cc2SJohn Scipione // the supplied BEntry and according to the specified open mode.
BFile(const BEntry * entry,uint32 openMode)5452a38012Sejakowatz BFile::BFile(const BEntry* entry, uint32 openMode)
55160f2d10SAxel Dörfler 	:
5652a38012Sejakowatz 	fMode(0)
5752a38012Sejakowatz {
5852a38012Sejakowatz 	SetTo(entry, openMode);
5952a38012Sejakowatz }
6052a38012Sejakowatz 
615905a0aeSAxel Dörfler 
62e9191cc2SJohn Scipione // Creates a BFile and initializes it to the file referred to by
63e9191cc2SJohn Scipione // the supplied path name and according to the specified open mode.
BFile(const char * path,uint32 openMode)6452a38012Sejakowatz BFile::BFile(const char* path, uint32 openMode)
65160f2d10SAxel Dörfler 	:
6652a38012Sejakowatz 	fMode(0)
6752a38012Sejakowatz {
6852a38012Sejakowatz 	SetTo(path, openMode);
6952a38012Sejakowatz }
7052a38012Sejakowatz 
715905a0aeSAxel Dörfler 
72e9191cc2SJohn Scipione // Creates a BFile and initializes it to the file referred to by
73e9191cc2SJohn Scipione // the supplied path name relative to the specified BDirectory and
74e9191cc2SJohn Scipione // according to the specified open mode.
BFile(const BDirectory * dir,const char * path,uint32 openMode)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 
83e9191cc2SJohn Scipione // Frees all allocated resources.
~BFile()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 
95e9191cc2SJohn Scipione // Re-initializes the BFile to the file referred to by the
96e9191cc2SJohn Scipione // supplied entry_ref and according to the specified open mode.
9752a38012Sejakowatz status_t
SetTo(const entry_ref * ref,uint32 openMode)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 
124e9191cc2SJohn Scipione // Re-initializes the BFile to the file referred to by the
125e9191cc2SJohn Scipione // supplied BEntry and according to the specified open mode.
12652a38012Sejakowatz status_t
SetTo(const BEntry * entry,uint32 openMode)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 
151e9191cc2SJohn Scipione // Re-initializes the BFile to the file referred to by the
152e9191cc2SJohn Scipione // supplied path name and according to the specified open mode.
15352a38012Sejakowatz status_t
SetTo(const char * path,uint32 openMode)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 
163*0ab7cc6dSAugustin Cavalier 	int fd = _kern_open(AT_FDCWD, 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 
175e9191cc2SJohn Scipione // Re-initializes the BFile to the file referred to by the
176e9191cc2SJohn Scipione // supplied path name relative to the specified BDirectory and
177e9191cc2SJohn Scipione // according to the specified open mode.
17852a38012Sejakowatz status_t
SetTo(const BDirectory * dir,const char * path,uint32 openMode)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 
200e9191cc2SJohn Scipione // Reports whether or not the file is readable.
20152a38012Sejakowatz bool
IsReadable() const20252a38012Sejakowatz 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 
209e9191cc2SJohn Scipione // Reports whether or not the file is writable.
21052a38012Sejakowatz bool
IsWritable() const21152a38012Sejakowatz 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 
218e9191cc2SJohn Scipione // Reads a number of bytes from the file into a buffer.
21952a38012Sejakowatz ssize_t
Read(void * buffer,size_t size)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 
228e9191cc2SJohn Scipione // Reads a number of bytes from a certain position within the file
229e9191cc2SJohn Scipione // into a buffer.
23052a38012Sejakowatz ssize_t
ReadAt(off_t location,void * buffer,size_t size)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 
242e9191cc2SJohn Scipione // Writes a number of bytes from a buffer into the file.
24352a38012Sejakowatz ssize_t
Write(const void * buffer,size_t size)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 
252e9191cc2SJohn Scipione // Writes a number of bytes from a buffer at a certain position
253e9191cc2SJohn Scipione // into the file.
25452a38012Sejakowatz ssize_t
WriteAt(off_t location,const void * buffer,size_t size)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 
266e9191cc2SJohn Scipione // Seeks to another read/write position within the file.
26752a38012Sejakowatz off_t
Seek(off_t offset,uint32 seekMode)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 
276e9191cc2SJohn Scipione // Gets the current read/write position within the file.
27752a38012Sejakowatz off_t
Position() const27852a38012Sejakowatz 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 
286e9191cc2SJohn Scipione // Sets the size of the file.
28752a38012Sejakowatz status_t
SetSize(off_t size)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 
300e9191cc2SJohn Scipione // Gets the size of the file.
30139c991c0SStephan Aßmus status_t
GetSize(off_t * size) const30239c991c0SStephan 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 
308e9191cc2SJohn Scipione // Assigns another BFile to this BFile.
30952a38012Sejakowatz BFile&
operator =(const BFile & file)31052a38012Sejakowatz BFile::operator=(const BFile &file)
31152a38012Sejakowatz {
312e9191cc2SJohn Scipione 	if (&file != this) {
313e9191cc2SJohn 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
_PhiloFile1()3327c44680aSIngo Weinhold void BFile::_PhiloFile1() {}
_PhiloFile2()3337c44680aSIngo Weinhold void BFile::_PhiloFile2() {}
_PhiloFile3()3347c44680aSIngo Weinhold void BFile::_PhiloFile3() {}
_PhiloFile4()3357c44680aSIngo Weinhold void BFile::_PhiloFile4() {}
_PhiloFile5()3367c44680aSIngo Weinhold void BFile::_PhiloFile5() {}
_PhiloFile6()3377c44680aSIngo Weinhold void BFile::_PhiloFile6() {}
33852a38012Sejakowatz 
33952a38012Sejakowatz 
340a30a4a41SJohn Scipione /*!	Gets the file descriptor of the BFile.
341a30a4a41SJohn Scipione 
342a30a4a41SJohn Scipione 	To be used instead of accessing the BNode's private \c fFd member directly.
343a30a4a41SJohn Scipione 
344a30a4a41SJohn Scipione 	\returns The file descriptor, or -1 if not properly initialized.
345a30a4a41SJohn Scipione */
346db10640dSIngo Weinhold int
get_fd() const34752a38012Sejakowatz BFile::get_fd() const
34852a38012Sejakowatz {
34952a38012Sejakowatz 	return fFd;
35052a38012Sejakowatz }
35152a38012Sejakowatz 
3525905a0aeSAxel Dörfler 
353a30a4a41SJohn Scipione //! Overrides BNode::close_fd() for binary compatibility with BeOS R5.
3544b9ec73eSIngo Weinhold void
close_fd()3554b9ec73eSIngo Weinhold BFile::close_fd()
3564b9ec73eSIngo Weinhold {
3574b9ec73eSIngo Weinhold 	BNode::close_fd();
3584b9ec73eSIngo Weinhold }
359