[41999] | 1 | /* $Id: AutostartDb-generic.cpp 98103 2023-01-17 14:15:46Z 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 | {
|
---|
| 49 | int rc = VINF_SUCCESS;
|
---|
| 50 | char *pszUser = NULL;
|
---|
| 51 |
|
---|
[42181] | 52 | /* Check if the path is set. */
|
---|
| 53 | if (!m_pszAutostartDbPath)
|
---|
| 54 | return VERR_PATH_NOT_FOUND;
|
---|
| 55 |
|
---|
[42069] | 56 | rc = RTProcQueryUsernameA(RTProcSelf(), &pszUser);
|
---|
| 57 | if (RT_SUCCESS(rc))
|
---|
[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 |
|
---|
| 70 | rc = RTStrAPrintf(&pszFile, "%s/%s.%s",
|
---|
[42181] | 71 | m_pszAutostartDbPath, pszUser, fAutostart ? "start" : "stop");
|
---|
[41999] | 72 | if (RT_SUCCESS(rc))
|
---|
| 73 | {
|
---|
| 74 | rc = RTFileOpen(&hAutostartFile, pszFile, fOpen);
|
---|
| 75 | if (RT_SUCCESS(rc))
|
---|
| 76 | {
|
---|
| 77 | uint64_t cbFile;
|
---|
| 78 |
|
---|
| 79 | /*
|
---|
| 80 | * Files with more than 16 bytes are rejected because they just contain
|
---|
| 81 | * a number of the amount of VMs with autostart configured, so they
|
---|
| 82 | * should be really really small. Anything else is bogus.
|
---|
| 83 | */
|
---|
[80585] | 84 | rc = RTFileQuerySize(hAutostartFile, &cbFile);
|
---|
[41999] | 85 | if ( RT_SUCCESS(rc)
|
---|
| 86 | && cbFile <= 16)
|
---|
| 87 | {
|
---|
| 88 | char abBuf[16 + 1]; /* trailing \0 */
|
---|
| 89 | uint32_t cAutostartVms = 0;
|
---|
| 90 |
|
---|
[47117] | 91 | RT_ZERO(abBuf);
|
---|
[41999] | 92 |
|
---|
| 93 | /* Check if the file was just created. */
|
---|
| 94 | if (cbFile)
|
---|
| 95 | {
|
---|
[63397] | 96 | rc = RTFileRead(hAutostartFile, abBuf, (size_t)cbFile, NULL);
|
---|
[41999] | 97 | if (RT_SUCCESS(rc))
|
---|
| 98 | {
|
---|
| 99 | rc = RTStrToUInt32Ex(abBuf, NULL, 10 /* uBase */, &cAutostartVms);
|
---|
| 100 | if ( rc == VWRN_TRAILING_CHARS
|
---|
| 101 | || rc == VWRN_TRAILING_SPACES)
|
---|
| 102 | rc = VINF_SUCCESS;
|
---|
| 103 | }
|
---|
| 104 | }
|
---|
| 105 |
|
---|
| 106 | if (RT_SUCCESS(rc))
|
---|
| 107 | {
|
---|
| 108 | size_t cbBuf;
|
---|
| 109 |
|
---|
| 110 | /* Modify VM counter and write back. */
|
---|
| 111 | if (fAddVM)
|
---|
| 112 | cAutostartVms++;
|
---|
| 113 | else
|
---|
| 114 | cAutostartVms--;
|
---|
| 115 |
|
---|
| 116 | if (cAutostartVms > 0)
|
---|
| 117 | {
|
---|
| 118 | cbBuf = RTStrPrintf(abBuf, sizeof(abBuf), "%u", cAutostartVms);
|
---|
| 119 | rc = RTFileSetSize(hAutostartFile, cbBuf);
|
---|
| 120 | if (RT_SUCCESS(rc))
|
---|
| 121 | rc = RTFileWriteAt(hAutostartFile, 0, abBuf, cbBuf, NULL);
|
---|
| 122 | }
|
---|
| 123 | else
|
---|
| 124 | {
|
---|
| 125 | /* Just delete the file if there are no VMs left. */
|
---|
| 126 | RTFileClose(hAutostartFile);
|
---|
| 127 | RTFileDelete(pszFile);
|
---|
| 128 | hAutostartFile = NIL_RTFILE;
|
---|
| 129 | }
|
---|
| 130 | }
|
---|
| 131 | }
|
---|
| 132 | else if (RT_SUCCESS(rc))
|
---|
| 133 | rc = VERR_FILE_TOO_BIG;
|
---|
| 134 |
|
---|
| 135 | if (hAutostartFile != NIL_RTFILE)
|
---|
| 136 | RTFileClose(hAutostartFile);
|
---|
| 137 | }
|
---|
| 138 | RTStrFree(pszFile);
|
---|
| 139 | }
|
---|
[42069] | 140 |
|
---|
| 141 | RTStrFree(pszUser);
|
---|
[41999] | 142 | }
|
---|
| 143 |
|
---|
| 144 | return rc;
|
---|
| 145 | }
|
---|
| 146 |
|
---|
| 147 | #endif
|
---|
| 148 |
|
---|
| 149 | AutostartDb::AutostartDb()
|
---|
| 150 | {
|
---|
| 151 | #ifdef RT_OS_LINUX
|
---|
| 152 | int rc = RTCritSectInit(&this->CritSect);
|
---|
| 153 | NOREF(rc);
|
---|
[42181] | 154 | m_pszAutostartDbPath = NULL;
|
---|
[41999] | 155 | #endif
|
---|
| 156 | }
|
---|
| 157 |
|
---|
| 158 | AutostartDb::~AutostartDb()
|
---|
| 159 | {
|
---|
| 160 | #ifdef RT_OS_LINUX
|
---|
| 161 | RTCritSectDelete(&this->CritSect);
|
---|
[42181] | 162 | if (m_pszAutostartDbPath)
|
---|
| 163 | RTStrFree(m_pszAutostartDbPath);
|
---|
[41999] | 164 | #endif
|
---|
| 165 | }
|
---|
| 166 |
|
---|
[42181] | 167 | int AutostartDb::setAutostartDbPath(const char *pszAutostartDbPathNew)
|
---|
| 168 | {
|
---|
| 169 | #if defined(RT_OS_LINUX)
|
---|
| 170 | char *pszAutostartDbPathTmp = NULL;
|
---|
| 171 |
|
---|
| 172 | if (pszAutostartDbPathNew)
|
---|
| 173 | {
|
---|
| 174 | pszAutostartDbPathTmp = RTStrDup(pszAutostartDbPathNew);
|
---|
| 175 | if (!pszAutostartDbPathTmp)
|
---|
| 176 | return VERR_NO_MEMORY;
|
---|
| 177 | }
|
---|
| 178 |
|
---|
| 179 | RTCritSectEnter(&this->CritSect);
|
---|
| 180 | if (m_pszAutostartDbPath)
|
---|
| 181 | RTStrFree(m_pszAutostartDbPath);
|
---|
| 182 |
|
---|
| 183 | m_pszAutostartDbPath = pszAutostartDbPathTmp;
|
---|
| 184 | RTCritSectLeave(&this->CritSect);
|
---|
| 185 | return VINF_SUCCESS;
|
---|
| 186 | #else
|
---|
| 187 | NOREF(pszAutostartDbPathNew);
|
---|
[42182] | 188 | return VERR_NOT_SUPPORTED;
|
---|
[42181] | 189 | #endif
|
---|
| 190 | }
|
---|
| 191 |
|
---|
[41999] | 192 | int AutostartDb::addAutostartVM(const char *pszVMId)
|
---|
| 193 | {
|
---|
| 194 | int rc = VERR_NOT_SUPPORTED;
|
---|
| 195 |
|
---|
| 196 | #if defined(RT_OS_LINUX)
|
---|
| 197 | NOREF(pszVMId); /* Not needed */
|
---|
| 198 |
|
---|
| 199 | RTCritSectEnter(&this->CritSect);
|
---|
| 200 | rc = autostartModifyDb(true /* fAutostart */, true /* fAddVM */);
|
---|
| 201 | RTCritSectLeave(&this->CritSect);
|
---|
[80569] | 202 | #elif defined(RT_OS_DARWIN) || defined(RT_OS_SOLARIS) || defined(RT_OS_WINDOWS)
|
---|
[41999] | 203 | NOREF(pszVMId); /* Not needed */
|
---|
| 204 | rc = VINF_SUCCESS;
|
---|
| 205 | #else
|
---|
| 206 | NOREF(pszVMId);
|
---|
| 207 | rc = VERR_NOT_SUPPORTED;
|
---|
| 208 | #endif
|
---|
| 209 |
|
---|
| 210 | return rc;
|
---|
| 211 | }
|
---|
| 212 |
|
---|
| 213 | int AutostartDb::removeAutostartVM(const char *pszVMId)
|
---|
| 214 | {
|
---|
| 215 | int rc = VINF_SUCCESS;
|
---|
| 216 |
|
---|
| 217 | #if defined(RT_OS_LINUX)
|
---|
| 218 | NOREF(pszVMId); /* Not needed */
|
---|
| 219 | RTCritSectEnter(&this->CritSect);
|
---|
| 220 | rc = autostartModifyDb(true /* fAutostart */, false /* fAddVM */);
|
---|
| 221 | RTCritSectLeave(&this->CritSect);
|
---|
[80569] | 222 | #elif defined(RT_OS_DARWIN) || defined(RT_OS_SOLARIS) || defined(RT_OS_WINDOWS)
|
---|
[41999] | 223 | NOREF(pszVMId); /* Not needed */
|
---|
| 224 | rc = VINF_SUCCESS;
|
---|
| 225 | #else
|
---|
| 226 | NOREF(pszVMId);
|
---|
| 227 | rc = VERR_NOT_SUPPORTED;
|
---|
| 228 | #endif
|
---|
| 229 |
|
---|
| 230 | return rc;
|
---|
| 231 | }
|
---|
| 232 |
|
---|
| 233 | int AutostartDb::addAutostopVM(const char *pszVMId)
|
---|
| 234 | {
|
---|
| 235 | int rc = VINF_SUCCESS;
|
---|
| 236 |
|
---|
| 237 | #if defined(RT_OS_LINUX)
|
---|
| 238 | NOREF(pszVMId); /* Not needed */
|
---|
| 239 | RTCritSectEnter(&this->CritSect);
|
---|
| 240 | rc = autostartModifyDb(false /* fAutostart */, true /* fAddVM */);
|
---|
| 241 | RTCritSectLeave(&this->CritSect);
|
---|
[80569] | 242 | #elif defined(RT_OS_DARWIN) || defined(RT_OS_WINDOWS)
|
---|
[41999] | 243 | NOREF(pszVMId); /* Not needed */
|
---|
| 244 | rc = VINF_SUCCESS;
|
---|
| 245 | #else
|
---|
| 246 | NOREF(pszVMId);
|
---|
| 247 | rc = VERR_NOT_SUPPORTED;
|
---|
| 248 | #endif
|
---|
| 249 |
|
---|
| 250 | return rc;
|
---|
| 251 | }
|
---|
| 252 |
|
---|
| 253 | int AutostartDb::removeAutostopVM(const char *pszVMId)
|
---|
| 254 | {
|
---|
| 255 | int rc = VINF_SUCCESS;
|
---|
| 256 |
|
---|
| 257 | #if defined(RT_OS_LINUX)
|
---|
| 258 | NOREF(pszVMId); /* Not needed */
|
---|
| 259 | RTCritSectEnter(&this->CritSect);
|
---|
| 260 | rc = autostartModifyDb(false /* fAutostart */, false /* fAddVM */);
|
---|
| 261 | RTCritSectLeave(&this->CritSect);
|
---|
[80569] | 262 | #elif defined(RT_OS_DARWIN) || defined (RT_OS_WINDOWS)
|
---|
[41999] | 263 | NOREF(pszVMId); /* Not needed */
|
---|
| 264 | rc = VINF_SUCCESS;
|
---|
| 265 | #else
|
---|
| 266 | NOREF(pszVMId);
|
---|
| 267 | rc = VERR_NOT_SUPPORTED;
|
---|
| 268 | #endif
|
---|
| 269 |
|
---|
| 270 | return rc;
|
---|
| 271 | }
|
---|
| 272 |
|
---|