From 483263c7b0cd3922b93be2cf9dad5eeccbb9fedb Mon Sep 17 00:00:00 2001 From: Paul Donald Date: Sun, 9 Nov 2025 16:11:46 +0100 Subject: [PATCH] file: append "target" for symbolic links When list encounters a symbolic link, we add its nested "target" entry, to where the symbolic link points. Just how `ls -l` reports. So when calling e.g.: ubus call file list '{"path":"/etc"}' instead of: ... "name": "os-release", "type": "symlink", "size": 21, "mode": 41471, "atime": 1760891865, "mtime": 1760891865, "ctime": 1760891865, "inode": 266, "uid": 0, "gid": 0, "target_type": "file" ... We get: ... "name": "os-release", "type": "symlink", "size": 21, "mode": 41471, "atime": 1760891865, "mtime": 1760891865, "ctime": 1760891865, "inode": 266, "uid": 0, "gid": 0, "target": { "name": "../usr/lib/os-release", "type": "file", "size": 582, "mode": 33188, "atime": 1760891865, "mtime": 1760891865, "ctime": 1760891865, "inode": 1744, "uid": 0, "gid": 0 } ... And should a link be broken: "name": "foo", "type": "symlink", "size": 8, "mode": 41471, "atime": 1762640365, "mtime": 1762640365, "ctime": 1762640365, "inode": 348, "uid": 0, "gid": 0, "target": { "name": "/tmp/foo", "type": "broken" } Tested on: OpenWrt 24.10.4 r28959-29397011cc Signed-off-by: Paul Donald Tested-by: Eric Fahlgren Link: https://github.com/openwrt/rpcd/pull/21 Signed-off-by: Robert Marko --- file.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/file.c b/file.c index dc9c88a..89ba6b4 100644 --- a/file.c +++ b/file.c @@ -537,12 +537,26 @@ rpc_file_list(struct ubus_context *ctx, struct ubus_object *obj, // add target type only for symlinks if (S_ISLNK(s.st_mode)) { + char tbuf[PATH_MAX + 1]; + ssize_t tlen; + void *t; + + // open nested table "target" for symbolic link + t = blobmsg_open_table(&buf, "target"); + + tlen = readlink(entrypath, tbuf, sizeof(tbuf) - 1); + if (tlen >= 0) { + tbuf[tlen] = '\0'; + } + blobmsg_add_string(&buf, "name", tbuf); + struct stat target; if (!stat(entrypath, &target)) { - blobmsg_add_string(&buf, "target_type", d_types[_get_stat_type(&target)]); + _rpc_file_add_stat(&target); } else { - blobmsg_add_string(&buf, "target_type", "broken"); + blobmsg_add_string(&buf, "type", "broken"); } + blobmsg_close_table(&buf, t); } blobmsg_close_table(&buf, d); } -- 2.30.2