Close all vdi's before exit, by Daniel.
[vdi_driver.git] / src / daemon / vdi_daemon.cpp
blobf7173ac131a80c15ec643a77166e94ef1c443a8c
1 /*
2 * vdi_daemon.c - Daemon of vdi driver
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 * To compile this file:
18 * g++ -o vdi_daemon vdi_daemon.cpp
20 * Substitute gcc with cc on some platforms.
22 * Daniel Borba / Tulio Magno
23 * 27/6/2008
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <fcntl.h>
32 #include <errno.h>
33 #include <unistd.h>
34 #include <syslog.h>
35 #include <string.h>
36 #include <assert.h>
37 #include <signal.h>
39 #include "vdi_daemon.h"
40 #include "../VBoxHDD.h"
41 #include "../VDICore.h"
42 #include "../const_defines.h"
44 #define DAEMON_NAME "vdi_daemon"
45 #define PID_FILE "/var/run/vdi_daemon.pid"
47 //Global variables
48 int mRunDaemon = 0;
50 /**************************************************************************
51 Function: Print Usage
53 Description:
54 Output the command-line options for this daemon.
56 Params:
57 @argc - Standard argument count
58 @argv - Standard argument array
60 Returns:
61 returns void always
62 **************************************************************************/
63 void PrintUsage(int argc, char *argv[]) {
64 if (argc >=1) {
65 printf("Usage: %s -h -n\n", argv[0]);
66 printf(" Options:\n");
67 printf(" -n\tDon't fork off as a daemon.\n");
68 printf(" -h\tShow this help screen\n");
69 printf("\n");
73 /**************************************************************************
74 Function: signal_handler
76 Description:
77 This function handles select signals that the daemon may
78 receive. This gives the daemon a chance to properly shut
79 down in emergency situations. This function is installed
80 as a signal handler in the 'main()' function.
82 Params:
83 @sig - The signal received
85 Returns:
86 returns void always
87 **************************************************************************/
88 void signal_handler(int sig) {
90 switch(sig) {
91 case SIGHUP:
92 syslog(LOG_WARNING, "Received SIGHUP signal.");
93 break;
94 case SIGTERM:
95 syslog(LOG_WARNING, "Received SIGTERM signal.");
96 mRunDaemon = 0;
97 break;
98 default:
99 syslog(LOG_WARNING, "Unhandled signal (%d) %s", strsignal(sig));
100 break;
104 /**************************************************************************
105 Function: main
107 Description:
108 The cpp standard 'main' entry point function.
110 Params:
111 @argc - count of command line arguments given on command line
112 @argv - array of arguments given on command line
114 Returns:
115 returns integer which is passed back to the parent process
116 **************************************************************************/
117 int main(int argc, char *argv[]) {
119 #if defined(DEBUG)
120 int daemonize = 0;
121 #else
122 int daemonize = 1;
123 #endif
125 // Setup signal handling before we start
126 signal(SIGHUP, signal_handler);
127 signal(SIGTERM, signal_handler);
128 signal(SIGINT, signal_handler);
129 signal(SIGQUIT, signal_handler);
131 int c;
132 while( (c = getopt(argc, argv, "nh:|help")) != -1) {
133 switch(c){
134 case 'h':
135 PrintUsage(argc, argv);
136 exit(0);
137 break;
138 case 'n':
139 daemonize = 0;
140 break;
141 default:
142 PrintUsage(argc, argv);
143 exit(0);
144 break;
148 syslog(LOG_INFO, "%s daemon starting up", DAEMON_NAME);
150 // Setup syslog logging - see SETLOGMASK(3)
151 #if defined(DEBUG)
152 setlogmask(LOG_UPTO(LOG_DEBUG));
153 openlog(DAEMON_NAME, LOG_CONS | LOG_NDELAY | LOG_PERROR | LOG_PID, LOG_USER);
154 #else
155 setlogmask(LOG_UPTO(LOG_INFO));
156 openlog(DAEMON_NAME, LOG_CONS, LOG_USER);
157 #endif
159 /* Our process ID and Session ID */
160 pid_t pid, sid;
162 if (daemonize) {
163 syslog(LOG_INFO, "starting the daemonizing process");
165 /* Fork off the parent process */
166 pid = fork();
167 if (pid < 0) {
168 exit(EXIT_FAILURE);
170 /* If we got a good PID, then
171 we can exit the parent process. */
172 if (pid > 0) {
173 exit(EXIT_SUCCESS);
176 /* Change the file mode mask */
177 umask(0);
179 /* Create a new SID for the child process */
180 sid = setsid();
181 if (sid < 0) {
182 /* Log the failure */
183 exit(EXIT_FAILURE);
186 /* Change the current working directory */
187 if ((chdir("/")) < 0) {
188 /* Log the failure */
189 exit(EXIT_FAILURE);
192 /* Close out the standard file descriptors */
193 //TODO: close(STDIN_FILENO);
194 //TODO: close(STDOUT_FILENO);
195 //TODO: close(STDERR_FILENO);
197 //****************************************************
198 // Daemon task
199 //****************************************************
200 //VDI Image File
201 char vVdiImageFile [255] = "tstVdiBase.vdi";
203 //VDI Request
204 vdi_request* req = NULL;
206 mRunDaemon = 1;
208 while (mRunDaemon)
210 //Espera uma chamada do sistema que voltara um vdi_request (Eh necessario que se permita ao daemon escrever e ler no buffer da requisicao)
211 if (req != NULL)
213 PVDIDISK vVdi = VDIDiskCreate();
214 int rc = VDIDiskOpenImage(vVdi, vVdiImageFile, VDI_OPEN_FLAGS_NORMAL);
216 if (VBOX_FAILURE(rc))
218 syslog(LOG_WARNING, "%s daemon: Can't open VDI image %s", DAEMON_NAME, vVdiImageFile);
220 else
222 unsigned long vOffsetStart = VDI_GEOMETRY_SECTOR_SIZE*req->sector;
223 unsigned long vSize = VDI_GEOMETRY_SECTOR_SIZE*req->nr_sectors;
225 switch(req->cmd)
227 case VDI_READ:
228 rc = VDIDiskRead(vVdi, vOffsetStart, req->buffer, vSize);
230 if (VBOX_FAILURE(rc))
232 syslog(LOG_WARNING, "%s daemon: Can't read from VDI image %s", DAEMON_NAME, vVdiImageFile);
235 break;
236 case VDI_WRITE:
237 rc = VDIDiskWrite(vVdi, vOffsetStart, req->buffer, vSize);
239 if (VBOX_FAILURE(rc))
241 syslog(LOG_WARNING, "%s daemon: Can't write in VDI image %s", DAEMON_NAME, vVdiImageFile);
244 break;
248 VDIDiskCloseAllImages(vVdi);
253 syslog(LOG_INFO, "%s daemon exiting", DAEMON_NAME);
255 //****************************************************
256 // TODO: Free any allocated resources before exiting
257 //****************************************************
259 exit(0);