xref: /haiku/src/add-ons/kernel/file_systems/bindfs/Volume.cpp (revision c80809a3ab0b0a2ce53ea861a2b00ace24ff452d)
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 
32 Volume::Volume(fs_volume* fsVolume)
33 	:
34 	fFSVolume(fsVolume),
35 	fSourceFSVolume(NULL),
36 	fRootNode(NULL)
37 {
38 }
39 
40 
41 Volume::~Volume()
42 {
43 	delete fRootNode;
44 }
45 
46 
47 status_t
48 Volume::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 
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