1/*
2 * Copyright 2007, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2008-2012, Axel D��rfler, axeld@pinc-software.de.
4 * Copyright 2012, Gerasim Troeglazov (3dEyes**), 3dEyes@gmail.com
5 * Copyright 2019, Les De Ridder, les@lesderid.net
6 *
7 * Distributed under the terms of the MIT License.
8 */
9
10
11#include "BTRFSAddOn.h"
12#include "InitializeParameterEditor.h"
13
14#include <new>
15
16#include <Directory.h>
17#include <List.h>
18#include <Path.h>
19#include <Volume.h>
20
21#include <DiskDeviceTypes.h>
22#include <MutablePartition.h>
23
24#include <AutoDeleter.h>
25#include <StringForSize.h>
26
27#include <cstdio>
28#include <debug.h>
29
30#include "btrfs.h"
31#include "btrfs_disk_system.h"
32
33#ifdef ASSERT
34#	undef ASSERT
35#endif
36
37
38using std::nothrow;
39
40static const uint32 kDiskSystemFlags =
41	0
42	| B_DISK_SYSTEM_SUPPORTS_INITIALIZING
43	| B_DISK_SYSTEM_SUPPORTS_CONTENT_NAME
44//	| B_DISK_SYSTEM_SUPPORTS_CHECKING
45//	| B_DISK_SYSTEM_SUPPORTS_REPAIRING
46//	| B_DISK_SYSTEM_SUPPORTS_CHECKING_WHILE_MOUNTED
47//	| B_DISK_SYSTEM_SUPPORTS_REPAIRING_WHILE_MOUNTED
48//	| B_DISK_SYSTEM_SUPPORTS_DEFRAGMENTING
49//	| B_DISK_SYSTEM_SUPPORTS_DEFRAGMENTING_WHILE_MOUNTED
50;
51
52//#define TRACE_BTRFS_ADD_ON
53#undef TRACE
54#ifdef TRACE_BTRFS_ADD_ON
55#	define TRACE(x...) printf(x)
56#else
57#	define TRACE(x...) do {} while (false)
58#endif
59
60BTRFSAddOn::BTRFSAddOn()
61	: BDiskSystemAddOn(kPartitionTypeBTRFS, kDiskSystemFlags)
62{
63}
64
65
66BTRFSAddOn::~BTRFSAddOn()
67{
68}
69
70
71status_t
72BTRFSAddOn::CreatePartitionHandle(BMutablePartition* partition,
73	BPartitionHandle** _handle)
74{
75	BTRFSPartitionHandle* handle = new(nothrow) BTRFSPartitionHandle(partition);
76	if (!handle)
77		return B_NO_MEMORY;
78
79	status_t error = handle->Init();
80	if (error != B_OK) {
81		delete handle;
82		return error;
83	}
84
85	*_handle = handle;
86
87	return B_OK;
88}
89
90
91bool
92BTRFSAddOn::CanInitialize(const BMutablePartition* partition)
93{
94	// We can initialize if the partition is large enough.
95
96	//TODO(lesderid): Check min size
97	return true;
98}
99
100
101status_t
102BTRFSAddOn::ValidateInitialize(const BMutablePartition* partition,
103	BString* name, const char* parameterString)
104{
105	if (!CanInitialize(partition) || !name)
106		return B_BAD_VALUE;
107
108	// truncate, if it is too long
109	if (name->Length() >= BTRFS_LABEL_SIZE)
110		name->Truncate(BTRFS_LABEL_SIZE - 1);
111
112	// replace '/' and '\\' by '-'
113	name->ReplaceAll('/', '-');
114	name->ReplaceAll('\\', '-');
115
116	// check parameters
117	initialize_parameters parameters;
118	status_t error = parse_initialize_parameters(parameterString, parameters);
119	if (error != B_OK)
120		return error;
121
122	return B_OK;
123}
124
125
126status_t
127BTRFSAddOn::Initialize(BMutablePartition* partition, const char* name,
128	const char* parameterString, BPartitionHandle** _handle)
129{
130	if (!CanInitialize(partition) || check_volume_name(name) != B_OK)
131		return B_BAD_VALUE;
132
133	initialize_parameters parameters;
134	status_t error = parse_initialize_parameters(parameterString, parameters);
135	if (error != B_OK)
136		return error;
137
138	BTRFSPartitionHandle* handle = new(nothrow) BTRFSPartitionHandle(partition);
139	if (!handle)
140		return B_NO_MEMORY;
141	ObjectDeleter<BTRFSPartitionHandle> handleDeleter(handle);
142
143	error = partition->SetContentType(Name());
144	if (error != B_OK)
145		return error;
146
147	partition->SetContentName(name);
148	partition->SetContentParameters(parameterString);
149	uint32 blockSize = parameters.blockSize;
150	partition->SetBlockSize(blockSize);
151	partition->SetContentSize(partition->Size() / blockSize * blockSize);
152	partition->Changed(B_PARTITION_CHANGED_INITIALIZATION);
153
154	*_handle = handleDeleter.Detach();
155
156	return B_OK;
157}
158
159
160status_t
161BTRFSAddOn::GetParameterEditor(B_PARAMETER_EDITOR_TYPE type,
162	BPartitionParameterEditor** editor)
163{
164	*editor = NULL;
165	if (type == B_INITIALIZE_PARAMETER_EDITOR) {
166		try {
167			*editor = new InitializeBTRFSEditor();
168		} catch (std::bad_alloc&) {
169			return B_NO_MEMORY;
170		}
171		return B_OK;
172	}
173	return B_NOT_SUPPORTED;
174}
175
176
177BTRFSPartitionHandle::BTRFSPartitionHandle(BMutablePartition* partition)
178	: BPartitionHandle(partition)
179{
180}
181
182
183BTRFSPartitionHandle::~BTRFSPartitionHandle()
184{
185}
186
187
188status_t
189BTRFSPartitionHandle::Init()
190{
191	return B_OK;
192}
193
194
195uint32
196BTRFSPartitionHandle::SupportedOperations(uint32 mask)
197{
198	return kDiskSystemFlags & mask;
199}
200
201
202status_t
203BTRFSPartitionHandle::Repair(bool checkOnly)
204{
205	TRACE("BTRFSPartitionHandle::Repair(checkOnly=%d)\n", checkOnly);
206	return B_NOT_SUPPORTED;
207}
208
209
210status_t
211get_disk_system_add_ons(BList* addOns)
212{
213	BTRFSAddOn* addOn = new(nothrow) BTRFSAddOn;
214	if (!addOn) {
215		return B_NO_MEMORY;
216	}
217
218	if (!addOns->AddItem(addOn)) {
219		delete addOn;
220		return B_NO_MEMORY;
221	}
222
223	return B_OK;
224}
225