/* * Copyright 2005, Axel Dörfler, axeld@pinc-software.de * All rights reserved. Distributed under the terms of the MIT License. * * Copyright 2010-2012 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: * Hamish Morrison, hamish@lavabit.com * Alexander von Gluck, kallisti5@unixzen.com */ #include "Settings.h" #include #include #include #include #include #include #include #include #include #include static const char* const kWindowSettingsFile = "virtualmemory_preferences"; static const char* const kVirtualMemorySettings = "virtual_memory"; static const off_t kMegaByte = 1024 * 1024; static const off_t kGigaByte = kMegaByte * 1024; Settings::Settings() { fDefaultSettings.enabled = true; fDefaultSettings.automatic = true; system_info sysInfo; get_system_info(&sysInfo); fDefaultSettings.size = (off_t)sysInfo.max_pages * B_PAGE_SIZE; if (fDefaultSettings.size <= kGigaByte) { // Memory under 1GB? double the swap // This matches the behaviour of the kernel fDefaultSettings.size *= 2; } fDefaultSettings.volume = dev_for_path("/boot"); } void Settings::SetSwapEnabled(bool enabled, bool revertable) { fCurrentSettings.enabled = enabled; if (!revertable) fInitialSettings.enabled = enabled; } void Settings::SetSwapAutomatic(bool automatic, bool revertable) { fCurrentSettings.automatic = automatic; if (!revertable) fInitialSettings.automatic = automatic; } void Settings::SetSwapSize(off_t size, bool revertable) { fCurrentSettings.size = size; if (!revertable) fInitialSettings.size = size; } void Settings::SetSwapVolume(dev_t volume, bool revertable) { fCurrentSettings.volume = volume; if (!revertable) fInitialSettings.volume = volume; } void Settings::SetWindowPosition(BPoint position) { fWindowPosition = position; } status_t Settings::ReadWindowSettings() { BPath path; if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) return B_ERROR; path.Append(kWindowSettingsFile); BFile file; if (file.SetTo(path.Path(), B_READ_ONLY) != B_OK) return B_ERROR; if (file.Read(&fWindowPosition, sizeof(BPoint)) == sizeof(BPoint)) return B_OK; return B_ERROR; } status_t Settings::WriteWindowSettings() { BPath path; if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) < B_OK) return B_ERROR; path.Append(kWindowSettingsFile); BFile file; if (file.SetTo(path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE) != B_OK) return B_ERROR; file.Write(&fWindowPosition, sizeof(BPoint)); return B_OK; } status_t Settings::ReadSwapSettings() { DriverSettingsUnloader settings( load_driver_settings(kVirtualMemorySettings)); if (!settings.IsSet()) return kErrorSettingsNotFound; const char* enabled = get_driver_parameter(settings.Get(), "vm", NULL, NULL); const char* automatic = get_driver_parameter(settings.Get(), "swap_auto", NULL, NULL); const char* size = get_driver_parameter(settings.Get(), "swap_size", NULL, NULL); const char* volume = get_driver_parameter(settings.Get(), "swap_volume_name", NULL, NULL); const char* device = get_driver_parameter(settings.Get(), "swap_volume_device", NULL, NULL); const char* filesystem = get_driver_parameter(settings.Get(), "swap_volume_filesystem", NULL, NULL); const char* capacity = get_driver_parameter(settings.Get(), "swap_volume_capacity", NULL, NULL); if (enabled == NULL || automatic == NULL || size == NULL || device == NULL || volume == NULL || capacity == NULL || filesystem == NULL) return kErrorSettingsInvalid; off_t volCapacity = atoll(capacity); SetSwapEnabled(get_driver_boolean_parameter(settings.Get(), "vm", true, false)); SetSwapAutomatic(get_driver_boolean_parameter(settings.Get(), "swap_auto", true, false)); SetSwapSize(atoll(size)); int32 bestScore = -1; dev_t bestVol = -1; BVolume vol; fs_info volStat; BVolumeRoster roster; while (roster.GetNextVolume(&vol) == B_OK) { if (!vol.IsPersistent() || vol.IsReadOnly() || vol.IsRemovable() || vol.IsShared()) continue; if (fs_stat_dev(vol.Device(), &volStat) == 0) { int32 score = 0; if (strcmp(volume, volStat.volume_name) == 0) score += 4; if (strcmp(device, volStat.device_name) == 0) score += 3; if (volCapacity == volStat.total_blocks * volStat.block_size) score += 2; if (strcmp(filesystem, volStat.fsh_name) == 0) score += 1; if (score >= 4 && score > bestScore) { bestVol = vol.Device(); bestScore = score; } } } SetSwapVolume(bestVol); fInitialSettings = fCurrentSettings; if (bestVol < 0) return kErrorVolumeNotFound; return B_OK; } status_t Settings::WriteSwapSettings() { BPath path; if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) return B_ERROR; path.Append("kernel/drivers"); path.Append(kVirtualMemorySettings); BFile file; if (file.SetTo(path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE) != B_OK) return B_ERROR; fs_info info; if (fs_stat_dev(SwapVolume(), &info) != 0) return B_ERROR; char buffer[1024]; snprintf(buffer, sizeof(buffer), "vm %s\nswap_auto %s\nswap_size %" B_PRIdOFF "\nswap_volume_name %s\nswap_volume_device %s\n" "swap_volume_filesystem %s\nswap_volume_capacity %" B_PRIdOFF "\n", SwapEnabled() ? "on" : "off", SwapAutomatic() ? "yes" : "no", SwapSize(), info.volume_name, info.device_name, info.fsh_name, info.total_blocks * info.block_size); file.Write(buffer, strlen(buffer)); return B_OK; } bool Settings::IsRevertable() { return SwapEnabled() != fInitialSettings.enabled || SwapAutomatic() != fInitialSettings.automatic || SwapSize() != fInitialSettings.size || SwapVolume() != fInitialSettings.volume; } void Settings::RevertSwapSettings() { SetSwapEnabled(fInitialSettings.enabled); SetSwapAutomatic(fInitialSettings.automatic); SetSwapSize(fInitialSettings.size); SetSwapVolume(fInitialSettings.volume); } bool Settings::IsDefaultable() { return SwapEnabled() != fDefaultSettings.enabled || SwapAutomatic() != fDefaultSettings.automatic || SwapSize() != fDefaultSettings.size || SwapVolume() != fDefaultSettings.volume; } void Settings::DefaultSwapSettings(bool revertable) { SetSwapEnabled(fDefaultSettings.enabled); SetSwapAutomatic(fDefaultSettings.automatic); SetSwapSize(fDefaultSettings.size); SetSwapVolume(fDefaultSettings.volume); if (!revertable) fInitialSettings = fDefaultSettings; }