1 /* 2 * Copyright 2010-2011, Hamish Morrison, hamish@lavabit.com 3 * Copyright 2005, Axel Dörfler, axeld@pinc-software.de 4 * All rights reserved. Distributed under the terms of the MIT License. 5 */ 6 7 8 #include "Settings.h" 9 10 #include <File.h> 11 #include <Entry.h> 12 #include <FindDirectory.h> 13 #include <Path.h> 14 #include <Volume.h> 15 #include <VolumeRoster.h> 16 #include <driver_settings.h> 17 18 #include <stdio.h> 19 #include <stdlib.h> 20 #include <string.h> 21 22 23 static const char* kWindowSettingsFile = "VM_data"; 24 static const char* kVirtualMemorySettings = "virtual_memory"; 25 static const int64 kMegaByte = 1024 * 1024; 26 27 28 Settings::Settings() 29 : 30 fPositionUpdated(false) 31 { 32 _ReadWindowSettings(); 33 _ReadSwapSettings(); 34 } 35 36 37 Settings::~Settings() 38 { 39 _WriteWindowSettings(); 40 _WriteSwapSettings(); 41 } 42 43 44 void 45 Settings::SetWindowPosition(BPoint position) 46 { 47 if (position == fWindowPosition) 48 return; 49 50 fWindowPosition = position; 51 fPositionUpdated = true; 52 } 53 54 55 void 56 Settings::SetSwapEnabled(bool enabled) 57 { 58 fSwapEnabled = enabled; 59 } 60 61 62 void 63 Settings::SetSwapSize(off_t size) 64 { 65 fSwapSize = size; 66 } 67 68 69 void 70 Settings::SetSwapVolume(BVolume &volume) 71 { 72 if (volume.Device() == SwapVolume().Device() 73 || volume.InitCheck() != B_OK) 74 return; 75 76 fSwapVolume.SetTo(volume.Device()); 77 } 78 79 80 void 81 Settings::RevertSwapChanges() 82 { 83 fSwapEnabled = fInitialSwapEnabled; 84 fSwapSize = fInitialSwapSize; 85 fSwapVolume.SetTo(fInitialSwapVolume); 86 } 87 88 89 bool 90 Settings::IsRevertible() 91 { 92 return fSwapEnabled != fInitialSwapEnabled 93 || fSwapSize != fInitialSwapSize 94 || fSwapVolume.Device() != fInitialSwapVolume; 95 } 96 97 98 void 99 Settings::_ReadWindowSettings() 100 { 101 bool success = false; 102 103 BPath path; 104 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) { 105 path.Append(kWindowSettingsFile); 106 BFile file; 107 if (file.SetTo(path.Path(), B_READ_ONLY) == B_OK) 108 if (file.Read(&fWindowPosition, sizeof(BPoint)) == sizeof(BPoint)) 109 success = true; 110 } 111 112 if (!success) 113 fWindowPosition.Set(-1, -1); 114 } 115 116 117 void 118 Settings::_WriteWindowSettings() 119 { 120 if (!fPositionUpdated) 121 return; 122 123 BPath path; 124 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) < B_OK) 125 return; 126 127 path.Append(kWindowSettingsFile); 128 129 BFile file; 130 if (file.SetTo(path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE) == B_OK) 131 file.Write(&fWindowPosition, sizeof(BPoint)); 132 } 133 134 135 void 136 Settings::_ReadSwapSettings() 137 { 138 void* settings = load_driver_settings(kVirtualMemorySettings); 139 if (settings != NULL) { 140 SetSwapEnabled(get_driver_boolean_parameter(settings, "vm", false, false)); 141 const char* swapSize = get_driver_parameter(settings, "swap_size", NULL, NULL); 142 SetSwapSize(swapSize ? atoll(swapSize) : 0); 143 144 #ifdef SWAP_VOLUME_IMPLEMENTED 145 // we need to hang onto this one 146 fBadVolName = strdup(get_driver_parameter(settings, "swap_volume", NULL, NULL)); 147 148 BVolumeRoster volumeRoster; 149 BVolume temporaryVolume; 150 151 if (fBadVolName != NULL) { 152 status_t result = volumeRoster.GetNextVolume(&temporaryVolume); 153 char volumeName[B_FILE_NAME_LENGTH]; 154 while (result != B_BAD_VALUE) { 155 temporaryVolume.GetName(volumeName); 156 if (strcmp(volumeName, fBadVolName) == 0 157 && temporaryVolume.IsPersistent() && volumeName[0]) { 158 SetSwapVolume(temporaryVolume); 159 break; 160 } 161 result = volumeRoster.GetNextVolume(&temporaryVolume); 162 } 163 } else 164 volumeRoster.GetBootVolume(&fSwapVolume); 165 #endif 166 unload_driver_settings(settings); 167 } else 168 _SetSwapNull(); 169 170 #ifndef SWAP_VOLUME_IMPLEMENTED 171 BVolumeRoster volumeRoster; 172 volumeRoster.GetBootVolume(&fSwapVolume); 173 #endif 174 175 fInitialSwapEnabled = fSwapEnabled; 176 fInitialSwapSize = fSwapSize; 177 fInitialSwapVolume = fSwapVolume.Device(); 178 } 179 180 181 void 182 Settings::_WriteSwapSettings() 183 { 184 if (!IsRevertible()) 185 return; 186 187 BPath path; 188 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) 189 return; 190 191 path.Append("kernel/drivers"); 192 path.Append(kVirtualMemorySettings); 193 194 BFile file; 195 if (file.SetTo(path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE) 196 != B_OK) 197 return; 198 199 char buffer[256]; 200 #ifdef SWAP_VOLUME_IMPLEMENTED 201 char volumeName[B_FILE_NAME_LENGTH] = {0}; 202 if (SwapVolume().InitCheck() != B_NO_INIT) 203 SwapVolume().GetName(volumeName); 204 else if (fBadVolName) 205 strcpy(volumeName, fBadVolName); 206 snprintf(buffer, sizeof(buffer), "vm %s\nswap_size %Ld\nswap_volume %s\n", 207 SwapEnabled() ? "on" : "off", SwapSize(), 208 volumeName[0] ? volumeName : NULL); 209 #else 210 snprintf(buffer, sizeof(buffer), "vm %s\nswap_size %Ld\n", 211 fSwapEnabled ? "on" : "off", fSwapSize); 212 #endif 213 214 file.Write(buffer, strlen(buffer)); 215 } 216 217 218 void 219 Settings::_SetSwapNull() 220 { 221 SetSwapEnabled(false); 222 BVolumeRoster volumeRoster; 223 BVolume temporaryVolume; 224 volumeRoster.GetBootVolume(&temporaryVolume); 225 SetSwapVolume(temporaryVolume); 226 SetSwapSize(0); 227 } 228 229 230