/* This file contains the main message loop of the HGFS file system server. * * The entry points into this file are: * main main program function * * Created: * April 2009 (D.C. van Moolenbroek) */ #include "inc.h" #include #include #include FORWARD void get_work(endpoint_t *who_e); FORWARD void send_reply(int err, int transid); PRIVATE struct optset optset_table[] = { { "prefix", OPT_STRING, opt.prefix, sizeof(opt.prefix) }, { "uid", OPT_INT, &opt.uid, 10 }, { "gid", OPT_INT, &opt.gid, 10 }, { "fmask", OPT_INT, &opt.file_mask, 8 }, { "dmask", OPT_INT, &opt.dir_mask, 8 }, { "icase", OPT_BOOL, &opt.case_insens, TRUE }, { "noicase", OPT_BOOL, &opt.case_insens, FALSE }, { NULL, 0, NULL, 0 } }; /* SEF functions and variables. */ FORWARD void sef_local_startup(void); FORWARD int sef_cb_init_fresh(int type, sef_init_info_t *info); FORWARD void sef_cb_signal_handler(int signo); /*===========================================================================* * sef_cb_init_fresh * *===========================================================================*/ PRIVATE int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info)) { /* Initialize this file server. Called at startup time. */ int i, r; /* Defaults */ opt.prefix[0] = 0; opt.uid = 0; opt.gid = 0; opt.file_mask = 0755; opt.dir_mask = 0755; opt.case_insens = FALSE; /* If we have been given an options string, parse options from there. */ for (i = 1; i < env_argc - 1; i++) if (!strcmp(env_argv[i], "-o")) optset_parse(optset_table, env_argv[++i]); /* Make sure that the given path prefix doesn't end with a slash. */ for (i = strlen(opt.prefix); i > 0 && opt.prefix[i - 1] == '/'; i--); opt.prefix[i] = 0; /* Initialize the HGFS library. If this fails, exit immediately. */ r = hgfs_init(); if (r != OK && r != EAGAIN) { printf("HGFS: unable to initialize HGFS library (%d)\n", r); return r; } state.mounted = FALSE; return OK; } /*===========================================================================* * sef_cb_signal_handler * *===========================================================================*/ PRIVATE void sef_cb_signal_handler(int signo) { /* Only check for termination signal, ignore anything else. */ if (signo != SIGTERM) return; if (state.mounted) { dprintf(("HGFS: got SIGTERM, still mounted\n")); } else { dprintf(("HGFS: got SIGTERM, shutting down\n")); /* Pass on the cleanup request to the HGFS library. */ hgfs_cleanup(); exit(0); } } /*===========================================================================* * sef_local_startup * *===========================================================================*/ PRIVATE void sef_local_startup(void) { /* Register init callbacks. */ sef_setcb_init_fresh(sef_cb_init_fresh); sef_setcb_init_restart(sef_cb_init_fresh); /* No live update support yet. */ /* Register signal callbacks. */ sef_setcb_signal_handler(sef_cb_signal_handler); sef_startup(); } /*===========================================================================* * main * *===========================================================================*/ PUBLIC int main(argc, argv) int argc; char *argv[]; { /* The main function of this file server. After initializing, loop forever * receiving one request from VFS at a time, processing it, and sending a * reply back to VFS. */ endpoint_t who_e; int call_nr, err, transid; env_setargs(argc, argv); sef_local_startup(); for (;;) { get_work(&who_e); 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.mounted || call_nr == REQ_READSUPER) { call_nr -= VFS_BASE; dprintf(("HGFS: call %d\n", call_nr)); if (call_nr >= 0 && call_nr < NREQS) { err = (*call_vec[call_nr])(); } else { err = ENOSYS; } dprintf(("HGFS: call %d result %d\n", call_nr, err)); } else err = EINVAL; send_reply(err, transid); } return 0; } /*===========================================================================* * get_work * *===========================================================================*/ PRIVATE void get_work(who_e) endpoint_t *who_e; { /* Receive a request message from VFS. Return the request call number. */ int r; if ((r = sef_receive(ANY, &m_in)) != OK) panic("receive failed: %d", r); *who_e = m_in.m_source; } /*===========================================================================* * send_reply * *===========================================================================*/ PRIVATE 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("HGFS: send failed (%d)\n", r); }