/**************************************************************************** * apps/nshlib/nsh_mntcmds.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. The * ASF licenses this file to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "nsh.h" #include "nsh_console.h" /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: cmd_df ****************************************************************************/ #if !defined(CONFIG_DISABLE_MOUNTPOINT) && !defined(CONFIG_NSH_DISABLE_DF) #ifdef NSH_HAVE_CATFILE int cmd_df(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv) { #if defined(HAVE_DF_HUMANREADBLE) && defined(HAVE_DF_BLOCKOUTPUT) if (argc > 1 && strcmp(argv[1], "-h") == 0) #endif #ifdef HAVE_DF_HUMANREADBLE { return nsh_catfile(vtbl, argv[0], CONFIG_NSH_PROC_MOUNTPOINT "/fs/usage"); } #endif #if defined(HAVE_DF_HUMANREADBLE) && defined(HAVE_DF_BLOCKOUTPUT) else #endif #ifdef HAVE_DF_BLOCKOUTPUT { return nsh_catfile(vtbl, argv[0], CONFIG_NSH_PROC_MOUNTPOINT "/fs/blocks"); } #endif } #endif #endif /**************************************************************************** * Name: cmd_mount ****************************************************************************/ #if !defined(CONFIG_DISABLE_MOUNTPOINT) && !defined(CONFIG_NSH_DISABLE_MOUNT) int cmd_mount(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv) { FAR const char *source; FAR char *fullsource; FAR const char *target; FAR char *fulltarget; FAR const char *filesystem = NULL; FAR const char *options = NULL; bool badarg = false; int option; int ret; /* The mount command behaves differently if no parameters are provided. */ #if defined(NSH_HAVE_CATFILE) && defined(HAVE_MOUNT_LIST) if (argc < 2) { return nsh_catfile(vtbl, argv[0], CONFIG_NSH_PROC_MOUNTPOINT "/fs/mount"); } #endif /* Get the mount options. NOTE: getopt() is not thread safe nor re- * entrant. To keep its state proper for the next usage, it is necessary * to parse to the end of the line even if an error occurs. If an error * occurs, this logic just sets 'badarg' and continues. */ while ((option = getopt(argc, argv, ":o:t:")) != ERROR) { switch (option) { case 't': filesystem = optarg; break; case 'o': options = optarg; break; case ':': nsh_error(vtbl, g_fmtargrequired, argv[0]); badarg = true; break; case '?': default: nsh_error(vtbl, g_fmtarginvalid, argv[0]); badarg = true; break; } } /* If a bad argument was encountered, then return without processing the * command. */ if (badarg) { return ERROR; } /* There may be one or two required arguments after the options: the source * and target paths. Some file systems do not require the source parameter * so if there is only one parameter left, it must be the target. */ if (optind >= argc) { nsh_error(vtbl, g_fmtargrequired, argv[0]); return ERROR; } source = NULL; target = argv[optind]; optind++; if (optind < argc) { source = target; target = argv[optind]; optind++; if (optind < argc) { nsh_error(vtbl, g_fmttoomanyargs, argv[0]); return ERROR; } } /* While the above parsing for the -t argument looks nice, the -t argument * not really optional. */ if (!filesystem) { nsh_error(vtbl, g_fmtargrequired, argv[0]); return ERROR; } /* The source and target paths might be relative to the current * working directory. */ fullsource = NULL; fulltarget = NULL; if (source) { fullsource = nsh_getfullpath(vtbl, source); if (!fullsource) { return ERROR; } } fulltarget = nsh_getfullpath(vtbl, target); if (!fulltarget) { ret = ERROR; goto errout; } /* Perform the mount */ ret = mount(fullsource, fulltarget, filesystem, 0, options); if (ret < 0) { nsh_error(vtbl, g_fmtcmdfailed, argv[0], "mount", NSH_ERRNO); } errout: if (fullsource) { nsh_freefullpath(fullsource); } if (fulltarget) { nsh_freefullpath(fulltarget); } return ret; } #endif /**************************************************************************** * Name: cmd_nfsmount ****************************************************************************/ #if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_NET) && \ defined(CONFIG_NFS) && !defined(CONFIG_NSH_DISABLE_NFSMOUNT) int cmd_nfsmount(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv) { struct nfs_args data; FAR char *address; FAR char *lpath; FAR char *rpath; int ret; /* The fist argument on the command line should be the NFS server IP * address in standard IPv4 (or IPv6) dot format. */ address = argv[1]; if (!address) { return ERROR; } /* Get the remote mount point path */ rpath = argv[3]; /* Place all of the NFS arguments into the nfs_args structure */ memset(&data, 0, sizeof(data)); /* Convert the IP address string into its binary form */ #ifdef CONFIG_LIBC_NETDB if (data.addrlen == 0) { FAR struct addrinfo *res; char serv[16]; itoa(NFS_PMAPPORT, serv, 10); ret = getaddrinfo(address, serv, NULL, &res); if (ret == OK) { data.addrlen = res->ai_addrlen; memcpy(&data.addr, res->ai_addr, res->ai_addrlen); freeaddrinfo(res); } } #endif #ifdef CONFIG_NET_IPv6 if (data.addrlen == 0) { FAR struct sockaddr_in6 *sin; sin = (FAR struct sockaddr_in6 *)&data.addr; ret = inet_pton(AF_INET6, address, &sin->sin6_addr); if (ret == 1) { sin->sin6_family = AF_INET6; sin->sin6_port = htons(NFS_PMAPPORT); data.addrlen = sizeof(struct sockaddr_in6); } } #endif #ifdef CONFIG_NET_IPv4 if (data.addrlen == 0) { FAR struct sockaddr_in *sin; sin = (FAR struct sockaddr_in *)&data.addr; ret = inet_pton(AF_INET, address, &sin->sin_addr); if (ret == 1) { sin->sin_family = AF_INET; sin->sin_port = htons(NFS_PMAPPORT); data.addrlen = sizeof(struct sockaddr_in); } } #endif if (data.addrlen == 0) { return ERROR; } if (argc > 4 && strcmp(argv[4], "udp") == 0) { data.sotype = SOCK_DGRAM; } else { data.sotype = SOCK_STREAM; } data.path = rpath; data.flags = 0; /* 0=Use all defaults */ /* The local mount point path (lpath) might be relative to the current * working directory. */ lpath = nsh_getfullpath(vtbl, argv[2]); if (!lpath) { return ERROR; } /* Perform the mount */ ret = mount(NULL, lpath, "nfs", 0, (FAR void *)&data); if (ret < 0) { nsh_error(vtbl, g_fmtcmdfailed, argv[0], "mount", NSH_ERRNO); } /* We no longer need the allocated mount point path */ nsh_freefullpath(lpath); return ret; } #endif /**************************************************************************** * Name: cmd_umount ****************************************************************************/ #if !defined(CONFIG_DISABLE_MOUNTPOINT) && !defined(CONFIG_NSH_DISABLE_UMOUNT) int cmd_umount(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv) { UNUSED(argc); FAR char *fullpath = nsh_getfullpath(vtbl, argv[1]); int ret = ERROR; if (fullpath) { /* Perform the umount */ ret = umount(fullpath); if (ret < 0) { nsh_error(vtbl, g_fmtcmdfailed, argv[0], "umount", NSH_ERRNO); } nsh_freefullpath(fullpath); } return ret; } #endif