xref: /haiku/src/add-ons/kernel/file_systems/bindfs/Volume.cpp (revision 99d1318ec02694fc520a0dc38ae38565db7e8c3c)
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 #include <AutoDeleterDrivers.h>
23 
24 #include "DebugSupport.h"
25 #include "kernel_interface.h"
26 #include "Node.h"
27 
28 
29 // #pragma mark - Volume
30 
31 
32 Volume::Volume(fs_volume* fsVolume)
33 	:
34 	fFSVolume(fsVolume),
35 	fSourceFSVolume(NULL),
36 	fSourceVnode(NULL),
37 	fRootNode(NULL)
38 {
39 }
40 
41 
42 Volume::~Volume()
43 {
44 	if (fSourceVnode != NULL)
45 		vfs_put_vnode(fSourceVnode);
46 }
47 
48 
49 status_t
50 Volume::Mount(const char* parameterString)
51 {
52 	const char* source = NULL;
53 	DriverSettingsUnloader parametersHandle(
54 		parse_driver_settings_string(parameterString));
55 	if (parametersHandle.IsSet())
56 		source = get_driver_parameter(
57 			parametersHandle.Get(), "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 
98 void
99 Volume::Unmount()
100 {
101 }
102 
103 
104 status_t
105 Volume::_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