VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/generic/AutostartDb-generic.cpp@ 41999

Last change on this file since 41999 was 41999, checked in by vboxsync, 13 years ago

More autostart service updates, work in progress

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.4 KB
Line 
1/* $Id: AutostartDb-generic.cpp 41999 2012-07-03 12:50:18Z vboxsync $ */
2/** @file
3 * VirtualBox Main - Autostart implementation.
4 */
5
6/*
7 * Copyright (C) 2009-2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include <VBox/err.h>
19#include <VBox/log.h>
20#include <iprt/assert.h>
21#include <iprt/process.h>
22#include <iprt/path.h>
23#include <iprt/mem.h>
24#include <iprt/file.h>
25#include <iprt/string.h>
26
27#include "AutostartDb.h"
28
29/** @todo: Make configurable through kmk/installer. */
30#define AUTOSTART_DATABASE "/etc/vbox/autostart.d"
31
32#if defined(RT_OS_LINUX)
33/**
34 * Return the username of the current process.
35 *
36 * @returns Pointer to the string containing the username of
37 * NULL in case of an error. Free with RTMemFree().
38 */
39static int autostartGetProcessUser(char **ppszUser)
40{
41 int rc = VINF_SUCCESS;
42 size_t cbUser = 128;
43 char *pszUser = (char *)RTMemAllocZ(cbUser);
44
45 if (pszUser)
46 {
47 rc = RTProcQueryUsername(RTProcSelf(), pszUser, cbUser, &cbUser);
48 if (rc == VERR_BUFFER_OVERFLOW)
49 {
50 char *pszTmp = (char *)RTMemRealloc(pszUser, cbUser);
51 if (pszTmp)
52 {
53 pszUser = pszTmp;
54 rc = RTProcQueryUsername(RTProcSelf(), pszUser, cbUser, &cbUser);
55 Assert(rc != VERR_BUFFER_OVERFLOW);
56 }
57 }
58
59 if (RT_FAILURE(rc))
60 {
61 RTMemFree(pszUser);
62 pszUser = NULL;
63 }
64 else
65 *ppszUser = pszUser;
66 }
67
68 return rc;
69}
70
71/**
72 * Modifies the autostart database.
73 *
74 * @returns VBox status code.
75 * @param fAutostart Flag whether the autostart or autostop database is modified.
76 * @param fAddVM Flag whether a VM is added or removed from the database.
77 */
78static int autostartModifyDb(bool fAutostart, bool fAddVM)
79{
80 int rc = VINF_SUCCESS;
81 char *pszUser = NULL;
82
83 rc = autostartGetProcessUser(&pszUser);
84 if ( RT_SUCCESS(rc)
85 && pszUser)
86 {
87 char *pszFile;
88 uint64_t fOpen = RTFILE_O_DENY_ALL | RTFILE_O_READWRITE;
89 RTFILE hAutostartFile;
90
91 if (fAddVM)
92 fOpen |= RTFILE_O_OPEN_CREATE;
93
94 rc = RTStrAPrintf(&pszFile, "%s/%s.%s",
95 AUTOSTART_DATABASE, pszUser, fAutostart ? "start" : "stop");
96 if (RT_SUCCESS(rc))
97 {
98 rc = RTFileOpen(&hAutostartFile, pszFile, fOpen);
99 if (RT_SUCCESS(rc))
100 {
101 uint64_t cbFile;
102
103 /*
104 * Files with more than 16 bytes are rejected because they just contain
105 * a number of the amount of VMs with autostart configured, so they
106 * should be really really small. Anything else is bogus.
107 */
108 rc = RTFileGetSize(hAutostartFile, &cbFile);
109 if ( RT_SUCCESS(rc)
110 && cbFile <= 16)
111 {
112 char abBuf[16 + 1]; /* trailing \0 */
113 uint32_t cAutostartVms = 0;
114
115 memset(abBuf, 0, sizeof(abBuf));
116
117 /* Check if the file was just created. */
118 if (cbFile)
119 {
120 rc = RTFileRead(hAutostartFile, abBuf, cbFile, NULL);
121 if (RT_SUCCESS(rc))
122 {
123 rc = RTStrToUInt32Ex(abBuf, NULL, 10 /* uBase */, &cAutostartVms);
124 if ( rc == VWRN_TRAILING_CHARS
125 || rc == VWRN_TRAILING_SPACES)
126 rc = VINF_SUCCESS;
127 }
128 }
129
130 if (RT_SUCCESS(rc))
131 {
132 size_t cbBuf;
133
134 /* Modify VM counter and write back. */
135 if (fAddVM)
136 cAutostartVms++;
137 else
138 cAutostartVms--;
139
140 if (cAutostartVms > 0)
141 {
142 cbBuf = RTStrPrintf(abBuf, sizeof(abBuf), "%u", cAutostartVms);
143 rc = RTFileSetSize(hAutostartFile, cbBuf);
144 if (RT_SUCCESS(rc))
145 rc = RTFileWriteAt(hAutostartFile, 0, abBuf, cbBuf, NULL);
146 }
147 else
148 {
149 /* Just delete the file if there are no VMs left. */
150 RTFileClose(hAutostartFile);
151 RTFileDelete(pszFile);
152 hAutostartFile = NIL_RTFILE;
153 }
154 }
155 }
156 else if (RT_SUCCESS(rc))
157 rc = VERR_FILE_TOO_BIG;
158
159 if (hAutostartFile != NIL_RTFILE)
160 RTFileClose(hAutostartFile);
161 }
162 RTStrFree(pszFile);
163 }
164 }
165 else if (pszUser)
166 rc = VERR_NOT_SUPPORTED;
167
168 return rc;
169}
170
171#endif
172
173AutostartDb::AutostartDb()
174{
175#ifdef RT_OS_LINUX
176 int rc = RTCritSectInit(&this->CritSect);
177 NOREF(rc);
178#endif
179}
180
181AutostartDb::~AutostartDb()
182{
183#ifdef RT_OS_LINUX
184 RTCritSectDelete(&this->CritSect);
185#endif
186}
187
188int AutostartDb::addAutostartVM(const char *pszVMId)
189{
190 int rc = VERR_NOT_SUPPORTED;
191
192#if defined(RT_OS_LINUX)
193 NOREF(pszVMId); /* Not needed */
194
195 RTCritSectEnter(&this->CritSect);
196 rc = autostartModifyDb(true /* fAutostart */, true /* fAddVM */);
197 RTCritSectLeave(&this->CritSect);
198#elif defined(RT_OS_DARWIN)
199 NOREF(pszVMId); /* Not needed */
200 rc = VINF_SUCCESS;
201#else
202 NOREF(pszVMId);
203 rc = VERR_NOT_SUPPORTED;
204#endif
205
206 return rc;
207}
208
209int AutostartDb::removeAutostartVM(const char *pszVMId)
210{
211 int rc = VINF_SUCCESS;
212
213#if defined(RT_OS_LINUX)
214 NOREF(pszVMId); /* Not needed */
215 RTCritSectEnter(&this->CritSect);
216 rc = autostartModifyDb(true /* fAutostart */, false /* fAddVM */);
217 RTCritSectLeave(&this->CritSect);
218#elif defined(RT_OS_DARWIN)
219 NOREF(pszVMId); /* Not needed */
220 rc = VINF_SUCCESS;
221#else
222 NOREF(pszVMId);
223 rc = VERR_NOT_SUPPORTED;
224#endif
225
226 return rc;
227}
228
229int AutostartDb::addAutostopVM(const char *pszVMId)
230{
231 int rc = VINF_SUCCESS;
232
233#if defined(RT_OS_LINUX)
234 NOREF(pszVMId); /* Not needed */
235 RTCritSectEnter(&this->CritSect);
236 rc = autostartModifyDb(false /* fAutostart */, true /* fAddVM */);
237 RTCritSectLeave(&this->CritSect);
238#elif defined(RT_OS_DARWIN)
239 NOREF(pszVMId); /* Not needed */
240 rc = VINF_SUCCESS;
241#else
242 NOREF(pszVMId);
243 rc = VERR_NOT_SUPPORTED;
244#endif
245
246 return rc;
247}
248
249int AutostartDb::removeAutostopVM(const char *pszVMId)
250{
251 int rc = VINF_SUCCESS;
252
253#if defined(RT_OS_LINUX)
254 NOREF(pszVMId); /* Not needed */
255 RTCritSectEnter(&this->CritSect);
256 rc = autostartModifyDb(false /* fAutostart */, false /* fAddVM */);
257 RTCritSectLeave(&this->CritSect);
258#elif defined(RT_OS_DARWIN)
259 NOREF(pszVMId); /* Not needed */
260 rc = VINF_SUCCESS;
261#else
262 NOREF(pszVMId);
263 rc = VERR_NOT_SUPPORTED;
264#endif
265
266 return rc;
267}
268
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette