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/include/posix/utils.h b/include/posix/utils.h index 8cecf557..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" { @@ -25,6 +26,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/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/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)); +} diff --git a/unistd/file.c b/unistd/file.c index 98caa6f5..a845de27 100644 --- a/unistd/file.c +++ b/unistd/file.c @@ -628,6 +628,118 @@ 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, *tpathalloc = NULL; + const char *tpath = path; + + if (path == NULL) { + return -EINVAL; + } + + while (lookup("devfs", NULL, &odev) < 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) { + /* 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); + } + } + + 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);