From 0ff9fe20a45f5e21d0f828669388f4866db786d9 Mon Sep 17 00:00:00 2001 From: julianuziemblo Date: Mon, 16 Mar 2026 17:31:12 +0100 Subject: [PATCH 1/4] unistd/file: add destroy_dev() destroy_dev() is a counterpart to create_dev() that allows for device removal without sending messages back to the calling port unlike remove()/unlink() functions YT: RTOS-1254 --- include/posix/utils.h | 3 ++ unistd/file.c | 93 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/include/posix/utils.h b/include/posix/utils.h index 8cecf557..f3188c66 100644 --- a/include/posix/utils.h +++ b/include/posix/utils.h @@ -25,6 +25,9 @@ extern "C" { extern int create_dev(oid_t *oid, const char *path); +extern int destroy_dev(const char *path); + + extern void splitname(char *path, char **base, char **dir); diff --git a/unistd/file.c b/unistd/file.c index 98caa6f5..3dd3d119 100644 --- a/unistd/file.c +++ b/unistd/file.c @@ -628,6 +628,99 @@ int create_dev(oid_t *oid, const char *path) } +int destroy_dev(const char *path) +{ + static int nodevfs = 0; + + oid_t oid, odev; + int retry = 0, err; + char *canonical_path, *dir, *sep; + + if (path == NULL) { + return -EINVAL; + } + + while (lookup("devfs", NULL, &odev) < 0) { + if (++retry < 3 || nodevfs != 0) { + if (lookup("/dev", NULL, &odev) < 0) { + return -ENOSYS; + } + else { + break; + } + } + + usleep(100000); + } + + if (strncmp("/dev/", path, 5) == 0) { + canonical_path = strdup(path); + } + else { + size_t len = 5 + strlen(path) + 1; + canonical_path = malloc(len); + snprintf(canonical_path, len, "/dev/%s", path); + } + + if (lookup(canonical_path, NULL, &oid) < 0) { + return -ENODEV; + } + + dir = canonical_path + 5; + + for (;;) { + sep = strchr(dir, '/'); + if (sep == NULL) { + break; + } + *sep = '\0'; + + msg_t msg; + msg.type = mtLookup; + msg.oid = odev; + msg.i.size = strlen(dir) + 1; + msg.i.data = dir; + + err = msgSend(odev.port, &msg); + if (err < 0) { + free(canonical_path); + return err; + } + + if (msg.o.err >= 0) { + odev = msg.o.lookup.dev; + } + else { + free(canonical_path); + return msg.o.err; + } + + do { + sep++; + } while (*sep == '/'); + dir = sep; + } + + path = dir; + + msg_t msg; + msg.type = mtUnlink, + msg.oid = odev, + msg.i.ln.oid = oid, + msg.i.data = path, + msg.i.size = strlen(path) + 1, + + err = msgSend(odev.port, &msg); + if (err < 0) { + return err; + } + + free(canonical_path); + + return msg.o.err; +} + + extern int sys_fcntl(int fd, int cmd, unsigned val); From 776f1b1df5fe9950f008f6ebc1ada10e64a87936 Mon Sep 17 00:00:00 2001 From: julianuziemblo Date: Mon, 16 Mar 2026 17:32:13 +0100 Subject: [PATCH 2/4] unistd: add portUnregister syscall to help with destroy_dev() error path To make destroy_dev() resemble create_dev(), a fallback was added to unregister the port in the case we don't have a filesystem. YT: RTOS-1254 --- include/sys/msg.h | 2 ++ unistd/file.c | 35 +++++++++++++++++++++++++++-------- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/include/sys/msg.h b/include/sys/msg.h index 1b4c3a71..006f1051 100644 --- a/include/sys/msg.h +++ b/include/sys/msg.h @@ -35,6 +35,8 @@ extern void portDestroy(uint32_t port); extern int portRegister(uint32_t port, const char *name, oid_t *oid); +extern int portUnregister(const char *name); + extern int lookup(const char *name, oid_t *file, oid_t *dev); diff --git a/unistd/file.c b/unistd/file.c index 3dd3d119..a845de27 100644 --- a/unistd/file.c +++ b/unistd/file.c @@ -634,23 +634,42 @@ int destroy_dev(const char *path) oid_t oid, odev; int retry = 0, err; - char *canonical_path, *dir, *sep; + char *canonical_path, *dir, *sep, *tpathalloc = NULL; + const char *tpath = path; if (path == NULL) { return -EINVAL; } while (lookup("devfs", NULL, &odev) < 0) { - if (++retry < 3 || nodevfs != 0) { + /* if remove_dev() is called by anyone started from syspage devfs + * may be not registered yet so we try 3 times until we give up */ + if (++retry > 3 || nodevfs != 0) { + nodevfs = 1; + if (lookup("/dev", NULL, &odev) < 0) { - return -ENOSYS; - } - else { - break; + /* Looks like we don't have a filesystem. + * Fall back to portUnregister. */ + if (*path != '/') { + /* Move point to /dev */ + tpathalloc = malloc(strlen(path) + 6); + if (tpathalloc == NULL) { + return -ENOMEM; + } + strcpy(tpathalloc, "/dev/"); + strcat(tpathalloc, path); + tpath = tpathalloc; + } + + err = portUnregister(tpath); + free(tpathalloc); + return err; } + break; + } + else { + usleep(100000); } - - usleep(100000); } if (strncmp("/dev/", path, 5) == 0) { From 0de023ba31bc0326a456dbe2c310c26b4dc9e9b3 Mon Sep 17 00:00:00 2001 From: julianuziemblo Date: Tue, 17 Mar 2026 11:37:17 +0100 Subject: [PATCH 3/4] !sys/msg: pass string len for sys_portRegister and sys_portUnregister syscalls YT: RTOS-1254 --- common/util.h | 27 +++++++++++++++++++++++++++ sys/Makefile | 2 +- sys/msg.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 common/util.h create mode 100644 sys/msg.c diff --git a/common/util.h b/common/util.h new file mode 100644 index 00000000..6ba63ace --- /dev/null +++ b/common/util.h @@ -0,0 +1,27 @@ +/* + * Phoenix-RTOS + * + * libphoenix + * + * Common libphoenix utilities + * + * Copyright 2026 Phoenix Systems + * Author: Julian Uziembło + * + * %LICENSE% + */ + +#ifndef _LIBPHOENIX_COMMON_UTIL_H_ +#define _LIBPHOENIX_COMMON_UTIL_H_ + +#include +#include + + +static inline size_t __strlenNull(const char *str) +{ + return (str == NULL) ? 0 : strlen(str); +} + + +#endif /* _LIBPHOENIX_COMMON_UTIL_H_ */ diff --git a/sys/Makefile b/sys/Makefile index b6a38f89..6ab64656 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -5,4 +5,4 @@ # OBJS += $(addprefix $(PREFIX_O)sys/, events.o ioctl.o list.o mount.o rb.o resource.o select.o \ -semaphore.o socket.o stat.o statvfs.o threads.o time.o times.o wait.o uio.o proto.o mman.o uname.o perf.o) +semaphore.o socket.o stat.o statvfs.o threads.o time.o times.o wait.o uio.o proto.o mman.o uname.o perf.o msg.o) diff --git a/sys/msg.c b/sys/msg.c new file mode 100644 index 00000000..5833dbf2 --- /dev/null +++ b/sys/msg.c @@ -0,0 +1,31 @@ +/* + * Phoenix-RTOS + * + * libphoenix + * + * sys/msg + * + * Copyright 2026 Phoenix Systems + * Author: Julian Uziembło + * + * %LICENSE% + */ + +#include "../common/util.h" + + +extern int sys_portRegister(uint32_t port, const char *name, size_t len, oid_t *oid); + +extern int sys_portUnregister(const char *name, size_t len); + + +int portRegister(uint32_t port, const char *name, oid_t *oid) +{ + return sys_portRegister(port, name, __strlenNull(name), oid); +} + + +int portUnregister(const char *name) +{ + return sys_portUnregister(name, __strlenNull(name)); +} From 2b7f7e95ac549608a718783877f5be8407efd920 Mon Sep 17 00:00:00 2001 From: julianuziemblo Date: Thu, 19 Mar 2026 14:14:34 +0100 Subject: [PATCH 4/4] posix/utils: include sys/types.h for oid_t type YT: RTOS-1254 --- include/posix/utils.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/posix/utils.h b/include/posix/utils.h index f3188c66..b825cfa6 100644 --- a/include/posix/utils.h +++ b/include/posix/utils.h @@ -16,6 +16,7 @@ #ifndef _LIBPHOENIX_POSIX_UTILS_H_ #define _LIBPHOENIX_POSIX_UTILS_H_ +#include #ifdef __cplusplus extern "C" {