xref: /haiku/src/add-ons/kernel/file_systems/bindfs/Volume.cpp (revision 02354704729d38c3b078c696adc1bbbd33cbcf72)
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 	void* parameterHandle = parse_driver_settings_string(parameterString);
54 	DriverSettingsUnloader parameterDeleter(parameterHandle);
55 	if (parameterHandle != NULL)
56 		source = get_driver_parameter(parameterHandle, "source", NULL, NULL);
57 	if (source == NULL || source[0] == '\0') {
58 		ERROR("need source folder ('source' parameter)!\n");
59 		RETURN_ERROR(B_BAD_VALUE);
60 	}
61 
62 	status_t error = vfs_get_vnode_from_path(source, true, &fSourceVnode);
63 	if (error != B_OK)
64 		RETURN_ERROR(error);
65 	if (fSourceVnode == NULL)
66 		RETURN_ERROR(B_ENTRY_NOT_FOUND);
67 	fs_vnode* sourceFSNode = vfs_fsnode_for_vnode(fSourceVnode);
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 
97 void
98 Volume::Unmount()
99 {
100 }
101 
102 
103 status_t
104 Volume::_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