xref: /haiku/src/kits/storage/File.cpp (revision 9a6a20d4689307142a7ed26a1437ba47e244e73f)
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.
26 BFile::BFile()
27 	:
28 	fMode(0)
29 {
30 }
31 
32 
33 // Creates a copy of the supplied BFile.
34 BFile::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.
44 BFile::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.
54 BFile::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.
64 BFile::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.
75 BFile::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.
84 BFile::~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.
97 status_t
98 BFile::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.
126 status_t
127 BFile::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.
153 status_t
154 BFile::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(AT_FDCWD, 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.
178 status_t
179 BFile::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.
201 bool
202 BFile::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.
210 bool
211 BFile::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.
219 ssize_t
220 BFile::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.
230 ssize_t
231 BFile::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.
243 ssize_t
244 BFile::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.
254 ssize_t
255 BFile::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.
267 off_t
268 BFile::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.
277 off_t
278 BFile::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.
287 status_t
288 BFile::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.
301 status_t
302 BFile::GetSize(off_t* size) const
303 {
304 	return BStatable::GetSize(size);
305 }
306 
307 
308 // Assigns another BFile to this BFile.
309 BFile&
310 BFile::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
332 void BFile::_PhiloFile1() {}
333 void BFile::_PhiloFile2() {}
334 void BFile::_PhiloFile3() {}
335 void BFile::_PhiloFile4() {}
336 void BFile::_PhiloFile5() {}
337 void 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 */
346 int
347 BFile::get_fd() const
348 {
349 	return fFd;
350 }
351 
352 
353 //! Overrides BNode::close_fd() for binary compatibility with BeOS R5.
354 void
355 BFile::close_fd()
356 {
357 	BNode::close_fd();
358 }
359