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 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 main(int argc, char *argv[]) { int c; int exportid = 0; char buffer[CMD_BUFFER_SIZE]; char str[2 * CMD_BUFFER_SIZE]; fhandle2 filehandle_v2; struct nfs_fh3 filehandle_v3; nfs_fh4 filehandle_v4; int flag_i = FALSE; char exec_name[MAXPATHLEN]; char *tempo_exec_name = NULL; cache_inode_fsal_data_t fsal_data; fsal_op_context_t fsal_op_context; fsal_export_context_t fsal_export_context; exportlist_t *pexportlist = NULL; exportlist_t *pexport = NULL; nfs_start_info_t nfs_start_info; fsal_status_t fsal_status; unsigned int nfs_version = 3; path_str_t fsal_path_lib[NB_AVAILABLE_FSAL]; #ifdef _USE_SHARED_FSAL int lentab = NB_AVAILABLE_FSAL ; #endif short cache_content_hash; char entry_path[MAXPATHLEN]; int i, nb_char; fsal_path_t export_path = FSAL_PATH_INITIALIZER; unsigned int cookie; fsal_xattrent_t xattr_array[256]; unsigned int nb_returned; int eol; char attr_buffer[4096]; size_t sz_returned; fsal_u64_t objid; char options[] = "h@f:v:i:"; char usage[] = "%s [-h][-f <cfg_path>] {-v 2|3|4 <NFS_FileHandle> | -i <inum>}\n" " -h : prints this help\n" " -f <config_file> : sets the ganesha configuration file to be used\n" " -v <nfs_version> : sets the NFS version the file handle passed as argument\n" " -i <inum> : get datacache path for the given inode number (decimal)\n"; ServerBootTime = time(NULL); SetDefaultLogging("STDERR"); /* What is the executable file's name */ if((tempo_exec_name = strrchr(argv[0], '/')) != NULL) strcpy((char *)exec_name, tempo_exec_name + 1); strncpy(config_path, DEFAULT_CONFIG_FILE, MAXPATHLEN); /* now parsing options with getopt */ while((c = getopt(argc, argv, options)) != EOF) { switch (c) { case '@': printf("%s compiled on %s at %s\n", exec_name, __DATE__, __TIME__); exit(0); break; case 'h': printf(usage, exec_name); exit(0); break; case 'f': strncpy(config_path, optarg, MAXPATHLEN); break; case 'i': if(sscanf(optarg, "%llu", &objid) != 1) { fprintf(stderr, "Invalid object_id %s (base-10 integer expected)\n", optarg); exit(1); } flag_i = TRUE; break; case 'v': nfs_version = atoi(optarg); if((nfs_version < 2) || (nfs_version > 4)) { fprintf(stderr, "Invalid nfs version %u\n", nfs_version); exit(1); } break; case '?': printf("Unknown option: %c\n", optopt); printf(usage, exec_name); exit(1); } } if(!flag_i && (optind != argc - 1)) { printf("Missing argument: <NFS_FileHandle>\n"); printf(usage, exec_name); exit(1); } /* initialize memory and logging */ nfs_prereq_init("convert_fh", "localhost", NIV_MAJ, "/dev/tty"); #ifdef _USE_SHARED_FSAL if(nfs_get_fsalpathlib_conf(config_path, fsal_path_lib, &lentab)) { fprintf(stderr, "NFS MAIN: Error parsing configuration file."); exit(1); } #endif /* _USE_SHARED_FSAL */ /* Load the FSAL library (if needed) */ if(!FSAL_LoadLibrary((char *)fsal_path_lib)) /** @todo: this part of the code and this utility has to be checked */ { fprintf(stderr, "NFS MAIN: Could not load FSAL dynamic library %s", (char *)fsal_path_lib[0]); exit(1); } /* Get the FSAL functions */ FSAL_LoadFunctions(); /* Get the FSAL consts */ FSAL_LoadConsts(); /* initialize default parameters */ nfs_set_param_default(); /* parse configuration file */ if(nfs_set_param_from_conf(&nfs_start_info)) { fprintf(stderr, "Error parsing configuration file '%s'", config_path); exit(1); } /* check parameters consitency */ if(nfs_check_param_consistency()) { fprintf(stderr, "Inconsistent parameters found"); exit(1); } if(!nfs_param.pexportlist) { fprintf(stderr, "No export entries found in configuration file !!!\n"); return -1; } pexportlist = nfs_param.pexportlist; /* not initialization is needed for converting fileid to path in datacache */ if(!flag_i) { #ifdef _USE_SHARED_FSAL fsal_status = FSAL_Init(&nfs_param.fsal_param[0]); #else fsal_status = FSAL_Init(&nfs_param.fsal_param); #endif if(FSAL_IS_ERROR(fsal_status)) { /* Failed init */ fprintf(stderr, "FSAL library could not be initialized, major=%d minor=%d\n", fsal_status.major, fsal_status.minor); exit(1); } strncpy(str, argv[optind], 2 * CMD_BUFFER_SIZE); switch (nfs_version) { case 2: if(sscanmem(filehandle_v2, sizeof(file_handle_v2_t), (char *)str) == -1) { fprintf(stderr, "Bad FH as input (expected size: %lu bytes)\n", (unsigned long)sizeof(file_handle_v2_t)); exit(1); } exportid = nfs2_FhandleToExportId(&filehandle_v2); break; case 3: if(sscanmem(buffer, sizeof(file_handle_v3_t), (char *)str) == -1) { fprintf(stderr, "Bad FH as input (expected size: %lu bytes)\n", (unsigned long)sizeof(file_handle_v3_t)); exit(1); } filehandle_v3.data.data_val = (char *)buffer; filehandle_v3.data.data_len = sizeof(file_handle_v3_t); exportid = nfs3_FhandleToExportId(&filehandle_v3); break; case 4: if(sscanmem(buffer, sizeof(file_handle_v4_t), (char *)str) == -1) { fprintf(stderr, "Bad FH as input (expected size: %lu bytes)\n", (unsigned long)sizeof(file_handle_v4_t)); exit(1); } filehandle_v4.nfs_fh4_val = (char *)buffer; filehandle_v4.nfs_fh4_len = sizeof(file_handle_v4_t); exportid = nfs4_FhandleToExportId(&filehandle_v4); break; } if((pexport = nfs_Get_export_by_id(pexportlist, exportid)) == NULL) { fprintf(stderr, "NFS FH has exportid %u which is invalid....\n", exportid); exit(1); } /* INITIALIZING A CLIENT CONTEXT FOR FSAL */ FSAL_str2path(pexport->fullpath, MAXPATHLEN, &export_path); if(FSAL_IS_ERROR (fsal_status = FSAL_BuildExportContext(&fsal_export_context, &export_path, pexport->FS_specific))) { fprintf(stderr, "Error in FSAL_BuildExportContext, major=%u, minor=%u\n", fsal_status.major, fsal_status.minor); exit(1); } fsal_status = FSAL_InitClientContext(&fsal_op_context); if(FSAL_IS_ERROR(fsal_status)) { /* Failed init */ fprintf(stderr, "Could not init client context... major=%d minor=%d\n", fsal_status.major, fsal_status.minor); exit(1); } fsal_status = FSAL_GetClientContext(&fsal_op_context, &fsal_export_context, 0, 0, NULL, 0); if(FSAL_IS_ERROR(fsal_status)) { /* Failed init */ fprintf(stderr, "Could not get cred for uid=%d gid=%d, major=%d minor=%d\n", getuid(), getgid(), fsal_status.major, fsal_status.minor); exit(1); } /* now, can use the fsal_op_context */ switch (nfs_version) { case 2: if(!nfs2_FhandleToFSAL(&filehandle_v2, &fsal_data.handle, &fsal_op_context)) { fprintf(stderr, "Cannot convert Fhandle to FSAL\n"); exit(1); } break; case 3: if(!nfs3_FhandleToFSAL(&filehandle_v3, &fsal_data.handle, &fsal_op_context)) { fprintf(stderr, "Cannot convert Fhandle to FSAL\n"); exit(1); } break; case 4: if(!nfs4_FhandleToFSAL(&filehandle_v4, &fsal_data.handle, &fsal_op_context)) { fprintf(stderr, "Cannot convert Fhandle to FSAL\n"); exit(1); } break; } printf("\n"); snprintmem((caddr_t) str, 2 * CMD_BUFFER_SIZE, (caddr_t) & fsal_data.handle, sizeof(fsal_data.handle)); printf("%-18s = %s\n", "FSAL Handle", str); /* Now, list FSAL extended attributes */ cookie = XATTRS_READLIST_FROM_BEGINNING; eol = FALSE; while(!eol) { unsigned int index; fsal_status = FSAL_ListXAttrs(&fsal_data.handle, cookie, &fsal_op_context, xattr_array, 256, &nb_returned, &eol); if(FSAL_IS_ERROR(fsal_status)) { fprintf(stderr, "Error executing FSAL_ListXAttrs\n"); exit(1); } /* list attributes and get their value */ for(index = 0; index < nb_returned; index++) { cookie = xattr_array[index].xattr_cookie; printf("%-18s = ", xattr_array[index].xattr_name.name); fsal_status = FSAL_GetXAttrValueByName(&fsal_data.handle, &xattr_array[index].xattr_name, &fsal_op_context, attr_buffer, 4096, &sz_returned); if(FSAL_IS_ERROR(fsal_status)) { fprintf(stderr, "Error executing FSAL_GetXAttrValueByName\n"); } /* Display it */ print_buffer(attr_buffer, sz_returned); } } /* get object ID */ fsal_status = FSAL_DigestHandle(&fsal_export_context, FSAL_DIGEST_FILEID4, &fsal_data.handle, (caddr_t) & objid); if(FSAL_IS_ERROR(fsal_status)) { fprintf(stderr, "Error retrieving fileid from handle\n"); } else { printf("%-18s = %llu\n", "FileId", objid); } } /* end of retrieval of objid */ /* build the path in the datacache */ cache_content_hash = HashFileID4(objid); /* for limiting the number of entries into each datacache directory * we create 256 subdirectories on 2 levels, depending on the entry's fileid. */ nb_char = snprintf(entry_path, MAXPATHLEN, "export_id=%d", 0); for(i = 0; i <= 8; i += 8) { /* concatenation of hashval */ nb_char += snprintf((char *)(entry_path + nb_char), MAXPATHLEN - nb_char, "/%02hhX", (char)((cache_content_hash >> i) & 0xFF)); } /* displays the node name */ printf("%-18s = %s/%s/node=%llx*\n", "DataCache path", nfs_param.cache_layers_param.cache_content_client_param.cache_dir, entry_path, objid); exit(0); }
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; }