118d457f8SIngo Weinhold/*
218d457f8SIngo Weinhold * Copyright 2005-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
318d457f8SIngo Weinhold * Distributed under the terms of the MIT License.
418d457f8SIngo Weinhold */
518d457f8SIngo Weinhold
6a9bf6ecbSIngo Weinhold
74f4e5272SIngo Weinhold#ifdef BUILDING_FS_SHELL
84f4e5272SIngo Weinhold#	include "compat.h"
94f4e5272SIngo Weinhold#	define B_OK			0
104f4e5272SIngo Weinhold#	define B_FILE_ERROR	EBADF
114f4e5272SIngo Weinhold#else
124f4e5272SIngo Weinhold#	include <BeOSBuildCompatibility.h>
134f4e5272SIngo Weinhold#endif
14a9bf6ecbSIngo Weinhold
15a9bf6ecbSIngo Weinhold#include "fs_descriptors.h"
16a9bf6ecbSIngo Weinhold
17a9bf6ecbSIngo Weinhold#include <map>
18a9bf6ecbSIngo Weinhold
19e781b1b5SIngo Weinhold#include <fcntl.h>
20a9bf6ecbSIngo Weinhold#include <stdio.h>
21e781b1b5SIngo Weinhold#include <stdlib.h>
22a9bf6ecbSIngo Weinhold#include <unistd.h>
23a9bf6ecbSIngo Weinhold
24a9bf6ecbSIngo Weinhold#include <fs_attr.h>
25a9bf6ecbSIngo Weinhold
263da422adSIngo Weinhold#include <syscalls.h>
273da422adSIngo Weinhold
28a9bf6ecbSIngo Weinhold#include "fs_impl.h"
29a9bf6ecbSIngo Weinhold
30a9bf6ecbSIngo Weinholdusing std::map;
31a9bf6ecbSIngo Weinhold
32a9bf6ecbSIngo Weinholdstatic const int kVirtualDescriptorStart = 10000;
33a9bf6ecbSIngo Weinhold
34a9bf6ecbSIngo Weinholdtypedef map<int, BPrivate::Descriptor*> DescriptorMap;
358e27997cSMaurice Kalinowskistatic DescriptorMap *sDescriptors;
36a9bf6ecbSIngo Weinhold
37a9bf6ecbSIngo Weinholdnamespace BPrivate {
38a9bf6ecbSIngo Weinhold
39a9bf6ecbSIngo Weinhold
403da422adSIngo Weinholdstatic int
413da422adSIngo Weinholddup_maybe_system(int fd)
423da422adSIngo Weinhold{
433da422adSIngo Weinhold	if (get_descriptor(fd) != NULL)
443da422adSIngo Weinhold		return _kern_dup(fd);
453da422adSIngo Weinhold
463da422adSIngo Weinhold	int clonedFD = dup(fd);
473da422adSIngo Weinhold	return clonedFD >= 0 ? clonedFD : errno;
483da422adSIngo Weinhold}
493da422adSIngo Weinhold
503da422adSIngo Weinhold
513da422adSIngo Weinholdstatic status_t
523da422adSIngo Weinholdclose_maybe_system(int fd)
533da422adSIngo Weinhold{
543da422adSIngo Weinhold	if (get_descriptor(fd) != NULL)
553da422adSIngo Weinhold		return _kern_close(fd);
563da422adSIngo Weinhold
573da422adSIngo Weinhold	return close(fd) == 0 ? B_OK : errno;
583da422adSIngo Weinhold}
593da422adSIngo Weinhold
603da422adSIngo Weinhold
61a9bf6ecbSIngo Weinhold// #pragma mark - Descriptor
62a9bf6ecbSIngo Weinhold
63a9bf6ecbSIngo Weinhold
64a9bf6ecbSIngo Weinhold// constructor
65a9bf6ecbSIngo WeinholdDescriptor::~Descriptor()
66a9bf6ecbSIngo Weinhold{
67a9bf6ecbSIngo Weinhold}
68a9bf6ecbSIngo Weinhold
694f4e5272SIngo Weinhold// IsSystemFD
704f4e5272SIngo Weinholdbool
714f4e5272SIngo WeinholdDescriptor::IsSystemFD() const
724f4e5272SIngo Weinhold{
734f4e5272SIngo Weinhold	return false;
744f4e5272SIngo Weinhold}
754f4e5272SIngo Weinhold
764f4e5272SIngo Weinhold// GetPath
774f4e5272SIngo Weinholdstatus_t
784f4e5272SIngo WeinholdDescriptor::GetPath(string& path) const
794f4e5272SIngo Weinhold{
804f4e5272SIngo Weinhold	return get_path(fd, NULL, path);
814f4e5272SIngo Weinhold}
824f4e5272SIngo Weinhold
83a9bf6ecbSIngo Weinhold// GetNodeRef
84a9bf6ecbSIngo Weinholdstatus_t
85a9bf6ecbSIngo WeinholdDescriptor::GetNodeRef(NodeRef &ref)
86a9bf6ecbSIngo Weinhold{
87a9bf6ecbSIngo Weinhold	struct stat st;
88a9bf6ecbSIngo Weinhold	status_t error = GetStat(false, &st);
89a9bf6ecbSIngo Weinhold	if (error != B_OK)
90a9bf6ecbSIngo Weinhold		return error;
91a9bf6ecbSIngo Weinhold
92a9bf6ecbSIngo Weinhold	ref = NodeRef(st);
93a9bf6ecbSIngo Weinhold
94a9bf6ecbSIngo Weinhold	return B_OK;
95a9bf6ecbSIngo Weinhold}
96a9bf6ecbSIngo Weinhold
97a9bf6ecbSIngo Weinhold
98a9bf6ecbSIngo Weinhold// #pragma mark - FileDescriptor
99a9bf6ecbSIngo Weinhold
100a9bf6ecbSIngo Weinhold
101a9bf6ecbSIngo Weinhold// constructor
102a9bf6ecbSIngo WeinholdFileDescriptor::FileDescriptor(int fd)
103a9bf6ecbSIngo Weinhold{
104a9bf6ecbSIngo Weinhold	this->fd = fd;
105a9bf6ecbSIngo Weinhold}
106a9bf6ecbSIngo Weinhold
107a9bf6ecbSIngo Weinhold// destructor
108a9bf6ecbSIngo WeinholdFileDescriptor::~FileDescriptor()
109a9bf6ecbSIngo Weinhold{
110a9bf6ecbSIngo Weinhold	Close();
111a9bf6ecbSIngo Weinhold}
112a9bf6ecbSIngo Weinhold
113a9bf6ecbSIngo Weinhold// Close
114a9bf6ecbSIngo Weinholdstatus_t
115a9bf6ecbSIngo WeinholdFileDescriptor::Close()
116a9bf6ecbSIngo Weinhold{
117a9bf6ecbSIngo Weinhold	if (fd >= 0) {
118a9bf6ecbSIngo Weinhold		int oldFD = fd;
119a9bf6ecbSIngo Weinhold		fd = -1;
120a9bf6ecbSIngo Weinhold		if (close(oldFD) < 0)
121a9bf6ecbSIngo Weinhold			return errno;
122a9bf6ecbSIngo Weinhold	}
123a9bf6ecbSIngo Weinhold
1247db9e218SMaurice Kalinowski	return B_OK;
125a9bf6ecbSIngo Weinhold}
126a9bf6ecbSIngo Weinhold
127a9bf6ecbSIngo Weinhold// Dup
128a9bf6ecbSIngo Weinholdstatus_t
129a9bf6ecbSIngo WeinholdFileDescriptor::Dup(Descriptor *&clone)
130a9bf6ecbSIngo Weinhold{
131a9bf6ecbSIngo Weinhold	int dupFD = dup(fd);
132a9bf6ecbSIngo Weinhold	if (dupFD < 0)
133a9bf6ecbSIngo Weinhold		return errno;
1347db9e218SMaurice Kalinowski
135a9bf6ecbSIngo Weinhold	clone = new FileDescriptor(dupFD);
136a9bf6ecbSIngo Weinhold	return B_OK;
137a9bf6ecbSIngo Weinhold}
138a9bf6ecbSIngo Weinhold
139a9bf6ecbSIngo Weinhold// GetStat
140a9bf6ecbSIngo Weinholdstatus_t
141a9bf6ecbSIngo WeinholdFileDescriptor::GetStat(bool traverseLink, struct stat *st)
142a9bf6ecbSIngo Weinhold{
143a9bf6ecbSIngo Weinhold	if (fstat(fd, st) < 0)
144a9bf6ecbSIngo Weinhold		return errno;
145a9bf6ecbSIngo Weinhold	return B_OK;
146a9bf6ecbSIngo Weinhold}
147a9bf6ecbSIngo Weinhold
1484f4e5272SIngo Weinhold// IsSystemFD
1494f4e5272SIngo Weinholdbool
1504f4e5272SIngo WeinholdFileDescriptor::IsSystemFD() const
1514f4e5272SIngo Weinhold{
1524f4e5272SIngo Weinhold	return true;
1534f4e5272SIngo Weinhold}
1544f4e5272SIngo Weinhold
155a9bf6ecbSIngo Weinhold
156a9bf6ecbSIngo Weinhold// #pragma mark - DirectoryDescriptor
157a9bf6ecbSIngo Weinhold
158a9bf6ecbSIngo Weinhold
159a9bf6ecbSIngo Weinhold// constructor
160a9bf6ecbSIngo WeinholdDirectoryDescriptor::DirectoryDescriptor(DIR *dir, const NodeRef &ref)
161a9bf6ecbSIngo Weinhold{
162a9bf6ecbSIngo Weinhold	this->dir = dir;
163a9bf6ecbSIngo Weinhold	this->ref = ref;
164a9bf6ecbSIngo Weinhold}
165a9bf6ecbSIngo Weinhold
166a9bf6ecbSIngo Weinhold// destructor
167a9bf6ecbSIngo WeinholdDirectoryDescriptor::~DirectoryDescriptor()
168a9bf6ecbSIngo Weinhold{
169a9bf6ecbSIngo Weinhold	Close();
170a9bf6ecbSIngo Weinhold}
171a9bf6ecbSIngo Weinhold
172a9bf6ecbSIngo Weinhold// Close
173a9bf6ecbSIngo Weinholdstatus_t
174a9bf6ecbSIngo WeinholdDirectoryDescriptor::Close()
175a9bf6ecbSIngo Weinhold{
176a9bf6ecbSIngo Weinhold	if (dir) {
177a9bf6ecbSIngo Weinhold		DIR *oldDir = dir;
178a9bf6ecbSIngo Weinhold		dir = NULL;
179a9bf6ecbSIngo Weinhold		if (closedir(oldDir) < 0)
180a9bf6ecbSIngo Weinhold			return errno;
181a9bf6ecbSIngo Weinhold	}
182a9bf6ecbSIngo Weinhold
1837db9e218SMaurice Kalinowski	return B_OK;
184a9bf6ecbSIngo Weinhold}
185a9bf6ecbSIngo Weinhold
186a9bf6ecbSIngo Weinhold// Dup
187a9bf6ecbSIngo Weinholdstatus_t
188a9bf6ecbSIngo WeinholdDirectoryDescriptor::Dup(Descriptor *&clone)
189a9bf6ecbSIngo Weinhold{
190a9bf6ecbSIngo Weinhold	string path;
191a9bf6ecbSIngo Weinhold	status_t error = get_path(fd, NULL, path);
192a9bf6ecbSIngo Weinhold	if (error != B_OK)
193a9bf6ecbSIngo Weinhold		return error;
194a9bf6ecbSIngo Weinhold
195a9bf6ecbSIngo Weinhold	DIR *dupDir = opendir(path.c_str());
196a9bf6ecbSIngo Weinhold	if (!dupDir)
197a9bf6ecbSIngo Weinhold		return errno;
1987db9e218SMaurice Kalinowski
199a9bf6ecbSIngo Weinhold	clone = new DirectoryDescriptor(dupDir, ref);
200a9bf6ecbSIngo Weinhold	return B_OK;
201a9bf6ecbSIngo Weinhold}
202a9bf6ecbSIngo Weinhold
203a9bf6ecbSIngo Weinhold// GetStat
204a9bf6ecbSIngo Weinholdstatus_t
205a9bf6ecbSIngo WeinholdDirectoryDescriptor::GetStat(bool traverseLink, struct stat *st)
206a9bf6ecbSIngo Weinhold{
207a9bf6ecbSIngo Weinhold	// get a usable path
208a9bf6ecbSIngo Weinhold	string realPath;
209a9bf6ecbSIngo Weinhold	status_t error = get_path(fd, NULL, realPath);
210a9bf6ecbSIngo Weinhold	if (error != B_OK)
211a9bf6ecbSIngo Weinhold		return error;
212a9bf6ecbSIngo Weinhold
213a9bf6ecbSIngo Weinhold	// stat
214a9bf6ecbSIngo Weinhold	int result;
215a9bf6ecbSIngo Weinhold	result = stat(realPath.c_str(), st);
216a9bf6ecbSIngo Weinhold
217a9bf6ecbSIngo Weinhold	if (result < 0)
218a9bf6ecbSIngo Weinhold		return errno;
219a9bf6ecbSIngo Weinhold
220a9bf6ecbSIngo Weinhold	return B_OK;
221a9bf6ecbSIngo Weinhold}
222a9bf6ecbSIngo Weinhold
223a9bf6ecbSIngo Weinhold// GetNodeRef
224a9bf6ecbSIngo Weinholdstatus_t
225a9bf6ecbSIngo WeinholdDirectoryDescriptor::GetNodeRef(NodeRef &ref)
226a9bf6ecbSIngo Weinhold{
227a9bf6ecbSIngo Weinhold	ref = this->ref;
228a9bf6ecbSIngo Weinhold
229a9bf6ecbSIngo Weinhold	return B_OK;
230a9bf6ecbSIngo Weinhold}
231a9bf6ecbSIngo Weinhold
232a9bf6ecbSIngo Weinhold
233a9bf6ecbSIngo Weinhold// #pragma mark - SymlinkDescriptor
234a9bf6ecbSIngo Weinhold
235a9bf6ecbSIngo Weinhold
236a9bf6ecbSIngo Weinhold// constructor
237a9bf6ecbSIngo WeinholdSymlinkDescriptor::SymlinkDescriptor(const char *path)
238a9bf6ecbSIngo Weinhold{
239a9bf6ecbSIngo Weinhold	this->path = path;
240a9bf6ecbSIngo Weinhold}
241a9bf6ecbSIngo Weinhold
242a9bf6ecbSIngo Weinhold// Close
243a9bf6ecbSIngo Weinholdstatus_t
244a9bf6ecbSIngo WeinholdSymlinkDescriptor::Close()
245a9bf6ecbSIngo Weinhold{
2467db9e218SMaurice Kalinowski	return B_OK;
247a9bf6ecbSIngo Weinhold}
248a9bf6ecbSIngo Weinhold
249a9bf6ecbSIngo Weinhold// Dup
250a9bf6ecbSIngo Weinholdstatus_t
251a9bf6ecbSIngo WeinholdSymlinkDescriptor::Dup(Descriptor *&clone)
252a9bf6ecbSIngo Weinhold{
253a9bf6ecbSIngo Weinhold	clone = new SymlinkDescriptor(path.c_str());
254a9bf6ecbSIngo Weinhold	return B_OK;
255a9bf6ecbSIngo Weinhold}
256a9bf6ecbSIngo Weinhold
257a9bf6ecbSIngo Weinhold// GetStat
258a9bf6ecbSIngo Weinholdstatus_t
259a9bf6ecbSIngo WeinholdSymlinkDescriptor::GetStat(bool traverseLink, struct stat *st)
260a9bf6ecbSIngo Weinhold{
261a9bf6ecbSIngo Weinhold	// stat
262a9bf6ecbSIngo Weinhold	int result;
263a9bf6ecbSIngo Weinhold	if (traverseLink)
264a9bf6ecbSIngo Weinhold		result = stat(path.c_str(), st);
265a9bf6ecbSIngo Weinhold	else
266a9bf6ecbSIngo Weinhold		result = lstat(path.c_str(), st);
267a9bf6ecbSIngo Weinhold
268a9bf6ecbSIngo Weinhold	if (result < 0)
269a9bf6ecbSIngo Weinhold		return errno;
270a9bf6ecbSIngo Weinhold
271a9bf6ecbSIngo Weinhold	return B_OK;
272a9bf6ecbSIngo Weinhold}
273a9bf6ecbSIngo Weinhold
2744f4e5272SIngo Weinhold// GetPath
2754f4e5272SIngo Weinholdstatus_t
2764f4e5272SIngo WeinholdSymlinkDescriptor::GetPath(string& path) const
2774f4e5272SIngo Weinhold{
2784f4e5272SIngo Weinhold	path = this->path;
2794f4e5272SIngo Weinhold	return B_OK;
2804f4e5272SIngo Weinhold}
2814f4e5272SIngo Weinhold
282a9bf6ecbSIngo Weinhold
283e781b1b5SIngo Weinhold// #pragma mark - AttributeDescriptor
284e781b1b5SIngo Weinhold
285e781b1b5SIngo Weinhold
286e781b1b5SIngo WeinholdAttributeDescriptor::AttributeDescriptor(int fileFD, const char* attribute,
287e781b1b5SIngo Weinhold	uint32 type, int openMode)
288e781b1b5SIngo Weinhold	:
2893da422adSIngo Weinhold	fFileFD(dup_maybe_system(fileFD)),
290e781b1b5SIngo Weinhold	fType(type),
291e781b1b5SIngo Weinhold	fOpenMode(openMode),
292e781b1b5SIngo Weinhold	fData(NULL),
293e781b1b5SIngo Weinhold	fDataSize(0)
294e781b1b5SIngo Weinhold
295e781b1b5SIngo Weinhold{
296e781b1b5SIngo Weinhold	strlcpy(fAttribute, attribute, sizeof(fAttribute));
297e781b1b5SIngo Weinhold}
298e781b1b5SIngo Weinhold
299e781b1b5SIngo Weinhold
300e781b1b5SIngo WeinholdAttributeDescriptor::~AttributeDescriptor()
301e781b1b5SIngo Weinhold{
302e781b1b5SIngo Weinhold	Close();
303e781b1b5SIngo Weinhold}
304e781b1b5SIngo Weinhold
305e781b1b5SIngo Weinhold
306e781b1b5SIngo Weinholdstatus_t
307e781b1b5SIngo WeinholdAttributeDescriptor::Init()
308e781b1b5SIngo Weinhold{
309e781b1b5SIngo Weinhold	if (fFileFD < 0)
310e781b1b5SIngo Weinhold		return B_IO_ERROR;
311e781b1b5SIngo Weinhold
312e781b1b5SIngo Weinhold	// stat the attribute
313e781b1b5SIngo Weinhold	attr_info info;
314e781b1b5SIngo Weinhold	if (fs_stat_attr(fFileFD, fAttribute, &info) < 0) {
315e781b1b5SIngo Weinhold		if (errno == B_ENTRY_NOT_FOUND) {
316e781b1b5SIngo Weinhold			if ((fOpenMode & O_CREAT) == 0)
317e781b1b5SIngo Weinhold				return errno;
318e781b1b5SIngo Weinhold
319e781b1b5SIngo Weinhold			// create the attribute
320e781b1b5SIngo Weinhold			if (fs_write_attr(fFileFD, fAttribute, fType, 0, NULL, 0) < 0)
321e781b1b5SIngo Weinhold				return errno;
322e781b1b5SIngo Weinhold			return B_OK;
323e781b1b5SIngo Weinhold		}
324e781b1b5SIngo Weinhold		return errno;
325e781b1b5SIngo Weinhold	}
326e781b1b5SIngo Weinhold
327e781b1b5SIngo Weinhold	if ((fOpenMode & O_TRUNC) == 0) {
328e781b1b5SIngo Weinhold		// truncate the attribute
329e781b1b5SIngo Weinhold		if (fs_write_attr(fFileFD, fAttribute, fType, 0, NULL, 0) < 0)
330e781b1b5SIngo Weinhold			return errno;
331e781b1b5SIngo Weinhold		return B_OK;
332e781b1b5SIngo Weinhold	}
333e781b1b5SIngo Weinhold
334e781b1b5SIngo Weinhold	// we have to read in the attribute data
335e781b1b5SIngo Weinhold	if (info.size == 0)
336e781b1b5SIngo Weinhold		return B_OK;
337e781b1b5SIngo Weinhold
338e781b1b5SIngo Weinhold	fData = (uint8*)malloc(info.size);
339e781b1b5SIngo Weinhold	if (fData == NULL)
340e781b1b5SIngo Weinhold		return B_NO_MEMORY;
341e781b1b5SIngo Weinhold
342e781b1b5SIngo Weinhold	fDataSize = info.size;
343e781b1b5SIngo Weinhold
344e781b1b5SIngo Weinhold	ssize_t bytesRead = fs_read_attr(fFileFD, fAttribute, fType, 0, fData,
345e781b1b5SIngo Weinhold		fDataSize);
346e781b1b5SIngo Weinhold	if (bytesRead < 0)
347e781b1b5SIngo Weinhold		return errno;
348e781b1b5SIngo Weinhold	if ((size_t)bytesRead != fDataSize)
349e781b1b5SIngo Weinhold		return B_IO_ERROR;
350e781b1b5SIngo Weinhold
351e781b1b5SIngo Weinhold	return B_OK;
352e781b1b5SIngo Weinhold}
353e781b1b5SIngo Weinhold
354e781b1b5SIngo Weinhold
355e781b1b5SIngo Weinholdstatus_t
356e781b1b5SIngo WeinholdAttributeDescriptor::Write(off_t offset, const void* buffer, size_t bufferSize)
357e781b1b5SIngo Weinhold{
358e781b1b5SIngo Weinhold	if (offset < 0)
359e781b1b5SIngo Weinhold		return B_BAD_VALUE;
360e781b1b5SIngo Weinhold
361e781b1b5SIngo Weinhold	if ((fOpenMode & O_ACCMODE) != O_WRONLY
362e781b1b5SIngo Weinhold		&& (fOpenMode & O_ACCMODE) != O_RDWR) {
363e781b1b5SIngo Weinhold		return B_NOT_ALLOWED;
364e781b1b5SIngo Weinhold	}
365e781b1b5SIngo Weinhold
366e781b1b5SIngo Weinhold	// we may need to resize the buffer
367e781b1b5SIngo Weinhold	size_t minSize = (size_t)offset + bufferSize;
368e781b1b5SIngo Weinhold	if (minSize > fDataSize) {
369e781b1b5SIngo Weinhold		uint8* data = (uint8*)realloc(fData, minSize);
370e781b1b5SIngo Weinhold		if (data == NULL)
371e781b1b5SIngo Weinhold			return B_NO_MEMORY;
372e781b1b5SIngo Weinhold
373e781b1b5SIngo Weinhold		if ((size_t)offset > fDataSize)
374e781b1b5SIngo Weinhold			memset(data + offset, 0, offset - fDataSize);
375e781b1b5SIngo Weinhold
376e781b1b5SIngo Weinhold		fData = data;
377e781b1b5SIngo Weinhold		fDataSize = minSize;
378e781b1b5SIngo Weinhold	}
379e781b1b5SIngo Weinhold
380e781b1b5SIngo Weinhold	// copy the data and write all of it
381e781b1b5SIngo Weinhold	if (bufferSize == 0)
382e781b1b5SIngo Weinhold		return B_OK;
383e781b1b5SIngo Weinhold
384e781b1b5SIngo Weinhold	memcpy((uint8*)fData + offset, buffer, bufferSize);
385e781b1b5SIngo Weinhold
386e781b1b5SIngo Weinhold	ssize_t bytesWritten = fs_write_attr(fFileFD, fAttribute, fType, 0,
387e781b1b5SIngo Weinhold		fData, fDataSize);
388e781b1b5SIngo Weinhold	if (bytesWritten < 0)
389e781b1b5SIngo Weinhold		return errno;
390e781b1b5SIngo Weinhold	if ((size_t)bytesWritten != fDataSize)
391e781b1b5SIngo Weinhold		return B_IO_ERROR;
392e781b1b5SIngo Weinhold
393e781b1b5SIngo Weinhold	return B_OK;
394e781b1b5SIngo Weinhold}
395e781b1b5SIngo Weinhold
396e781b1b5SIngo Weinhold
397e781b1b5SIngo Weinholdstatus_t
398e781b1b5SIngo WeinholdAttributeDescriptor::Close()
399e781b1b5SIngo Weinhold{
400e781b1b5SIngo Weinhold	if (fFileFD < 0)
401e781b1b5SIngo Weinhold		return B_BAD_VALUE;
402e781b1b5SIngo Weinhold
4033da422adSIngo Weinhold	close_maybe_system(fFileFD);
404e781b1b5SIngo Weinhold	fFileFD = -1;
405e781b1b5SIngo Weinhold
406e781b1b5SIngo Weinhold	free(fData);
407e781b1b5SIngo Weinhold	fData = NULL;
408e781b1b5SIngo Weinhold	fDataSize = 0;
409e781b1b5SIngo Weinhold
410e781b1b5SIngo Weinhold	return B_OK;
411e781b1b5SIngo Weinhold}
412e781b1b5SIngo Weinhold
413e781b1b5SIngo Weinhold
414e781b1b5SIngo Weinholdstatus_t
415e781b1b5SIngo WeinholdAttributeDescriptor::Dup(Descriptor*& clone)
416e781b1b5SIngo Weinhold{
417e781b1b5SIngo Weinhold	return B_NOT_SUPPORTED;
418e781b1b5SIngo Weinhold}
419e781b1b5SIngo Weinhold
420e781b1b5SIngo Weinhold
421e781b1b5SIngo Weinholdstatus_t
422e781b1b5SIngo WeinholdAttributeDescriptor::GetStat(bool traverseLink, struct stat* st)
423e781b1b5SIngo Weinhold{
424e781b1b5SIngo Weinhold	return B_NOT_SUPPORTED;
425e781b1b5SIngo Weinhold}
426e781b1b5SIngo Weinhold
427e781b1b5SIngo Weinhold
428a9bf6ecbSIngo Weinhold// #pragma mark - AttrDirDescriptor
429a9bf6ecbSIngo Weinhold
430a9bf6ecbSIngo Weinhold
431a9bf6ecbSIngo Weinhold// constructor
432a9bf6ecbSIngo WeinholdAttrDirDescriptor::AttrDirDescriptor(DIR *dir, const NodeRef &ref)
433a9bf6ecbSIngo Weinhold	: DirectoryDescriptor(dir, ref)
434a9bf6ecbSIngo Weinhold{
435a9bf6ecbSIngo Weinhold}
436a9bf6ecbSIngo Weinhold
437a9bf6ecbSIngo Weinhold// destructor
438a9bf6ecbSIngo WeinholdAttrDirDescriptor::~AttrDirDescriptor()
439a9bf6ecbSIngo Weinhold{
440a9bf6ecbSIngo Weinhold	Close();
441a9bf6ecbSIngo Weinhold}
442a9bf6ecbSIngo Weinhold
443a9bf6ecbSIngo Weinhold// Close
444a9bf6ecbSIngo Weinholdstatus_t
445a9bf6ecbSIngo WeinholdAttrDirDescriptor::Close()
446a9bf6ecbSIngo Weinhold{
447a9bf6ecbSIngo Weinhold	if (dir) {
448a9bf6ecbSIngo Weinhold		DIR *oldDir = dir;
449a9bf6ecbSIngo Weinhold		dir = NULL;
450a9bf6ecbSIngo Weinhold		if (fs_close_attr_dir(oldDir) < 0)
451a9bf6ecbSIngo Weinhold			return errno;
452a9bf6ecbSIngo Weinhold	}
453a9bf6ecbSIngo Weinhold
4547db9e218SMaurice Kalinowski	return B_OK;
455a9bf6ecbSIngo Weinhold}
456a9bf6ecbSIngo Weinhold
457a9bf6ecbSIngo Weinhold// Dup
458a9bf6ecbSIngo Weinholdstatus_t
459a9bf6ecbSIngo WeinholdAttrDirDescriptor::Dup(Descriptor *&clone)
460a9bf6ecbSIngo Weinhold{
461a9bf6ecbSIngo Weinhold	// we don't allow dup()int attr dir descriptors
462a9bf6ecbSIngo Weinhold	return B_FILE_ERROR;
463a9bf6ecbSIngo Weinhold}
464a9bf6ecbSIngo Weinhold
465a9bf6ecbSIngo Weinhold// GetStat
466a9bf6ecbSIngo Weinholdstatus_t
467a9bf6ecbSIngo WeinholdAttrDirDescriptor::GetStat(bool traverseLink, struct stat *st)
468a9bf6ecbSIngo Weinhold{
469a9bf6ecbSIngo Weinhold	// we don't allow stat()int attr dir descriptors
470a9bf6ecbSIngo Weinhold	return B_FILE_ERROR;
471a9bf6ecbSIngo Weinhold}
472a9bf6ecbSIngo Weinhold
473a9bf6ecbSIngo Weinhold// GetNodeRef
474a9bf6ecbSIngo Weinholdstatus_t
475a9bf6ecbSIngo WeinholdAttrDirDescriptor::GetNodeRef(NodeRef &ref)
476a9bf6ecbSIngo Weinhold{
477a9bf6ecbSIngo Weinhold	ref = this->ref;
478a9bf6ecbSIngo Weinhold
479a9bf6ecbSIngo Weinhold	return B_OK;
480a9bf6ecbSIngo Weinhold}
481a9bf6ecbSIngo Weinhold
482a9bf6ecbSIngo Weinhold
483a9bf6ecbSIngo Weinhold// get_descriptor
484a9bf6ecbSIngo WeinholdDescriptor *
485a9bf6ecbSIngo Weinholdget_descriptor(int fd)
486a9bf6ecbSIngo Weinhold{
4877db9e218SMaurice Kalinowski	if (!sDescriptors)
4887db9e218SMaurice Kalinowski		return NULL;
4897db9e218SMaurice Kalinowski	DescriptorMap::iterator it = sDescriptors->find(fd);
4907db9e218SMaurice Kalinowski	if (it == sDescriptors->end())
491a9bf6ecbSIngo Weinhold		return NULL;
492a9bf6ecbSIngo Weinhold	return it->second;
493a9bf6ecbSIngo Weinhold}
494a9bf6ecbSIngo Weinhold
495a9bf6ecbSIngo Weinhold// add_descriptor
496a9bf6ecbSIngo Weinholdint
497a9bf6ecbSIngo Weinholdadd_descriptor(Descriptor *descriptor)
498a9bf6ecbSIngo Weinhold{
4997db9e218SMaurice Kalinowski	if (!sDescriptors)
5007db9e218SMaurice Kalinowski		sDescriptors = new DescriptorMap;
5017db9e218SMaurice Kalinowski
502a9bf6ecbSIngo Weinhold	int fd = -1;
503a9bf6ecbSIngo Weinhold	if (FileDescriptor *file = dynamic_cast<FileDescriptor*>(descriptor)) {
504a9bf6ecbSIngo Weinhold		fd = file->fd;
505a9bf6ecbSIngo Weinhold	} else {
506a9bf6ecbSIngo Weinhold		// find a free slot
507a9bf6ecbSIngo Weinhold		for (fd = kVirtualDescriptorStart;
5087db9e218SMaurice Kalinowski			sDescriptors->find(fd) != sDescriptors->end();
509a9bf6ecbSIngo Weinhold			fd++) {
510a9bf6ecbSIngo Weinhold		}
511a9bf6ecbSIngo Weinhold	}
512a9bf6ecbSIngo Weinhold
5137db9e218SMaurice Kalinowski	(*sDescriptors)[fd] = descriptor;
514a9bf6ecbSIngo Weinhold	descriptor->fd = fd;
515a9bf6ecbSIngo Weinhold
516a9bf6ecbSIngo Weinhold	return fd;
517a9bf6ecbSIngo Weinhold}
518a9bf6ecbSIngo Weinhold
519a9bf6ecbSIngo Weinhold// delete_descriptor
520a9bf6ecbSIngo Weinholdstatus_t
521a9bf6ecbSIngo Weinholddelete_descriptor(int fd)
522a9bf6ecbSIngo Weinhold{
5237db9e218SMaurice Kalinowski	DescriptorMap::iterator it = sDescriptors->find(fd);
5247db9e218SMaurice Kalinowski	if (it == sDescriptors->end())
525a9bf6ecbSIngo Weinhold		return B_FILE_ERROR;
526a9bf6ecbSIngo Weinhold
527a9bf6ecbSIngo Weinhold	status_t error = it->second->Close();
528a9bf6ecbSIngo Weinhold	delete it->second;
5297db9e218SMaurice Kalinowski	sDescriptors->erase(it);
5307db9e218SMaurice Kalinowski
5317db9e218SMaurice Kalinowski	if (sDescriptors->size() == 0) {
5327db9e218SMaurice Kalinowski		delete sDescriptors;
5338e27997cSMaurice Kalinowski		sDescriptors = NULL;
5347db9e218SMaurice Kalinowski	}
535a9bf6ecbSIngo Weinhold	return error;
536a9bf6ecbSIngo Weinhold}
537a9bf6ecbSIngo Weinhold
53818d457f8SIngo Weinhold
53918d457f8SIngo Weinholdbool
54018d457f8SIngo Weinholdis_unknown_or_system_descriptor(int fd)
54118d457f8SIngo Weinhold{
54218d457f8SIngo Weinhold	Descriptor* descriptor = get_descriptor(fd);
54318d457f8SIngo Weinhold	return descriptor == NULL || descriptor->IsSystemFD();
54418d457f8SIngo Weinhold}
54518d457f8SIngo Weinhold
54618d457f8SIngo Weinhold
547a9bf6ecbSIngo Weinhold} // namespace BPrivate
548