This is an automated email from the ASF dual-hosted git repository.
xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git
The following commit(s) were added to refs/heads/master by this push:
new ecfc1b5b6 nshlib: add chmod and chown builtins
ecfc1b5b6 is described below
commit ecfc1b5b61ad505aeb0f75a399ed2738d200c459
Author: Abhishek Mishra <[email protected]>
AuthorDate: Wed May 13 21:40:51 2026 +0000
nshlib: add chmod and chown builtins
Add minimal chmod/chown support to NSH using the
existing libc/VFS syscall interfaces.
Supported forms:
- chmod <octal-mode> <path>
- chown <uid>[:gid] <path>
The chown implementation supports the numeric
ownership forms already handled by the underlying
NuttX chown() implementation, including unchanged
uid/gid semantics via omitted fields.
Only numeric permission modes and numeric uid/gid
forms are supported in this initial implementation.
This adds interactive filesystem permission and
ownership management support to NSH and aligns the
shell more closely with standard POSIX environments.
Signed-off-by: Abhishek Mishra <[email protected]>
---
nshlib/Kconfig | 10 +++++
nshlib/nsh.h | 6 +++
nshlib/nsh_command.c | 8 ++++
nshlib/nsh_fscmds.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 147 insertions(+)
diff --git a/nshlib/Kconfig b/nshlib/Kconfig
index 1fc34cb21..2d1570b87 100644
--- a/nshlib/Kconfig
+++ b/nshlib/Kconfig
@@ -341,6 +341,16 @@ config NSH_DISABLE_CD
bool "Disable cd"
default DEFAULT_SMALL
+config NSH_DISABLE_CHMOD
+ bool "Disable chmod"
+ default DEFAULT_SMALL
+ depends on FS_PERMISSION
+
+config NSH_DISABLE_CHOWN
+ bool "Disable chown"
+ default DEFAULT_SMALL
+ depends on FS_PERMISSION
+
config NSH_DISABLE_CP
bool "Disable cp"
default DEFAULT_SMALL
diff --git a/nshlib/nsh.h b/nshlib/nsh.h
index 2fb3cf867..7abb7c38f 100644
--- a/nshlib/nsh.h
+++ b/nshlib/nsh.h
@@ -963,6 +963,12 @@ int cmd_irqinfo(FAR struct nsh_vtbl_s *vtbl, int argc, FAR
char **argv);
#ifndef CONFIG_NSH_DISABLE_CAT
int cmd_cat(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv);
#endif
+#if defined(CONFIG_FS_PERMISSION) && !defined(CONFIG_NSH_DISABLE_CHMOD)
+ int cmd_chmod(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv);
+#endif
+#if defined(CONFIG_FS_PERMISSION) && !defined(CONFIG_NSH_DISABLE_CHOWN)
+ int cmd_chown(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv);
+#endif
#ifndef CONFIG_NSH_DISABLE_CP
int cmd_cp(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv);
#endif
diff --git a/nshlib/nsh_command.c b/nshlib/nsh_command.c
index ec3f8a385..23534fbe5 100644
--- a/nshlib/nsh_command.c
+++ b/nshlib/nsh_command.c
@@ -168,6 +168,14 @@ static const struct cmdmap_s g_cmdmap[] =
CMD_MAP("cd", cmd_cd, 1, 2, "[<dir-path>|-|~|..]"),
#endif
+#if defined(CONFIG_FS_PERMISSION) && !defined(CONFIG_NSH_DISABLE_CHMOD)
+ CMD_MAP("chmod", cmd_chmod, 3, 3, "<octal-mode> <path>"),
+#endif
+
+#if defined(CONFIG_FS_PERMISSION) && !defined(CONFIG_NSH_DISABLE_CHOWN)
+ CMD_MAP("chown", cmd_chown, 3, 3, "[<uid>][:<gid>] <path>"),
+#endif
+
#ifndef CONFIG_NSH_DISABLE_CP
CMD_MAP("cp", cmd_cp, 3, 4, "[-r] <source-path> <dest-path>"),
#endif
diff --git a/nshlib/nsh_fscmds.c b/nshlib/nsh_fscmds.c
index a88c1a20d..13daa8258 100644
--- a/nshlib/nsh_fscmds.c
+++ b/nshlib/nsh_fscmds.c
@@ -843,6 +843,129 @@ int cmd_cat(FAR struct nsh_vtbl_s *vtbl, int argc, FAR
char **argv)
}
#endif
+/****************************************************************************
+ * Name: cmd_chmod
+ *
+ * Description:
+ * chmod <octal-mode> <path>
+ *
+ * Only numeric (octal) modes are supported.
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_FS_PERMISSION) && !defined(CONFIG_NSH_DISABLE_CHMOD)
+int cmd_chmod(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv)
+{
+ FAR char *fullpath;
+ FAR char *endptr;
+ long mode;
+ int ret = ERROR;
+
+ UNUSED(argc);
+
+ mode = strtol(argv[1], &endptr, 8);
+ if (endptr == argv[1] || *endptr != '\0' || mode < 0 || mode > 0777)
+ {
+ nsh_error(vtbl, g_fmtarginvalid, argv[0]);
+ return ERROR;
+ }
+
+ fullpath = nsh_getfullpath(vtbl, argv[2]);
+ if (fullpath != NULL)
+ {
+ ret = chmod(fullpath, (mode_t)mode);
+ if (ret < 0)
+ {
+ nsh_error(vtbl, g_fmtcmdfailed, argv[0], "chmod", NSH_ERRNO);
+ }
+
+ nsh_freefullpath(fullpath);
+ }
+
+ return ret;
+}
+#endif
+
+/****************************************************************************
+ * Name: cmd_chown
+ *
+ * Description:
+ * chown <uid>[:<gid>] <path>
+ * chown [<uid>]:<gid> <path>
+ *
+ * Only numeric uid/gid forms are supported. Empty uid or gid fields
+ * leave that side unchanged.
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_FS_PERMISSION) && !defined(CONFIG_NSH_DISABLE_CHOWN)
+int cmd_chown(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv)
+{
+ FAR const char *spec = argv[1];
+ FAR char *endptr;
+ FAR char *fullpath;
+ long value;
+ uid_t uid = (uid_t)-1;
+ gid_t gid = (gid_t)-1;
+ int ret = ERROR;
+
+ UNUSED(argc);
+
+ value = strtol(spec, &endptr, 10);
+ if (endptr != spec)
+ {
+ if (value < 0)
+ {
+ nsh_error(vtbl, g_fmtarginvalid, argv[0]);
+ return ERROR;
+ }
+
+ uid = (uid_t)value;
+ }
+
+ if (*endptr == ':')
+ {
+ FAR const char *gidstr = endptr + 1;
+ if (*gidstr != '\0')
+ {
+ value = strtol(gidstr, &endptr, 10);
+ if (*endptr != '\0' || value < 0)
+ {
+ nsh_error(vtbl, g_fmtarginvalid, argv[0]);
+ return ERROR;
+ }
+
+ gid = (gid_t)value;
+ }
+ }
+ else if (*endptr != '\0')
+ {
+ nsh_error(vtbl, g_fmtarginvalid, argv[0]);
+ return ERROR;
+ }
+
+ if (uid == (uid_t)-1 && gid == (gid_t)-1)
+ {
+ nsh_error(vtbl, g_fmtarginvalid, argv[0]);
+ return ERROR;
+ }
+
+ fullpath = nsh_getfullpath(vtbl, argv[2]);
+ if (fullpath != NULL)
+ {
+ ret = lchown(fullpath, uid, gid);
+ if (ret < 0)
+ {
+ nsh_error(vtbl, g_fmtcmdfailed, argv[0], "chown", NSH_ERRNO);
+ }
+
+ nsh_freefullpath(fullpath);
+ }
+
+ return ret;
+}
+#endif
+
/****************************************************************************
* Name: cmd_dmesg
****************************************************************************/