⛏️ index : haiku.git

// Settings.cpp
//
// Copyright (c) 2003, Ingo Weinhold (bonefish@cs.tu-berlin.de)
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// You can alternatively use *this file* under the terms of the the MIT
// license included in this package.

#include <new>

#include "Settings.h"
#include "Debug.h"

using std::nothrow;

/*!
	\class Settings
	\brief Manages the ReiserFS settings.
*/

static const char *kFSName = "reiserfs";

// defaults
static const char *kDefaultDefaultVolumeName = "ReiserFS untitled";
static const bool kDefaultHideEsoteric	= true;

// constructor
Settings::Settings()
	:
	fDefaultVolumeName(),
	fVolumeName(),
	fHideEsoteric(kDefaultHideEsoteric),
	fHiddenEntries(5)
{
}

// destructor
Settings::~Settings()
{
	Unset();
}

// SetTo
status_t
Settings::SetTo(const char *volumeName)
{
	// unset
	Unset();
	// load the driver settings and find the entry for the volume
	void *settings = load_driver_settings(kFSName);
	const driver_parameter *volume = NULL;
	const driver_settings *ds = get_driver_settings(settings);
	if (ds && volumeName)
		volume = _FindVolumeParameter(ds, volumeName);
	// init the object and unload the settings
	_Init(ds, volume);
	unload_driver_settings(settings);
	return B_OK;
}

// SetTo
status_t
Settings::SetTo(off_t volumeOffset, off_t volumeSize)
{
	PRINT(("Settings::SetTo(%" B_PRIdOFF ", %" B_PRIdOFF ")\n", volumeOffset,
		volumeSize));
	// unset
	Unset();
	// load the driver settings and find the entry for the volume
	void *settings = load_driver_settings(kFSName);
	const driver_parameter *volume = NULL;
	const driver_settings *ds = get_driver_settings(settings);
	if (ds)
		volume = _FindVolumeParameter(ds, volumeOffset, volumeSize);
	// init the object and unload the settings
	_Init(ds, volume);
	unload_driver_settings(settings);
	PRINT(("Settings::SetTo(%" B_PRIdOFF ", %" B_PRIdOFF ") done: B_OK\n",
		volumeOffset, volumeSize));
	return B_OK;
}

// Unset
void
Settings::Unset()
{
	fDefaultVolumeName.Unset();
	fVolumeName.Unset();
	fHideEsoteric = kDefaultHideEsoteric;
	fHiddenEntries.MakeEmpty();
}

// GetDefaultVolumeName
const char *
Settings::GetDefaultVolumeName() const
{
	if (fDefaultVolumeName.GetLength() > 0)
		return fDefaultVolumeName.GetString();
	return kDefaultDefaultVolumeName;
}

// GetVolumeName
const char *
Settings::GetVolumeName() const
{
	if (fVolumeName.GetLength() > 0)
		return fVolumeName.GetString();
	return GetDefaultVolumeName();
}

// GetHideEsoteric
bool
Settings::GetHideEsoteric() const
{
	return fHideEsoteric;
}

// HiddenEntryAt
const char *
Settings::HiddenEntryAt(int32 index) const
{
	const char *entry = NULL;
	if (index >= 0 && index < fHiddenEntries.CountItems())
		entry = fHiddenEntries.ItemAt(index).GetString();
	return entry;
}

// Dump
void
Settings::Dump()
{
#if DEBUG
	PRINT(("Settings:\n"));
	PRINT(("  default volume name:   `%s'\n", GetDefaultVolumeName()));
	PRINT(("  volume name:           `%s'\n", GetVolumeName()));
	PRINT(("  hide esoteric entries: %d\n", GetHideEsoteric()));
	PRINT(("  %" B_PRId32 " hidden entries:\n", fHiddenEntries.CountItems()));
	for (int32 i = 0; const char *entry = HiddenEntryAt(i); i++)
		PRINT(("    `%s'\n", entry));
#endif
}

// _Init
status_t
Settings::_Init(const driver_settings *settings,
				const driver_parameter *volume)
{
PRINT(("Settings::_Init(%p, %p)\n", settings, volume));
	status_t error = B_OK;
	// get the global values
	fDefaultVolumeName.SetTo(_GetParameterValue(settings,
		"default_volume_name", (const char*)NULL, NULL));
PRINT(("  default_volume_name is: `%s'\n", fDefaultVolumeName.GetString()));
	fHideEsoteric = _GetParameterValue(settings, "hide_esoteric_entries",
										kDefaultHideEsoteric,
										kDefaultHideEsoteric);
PRINT(("  hide_esoteric_entries is: %d\n", fHideEsoteric));
	// get the per volume settings
	if (volume) {
PRINT(("  getting volume parameters:\n"));
		fVolumeName.SetTo(_GetParameterValue(volume, "name", (const char*)NULL,
												NULL));
PRINT(("    name is: `%s'\n", fVolumeName.GetString()));
		fHideEsoteric = _GetParameterValue(volume, "hide_esoteric_entries",
											fHideEsoteric, fHideEsoteric);
PRINT(("    hide_esoteric_entries is: %d\n", fHideEsoteric));
		int32 cookie = 0;
		while (const driver_parameter *parameter
				= _FindNextParameter(volume, "hide_entries", cookie)) {
			for (int32 i = 0; i < parameter->value_count; i++)
{
				fHiddenEntries.AddItem(parameter->values[i]);
PRINT(("    hidden entry: `%s'\n", parameter->values[i]));
}
		}
	}
	// check the values
PRINT(("  checking volume names...'\n"));
	_CheckVolumeName(fDefaultVolumeName);
	_CheckVolumeName(fVolumeName);
PRINT(("  checking hidden entry names...'\n"));
	for (int32 i = fHiddenEntries.CountItems(); i >= 0; i--) {
		String &entry = fHiddenEntries.ItemAt(i);
		if (!_CheckEntryName(entry.GetString()))
{
PRINT(("    ignoring: `%s'\n", entry.GetString()));
			fHiddenEntries.RemoveItem(i);
}
	}
PRINT(("Settings::_Init() done: %s\n", strerror(error)));
	return error;
}

// _FindVolumeParameter
const driver_parameter *
Settings::_FindVolumeParameter(const driver_settings *settings,
								const char *name)
{
	if (settings) {
		int32 cookie = 0;
		while (const driver_parameter *parameter
				= _FindNextParameter(settings, "volume", cookie)) {
			if (parameter->value_count == 1
				&& !strcmp(parameter->values[0], name)) {
				return parameter;
			}
		}
	}
	return NULL;
}

// _FindVolumeParameter
const driver_parameter *
Settings::_FindVolumeParameter(const driver_settings *settings,
								off_t offset, off_t size)
{
	PRINT(("Settings::_FindVolumeParameter(%" B_PRIdOFF ", %" B_PRIdOFF ")\n",
		offset, size));
	if (settings) {
		int32 cookie = 0;
		while (const driver_parameter *parameter
				= _FindNextParameter(settings, "volume", cookie)) {
			if (_GetParameterValue(parameter, "offset", offset + 1, offset + 1)
					== offset
				&& _GetParameterValue(parameter, "size", size + 1, size + 1)
					== size) {
				PRINT(("Settings::_FindVolumeParameter() done: found parameter:"
					" index: %" B_PRId32 ", (%p)\n", cookie - 1, parameter));
				return parameter;
			}
		}
	}
	PRINT(("Settings::_FindVolumeParameter() done: failed\n"));
	return NULL;
}

// _CheckVolumeName
void
Settings::_CheckVolumeName(String &name)
{
	// truncate, if it is too long
	if (name.GetLength() >= B_FILE_NAME_LENGTH) {
		char buffer[B_FILE_NAME_LENGTH];
		memcpy(buffer, name.GetString(), B_FILE_NAME_LENGTH - 1);
		name.SetTo(buffer, B_FILE_NAME_LENGTH - 1);
	}
	// check for bad characters
	bool invalid = false;
	const char *string = name.GetString();
	for (int32 i = 0; !invalid && i < name.GetLength(); i++) {
		if (string[i] == '/')	// others?
			invalid = true;
	}
	if (invalid)
		name.Unset();
}

// _CheckEntryName
bool
Settings::_CheckEntryName(const char *name)
{
	int32 len = (name ? strlen(name) : 0);
	// any further restictions?
	return (len > 0);
}