121f2402eSStephan Aßmus/*
2ae47dec0SAxel Dörfler * Copyright 2007-2018, Haiku, Inc. All rights reserved.
321f2402eSStephan Aßmus * Distributed under the terms of the MIT License.
44cdd7099SAxel Dörfler *
54cdd7099SAxel Dörfler * Authors:
64cdd7099SAxel Dörfler *		Stephan A��mus, superstippi@gmx.de
74cdd7099SAxel Dörfler *		Axel D��rfler, axeld@pinc-software.de
821f2402eSStephan Aßmus */
921f2402eSStephan Aßmus
103f027ce9SStephan Aßmus
1121f2402eSStephan Aßmus#include "AutoMounter.h"
1221f2402eSStephan Aßmus
1321f2402eSStephan Aßmus#include <new>
1421f2402eSStephan Aßmus
1521f2402eSStephan Aßmus#include <string.h>
1621f2402eSStephan Aßmus#include <unistd.h>
1721f2402eSStephan Aßmus
1821f2402eSStephan Aßmus#include <Alert.h>
1921f2402eSStephan Aßmus#include <AutoLocker.h>
203f027ce9SStephan Aßmus#include <Catalog.h>
2121f2402eSStephan Aßmus#include <Debug.h>
2221f2402eSStephan Aßmus#include <Directory.h>
2321f2402eSStephan Aßmus#include <DiskDevice.h>
2421f2402eSStephan Aßmus#include <DiskDeviceRoster.h>
2521f2402eSStephan Aßmus#include <DiskDeviceList.h>
2621f2402eSStephan Aßmus#include <DiskDeviceTypes.h>
2721f2402eSStephan Aßmus#include <DiskSystem.h>
2821f2402eSStephan Aßmus#include <FindDirectory.h>
2921f2402eSStephan Aßmus#include <fs_info.h>
3021f2402eSStephan Aßmus#include <fs_volume.h>
315e17d2d7SAxel Dörfler#include <LaunchRoster.h>
323f027ce9SStephan Aßmus#include <Locale.h>
3321f2402eSStephan Aßmus#include <Message.h>
3421f2402eSStephan Aßmus#include <Node.h>
3521f2402eSStephan Aßmus#include <NodeMonitor.h>
3621f2402eSStephan Aßmus#include <Path.h>
3721f2402eSStephan Aßmus#include <PropertyInfo.h>
3821f2402eSStephan Aßmus#include <String.h>
3921f2402eSStephan Aßmus#include <VolumeRoster.h>
4021f2402eSStephan Aßmus
4121f2402eSStephan Aßmus#include "MountServer.h"
4221f2402eSStephan Aßmus
43ae47dec0SAxel Dörfler#include "Utilities.h"
44ae47dec0SAxel Dörfler
4521f2402eSStephan Aßmus
46546208a5SOliver Tappe#undef B_TRANSLATION_CONTEXT
47546208a5SOliver Tappe#define B_TRANSLATION_CONTEXT "AutoMounter"
483f027ce9SStephan Aßmus
493f027ce9SStephan Aßmus
5021f2402eSStephan Aßmusstatic const char* kMountServerSettings = "mount_server";
5121f2402eSStephan Aßmusstatic const char* kMountFlagsKeyExtension = " mount flags";
5221f2402eSStephan Aßmus
535e17d2d7SAxel Dörflerstatic const char* kInitialMountEvent = "initial_volumes_mounted";
5421f2402eSStephan Aßmus
555e17d2d7SAxel Dörfler
56ae47dec0SAxel Dörflerclass MountVisitor : public BDiskDeviceVisitor {
57ae47dec0SAxel Dörflerpublic:
58ae47dec0SAxel Dörfler								MountVisitor(mount_mode normalMode,
59ae47dec0SAxel Dörfler									mount_mode removableMode,
60ae47dec0SAxel Dörfler									bool initialRescan, BMessage& previous,
61ae47dec0SAxel Dörfler									partition_id deviceID);
62ae47dec0SAxel Dörfler	virtual						~MountVisitor()
63ae47dec0SAxel Dörfler									{}
64ae47dec0SAxel Dörfler
65ae47dec0SAxel Dörfler	virtual	bool				Visit(BDiskDevice* device);
66ae47dec0SAxel Dörfler	virtual	bool				Visit(BPartition* partition, int32 level);
67ae47dec0SAxel Dörfler
68ae47dec0SAxel Dörflerprivate:
69ae47dec0SAxel Dörfler			bool				_WasPreviouslyMounted(const BPath& path,
70ae47dec0SAxel Dörfler									const BPartition* partition);
71ae47dec0SAxel Dörfler
72ae47dec0SAxel Dörflerprivate:
73ae47dec0SAxel Dörfler			mount_mode			fNormalMode;
74ae47dec0SAxel Dörfler			mount_mode			fRemovableMode;
75ae47dec0SAxel Dörfler			bool				fInitialRescan;
76ae47dec0SAxel Dörfler			BMessage&			fPrevious;
77ae47dec0SAxel Dörfler			partition_id		fOnlyOnDeviceID;
78ae47dec0SAxel Dörfler};
79ae47dec0SAxel Dörfler
80ae47dec0SAxel Dörfler
81ae47dec0SAxel Dörflerclass MountArchivedVisitor : public BDiskDeviceVisitor {
82ae47dec0SAxel Dörflerpublic:
83ae47dec0SAxel Dörfler								MountArchivedVisitor(
84ae47dec0SAxel Dörfler									const BDiskDeviceList& devices,
85ae47dec0SAxel Dörfler									const BMessage& archived);
86ae47dec0SAxel Dörfler	virtual						~MountArchivedVisitor();
87ae47dec0SAxel Dörfler
88ae47dec0SAxel Dörfler	virtual	bool				Visit(BDiskDevice* device);
89ae47dec0SAxel Dörfler	virtual	bool				Visit(BPartition* partition, int32 level);
90ae47dec0SAxel Dörfler
91ae47dec0SAxel Dörflerprivate:
92ae47dec0SAxel Dörfler			int					_Score(BPartition* partition);
93ae47dec0SAxel Dörfler
94ae47dec0SAxel Dörflerprivate:
95ae47dec0SAxel Dörfler			const BDiskDeviceList& fDevices;
96ae47dec0SAxel Dörfler			const BMessage&		fArchived;
97ae47dec0SAxel Dörfler			int					fBestScore;
98ae47dec0SAxel Dörfler			partition_id		fBestID;
99ae47dec0SAxel Dörfler};
100ae47dec0SAxel Dörfler
101ae47dec0SAxel Dörfler
1025e17d2d7SAxel Dörflerstatic bool
10321f2402eSStephan AßmusBootedInSafeMode()
10421f2402eSStephan Aßmus{
105ae47dec0SAxel Dörfler	const char* safeMode = getenv("SAFEMODE");
106ae47dec0SAxel Dörfler	return safeMode != NULL && strcmp(safeMode, "yes") == 0;
107ae47dec0SAxel Dörfler}
108ae47dec0SAxel Dörfler
109ae47dec0SAxel Dörfler
110ae47dec0SAxel Dörflerclass ArchiveVisitor : public BDiskDeviceVisitor {
111ae47dec0SAxel Dörflerpublic:
112ae47dec0SAxel Dörfler								ArchiveVisitor(BMessage& message);
113ae47dec0SAxel Dörfler	virtual						~ArchiveVisitor();
114ae47dec0SAxel Dörfler
115ae47dec0SAxel Dörfler	virtual	bool				Visit(BDiskDevice* device);
116ae47dec0SAxel Dörfler	virtual	bool				Visit(BPartition* partition, int32 level);
117ae47dec0SAxel Dörfler
118ae47dec0SAxel Dörflerprivate:
119ae47dec0SAxel Dörfler			BMessage&			fMessage;
120ae47dec0SAxel Dörfler};
121ae47dec0SAxel Dörfler
122ae47dec0SAxel Dörfler
123ae47dec0SAxel Dörfler// #pragma mark - MountVisitor
124ae47dec0SAxel Dörfler
125ae47dec0SAxel Dörfler
126ae47dec0SAxel DörflerMountVisitor::MountVisitor(mount_mode normalMode, mount_mode removableMode,
127ae47dec0SAxel Dörfler		bool initialRescan, BMessage& previous, partition_id deviceID)
128ae47dec0SAxel Dörfler	:
129ae47dec0SAxel Dörfler	fNormalMode(normalMode),
130ae47dec0SAxel Dörfler	fRemovableMode(removableMode),
131ae47dec0SAxel Dörfler	fInitialRescan(initialRescan),
132ae47dec0SAxel Dörfler	fPrevious(previous),
133ae47dec0SAxel Dörfler	fOnlyOnDeviceID(deviceID)
134ae47dec0SAxel Dörfler{
135ae47dec0SAxel Dörfler}
136ae47dec0SAxel Dörfler
137ae47dec0SAxel Dörfler
138ae47dec0SAxel Dörflerbool
139ae47dec0SAxel DörflerMountVisitor::Visit(BDiskDevice* device)
140ae47dec0SAxel Dörfler{
141ae47dec0SAxel Dörfler	return Visit(device, 0);
142ae47dec0SAxel Dörfler}
143ae47dec0SAxel Dörfler
144ae47dec0SAxel Dörfler
145ae47dec0SAxel Dörflerbool
146ae47dec0SAxel DörflerMountVisitor::Visit(BPartition* partition, int32 level)
147ae47dec0SAxel Dörfler{
148ae47dec0SAxel Dörfler	if (fOnlyOnDeviceID >= 0) {
149ae47dec0SAxel Dörfler		// only mount partitions on the given device id
150ae47dec0SAxel Dörfler		// or if the partition ID is already matched
151ae47dec0SAxel Dörfler		BPartition* device = partition;
152ae47dec0SAxel Dörfler		while (device->Parent() != NULL) {
153ae47dec0SAxel Dörfler			if (device->ID() == fOnlyOnDeviceID) {
154ae47dec0SAxel Dörfler				// we are happy
155ae47dec0SAxel Dörfler				break;
156ae47dec0SAxel Dörfler			}
157ae47dec0SAxel Dörfler			device = device->Parent();
158ae47dec0SAxel Dörfler		}
159ae47dec0SAxel Dörfler		if (device->ID() != fOnlyOnDeviceID)
160ae47dec0SAxel Dörfler			return false;
161ae47dec0SAxel Dörfler	}
162ae47dec0SAxel Dörfler
163ae47dec0SAxel Dörfler	mount_mode mode = !fInitialRescan && partition->Device()->IsRemovableMedia()
164ae47dec0SAxel Dörfler		? fRemovableMode : fNormalMode;
165ae47dec0SAxel Dörfler	if (mode == kNoVolumes || partition->IsMounted()
166ae47dec0SAxel Dörfler		|| !partition->ContainsFileSystem()) {
167ae47dec0SAxel Dörfler		return false;
168ae47dec0SAxel Dörfler	}
169ae47dec0SAxel Dörfler
170ae47dec0SAxel Dörfler	BPath path;
171ae47dec0SAxel Dörfler	if (partition->GetPath(&path) != B_OK)
172ae47dec0SAxel Dörfler		return false;
173ae47dec0SAxel Dörfler
174ae47dec0SAxel Dörfler	if (mode == kRestorePreviousVolumes) {
175ae47dec0SAxel Dörfler		// mount all volumes that were stored in the settings file
176ae47dec0SAxel Dörfler		if (!_WasPreviouslyMounted(path, partition))
177ae47dec0SAxel Dörfler			return false;
178ae47dec0SAxel Dörfler	} else if (mode == kOnlyBFSVolumes) {
179ae47dec0SAxel Dörfler		if (partition->ContentType() == NULL
180ae47dec0SAxel Dörfler			|| strcmp(partition->ContentType(), kPartitionTypeBFS))
181ae47dec0SAxel Dörfler			return false;
182ae47dec0SAxel Dörfler	}
183ae47dec0SAxel Dörfler
184ae47dec0SAxel Dörfler	uint32 mountFlags;
185ae47dec0SAxel Dörfler	if (!fInitialRescan) {
186ae47dec0SAxel Dörfler		// Ask the user about mount flags if this is not the
187ae47dec0SAxel Dörfler		// initial scan.
1880d1e94a4SJérôme Duval		if (!AutoMounter::_SuggestMountFlags(partition, &mountFlags))
189ae47dec0SAxel Dörfler			return false;
190ae47dec0SAxel Dörfler	} else {
191ae47dec0SAxel Dörfler		BString mountFlagsKey(path.Path());
192ae47dec0SAxel Dörfler		mountFlagsKey << kMountFlagsKeyExtension;
193ae47dec0SAxel Dörfler		if (fPrevious.FindInt32(mountFlagsKey.String(),
194ae47dec0SAxel Dörfler				(int32*)&mountFlags) < B_OK) {
195ae47dec0SAxel Dörfler			mountFlags = 0;
196ae47dec0SAxel Dörfler		}
197ae47dec0SAxel Dörfler	}
198ae47dec0SAxel Dörfler
199ae47dec0SAxel Dörfler	if (partition->Mount(NULL, mountFlags) != B_OK) {
200ae47dec0SAxel Dörfler		// TODO: Error to syslog
201ae47dec0SAxel Dörfler	}
202ae47dec0SAxel Dörfler	return false;
203ae47dec0SAxel Dörfler}
204ae47dec0SAxel Dörfler
205ae47dec0SAxel Dörfler
206ae47dec0SAxel Dörflerbool
207ae47dec0SAxel DörflerMountVisitor::_WasPreviouslyMounted(const BPath& path,
208ae47dec0SAxel Dörfler	const BPartition* partition)
209ae47dec0SAxel Dörfler{
210ae47dec0SAxel Dörfler	// We only check the legacy config data here; the current method
211ae47dec0SAxel Dörfler	// is implemented in ArchivedVolumeVisitor -- this can be removed
212ae47dec0SAxel Dörfler	// some day.
213ae47dec0SAxel Dörfler	const char* volumeName = NULL;
214ae47dec0SAxel Dörfler	if (partition->ContentName() == NULL
215ae47dec0SAxel Dörfler		|| fPrevious.FindString(path.Path(), &volumeName) != B_OK
216ae47dec0SAxel Dörfler		|| strcmp(volumeName, partition->ContentName()) != 0)
217ae47dec0SAxel Dörfler		return false;
218ae47dec0SAxel Dörfler
219ae47dec0SAxel Dörfler	return true;
220ae47dec0SAxel Dörfler}
221ae47dec0SAxel Dörfler
222ae47dec0SAxel Dörfler
223ae47dec0SAxel Dörfler// #pragma mark - MountArchivedVisitor
224ae47dec0SAxel Dörfler
225ae47dec0SAxel Dörfler
226ae47dec0SAxel DörflerMountArchivedVisitor::MountArchivedVisitor(const BDiskDeviceList& devices,
227ae47dec0SAxel Dörfler		const BMessage& archived)
228ae47dec0SAxel Dörfler	:
229ae47dec0SAxel Dörfler	fDevices(devices),
230ae47dec0SAxel Dörfler	fArchived(archived),
231ae47dec0SAxel Dörfler	fBestScore(-1),
232ae47dec0SAxel Dörfler	fBestID(-1)
233ae47dec0SAxel Dörfler{
234ae47dec0SAxel Dörfler}
235ae47dec0SAxel Dörfler
236ae47dec0SAxel Dörfler
237ae47dec0SAxel DörflerMountArchivedVisitor::~MountArchivedVisitor()
238ae47dec0SAxel Dörfler{
239ae47dec0SAxel Dörfler	if (fBestScore >= 6) {
240ae47dec0SAxel Dörfler		uint32 mountFlags = fArchived.GetUInt32("mountFlags", 0);
241ae47dec0SAxel Dörfler		BPartition* partition = fDevices.PartitionWithID(fBestID);
242ae47dec0SAxel Dörfler		if (partition != NULL)
243ae47dec0SAxel Dörfler			partition->Mount(NULL, mountFlags);
244ae47dec0SAxel Dörfler	}
245ae47dec0SAxel Dörfler}
246ae47dec0SAxel Dörfler
247ae47dec0SAxel Dörfler
248ae47dec0SAxel Dörflerbool
249ae47dec0SAxel DörflerMountArchivedVisitor::Visit(BDiskDevice* device)
250ae47dec0SAxel Dörfler{
251ae47dec0SAxel Dörfler	return Visit(device, 0);
252ae47dec0SAxel Dörfler}
253ae47dec0SAxel Dörfler
254ae47dec0SAxel Dörfler
255ae47dec0SAxel Dörflerbool
256ae47dec0SAxel DörflerMountArchivedVisitor::Visit(BPartition* partition, int32 level)
257ae47dec0SAxel Dörfler{
258ae47dec0SAxel Dörfler	if (partition->IsMounted() || !partition->ContainsFileSystem())
259ae47dec0SAxel Dörfler		return false;
260ae47dec0SAxel Dörfler
261ae47dec0SAxel Dörfler	int score = _Score(partition);
262ae47dec0SAxel Dörfler	if (score > fBestScore) {
263ae47dec0SAxel Dörfler		fBestScore = score;
264ae47dec0SAxel Dörfler		fBestID = partition->ID();
265ae47dec0SAxel Dörfler	}
266ae47dec0SAxel Dörfler
267ae47dec0SAxel Dörfler	return false;
268ae47dec0SAxel Dörfler}
269ae47dec0SAxel Dörfler
270ae47dec0SAxel Dörfler
271ae47dec0SAxel Dörflerint
272ae47dec0SAxel DörflerMountArchivedVisitor::_Score(BPartition* partition)
273ae47dec0SAxel Dörfler{
274ae47dec0SAxel Dörfler	BPath path;
275ae47dec0SAxel Dörfler	if (partition->GetPath(&path) != B_OK)
276ae47dec0SAxel Dörfler		return false;
277ae47dec0SAxel Dörfler
278ae47dec0SAxel Dörfler	int score = 0;
279ae47dec0SAxel Dörfler
280ae47dec0SAxel Dörfler	int64 capacity = fArchived.GetInt64("capacity", 0);
281ae47dec0SAxel Dörfler	if (capacity == partition->ContentSize())
282ae47dec0SAxel Dörfler		score += 4;
283ae47dec0SAxel Dörfler
284ae47dec0SAxel Dörfler	BString deviceName = fArchived.GetString("deviceName");
285ae47dec0SAxel Dörfler	if (deviceName == path.Path())
286ae47dec0SAxel Dörfler		score += 3;
287ae47dec0SAxel Dörfler
288ae47dec0SAxel Dörfler	BString volumeName = fArchived.GetString("volumeName");
289ae47dec0SAxel Dörfler	if (volumeName == partition->ContentName())
290ae47dec0SAxel Dörfler		score += 2;
291ae47dec0SAxel Dörfler
292ae47dec0SAxel Dörfler	BString fsName = fArchived.FindString("fsName");
293ae47dec0SAxel Dörfler	if (fsName == partition->ContentType())
294ae47dec0SAxel Dörfler		score += 1;
295ae47dec0SAxel Dörfler
296ae47dec0SAxel Dörfler	uint32 blockSize = fArchived.GetUInt32("blockSize", 0);
297ae47dec0SAxel Dörfler	if (blockSize == partition->BlockSize())
298ae47dec0SAxel Dörfler		score += 1;
299ae47dec0SAxel Dörfler
300ae47dec0SAxel Dörfler	return score;
301ae47dec0SAxel Dörfler}
302ae47dec0SAxel Dörfler
303ae47dec0SAxel Dörfler
304ae47dec0SAxel Dörfler// #pragma mark - ArchiveVisitor
305ae47dec0SAxel Dörfler
306ae47dec0SAxel Dörfler
307ae47dec0SAxel DörflerArchiveVisitor::ArchiveVisitor(BMessage& message)
308ae47dec0SAxel Dörfler	:
309ae47dec0SAxel Dörfler	fMessage(message)
310ae47dec0SAxel Dörfler{
311ae47dec0SAxel Dörfler}
312ae47dec0SAxel Dörfler
313ae47dec0SAxel Dörfler
314ae47dec0SAxel DörflerArchiveVisitor::~ArchiveVisitor()
315ae47dec0SAxel Dörfler{
316ae47dec0SAxel Dörfler}
317ae47dec0SAxel Dörfler
318ae47dec0SAxel Dörfler
319ae47dec0SAxel Dörflerbool
320ae47dec0SAxel DörflerArchiveVisitor::Visit(BDiskDevice* device)
321ae47dec0SAxel Dörfler{
322ae47dec0SAxel Dörfler	return Visit(device, 0);
323ae47dec0SAxel Dörfler}
324ae47dec0SAxel Dörfler
325ae47dec0SAxel Dörfler
326ae47dec0SAxel Dörflerbool
327ae47dec0SAxel DörflerArchiveVisitor::Visit(BPartition* partition, int32 level)
328ae47dec0SAxel Dörfler{
329ae47dec0SAxel Dörfler	if (!partition->ContainsFileSystem())
330ae47dec0SAxel Dörfler		return false;
331ae47dec0SAxel Dörfler
332ae47dec0SAxel Dörfler	BPath path;
333ae47dec0SAxel Dörfler	if (partition->GetPath(&path) != B_OK)
334ae47dec0SAxel Dörfler		return false;
335ae47dec0SAxel Dörfler
336ae47dec0SAxel Dörfler	BMessage info;
337ae47dec0SAxel Dörfler	info.AddUInt32("blockSize", partition->BlockSize());
338ae47dec0SAxel Dörfler	info.AddInt64("capacity", partition->ContentSize());
339ae47dec0SAxel Dörfler	info.AddString("deviceName", path.Path());
340ae47dec0SAxel Dörfler	info.AddString("volumeName", partition->ContentName());
341ae47dec0SAxel Dörfler	info.AddString("fsName", partition->ContentType());
342ae47dec0SAxel Dörfler
343ae47dec0SAxel Dörfler	fMessage.AddMessage("info", &info);
344ae47dec0SAxel Dörfler	return false;
34521f2402eSStephan Aßmus}
34621f2402eSStephan Aßmus
34721f2402eSStephan Aßmus
34821f2402eSStephan Aßmus// #pragma mark -
34921f2402eSStephan Aßmus
35021f2402eSStephan Aßmus
35121f2402eSStephan AßmusAutoMounter::AutoMounter()
35221f2402eSStephan Aßmus	:
3535e17d2d7SAxel Dörfler	BServer(kMountServerSignature, true, NULL),
35421f2402eSStephan Aßmus	fNormalMode(kRestorePreviousVolumes),
35521f2402eSStephan Aßmus	fRemovableMode(kAllVolumes),
35621f2402eSStephan Aßmus	fEjectWhenUnmounting(true)
35721f2402eSStephan Aßmus{
35821f2402eSStephan Aßmus	set_thread_priority(Thread(), B_LOW_PRIORITY);
35921f2402eSStephan Aßmus
36021f2402eSStephan Aßmus	if (!BootedInSafeMode()) {
36121f2402eSStephan Aßmus		_ReadSettings();
36221f2402eSStephan Aßmus	} else {
36321f2402eSStephan Aßmus		// defeat automounter in safe mode, don't even care about the settings
36421f2402eSStephan Aßmus		fNormalMode = kNoVolumes;
36521f2402eSStephan Aßmus		fRemovableMode = kNoVolumes;
36621f2402eSStephan Aßmus	}
36721f2402eSStephan Aßmus
36821f2402eSStephan Aßmus	BDiskDeviceRoster().StartWatching(this,
36921f2402eSStephan Aßmus		B_DEVICE_REQUEST_DEVICE | B_DEVICE_REQUEST_DEVICE_LIST);
3707cd19b7eSAxel Dörfler	BLaunchRoster().RegisterEvent(this, kInitialMountEvent, B_STICKY_EVENT);
37121f2402eSStephan Aßmus}
37221f2402eSStephan Aßmus
37321f2402eSStephan Aßmus
37421f2402eSStephan AßmusAutoMounter::~AutoMounter()
37521f2402eSStephan Aßmus{
3765e17d2d7SAxel Dörfler	BLaunchRoster().UnregisterEvent(this, kInitialMountEvent);
37721f2402eSStephan Aßmus	BDiskDeviceRoster().StopWatching(this);
37821f2402eSStephan Aßmus}
37921f2402eSStephan Aßmus
38021f2402eSStephan Aßmus
38121f2402eSStephan Aßmusvoid
3825e17d2d7SAxel DörflerAutoMounter::ReadyToRun()
38321f2402eSStephan Aßmus{
3845e17d2d7SAxel Dörfler	// Do initial scan
3855e17d2d7SAxel Dörfler	_MountVolumes(fNormalMode, fRemovableMode, true);
3865e17d2d7SAxel Dörfler	BLaunchRoster().NotifyEvent(this, kInitialMountEvent);
3875e17d2d7SAxel Dörfler}
38821f2402eSStephan Aßmus
38921f2402eSStephan Aßmus
3905e17d2d7SAxel Dörflervoid
3915e17d2d7SAxel DörflerAutoMounter::MessageReceived(BMessage* message)
3925e17d2d7SAxel Dörfler{
3935e17d2d7SAxel Dörfler	switch (message->what) {
39421f2402eSStephan Aßmus		case kMountVolume:
39521f2402eSStephan Aßmus			_MountVolume(message);
39621f2402eSStephan Aßmus			break;
39721f2402eSStephan Aßmus
39821f2402eSStephan Aßmus		case kUnmountVolume:
39921f2402eSStephan Aßmus			_UnmountAndEjectVolume(message);
40021f2402eSStephan Aßmus			break;
40121f2402eSStephan Aßmus
40221f2402eSStephan Aßmus		case kSetAutomounterParams:
40321f2402eSStephan Aßmus		{
40421f2402eSStephan Aßmus			bool rescanNow = false;
40521f2402eSStephan Aßmus			message->FindBool("rescanNow", &rescanNow);
40621f2402eSStephan Aßmus
40721f2402eSStephan Aßmus			_UpdateSettingsFromMessage(message);
40821f2402eSStephan Aßmus			_GetSettings(&fSettings);
40921f2402eSStephan Aßmus			_WriteSettings();
41021f2402eSStephan Aßmus
41121f2402eSStephan Aßmus			if (rescanNow)
41221f2402eSStephan Aßmus				_MountVolumes(fNormalMode, fRemovableMode);
41321f2402eSStephan Aßmus			break;
41421f2402eSStephan Aßmus		}
41521f2402eSStephan Aßmus
416011a4cdbSStephan Aßmus		case kGetAutomounterParams:
417011a4cdbSStephan Aßmus		{
418011a4cdbSStephan Aßmus			BMessage reply;
419011a4cdbSStephan Aßmus			_GetSettings(&reply);
420011a4cdbSStephan Aßmus			message->SendReply(&reply);
421011a4cdbSStephan Aßmus			break;
422011a4cdbSStephan Aßmus		}
423011a4cdbSStephan Aßmus
42421f2402eSStephan Aßmus		case kMountAllNow:
42521f2402eSStephan Aßmus			_MountVolumes(kAllVolumes, kAllVolumes);
42621f2402eSStephan Aßmus			break;
42721f2402eSStephan Aßmus
42821f2402eSStephan Aßmus		case B_DEVICE_UPDATE:
42921f2402eSStephan Aßmus			int32 event;
43021f2402eSStephan Aßmus			if (message->FindInt32("event", &event) != B_OK
43121f2402eSStephan Aßmus				|| (event != B_DEVICE_MEDIA_CHANGED
43221f2402eSStephan Aßmus					&& event != B_DEVICE_ADDED))
43321f2402eSStephan Aßmus				break;
43421f2402eSStephan Aßmus
43521f2402eSStephan Aßmus			partition_id deviceID;
43621f2402eSStephan Aßmus			if (message->FindInt32("id", &deviceID) != B_OK)
43721f2402eSStephan Aßmus				break;
43821f2402eSStephan Aßmus
43921f2402eSStephan Aßmus			_MountVolumes(kNoVolumes, fRemovableMode, false, deviceID);
44021f2402eSStephan Aßmus			break;
44121f2402eSStephan Aßmus
44221f2402eSStephan Aßmus#if 0
44321f2402eSStephan Aßmus		case B_NODE_MONITOR:
44421f2402eSStephan Aßmus		{
44521f2402eSStephan Aßmus			int32 opcode;
44621f2402eSStephan Aßmus			if (message->FindInt32("opcode", &opcode) != B_OK)
44721f2402eSStephan Aßmus				break;
44821f2402eSStephan Aßmus
44921f2402eSStephan Aßmus			switch (opcode) {
45021f2402eSStephan Aßmus				//	The name of a mount point has changed
45121f2402eSStephan Aßmus				case B_ENTRY_MOVED: {
45221f2402eSStephan Aßmus					WRITELOG(("*** Received Mount Point Renamed Notification"));
45321f2402eSStephan Aßmus
45421f2402eSStephan Aßmus					const char *newName;
45521f2402eSStephan Aßmus					if (message->FindString("name", &newName) != B_OK) {
4563f027ce9SStephan Aßmus						WRITELOG(("ERROR: Couldn't find name field in update "
4573f027ce9SStephan Aßmus							"message"));
45821f2402eSStephan Aßmus						PRINT_OBJECT(*message);
45921f2402eSStephan Aßmus						break ;
46021f2402eSStephan Aßmus					}
46121f2402eSStephan Aßmus
46221f2402eSStephan Aßmus					//
46321f2402eSStephan Aßmus					// When the node monitor reports a move, it gives the
46421f2402eSStephan Aßmus					// parent device and inode that moved.  The problem is
46521f2402eSStephan Aßmus					// that  the inode is the inode of root *in* the filesystem,
46621f2402eSStephan Aßmus					// which is generally always the same number for every
46721f2402eSStephan Aßmus					// filesystem of a type.
46821f2402eSStephan Aßmus					//
46921f2402eSStephan Aßmus					// What we'd really like is the device that the moved
47021f2402eSStephan Aßmus					// volume is mounted on.  Find this by using the
47121f2402eSStephan Aßmus					// *new* name and directory, and then stat()ing that to
47221f2402eSStephan Aßmus					// find the device.
47321f2402eSStephan Aßmus					//
47421f2402eSStephan Aßmus					dev_t parentDevice;
47521f2402eSStephan Aßmus					if (message->FindInt32("device", &parentDevice) != B_OK) {
4763f027ce9SStephan Aßmus						WRITELOG(("ERROR: Couldn't find 'device' field in "
4773f027ce9SStephan Aßmus							"update message"));
47821f2402eSStephan Aßmus						PRINT_OBJECT(*message);
47921f2402eSStephan Aßmus						break;
48021f2402eSStephan Aßmus					}
48121f2402eSStephan Aßmus
48221f2402eSStephan Aßmus					ino_t toDirectory;
4833f027ce9SStephan Aßmus					if (message->FindInt64("to directory", &toDirectory)
4843f027ce9SStephan Aßmus						!= B_OK) {
4853f027ce9SStephan Aßmus						WRITELOG(("ERROR: Couldn't find 'to directory' field "
4863f027ce9SStephan Aßmus							"in update message"));
48721f2402eSStephan Aßmus						PRINT_OBJECT(*message);
48821f2402eSStephan Aßmus						break;
48921f2402eSStephan Aßmus					}
49021f2402eSStephan Aßmus
49121f2402eSStephan Aßmus					entry_ref root_entry(parentDevice, toDirectory, newName);
49221f2402eSStephan Aßmus
49321f2402eSStephan Aßmus					BNode entryNode(&root_entry);
49421f2402eSStephan Aßmus					if (entryNode.InitCheck() != B_OK) {
4953f027ce9SStephan Aßmus						WRITELOG(("ERROR: Couldn't create mount point entry "
4963f027ce9SStephan Aßmus							"node: %s/n", strerror(entryNode.InitCheck())));
49721f2402eSStephan Aßmus						break;
49821f2402eSStephan Aßmus					}
49921f2402eSStephan Aßmus
50021f2402eSStephan Aßmus					node_ref mountPointNode;
50121f2402eSStephan Aßmus					if (entryNode.GetNodeRef(&mountPointNode) != B_OK) {
5023f027ce9SStephan Aßmus						WRITELOG(("ERROR: Couldn't get node ref for new mount "
5033f027ce9SStephan Aßmus							"point"));
50421f2402eSStephan Aßmus						break;
50521f2402eSStephan Aßmus					}
50621f2402eSStephan Aßmus
5073f027ce9SStephan Aßmus					WRITELOG(("Attempt to rename device %li to %s",
5083f027ce9SStephan Aßmus						mountPointNode.device, newName));
50921f2402eSStephan Aßmus
51021f2402eSStephan Aßmus					Partition *partition = FindPartition(mountPointNode.device);
51121f2402eSStephan Aßmus					if (partition != NULL) {
51221f2402eSStephan Aßmus						WRITELOG(("Found device, changing name."));
51321f2402eSStephan Aßmus
51421f2402eSStephan Aßmus						BVolume mountVolume(partition->VolumeDeviceID());
51521f2402eSStephan Aßmus						BDirectory mountDir;
51621f2402eSStephan Aßmus						mountVolume.GetRootDirectory(&mountDir);
51721f2402eSStephan Aßmus						BPath dirPath(&mountDir, 0);
51821f2402eSStephan Aßmus
51921f2402eSStephan Aßmus						partition->SetMountedAt(dirPath.Path());
52021f2402eSStephan Aßmus						partition->SetVolumeName(newName);
52121f2402eSStephan Aßmus						break;
52221f2402eSStephan Aßmus					} else {
5233f027ce9SStephan Aßmus						WRITELOG(("ERROR: Device %li does not appear to be "
5243f027ce9SStephan Aßmus							"present", mountPointNode.device));
52521f2402eSStephan Aßmus					}
52621f2402eSStephan Aßmus				}
52721f2402eSStephan Aßmus			}
52821f2402eSStephan Aßmus			break;
52921f2402eSStephan Aßmus		}
53021f2402eSStephan Aßmus#endif
53121f2402eSStephan Aßmus
53221f2402eSStephan Aßmus		default:
53321f2402eSStephan Aßmus			BLooper::MessageReceived(message);
53421f2402eSStephan Aßmus			break;
53521f2402eSStephan Aßmus	}
53621f2402eSStephan Aßmus}
53721f2402eSStephan Aßmus
53821f2402eSStephan Aßmus
53921f2402eSStephan Aßmusbool
54021f2402eSStephan AßmusAutoMounter::QuitRequested()
54121f2402eSStephan Aßmus{
54221f2402eSStephan Aßmus	if (!BootedInSafeMode()) {
5433f027ce9SStephan Aßmus		// Don't write out settings in safe mode - this would overwrite the
5443f027ce9SStephan Aßmus		// normal, non-safe mode settings.
54521f2402eSStephan Aßmus		_WriteSettings();
54621f2402eSStephan Aßmus	}
54721f2402eSStephan Aßmus
54821f2402eSStephan Aßmus	return true;
549