static int do_nfs(int argc, char *argv[]) { char *localfile; char *remotefile; if (argc < 2) return COMMAND_ERROR_USAGE; remotefile = argv[1]; if (argc == 2) localfile = basename(remotefile); else localfile = argv[2]; net_store_fd = open(localfile, O_WRONLY | O_CREAT); if (net_store_fd < 0) { perror("open"); return 1; } nfs_con = net_udp_new(net_get_serverip(), 0, nfs_handler, NULL); if (IS_ERR(nfs_con)) { nfs_err = PTR_ERR(nfs_con); goto err_udp; } net_udp_bind(nfs_con, 1000); nfs_err = 0; nfs_start(remotefile); while (nfs_state != STATE_DONE) { if (ctrlc()) { nfs_err = -EINTR; break; } net_poll(); if (is_timeout(nfs_timer_start, NFS_TIMEOUT * SECOND)) { show_progress(-1); nfs_send(); } } net_unregister(nfs_con); err_udp: close(net_store_fd); if (nfs_err) { printf("NFS failed: %s\n", strerror(-nfs_err)); unlink(localfile); } printf("\n"); return nfs_err == 0 ? 0 : 1; }
/* * Check if autoload is enabled. If so, use either NFS or TFTP to download * the boot file. */ void net_auto_load(void) { #if defined(CONFIG_CMD_NFS) const char *s = getenv("autoload"); if (s != NULL && strcmp(s, "NFS") == 0) { /* * Use NFS to load the bootfile. */ nfs_start(); return; } #endif if (getenv_yesno("autoload") == 0) { /* * Just use BOOTP/RARP to configure system; * Do not use TFTP to load the bootfile. */ net_set_state(NETLOOP_SUCCESS); return; } tftp_start(TFTPGET); }
int main(int argc, char *argv[]) { char *tempo_exec_name = NULL; char localmachine[MAXHOSTNAMELEN + 1]; int c; int pidfile; #ifndef HAVE_DAEMON pid_t son_pid; #endif sigset_t signals_to_block; /* Set the server's boot time and epoch */ now(&ServerBootTime); ServerEpoch = (time_t) ServerBootTime.tv_sec; tempo_exec_name = strrchr(argv[0], '/'); if (tempo_exec_name != NULL) { exec_name = gsh_strdup(tempo_exec_name + 1); if (!exec_name) { fprintf(stderr, "Unable to allocate memory for exec name, exiting...\n"); exit(1); } } if (*exec_name == '\0') exec_name = argv[0]; /* get host name */ if (gethostname(localmachine, sizeof(localmachine)) != 0) { fprintf(stderr, "Could not get local host name, exiting...\n"); exit(1); } else { host_name = gsh_strdup(localmachine); if (!host_name) { fprintf(stderr, "Unable to allocate memory for hostname, exiting...\n"); exit(1); } } /* now parsing options with getopt */ while ((c = getopt(argc, argv, options)) != EOF) { switch (c) { case '@': /* A litlle backdoor to keep track of binary versions */ printf("%s compiled on %s at %s\n", exec_name, __DATE__, __TIME__); printf("Release = %s\n", VERSION); printf("Release comment = %s\n", VERSION_COMMENT); printf("Git HEAD = %s\n", _GIT_HEAD_COMMIT); printf("Git Describe = %s\n", _GIT_DESCRIBE); exit(0); break; case 'L': /* Default Log */ log_path = gsh_strdup(optarg); if (!log_path) { fprintf(stderr, "Unable to allocate memory for log path.\n"); exit(1); } break; case 'N': /* debug level */ debug_level = ReturnLevelAscii(optarg); if (debug_level == -1) { fprintf(stderr, "Invalid value for option 'N': NIV_NULL, NIV_MAJ, NIV_CRIT, NIV_EVENT, NIV_DEBUG, NIV_MID_DEBUG or NIV_FULL_DEBUG expected.\n"); exit(1); } break; case 'f': /* config file */ config_path = gsh_strdup(optarg); if (!config_path) { fprintf(stderr, "Unable to allocate memory for config path.\n"); exit(1); } break; case 'p': /* PID file */ pidfile_path = gsh_strdup(optarg); if (!pidfile_path) { fprintf(stderr, "Path %s too long for option 'f'.\n", optarg); exit(1); } break; case 'd': /* Detach or not detach ? */ detach_flag = true; break; case 'R': /* Shall we manage RPCSEC_GSS ? */ fprintf(stderr, "\n\nThe -R flag is deprecated, use this syntax in the configuration file instead:\n\n"); fprintf(stderr, "NFS_KRB5\n"); fprintf(stderr, "{\n"); fprintf(stderr, "\tPrincipalName = nfs@<your_host> ;\n"); fprintf(stderr, "\tKeytabPath = /etc/krb5.keytab ;\n"); fprintf(stderr, "\tActive_krb5 = true ;\n"); fprintf(stderr, "}\n\n\n"); exit(1); break; case 'T': /* Dump the default configuration on stdout */ my_nfs_start_info.dump_default_config = true; break; case 'E': ServerEpoch = (time_t) atoll(optarg); break; case '?': case 'h': default: /* display the help */ fprintf(stderr, usage, exec_name); exit(0); break; } } /* initialize memory and logging */ nfs_prereq_init(exec_name, host_name, debug_level, log_path); LogEvent(COMPONENT_MAIN, "%s Starting: Version %s, built at %s %s on %s", exec_name, GANESHA_VERSION, __DATE__, __TIME__, BUILD_HOST); /* Start in background, if wanted */ if (detach_flag) { #ifdef HAVE_DAEMON /* daemonize the process (fork, close xterm fds, * detach from parent process) */ if (daemon(0, 0)) LogFatal(COMPONENT_MAIN, "Error detaching process from parent: %s", strerror(errno)); #else /* Step 1: forking a service process */ switch (son_pid = fork()) { case -1: /* Fork failed */ LogFatal(COMPONENT_MAIN, "Could not start nfs daemon (fork error %d (%s)", errno, strerror(errno)); break; case 0: /* This code is within the son (that will actually work) * Let's make it the leader of its group of process */ if (setsid() == -1) { LogFatal(COMPONENT_MAIN, "Could not start nfs daemon (setsid error %d (%s)", errno, strerror(errno)); } break; default: /* This code is within the parent process, * it is useless, it must die */ LogFullDebug(COMPONENT_MAIN, "Starting a child of pid %d", son_pid); exit(0); break; } #endif } /* Make sure Linux file i/o will return with error * if file size is exceeded. */ #ifdef _LINUX signal(SIGXFSZ, SIG_IGN); #endif /* Echo PID into pidfile */ pidfile = open(pidfile_path, O_CREAT | O_RDWR, 0644); if (pidfile == -1) { LogFatal(COMPONENT_MAIN, "Can't open pid file %s for writing", pidfile_path); } else { char linebuf[1024]; struct flock lk; /* Try to obtain a lock on the file */ lk.l_type = F_WRLCK; lk.l_whence = SEEK_SET; lk.l_start = (off_t) 0; lk.l_len = (off_t) 0; if (fcntl(pidfile, F_SETLK, &lk) == -1) LogFatal(COMPONENT_MAIN, "Ganesha already started"); /* Put pid into file, then close it */ (void)snprintf(linebuf, sizeof(linebuf), "%u\n", getpid()); if (write(pidfile, linebuf, strlen(linebuf)) == -1) LogCrit(COMPONENT_MAIN, "Couldn't write pid to file %s", pidfile_path); } /* Set up for the signal handler. * Blocks the signals the signal handler will handle. */ sigemptyset(&signals_to_block); sigaddset(&signals_to_block, SIGTERM); sigaddset(&signals_to_block, SIGHUP); sigaddset(&signals_to_block, SIGPIPE); if (pthread_sigmask(SIG_BLOCK, &signals_to_block, NULL) != 0) LogFatal(COMPONENT_MAIN, "Could not start nfs daemon, pthread_sigmask failed"); /* Parse the configuration file so we all know what is going on. */ if (config_path == NULL) { LogFatal(COMPONENT_INIT, "start_fsals: No configuration file named."); return 1; } config_struct = config_ParseFile(config_path); if (!config_struct) { LogFatal(COMPONENT_INIT, "Error while parsing %s: %s", config_path, config_GetErrorMsg()); } /* We need all the fsal modules loaded so we can have * the list available at exports parsing time. */ start_fsals(config_struct); /* parse configuration file */ if (nfs_set_param_from_conf(config_struct, &my_nfs_start_info)) { LogFatal(COMPONENT_INIT, "Error setting parameters from configuration file."); } if (nfs_check_param_consistency()) { LogFatal(COMPONENT_INIT, "Inconsistent parameters found. Exiting..."); } if (init_fsals(config_struct)) { /* init the FSALs from the config */ LogFatal(COMPONENT_INIT, "FSALs could not initialize. Exiting..."); } /* freeing syntax tree : */ config_Free(config_struct); /* Everything seems to be OK! We can now start service threads */ nfs_start(&my_nfs_start_info); return 0; }
int net_loop(enum proto_t protocol) { int ret = -EINVAL; net_restarted = 0; net_dev_exists = 0; net_try_count = 1; debug_cond(DEBUG_INT_STATE, "--- net_loop Entry\n"); bootstage_mark_name(BOOTSTAGE_ID_ETH_START, "eth_start"); net_init(); if (eth_is_on_demand_init() || protocol != NETCONS) { eth_halt(); eth_set_current(); ret = eth_init(); if (ret < 0) { eth_halt(); return ret; } } else { eth_init_state_only(); } restart: #ifdef CONFIG_USB_KEYBOARD net_busy_flag = 0; #endif net_set_state(NETLOOP_CONTINUE); /* * Start the ball rolling with the given start function. From * here on, this code is a state machine driven by received * packets and timer events. */ debug_cond(DEBUG_INT_STATE, "--- net_loop Init\n"); net_init_loop(); switch (net_check_prereq(protocol)) { case 1: /* network not configured */ eth_halt(); return -ENODEV; case 2: /* network device not configured */ break; case 0: net_dev_exists = 1; net_boot_file_size = 0; switch (protocol) { case TFTPGET: #ifdef CONFIG_CMD_TFTPPUT case TFTPPUT: #endif /* always use ARP to get server ethernet address */ tftp_start(protocol); break; #ifdef CONFIG_CMD_TFTPSRV case TFTPSRV: tftp_start_server(); break; #endif #if defined(CONFIG_CMD_DHCP) case DHCP: bootp_reset(); net_ip.s_addr = 0; dhcp_request(); /* Basically same as BOOTP */ break; #endif case BOOTP: bootp_reset(); net_ip.s_addr = 0; bootp_request(); break; #if defined(CONFIG_CMD_RARP) case RARP: rarp_try = 0; net_ip.s_addr = 0; rarp_request(); break; #endif #if defined(CONFIG_CMD_PING) case PING: ping_start(); break; #endif #if defined(CONFIG_CMD_NFS) case NFS: nfs_start(); break; #endif #if defined(CONFIG_CMD_CDP) case CDP: cdp_start(); break; #endif #if defined(CONFIG_NETCONSOLE) && !(CONFIG_SPL_BUILD) case NETCONS: nc_start(); break; #endif #if defined(CONFIG_CMD_SNTP) case SNTP: sntp_start(); break; #endif #if defined(CONFIG_CMD_DNS) case DNS: dns_start(); break; #endif #if defined(CONFIG_CMD_LINK_LOCAL) case LINKLOCAL: link_local_start(); break; #endif default: break; } break; } #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) #if defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN) && \ defined(CONFIG_STATUS_LED) && \ defined(STATUS_LED_RED) /* * Echo the inverted link state to the fault LED. */ if (miiphy_link(eth_get_dev()->name, CONFIG_SYS_FAULT_MII_ADDR)) status_led_set(STATUS_LED_RED, STATUS_LED_OFF); else status_led_set(STATUS_LED_RED, STATUS_LED_ON); #endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */ #endif /* CONFIG_MII, ... */ #ifdef CONFIG_USB_KEYBOARD net_busy_flag = 1; #endif /* * Main packet reception loop. Loop receiving packets until * someone sets `net_state' to a state that terminates. */ for (;;) { WATCHDOG_RESET(); #ifdef CONFIG_SHOW_ACTIVITY show_activity(1); #endif if (arp_timeout_check() > 0) time_start = get_timer(0); /* * Check the ethernet for a new packet. The ethernet * receive routine will process it. * Most drivers return the most recent packet size, but not * errors that may have happened. */ eth_rx(); /* * Abort if ctrl-c was pressed. */ if (ctrlc()) { /* cancel any ARP that may not have completed */ net_arp_wait_packet_ip.s_addr = 0; net_cleanup_loop(); eth_halt(); /* Invalidate the last protocol */ eth_set_last_protocol(BOOTP); puts("\nAbort\n"); /* include a debug print as well incase the debug messages are directed to stderr */ debug_cond(DEBUG_INT_STATE, "--- net_loop Abort!\n"); ret = -EINTR; goto done; } /* * Check for a timeout, and run the timeout handler * if we have one. */ if (time_handler && ((get_timer(0) - time_start) > time_delta)) { thand_f *x; #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) #if defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN) && \ defined(CONFIG_STATUS_LED) && \ defined(STATUS_LED_RED) /* * Echo the inverted link state to the fault LED. */ if (miiphy_link(eth_get_dev()->name, CONFIG_SYS_FAULT_MII_ADDR)) status_led_set(STATUS_LED_RED, STATUS_LED_OFF); else status_led_set(STATUS_LED_RED, STATUS_LED_ON); #endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */ #endif /* CONFIG_MII, ... */ debug_cond(DEBUG_INT_STATE, "--- net_loop timeout\n"); x = time_handler; time_handler = (thand_f *)0; (*x)(); } if (net_state == NETLOOP_FAIL) ret = net_start_again(); switch (net_state) { case NETLOOP_RESTART: net_restarted = 1; goto restart; case NETLOOP_SUCCESS: net_cleanup_loop(); if (net_boot_file_size > 0) { printf("Bytes transferred = %d (%x hex)\n", net_boot_file_size, net_boot_file_size); setenv_hex("filesize", net_boot_file_size); setenv_hex("fileaddr", load_addr); } if (protocol != NETCONS) eth_halt(); else eth_halt_state_only(); eth_set_last_protocol(protocol); ret = net_boot_file_size; debug_cond(DEBUG_INT_STATE, "--- net_loop Success!\n"); goto done; case NETLOOP_FAIL: net_cleanup_loop(); /* Invalidate the last protocol */ eth_set_last_protocol(BOOTP); debug_cond(DEBUG_INT_STATE, "--- net_loop Fail!\n"); goto done; case NETLOOP_CONTINUE: continue; } } done: #ifdef CONFIG_USB_KEYBOARD net_busy_flag = 0; #endif #ifdef CONFIG_CMD_TFTPPUT /* Clear out the handlers */ net_set_udp_handler(NULL); net_set_icmp_handler(NULL); #endif return ret; }
int main(int argc, char *argv[]) { char *tempo_exec_name = NULL; char localmachine[MAXHOSTNAMELEN + 1]; int c; int dsc; int rc; int pidfile; char *log_path = NULL; char *exec_name = "nfs-ganesha"; int debug_level = -1; int detach_flag = true; bool dump_trace = false; #ifndef HAVE_DAEMON int dev_null_fd = 0; pid_t son_pid; #endif sigset_t signals_to_block; struct config_error_type err_type; /* Set the server's boot time and epoch */ now(&nfs_ServerBootTime); nfs_ServerEpoch = (time_t) nfs_ServerBootTime.tv_sec; srand(nfs_ServerEpoch); tempo_exec_name = strrchr(argv[0], '/'); if (tempo_exec_name != NULL) exec_name = main_strdup("exec_name", tempo_exec_name + 1); if (*exec_name == '\0') exec_name = argv[0]; /* get host name */ if (gethostname(localmachine, sizeof(localmachine)) != 0) { fprintf(stderr, "Could not get local host name, exiting...\n"); exit(1); } else { nfs_host_name = main_strdup("host_name", localmachine); } /* now parsing options with getopt */ while ((c = getopt(argc, argv, options)) != EOF) { switch (c) { case 'v': case '@': printf("NFS-Ganesha Release = V%s\n", GANESHA_VERSION); #if !GANESHA_BUILD_RELEASE /* A little backdoor to keep track of binary versions */ printf("%s compiled on %s at %s\n", exec_name, __DATE__, __TIME__); printf("Release comment = %s\n", VERSION_COMMENT); printf("Git HEAD = %s\n", _GIT_HEAD_COMMIT); printf("Git Describe = %s\n", _GIT_DESCRIBE); #endif exit(0); break; case 'L': /* Default Log */ log_path = main_strdup("log_path", optarg); break; case 'N': /* debug level */ debug_level = ReturnLevelAscii(optarg); if (debug_level == -1) { fprintf(stderr, "Invalid value for option 'N': NIV_NULL, NIV_MAJ, NIV_CRIT, NIV_EVENT, NIV_DEBUG, NIV_MID_DEBUG or NIV_FULL_DEBUG expected.\n"); exit(1); } break; case 'f': /* config file */ nfs_config_path = main_strdup("config_path", optarg); break; case 'p': /* PID file */ nfs_pidfile_path = main_strdup("pidfile_path", optarg); break; case 'F': /* Don't detach, foreground mode */ detach_flag = false; break; case 'R': /* Shall we manage RPCSEC_GSS ? */ fprintf(stderr, "\n\nThe -R flag is deprecated, use this syntax in the configuration file instead:\n\n"); fprintf(stderr, "NFS_KRB5\n"); fprintf(stderr, "{\n"); fprintf(stderr, "\tPrincipalName = nfs@<your_host> ;\n"); fprintf(stderr, "\tKeytabPath = /etc/krb5.keytab ;\n"); fprintf(stderr, "\tActive_krb5 = true ;\n"); fprintf(stderr, "}\n\n\n"); exit(1); break; case 'T': /* Dump the default configuration on stdout */ my_nfs_start_info.dump_default_config = true; break; case 'C': dump_trace = true; break; case 'E': nfs_ServerEpoch = (time_t) atoll(optarg); break; case 'h': fprintf(stderr, usage, exec_name); exit(0); default: /* '?' */ fprintf(stderr, "Try '%s -h' for usage\n", exec_name); exit(1); } } /* initialize memory and logging */ nfs_prereq_init(exec_name, nfs_host_name, debug_level, log_path, dump_trace); #if GANESHA_BUILD_RELEASE LogEvent(COMPONENT_MAIN, "%s Starting: Ganesha Version %s", exec_name, GANESHA_VERSION); #else LogEvent(COMPONENT_MAIN, "%s Starting: %s", exec_name, "Ganesha Version " _GIT_DESCRIBE ", built at " __DATE__ " " __TIME__ " on " BUILD_HOST); #endif /* initialize nfs_init */ nfs_init_init(); nfs_check_malloc(); /* Start in background, if wanted */ if (detach_flag) { #ifdef HAVE_DAEMON /* daemonize the process (fork, close xterm fds, * detach from parent process) */ if (daemon(0, 0)) LogFatal(COMPONENT_MAIN, "Error detaching process from parent: %s", strerror(errno)); /* In the child process, change the log header * if not, the header will contain the parent's pid */ set_const_log_str(); #else /* Step 1: forking a service process */ switch (son_pid = fork()) { case -1: /* Fork failed */ LogFatal(COMPONENT_MAIN, "Could not start nfs daemon (fork error %d (%s)", errno, strerror(errno)); break; case 0: /* This code is within the son (that will actually work) * Let's make it the leader of its group of process */ if (setsid() == -1) { LogFatal(COMPONENT_MAIN, "Could not start nfs daemon (setsid error %d (%s)", errno, strerror(errno)); } /* stdin, stdout and stderr should not refer to a tty * I close 0, 1 & 2 and redirect them to /dev/null */ dev_null_fd = open("/dev/null", O_RDWR); if (dev_null_fd < 0) LogFatal(COMPONENT_MAIN, "Could not open /dev/null: %d (%s)", errno, strerror(errno)); if (close(STDIN_FILENO) == -1) LogEvent(COMPONENT_MAIN, "Error while closing stdin: %d (%s)", errno, strerror(errno)); else { LogEvent(COMPONENT_MAIN, "stdin closed"); dup(dev_null_fd); } if (close(STDOUT_FILENO) == -1) LogEvent(COMPONENT_MAIN, "Error while closing stdout: %d (%s)", errno, strerror(errno)); else { LogEvent(COMPONENT_MAIN, "stdout closed"); dup(dev_null_fd); } if (close(STDERR_FILENO) == -1) LogEvent(COMPONENT_MAIN, "Error while closing stderr: %d (%s)", errno, strerror(errno)); else { LogEvent(COMPONENT_MAIN, "stderr closed"); dup(dev_null_fd); } if (close(dev_null_fd) == -1) LogFatal(COMPONENT_MAIN, "Could not close tmp fd to /dev/null: %d (%s)", errno, strerror(errno)); /* In the child process, change the log header * if not, the header will contain the parent's pid */ set_const_log_str(); break; default: /* This code is within the parent process, * it is useless, it must die */ LogFullDebug(COMPONENT_MAIN, "Starting a child of pid %d", son_pid); exit(0); break; } #endif } /* Make sure Linux file i/o will return with error * if file size is exceeded. */ #ifdef _LINUX signal(SIGXFSZ, SIG_IGN); #endif /* Echo PID into pidfile */ pidfile = open(nfs_pidfile_path, O_CREAT | O_RDWR, 0644); if (pidfile == -1) { LogFatal(COMPONENT_MAIN, "Can't open pid file %s for writing", nfs_pidfile_path); } else { char linebuf[1024]; struct flock lk; /* Try to obtain a lock on the file */ lk.l_type = F_WRLCK; lk.l_whence = SEEK_SET; lk.l_start = (off_t) 0; lk.l_len = (off_t) 0; if (fcntl(pidfile, F_SETLK, &lk) == -1) LogFatal(COMPONENT_MAIN, "Ganesha already started"); /* Put pid into file, then close it */ (void)snprintf(linebuf, sizeof(linebuf), "%u\n", getpid()); if (write(pidfile, linebuf, strlen(linebuf)) == -1) LogCrit(COMPONENT_MAIN, "Couldn't write pid to file %s", nfs_pidfile_path); } /* Set up for the signal handler. * Blocks the signals the signal handler will handle. */ sigemptyset(&signals_to_block); sigaddset(&signals_to_block, SIGTERM); sigaddset(&signals_to_block, SIGHUP); sigaddset(&signals_to_block, SIGPIPE); if (pthread_sigmask(SIG_BLOCK, &signals_to_block, NULL) != 0) LogFatal(COMPONENT_MAIN, "Could not start nfs daemon, pthread_sigmask failed"); /* init URL package */ config_url_init(); /* Create a memstream for parser+processing error messages */ if (!init_error_type(&err_type)) goto fatal_die; /* Parse the configuration file so we all know what is going on. */ if (nfs_config_path == NULL || nfs_config_path[0] == '\0') { LogWarn(COMPONENT_INIT, "No configuration file named."); nfs_config_struct = NULL; } else nfs_config_struct = config_ParseFile(nfs_config_path, &err_type); if (!config_error_no_error(&err_type)) { char *errstr = err_type_str(&err_type); if (!config_error_is_harmless(&err_type)) { LogCrit(COMPONENT_INIT, "Error %s while parsing (%s)", errstr != NULL ? errstr : "unknown", nfs_config_path); if (errstr != NULL) gsh_free(errstr); goto fatal_die; } else LogWarn(COMPONENT_INIT, "Error %s while parsing (%s)", errstr != NULL ? errstr : "unknown", nfs_config_path); if (errstr != NULL) gsh_free(errstr); } if (read_log_config(nfs_config_struct, &err_type) < 0) { LogCrit(COMPONENT_INIT, "Error while parsing log configuration"); goto fatal_die; } /* We need all the fsal modules loaded so we can have * the list available at exports parsing time. */ start_fsals(); /* parse configuration file */ if (nfs_set_param_from_conf(nfs_config_struct, &my_nfs_start_info, &err_type)) { LogCrit(COMPONENT_INIT, "Error setting parameters from configuration file."); goto fatal_die; } /* initialize core subsystems and data structures */ if (init_server_pkgs() != 0) { LogCrit(COMPONENT_INIT, "Failed to initialize server packages"); goto fatal_die; } /* Load Data Server entries from parsed file * returns the number of DS entries. */ dsc = ReadDataServers(nfs_config_struct, &err_type); if (dsc < 0) { LogCrit(COMPONENT_INIT, "Error while parsing DS entries"); goto fatal_die; } /* Create stable storage directory, this needs to be done before * starting the recovery thread. */ rc = nfs4_recovery_init(); if (rc) { LogCrit(COMPONENT_INIT, "Recovery backend initialization failed!"); goto fatal_die; } /* Start grace period */ nfs_start_grace(NULL); /* Wait for enforcement to begin */ nfs_wait_for_grace_enforcement(); /* Load export entries from parsed file * returns the number of export entries. */ rc = ReadExports(nfs_config_struct, &err_type); if (rc < 0) { LogCrit(COMPONENT_INIT, "Error while parsing export entries"); goto fatal_die; } if (rc == 0 && dsc == 0) LogWarn(COMPONENT_INIT, "No export entries found in configuration file !!!"); report_config_errors(&err_type, NULL, config_errs_to_log); /* freeing syntax tree : */ config_Free(nfs_config_struct); /* Everything seems to be OK! We can now start service threads */ nfs_start(&my_nfs_start_info); return 0; fatal_die: report_config_errors(&err_type, NULL, config_errs_to_log); LogFatal(COMPONENT_INIT, "Fatal errors. Server exiting..."); /* NOT REACHED */ return 2; }
int ganefuse_main(int argc, char *argv[], const struct ganefuse_operations *op, void *user_data) { char *tempo_exec_name = NULL; char localmachine[MAXHOSTNAMELEN]; int c; pid_t son_pid; int argc_local = argc; char **argv_local = argv; /* local copy for keeping it read only */ ops = *op; /* retrieve executable file's name */ strncpy(ganesha_exec_path, argv[0], MAXPATHLEN); if((tempo_exec_name = strrchr(argv_local[0], '/')) != NULL) strcpy((char *)exec_name, tempo_exec_name + 1); if(*exec_name == '\0') strcpy((char *)exec_name, argv_local[0]); /* get host name */ if(gethostname(localmachine, sizeof(localmachine)) != 0) { fprintf(stderr, "Could not get local host name, exiting..."); exit(1); } else strncpy(host_name, localmachine, MAXHOSTNAMELEN); /* now parsing options with getopt */ while((c = getopt(argc_local, argv_local, options)) != EOF) { switch (c) { case '@': /* A litlle backdoor to keep track of binary versions */ printf("%s compiled on %s at %s\n", exec_name, __DATE__, __TIME__); printf("Release = %s\n", VERSION); printf("Release comment = %s\n", VERSION_COMMENT); exit(0); break; case 'L': /* Default Log */ strncpy(log_path, optarg, MAXPATHLEN); break; case 'N': /* debug level */ debug_level = ReturnLevelAscii(optarg); if(debug_level == -1) { fprintf(stderr, "Invalid value for option 'N': NIV_NULL, NIV_MAJ, NIV_CRIT, NIV_EVENT, NIV_DEBUG, NIV_MID_DEBUG or NIV_FULL_DEBUG expected.\n"); exit(1); } break; case 'f': /* config file */ strncpy(config_path, optarg, MAXPATHLEN); break; case 's': /* single threaded */ single_threaded = TRUE; break; case 'd': /* Detach or not detach ? */ detach_flag = TRUE; break; case 'R': /* Shall we manage RPCSEC_GSS ? */ fprintf(stderr, "\n\nThe -R flag is deprecated, use this syntax in the configuration file instead:\n\n"); fprintf(stderr, "NFS_KRB5\n"); fprintf(stderr, "{\n"); fprintf(stderr, "\tPrincipalName = nfs@<your_host> ;\n"); fprintf(stderr, "\tKeytabPath = /etc/krb5.keytab ;\n"); fprintf(stderr, "\tActive_krb5 = TRUE ;\n"); fprintf(stderr, "}\n\n\n"); exit(1); break; case 'F': /* Flushes the data cache to the FSAL and purges the cache */ nfs_start_info.flush_datacache_mode = TRUE; nfs_start_info.flush_behaviour = CACHE_CONTENT_FLUSH_AND_DELETE; nfs_start_info.nb_flush_threads = (unsigned int)atoi(optarg); if(nfs_start_info.nb_flush_threads > NB_MAX_FLUSHER_THREAD) nfs_start_info.nb_flush_threads = NB_MAX_FLUSHER_THREAD; break; case 'S': /* Flushes the data cache to the FSAL, without purging the cache */ nfs_start_info.flush_datacache_mode = TRUE; nfs_start_info.flush_behaviour = CACHE_CONTENT_FLUSH_SYNC_ONLY; nfs_start_info.nb_flush_threads = (unsigned int)atoi(optarg); if(nfs_start_info.nb_flush_threads > NB_MAX_FLUSHER_THREAD) nfs_start_info.nb_flush_threads = NB_MAX_FLUSHER_THREAD; break; case 'h': /* display the help */ fprintf(stderr, usage, exec_name); exit(0); break; case '?': default: /* ignore unsupported options */ fprintf(stderr, "WARNING: unknown GANESHA NFS daemon option: %c\n", (char)optopt); } } /* initialize memory and logging */ nfs_prereq_init(exec_name, host_name, debug_level, log_path); /* Start in background, if wanted */ if(detach_flag) { /* Step 1: forking a service process */ switch (son_pid = fork()) { case -1: /* Fork failed */ LogError(COMPONENT_MAIN, ERR_SYS, ERR_FORK, errno); LogCrit(COMPONENT_MAIN, "Could nout start nfs daemon, exiting..."); exit(1); case 0: /* This code is within the son (that will actually work) * Let's make it the leader of its group of process */ if(setsid() == -1) { LogError(COMPONENT_MAIN, ERR_SYS, ERR_SETSID, errno); LogCrit(COMPONENT_MAIN, "Could nout start nfs daemon, exiting..."); exit(1); } break; default: /* This code is within the father, it is useless, it must die */ LogFullDebug(COMPONENT_MAIN, "Starting a son of pid %d\n", son_pid); exit(0); break; } } /* Get the FSAL functions */ FSAL_LoadFunctions(); /* Get the FSAL consts */ FSAL_LoadConsts(); LogEvent(COMPONENT_MAIN, ">>>>>>>>>> Starting GANESHA NFS Daemon on FSAL/%s <<<<<<<<<<", FSAL_GetFSName()); /* initialize default parameters */ nfs_set_param_default(); /* return all errors */ nfs_param.core_param.drop_io_errors = FALSE; nfs_param.core_param.drop_inval_errors = FALSE; nfs_param.core_param.drop_delay_errors = FALSE; /* parse configuration file (if specified) */ if(strlen(config_path) > 0) { if(nfs_set_param_from_conf(&nfs_start_info)) { LogCrit(COMPONENT_MAIN, "NFS MAIN: Error parsing configuration file."); exit(1); } } /* set filesystem relative info */ ((fusefs_specific_initinfo_t *) &nfs_param.fsal_param.fs_specific_info)->fs_ops = &ops; ((fusefs_specific_initinfo_t *) &nfs_param.fsal_param.fs_specific_info)->user_data = user_data; #ifdef _SNMP_ADM_ACTIVE if(!nfs_param.extern_param.snmp_adm.snmp_log_file[0]) strcpy(nfs_param.extern_param.snmp_adm.snmp_log_file, log_path); #endif /* add export by hand if no export was defined * in config file (always '/') */ if(!nfs_param.pexportlist) { nfs_param.pexportlist = BuildDefaultExport(); if(nfs_param.pexportlist == NULL) { LogCrit(COMPONENT_MAIN, "NFS MAIN: Could not create export entry for '/'"); exit(1); } } /* if this is a single threaded application, set worker count */ if(single_threaded) nfs_param.core_param.nb_worker = 1; /* check parameters consitency */ if(nfs_check_param_consistency()) { LogMajor(COMPONENT_MAIN, "NFS MAIN: Inconsistent parameters found"); LogMajor(COMPONENT_MAIN, "MAJOR WARNING: /!\\ | Bad Parameters could have significant impact on the daemon behavior"); exit(1); } /* Everything seems to be OK! We can now start service threads */ nfs_start(&nfs_start_info); return 0; }