/** * @file utils/nfsref/add.c * @brief Add junction metadata to a local file system object */ /* * Copyright 2011, 2018 Oracle. All rights reserved. * * This file is part of nfs-utils. * * nfs-utils is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2.0 as * published by the Free Software Foundation. * * nfs-utils is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License version 2.0 for more details. * * You should have received a copy of the GNU General Public License * version 2.0 along with nfs-utils. If not, see: * * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt */ #include #include #include #include #include #include #include #include #include #include #include "junction.h" #include "xlog.h" #include "nfsref.h" /** * Default cache expiration for FSN information */ #define FSN_DEFAULT_TTL (300) /** * Display help message for "add" subcommand * * @param progname NUL-terminated C string containing name of program * @return program exit status */ int nfsref_add_help(const char *progname) { fprintf(stderr, " \n"); fprintf(stderr, "Usage: %s [ -t type ] add " " [ ... ]\n\n", progname); fprintf(stderr, "Add a new junction containing the specified list " "of fileset locations.\n"); fprintf(stderr, " is the filename of the new junction. " " is the hostname\n"); fprintf(stderr, "or IP address of an NFS server where the fileset is " "located. is the\n"); fprintf(stderr, "export pathname of the fileset on that server.\n\n"); fprintf(stderr, "For NFS basic junctions, the location list is stored " "locally in the junction.\n"); fprintf(stderr, "For FedFS junctions, the location list is stored " "as new FSN and FSL records\n"); fprintf(stderr, "on an NSDB.\n"); return EXIT_SUCCESS; } /** * Fill in default settings for NFSv4.0 fs_locations4 * * @param new NFS location structure to fill in * * See section 5.1.3.2 of the NSDB protocol draft. */ static void nfsref_add_fsloc_defaults(struct nfs_fsloc *new) { new->nfl_hostport = 0; new->nfl_flags.nfl_varsub = false; new->nfl_currency = -1; new->nfl_validfor = 0; new->nfl_genflags.nfl_writable = false; new->nfl_genflags.nfl_going = false; new->nfl_genflags.nfl_split = true; new->nfl_transflags.nfl_rdma = true; new->nfl_info.nfl_simul = 0; new->nfl_info.nfl_handle = 0; new->nfl_info.nfl_fileid = 0; new->nfl_info.nfl_writever = 0; new->nfl_info.nfl_change = 0; new->nfl_info.nfl_readdir = 0; new->nfl_info.nfl_readrank = 0; new->nfl_info.nfl_readorder = 0; new->nfl_info.nfl_writerank = 0; new->nfl_info.nfl_writeorder = 0; } /** * Convert a pair of command line arguments to one nfs_fsloc structure * * @param server NUL-terminated C string containing file server hostname * @param rootpath NUL-terminated C string containing POSIX-style export path * @param fsloc OUT: NFS location structure * @return a FedFsStatus code * * If nfsref_add_build_fsloc() returns FEDFS_OK, caller must free the * returned fsloc with nfs_free_location(). */ static FedFsStatus nfsref_add_build_fsloc(const char *server, const char *rootpath, struct nfs_fsloc **fsloc) { struct nfs_fsloc *new; FedFsStatus retval; if (server == NULL || rootpath == NULL) return FEDFS_ERR_INVAL; xlog(D_GENERAL, "%s: Building fsloc for %s:%s", __func__, server, rootpath); new = nfs_new_location(); if (new == NULL) { xlog(D_GENERAL, "%s: No memory", __func__); return FEDFS_ERR_SVRFAULT; } new->nfl_hostname = strdup(server); if (new->nfl_hostname == NULL) { nfs_free_location(new); xlog(D_GENERAL, "%s: No memory", __func__); return FEDFS_ERR_SVRFAULT; } retval = nsdb_posix_to_path_array(rootpath, &new->nfl_rootpath); if (retval != FEDFS_OK) { nfs_free_location(new); return retval; } nfsref_add_fsloc_defaults(new); *fsloc = new; return FEDFS_OK; } /** * Convert array of command line arguments to list of nfs_fsloc structures * * @param argv array of pointers to NUL-terminated C strings contains arguments * @param optind index of "argv" where "add" subcommand arguments start * @param fslocs OUT: list of NFS locations * @return a FedFsStatus code * * If nfsref_add_build_fsloc_list() returns FEDFS_OK, caller must free the * returned list of fslocs with nfs_free_locations(). */ static FedFsStatus nfsref_add_build_fsloc_list(char **argv, int optind, struct nfs_fsloc **fslocs) { struct nfs_fsloc *fsloc, *result = NULL; FedFsStatus retval; int i; for (i = optind + 2; argv[i] != NULL; i += 2) { retval = nfsref_add_build_fsloc(argv[i], argv[i + 1], &fsloc); if (retval != FEDFS_OK) { nfs_free_locations(result); return retval; } if (result == NULL) result = fsloc; else result->nfl_next = fsloc; } if (result == NULL) return FEDFS_ERR_INVAL; *fslocs = result; return FEDFS_OK; } /** * Add NFS locations to a junction * * @param junct_path NUL-terminated C string containing pathname of junction * @param argv array of pointers to NUL-terminated C strings contains arguments * @param optind index of "argv" where "add" subcommand arguments start * @return program exit status */ static int nfsref_add_nfs_basic(const char *junct_path, char **argv, int optind) { struct nfs_fsloc *fslocs = NULL; FedFsStatus retval; xlog(D_GENERAL, "%s: Adding basic junction to %s", __func__, junct_path); retval = nfsref_add_build_fsloc_list(argv, optind, &fslocs); switch (retval) { case FEDFS_OK: break; case FEDFS_ERR_INVAL: xlog(L_ERROR, "Missing arguments"); return EXIT_FAILURE; case FEDFS_ERR_SVRFAULT: xlog(L_ERROR, "No memory"); return EXIT_FAILURE; default: xlog(L_ERROR, "Failed to add NFS location metadata to %s: %s", junct_path, nsdb_display_fedfsstatus(retval)); return EXIT_FAILURE; } retval = nfs_add_junction(junct_path, fslocs); nfs_free_locations(fslocs); switch (retval) { case FEDFS_OK: break; case FEDFS_ERR_EXIST: xlog(L_ERROR, "%s already contains junction metadata", junct_path); return EXIT_FAILURE; default: xlog(L_ERROR, "Failed to add NFS location metadata to %s: %s", junct_path, nsdb_display_fedfsstatus(retval)); return EXIT_FAILURE; } printf("Created junction %s\n", junct_path); return EXIT_SUCCESS; } /** * Add locations to a junction * * @param type type of junction to add * @param junct_path NUL-terminated C string containing pathname of junction * @param argv array of pointers to NUL-terminated C strings contains arguments * @param optind index of "argv" where "add" subcommand arguments start * @return program exit status */ int nfsref_add(enum nfsref_type type, const char *junct_path, char **argv, int optind) { if (mkdir(junct_path, 0755) == -1) if (errno != EEXIST) { xlog(L_ERROR, "Failed to create junction object: %m"); return EXIT_FAILURE; } switch (type) { case NFSREF_TYPE_UNSPECIFIED: case NFSREF_TYPE_NFS_BASIC: return nfsref_add_nfs_basic(junct_path, argv, optind); default: xlog(L_ERROR, "Unrecognized junction type"); } return EXIT_FAILURE; }