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	fRootNode(NULL)
37{
38}
39
40
41Volume::~Volume()
42{
43	delete fRootNode;
44}
45
46
47status_t
48Volume::Mount(const char* parameterString)
49{
50	const char* source = NULL;
51	void* parameterHandle = parse_driver_settings_string(parameterString);
52	if (parameterHandle != NULL) {
53		source = get_driver_parameter(parameterHandle, "source", NULL, NULL);
54		delete_driver_settings(parameterHandle);
55	}
56	if (source == NULL || source[0] == '\0') {
57		ERROR("need source folder ('source' parameter)!\n");
58		RETURN_ERROR(B_BAD_VALUE);
59	}
60
61	struct vnode* sourceVnode;
62	status_t error = vfs_get_vnode_from_path(source, true, &sourceVnode);
63	if (error != B_OK)
64		RETURN_ERROR(error);
65	if (sourceVnode == NULL)
66		RETURN_ERROR(B_ENTRY_NOT_FOUND);
67	fs_vnode* sourceFSNode = vfs_fsnode_for_vnode(sourceVnode);
68	fSourceFSVolume = volume_for_vnode(sourceFSNode);
69
70	struct stat st;
71	if ((stat(source, &st)) != 0)
72		RETURN_ERROR(B_ERROR);
73
74	strlcpy(fName, "bindfs:", sizeof(fName));
75	strlcpy(fName, source, sizeof(fName));
76
77	// create the root node
78	fRootNode = new(std::nothrow) Node(st.st_ino, st.st_mode);
79	if (fRootNode == NULL)
80		RETURN_ERROR(B_NO_MEMORY);
81
82	_InitVnodeOpsFrom(sourceFSNode);
83
84	// publish the root node
85	error = publish_vnode(fFSVolume, fRootNode->ID(), fRootNode, &fVnodeOps,
86		fRootNode->Mode() & S_IFMT, 0);
87	if (error != B_OK) {
88		delete fRootNode;
89		fRootNode = NULL;
90		return error;
91	}
92
93	return B_OK;
94}
95
96
97void
98Volume::Unmount()
99{
100}
101
102
103status_t
104Volume::_InitVnodeOpsFrom(fs_vnode* sourceNode)
105{
106	// vnode ops
107	int opsCount = sizeof(fVnodeOps) / sizeof(void*);
108	for (int i = 0; i < opsCount; ++i) {
109		if (((void**)sourceNode->ops)[i] == NULL)
110			((void**)&fVnodeOps)[i] = NULL;
111		else
112			((void**)&fVnodeOps)[i] = ((void**)&gBindFSVnodeOps)[i];
113	}
114
115	return B_OK;
116}
117