ef7b484e5c
This Shared Folders File System library (libsffs) now contains all the file system logic originally in HGFS. The actual HGFS server code is now a stub that passes on all the work to libsffs. The libhgfs library is changed accordingly.
154 lines
4.1 KiB
C
154 lines
4.1 KiB
C
/* This file contains the SFFS initialization code and message loop.
|
|
*
|
|
* The entry points into this file are:
|
|
* sffs_init initialization
|
|
* sffs_signal signal handler
|
|
* sffs_loop main message loop
|
|
*
|
|
* Created:
|
|
* April 2009 (D.C. van Moolenbroek)
|
|
*/
|
|
|
|
#include "inc.h"
|
|
|
|
/*===========================================================================*
|
|
* sffs_init *
|
|
*===========================================================================*/
|
|
int sffs_init(char *name, const struct sffs_table *table,
|
|
struct sffs_params *params)
|
|
{
|
|
/* Initialize this file server. Called at startup time.
|
|
*/
|
|
int i;
|
|
|
|
/* Make sure that the given path prefix doesn't end with a slash. */
|
|
i = strlen(params->p_prefix);
|
|
while (i > 0 && params->p_prefix[i - 1] == '/') i--;
|
|
params->p_prefix[i] = 0;
|
|
|
|
state.s_mounted = FALSE;
|
|
state.s_signaled = FALSE;
|
|
|
|
sffs_name = name;
|
|
sffs_table = table;
|
|
sffs_params = params;
|
|
|
|
return OK;
|
|
}
|
|
|
|
/*===========================================================================*
|
|
* sffs_signal *
|
|
*===========================================================================*/
|
|
void sffs_signal(int signo)
|
|
{
|
|
|
|
/* Only check for termination signal, ignore anything else. */
|
|
if (signo != SIGTERM) return;
|
|
|
|
/* We can now terminate if we have also been unmounted. */
|
|
state.s_signaled = TRUE;
|
|
|
|
if (state.s_mounted) {
|
|
dprintf(("%s: got SIGTERM, still mounted\n", sffs_name));
|
|
} else {
|
|
dprintf(("%s: got SIGTERM, shutting down\n", sffs_name));
|
|
|
|
/* Break out of the main loop, giving the main program the chance to
|
|
* perform further cleanup. This causes sef_receive() to return with
|
|
* an EINTR error code.
|
|
*/
|
|
sef_cancel();
|
|
}
|
|
}
|
|
|
|
/*===========================================================================*
|
|
* get_work *
|
|
*===========================================================================*/
|
|
static int get_work(who_e)
|
|
endpoint_t *who_e;
|
|
{
|
|
/* Receive a request message from VFS. Return TRUE if a new message is ready
|
|
* to be processed, or FALSE if sef_stop() was called from the signal handler.
|
|
*/
|
|
int r;
|
|
|
|
if ((r = sef_receive(ANY, &m_in)) != OK) {
|
|
if (r != EINTR)
|
|
panic("receive failed: %d", r);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
*who_e = m_in.m_source;
|
|
return TRUE;
|
|
}
|
|
|
|
/*===========================================================================*
|
|
* send_reply *
|
|
*===========================================================================*/
|
|
static void send_reply(err, transid)
|
|
int err; /* resulting error code */
|
|
int transid;
|
|
{
|
|
/* Send a reply message to the requesting party, with the given error code.
|
|
*/
|
|
int r;
|
|
|
|
m_out.m_type = err;
|
|
if (IS_VFS_FS_TRANSID(transid)) {
|
|
/* If a transaction ID was set, reset it */
|
|
m_out.m_type = TRNS_ADD_ID(m_out.m_type, transid);
|
|
}
|
|
if ((r = send(m_in.m_source, &m_out)) != OK)
|
|
printf("%s: send failed (%d)\n", sffs_name, r);
|
|
}
|
|
|
|
/*===========================================================================*
|
|
* sffs_loop *
|
|
*===========================================================================*/
|
|
void sffs_loop(void)
|
|
{
|
|
/* The main function of this file server. After initializing, loop, receiving
|
|
* one request from VFS at a time, processing it, and sending a reply back to
|
|
* VFS. Termination occurs when we both have been unmounted and have received
|
|
* a termination signal.
|
|
*/
|
|
endpoint_t who_e;
|
|
int call_nr, err, transid;
|
|
|
|
while (state.s_mounted || !state.s_signaled) {
|
|
if (!get_work(&who_e))
|
|
continue; /* Recheck running conditions */
|
|
|
|
transid = TRNS_GET_ID(m_in.m_type);
|
|
m_in.m_type = TRNS_DEL_ID(m_in.m_type);
|
|
if (m_in.m_type == 0) {
|
|
assert(!IS_VFS_FS_TRANSID(transid));
|
|
m_in.m_type = transid; /* Backwards compat. */
|
|
transid = 0;
|
|
} else
|
|
assert(IS_VFS_FS_TRANSID(transid));
|
|
|
|
call_nr = m_in.m_type;
|
|
if (who_e != VFS_PROC_NR) {
|
|
continue;
|
|
}
|
|
|
|
if (state.s_mounted || call_nr == REQ_READSUPER) {
|
|
call_nr -= VFS_BASE;
|
|
|
|
dprintf(("%s: call %d\n", sffs_name, call_nr));
|
|
|
|
if (call_nr >= 0 && call_nr < NREQS) {
|
|
err = (*call_vec[call_nr])();
|
|
} else {
|
|
err = ENOSYS;
|
|
}
|
|
|
|
dprintf(("%s: call %d result %d\n", sffs_name, call_nr, err));
|
|
}
|
|
else err = EINVAL;
|
|
|
|
send_reply(err, transid);
|
|
}
|
|
}
|