[41999] | 1 | /* $Id: AutostartDb-generic.cpp 98288 2023-01-24 15:32:43Z vboxsync $ */
|
---|
| 2 | /** @file
|
---|
| 3 | * VirtualBox Main - Autostart implementation.
|
---|
| 4 | */
|
---|
| 5 |
|
---|
| 6 | /*
|
---|
[98103] | 7 | * Copyright (C) 2009-2023 Oracle and/or its affiliates.
|
---|
[41999] | 8 | *
|
---|
[96407] | 9 | * This file is part of VirtualBox base platform packages, as
|
---|
| 10 | * available from https://www.virtualbox.org.
|
---|
| 11 | *
|
---|
| 12 | * This program is free software; you can redistribute it and/or
|
---|
| 13 | * modify it under the terms of the GNU General Public License
|
---|
| 14 | * as published by the Free Software Foundation, in version 3 of the
|
---|
| 15 | * License.
|
---|
| 16 | *
|
---|
| 17 | * This program is distributed in the hope that it will be useful, but
|
---|
| 18 | * WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
| 20 | * General Public License for more details.
|
---|
| 21 | *
|
---|
| 22 | * You should have received a copy of the GNU General Public License
|
---|
| 23 | * along with this program; if not, see <https://www.gnu.org/licenses>.
|
---|
| 24 | *
|
---|
| 25 | * SPDX-License-Identifier: GPL-3.0-only
|
---|
[41999] | 26 | */
|
---|
| 27 |
|
---|
| 28 | #include <VBox/err.h>
|
---|
| 29 | #include <VBox/log.h>
|
---|
| 30 | #include <iprt/assert.h>
|
---|
| 31 | #include <iprt/process.h>
|
---|
| 32 | #include <iprt/path.h>
|
---|
| 33 | #include <iprt/mem.h>
|
---|
| 34 | #include <iprt/file.h>
|
---|
| 35 | #include <iprt/string.h>
|
---|
| 36 |
|
---|
| 37 | #include "AutostartDb.h"
|
---|
| 38 |
|
---|
| 39 | #if defined(RT_OS_LINUX)
|
---|
| 40 | /**
|
---|
| 41 | * Modifies the autostart database.
|
---|
| 42 | *
|
---|
| 43 | * @returns VBox status code.
|
---|
| 44 | * @param fAutostart Flag whether the autostart or autostop database is modified.
|
---|
| 45 | * @param fAddVM Flag whether a VM is added or removed from the database.
|
---|
| 46 | */
|
---|
[42181] | 47 | int AutostartDb::autostartModifyDb(bool fAutostart, bool fAddVM)
|
---|
[41999] | 48 | {
|
---|
[98288] | 49 | int vrc = VINF_SUCCESS;
|
---|
[41999] | 50 | char *pszUser = NULL;
|
---|
| 51 |
|
---|
[42181] | 52 | /* Check if the path is set. */
|
---|
| 53 | if (!m_pszAutostartDbPath)
|
---|
| 54 | return VERR_PATH_NOT_FOUND;
|
---|
| 55 |
|
---|
[98288] | 56 | vrc = RTProcQueryUsernameA(RTProcSelf(), &pszUser);
|
---|
| 57 | if (RT_SUCCESS(vrc))
|
---|
[41999] | 58 | {
|
---|
| 59 | char *pszFile;
|
---|
| 60 | uint64_t fOpen = RTFILE_O_DENY_ALL | RTFILE_O_READWRITE;
|
---|
| 61 | RTFILE hAutostartFile;
|
---|
| 62 |
|
---|
[42069] | 63 | AssertPtr(pszUser);
|
---|
| 64 |
|
---|
[41999] | 65 | if (fAddVM)
|
---|
| 66 | fOpen |= RTFILE_O_OPEN_CREATE;
|
---|
[42118] | 67 | else
|
---|
| 68 | fOpen |= RTFILE_O_OPEN;
|
---|
[41999] | 69 |
|
---|
[98288] | 70 | vrc = RTStrAPrintf(&pszFile, "%s/%s.%s", m_pszAutostartDbPath, pszUser, fAutostart ? "start" : "stop");
|
---|
| 71 | if (RT_SUCCESS(vrc))
|
---|
[41999] | 72 | {
|
---|
[98288] | 73 | vrc = RTFileOpen(&hAutostartFile, pszFile, fOpen);
|
---|
| 74 | if (RT_SUCCESS(vrc))
|
---|
[41999] | 75 | {
|
---|
| 76 | uint64_t cbFile;
|
---|
| 77 |
|
---|
| 78 | /*
|
---|
| 79 | * Files with more than 16 bytes are rejected because they just contain
|
---|
| 80 | * a number of the amount of VMs with autostart configured, so they
|
---|
| 81 | * should be really really small. Anything else is bogus.
|
---|
| 82 | */
|
---|
[98288] | 83 | vrc = RTFileQuerySize(hAutostartFile, &cbFile);
|
---|
| 84 | if ( RT_SUCCESS(vrc)
|
---|
[41999] | 85 | && cbFile <= 16)
|
---|
| 86 | {
|
---|
| 87 | char abBuf[16 + 1]; /* trailing \0 */
|
---|
| 88 | uint32_t cAutostartVms = 0;
|
---|
| 89 |
|
---|
[47117] | 90 | RT_ZERO(abBuf);
|
---|
[41999] | 91 |
|
---|
| 92 | /* Check if the file was just created. */
|
---|
| 93 | if (cbFile)
|
---|
| 94 | {
|
---|
[98288] | 95 | vrc = RTFileRead(hAutostartFile, abBuf, (size_t)cbFile, NULL);
|
---|
| 96 | if (RT_SUCCESS(vrc))
|
---|
[41999] | 97 | {
|
---|
[98288] | 98 | vrc = RTStrToUInt32Ex(abBuf, NULL, 10 /* uBase */, &cAutostartVms);
|
---|
| 99 | if ( vrc == VWRN_TRAILING_CHARS
|
---|
| 100 | || vrc == VWRN_TRAILING_SPACES)
|
---|
| 101 | vrc = VINF_SUCCESS;
|
---|
[41999] | 102 | }
|
---|
| 103 | }
|
---|
| 104 |
|
---|
[98288] | 105 | if (RT_SUCCESS(vrc))
|
---|
[41999] | 106 | {
|
---|
| 107 | size_t cbBuf;
|
---|
| 108 |
|
---|
| 109 | /* Modify VM counter and write back. */
|
---|
| 110 | if (fAddVM)
|
---|
| 111 | cAutostartVms++;
|
---|
| 112 | else
|
---|
| 113 | cAutostartVms--;
|
---|
| 114 |
|
---|
| 115 | if (cAutostartVms > 0)
|
---|
| 116 | {
|
---|
| 117 | cbBuf = RTStrPrintf(abBuf, sizeof(abBuf), "%u", cAutostartVms);
|
---|
[98288] | 118 | vrc = RTFileSetSize(hAutostartFile, cbBuf);
|
---|
| 119 | if (RT_SUCCESS(vrc))
|
---|
| 120 | vrc = RTFileWriteAt(hAutostartFile, 0, abBuf, cbBuf, NULL);
|
---|
[41999] | 121 | }
|
---|
| 122 | else
|
---|
| 123 | {
|
---|
| 124 | /* Just delete the file if there are no VMs left. */
|
---|
| 125 | RTFileClose(hAutostartFile);
|
---|
| 126 | RTFileDelete(pszFile);
|
---|
| 127 | hAutostartFile = NIL_RTFILE;
|
---|
| 128 | }
|
---|
| 129 | }
|
---|
| 130 | }
|
---|
[98288] | 131 | else if (RT_SUCCESS(vrc))
|
---|
| 132 | vrc = VERR_FILE_TOO_BIG;
|
---|
[41999] | 133 |
|
---|
| 134 | if (hAutostartFile != NIL_RTFILE)
|
---|
| 135 | RTFileClose(hAutostartFile);
|
---|
| 136 | }
|
---|
| 137 | RTStrFree(pszFile);
|
---|
| 138 | }
|
---|
[42069] | 139 |
|
---|
| 140 | RTStrFree(pszUser);
|
---|
[41999] | 141 | }
|
---|
| 142 |
|
---|
[98288] | 143 | return vrc;
|
---|
[41999] | 144 | }
|
---|
| 145 |
|
---|
| 146 | #endif
|
---|
| 147 |
|
---|
| 148 | AutostartDb::AutostartDb()
|
---|
| 149 | {
|
---|
| 150 | #ifdef RT_OS_LINUX
|
---|
[98288] | 151 | int vrc = RTCritSectInit(&this->CritSect);
|
---|
| 152 | NOREF(vrc);
|
---|
[42181] | 153 | m_pszAutostartDbPath = NULL;
|
---|
[41999] | 154 | #endif
|
---|
| 155 | }
|
---|
| 156 |
|
---|
| 157 | AutostartDb::~AutostartDb()
|
---|
| 158 | {
|
---|
| 159 | #ifdef RT_OS_LINUX
|
---|
| 160 | RTCritSectDelete(&this->CritSect);
|
---|
[42181] | 161 | if (m_pszAutostartDbPath)
|
---|
| 162 | RTStrFree(m_pszAutostartDbPath);
|
---|
[41999] | 163 | #endif
|
---|
| 164 | }
|
---|
| 165 |
|
---|
[42181] | 166 | int AutostartDb::setAutostartDbPath(const char *pszAutostartDbPathNew)
|
---|
| 167 | {
|
---|
| 168 | #if defined(RT_OS_LINUX)
|
---|
| 169 | char *pszAutostartDbPathTmp = NULL;
|
---|
| 170 |
|
---|
| 171 | if (pszAutostartDbPathNew)
|
---|
| 172 | {
|
---|
| 173 | pszAutostartDbPathTmp = RTStrDup(pszAutostartDbPathNew);
|
---|
| 174 | if (!pszAutostartDbPathTmp)
|
---|
| 175 | return VERR_NO_MEMORY;
|
---|
| 176 | }
|
---|
| 177 |
|
---|
| 178 | RTCritSectEnter(&this->CritSect);
|
---|
| 179 | if (m_pszAutostartDbPath)
|
---|
| 180 | RTStrFree(m_pszAutostartDbPath);
|
---|
| 181 |
|
---|
| 182 | m_pszAutostartDbPath = pszAutostartDbPathTmp;
|
---|
| 183 | RTCritSectLeave(&this->CritSect);
|
---|
| 184 | return VINF_SUCCESS;
|
---|
| 185 | #else
|
---|
| 186 | NOREF(pszAutostartDbPathNew);
|
---|
[42182] | 187 | return VERR_NOT_SUPPORTED;
|
---|
[42181] | 188 | #endif
|
---|
| 189 | }
|
---|
| 190 |
|
---|
[41999] | 191 | int AutostartDb::addAutostartVM(const char *pszVMId)
|
---|
| 192 | {
|
---|
[98288] | 193 | int vrc = VERR_NOT_SUPPORTED;
|
---|
[41999] | 194 |
|
---|
| 195 | #if defined(RT_OS_LINUX)
|
---|
| 196 | NOREF(pszVMId); /* Not needed */
|
---|
| 197 |
|
---|
| 198 | RTCritSectEnter(&this->CritSect);
|
---|
[98288] | 199 | vrc = autostartModifyDb(true /* fAutostart */, true /* fAddVM */);
|
---|
[41999] | 200 | RTCritSectLeave(&this->CritSect);
|
---|
[80569] | 201 | #elif defined(RT_OS_DARWIN) || defined(RT_OS_SOLARIS) || defined(RT_OS_WINDOWS)
|
---|
[41999] | 202 | NOREF(pszVMId); /* Not needed */
|
---|
[98288] | 203 | vrc = VINF_SUCCESS;
|
---|
[41999] | 204 | #else
|
---|
| 205 | NOREF(pszVMId);
|
---|
[98288] | 206 | vrc = VERR_NOT_SUPPORTED;
|
---|
[41999] | 207 | #endif
|
---|
| 208 |
|
---|
[98288] | 209 | return vrc;
|
---|
[41999] | 210 | }
|
---|
| 211 |
|
---|
| 212 | int AutostartDb::removeAutostartVM(const char *pszVMId)
|
---|
| 213 | {
|
---|
[98288] | 214 | int vrc = VINF_SUCCESS;
|
---|
[41999] | 215 |
|
---|
| 216 | #if defined(RT_OS_LINUX)
|
---|
| 217 | NOREF(pszVMId); /* Not needed */
|
---|
| 218 | RTCritSectEnter(&this->CritSect);
|
---|
[98288] | 219 | vrc = autostartModifyDb(true /* fAutostart */, false /* fAddVM */);
|
---|
[41999] | 220 | RTCritSectLeave(&this->CritSect);
|
---|
[80569] | 221 | #elif defined(RT_OS_DARWIN) || defined(RT_OS_SOLARIS) || defined(RT_OS_WINDOWS)
|
---|
[41999] | 222 | NOREF(pszVMId); /* Not needed */
|
---|
[98288] | 223 | vrc = VINF_SUCCESS;
|
---|
[41999] | 224 | #else
|
---|
| 225 | NOREF(pszVMId);
|
---|
[98288] | 226 | vrc = VERR_NOT_SUPPORTED;
|
---|
[41999] | 227 | #endif
|
---|
| 228 |
|
---|
[98288] | 229 | return vrc;
|
---|
[41999] | 230 | }
|
---|
| 231 |
|
---|
| 232 | int AutostartDb::addAutostopVM(const char *pszVMId)
|
---|
| 233 | {
|
---|
[98288] | 234 | int vrc = VINF_SUCCESS;
|
---|
[41999] | 235 |
|
---|
| 236 | #if defined(RT_OS_LINUX)
|
---|
| 237 | NOREF(pszVMId); /* Not needed */
|
---|
| 238 | RTCritSectEnter(&this->CritSect);
|
---|
[98288] | 239 | vrc = autostartModifyDb(false /* fAutostart */, true /* fAddVM */);
|
---|
[41999] | 240 | RTCritSectLeave(&this->CritSect);
|
---|
[80569] | 241 | #elif defined(RT_OS_DARWIN) || defined(RT_OS_WINDOWS)
|
---|
[41999] | 242 | NOREF(pszVMId); /* Not needed */
|
---|
[98288] | 243 | vrc = VINF_SUCCESS;
|
---|
[41999] | 244 | #else
|
---|
| 245 | NOREF(pszVMId);
|
---|
[98288] | 246 | vrc = VERR_NOT_SUPPORTED;
|
---|
[41999] | 247 | #endif
|
---|
| 248 |
|
---|
[98288] | 249 | return vrc;
|
---|
[41999] | 250 | }
|
---|
| 251 |
|
---|
| 252 | int AutostartDb::removeAutostopVM(const char *pszVMId)
|
---|
| 253 | {
|
---|
[98288] | 254 | int vrc = VINF_SUCCESS;
|
---|
[41999] | 255 |
|
---|
| 256 | #if defined(RT_OS_LINUX)
|
---|
| 257 | NOREF(pszVMId); /* Not needed */
|
---|
| 258 | RTCritSectEnter(&this->CritSect);
|
---|
[98288] | 259 | vrc = autostartModifyDb(false /* fAutostart */, false /* fAddVM */);
|
---|
[41999] | 260 | RTCritSectLeave(&this->CritSect);
|
---|
[80569] | 261 | #elif defined(RT_OS_DARWIN) || defined (RT_OS_WINDOWS)
|
---|
[41999] | 262 | NOREF(pszVMId); /* Not needed */
|
---|
[98288] | 263 | vrc = VINF_SUCCESS;
|
---|
[41999] | 264 | #else
|
---|
| 265 | NOREF(pszVMId);
|
---|
[98288] | 266 | vrc = VERR_NOT_SUPPORTED;
|
---|
[41999] | 267 | #endif
|
---|
| 268 |
|
---|
[98288] | 269 | return vrc;
|
---|
[41999] | 270 | }
|
---|
| 271 |
|
---|