1/*
2 * Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "Volume.h"
8
9#include <dirent.h>
10#include <errno.h>
11#include <fcntl.h>
12#include <string.h>
13#include <sys/stat.h>
14
15#include <new>
16
17#include <driver_settings.h>
18#include <KernelExport.h>
19#include <vfs.h>
20
21#include <AutoDeleter.h>
22
23#include "DebugSupport.h"
24#include "kernel_interface.h"
25#include "Node.h"
26#include "Utils.h"
27
28
29// #pragma mark - Volume
30
31
32Volume::Volume(fs_volume* fsVolume)
33	:
34	fFSVolume(fsVolume),
35	fSourceFSVolume(NULL),
36	fSourceVnode(NULL),
37	fRootNode(NULL)
38{
39}
40
41
42Volume::~Volume()
43{
44	if (fSourceVnode != NULL)
45		vfs_put_vnode(fSourceVnode);
46}
47
48
49status_t
50Volume::Mount(const char* parameterString)
51{
52	const char* source = NULL;
53	void* parameterHandle = parse_driver_settings_string(parameterString);
54	CObjectDeleter<void, status_t> parameterDeleter(parameterHandle,
55		delete_driver_settings);
56	if (parameterHandle != NULL)
57		source = get_driver_parameter(parameterHandle, "source", NULL, NULL);
58	if (source == NULL || source[0] == '\0') {
59		ERROR("need source folder ('source' parameter)!\n");
60		RETURN_ERROR(B_BAD_VALUE);
61	}
62
63	status_t error = vfs_get_vnode_from_path(source, true, &fSourceVnode);
64	if (error != B_OK)
65		RETURN_ERROR(error);
66	if (fSourceVnode == NULL)
67		RETURN_ERROR(B_ENTRY_NOT_FOUND);
68	fs_vnode* sourceFSNode = vfs_fsnode_for_vnode(fSourceVnode);
69	fSourceFSVolume = volume_for_vnode(sourceFSNode);
70
71	struct stat st;
72	if ((stat(source, &st)) != 0)
73		RETURN_ERROR(B_ERROR);
74
75	strlcpy(fName, "bindfs:", sizeof(fName));
76	strlcpy(fName, source, sizeof(fName));
77
78	// create the root node
79	fRootNode = new(std::nothrow) Node(st.st_ino, st.st_mode);
80	if (fRootNode == NULL)
81		RETURN_ERROR(B_NO_MEMORY);
82
83	_InitVnodeOpsFrom(sourceFSNode);
84
85	// publish the root node
86	error = publish_vnode(fFSVolume, fRootNode->ID(), fRootNode, &fVnodeOps,
87		fRootNode->Mode() & S_IFMT, 0);
88	if (error != B_OK) {
89		delete fRootNode;
90		fRootNode = NULL;
91		return error;
92	}
93
94	return B_OK;
95}
96
97
98void
99Volume::Unmount()
100{
101}
102
103
104status_t
105Volume::_InitVnodeOpsFrom(fs_vnode* sourceNode)
106{
107	// vnode ops
108	int opsCount = sizeof(fVnodeOps) / sizeof(void*);
109	for (int i = 0; i < opsCount; ++i) {
110		if (((void**)sourceNode->ops)[i] == NULL)
111			((void**)&fVnodeOps)[i] = NULL;
112		else
113			((void**)&fVnodeOps)[i] = ((void**)&gBindFSVnodeOps)[i];
114	}
115
116	return B_OK;
117}
118