diff --git a/fs/procfs/procfs_vnops.cc b/fs/procfs/procfs_vnops.cc index a03dd59172..2267654f30 100644 --- a/fs/procfs/procfs_vnops.cc +++ b/fs/procfs/procfs_vnops.cc @@ -7,6 +7,7 @@ #include +#include #include #include #include @@ -144,6 +145,17 @@ static std::string procfs_hostname() return std::string(hostname); } +static std::string procfs_exe() +{ + auto app = sched::thread::current_app(); + + if (app && app->lib()) { + return app->lib()->pathname(); + } else { + return ""; + } +} + static int procfs_mount(mount* mp, const char *dev, int flags, const void* data) { @@ -154,6 +166,9 @@ procfs_mount(mount* mp, const char *dev, int flags, const void* data) self->add("stat", inode_count++, procfs_stats); self->add("status", inode_count++, procfs_status); + auto exe = make_shared(inode_count++, procfs_exe); + self->add("exe", exe); + auto kernel = make_shared(inode_count++); kernel->add("hostname", inode_count++, procfs_hostname); @@ -216,7 +231,7 @@ vnops procfs_vnops = { (vnop_link_t) vop_eperm, // vop_link (vnop_cache_t) nullptr, // vop_arc (vnop_fallocate_t) vop_nullop, // vop_fallocate - (vnop_readlink_t) vop_nullop, // vop_readlink + pseudofs::readlink, // vop_readlink (vnop_symlink_t) vop_nullop, // vop_symlink }; diff --git a/fs/pseudofs/pseudofs.cc b/fs/pseudofs/pseudofs.cc index 91ed3e32fc..e9922b8c92 100644 --- a/fs/pseudofs/pseudofs.cc +++ b/fs/pseudofs/pseudofs.cc @@ -27,6 +27,12 @@ static pseudo_file_node *to_file_node(vnode *vp) { return dynamic_cast(np); } +static pseudo_symlink_node *to_symlink_node(vnode *vp) { + auto *np = to_node(vp); + + return dynamic_cast(np); +} + int open(file *fp) { auto *np = to_file_node(fp->f_dentry->d_vnode); if (np) { @@ -65,6 +71,18 @@ int read(vnode *vp, file *fp, uio *uio, int ioflags) { return uiomove(const_cast(data->data()) + uio->uio_offset, len, uio); } +int readlink(vnode *vp, uio *uio) { + if (vp->v_type != VLNK) + return EINVAL; + + auto *np = to_symlink_node(vp); + auto *target_path = np->target_path(); + if (uio->uio_offset >= (off_t) target_path->size()) + return 0; + + return uiomove(const_cast(target_path->data()) + uio->uio_offset, target_path->size(), uio); +} + int write(vnode *vp, uio *uio, int ioflags) { return EINVAL; } @@ -135,6 +153,8 @@ int readdir(vnode *vp, file *fp, dirent *dir) { auto np = dir_entry->second; if (np->type() == VDIR) { dir->d_type = DT_DIR; + } else if (np->type() == VLNK) { + dir->d_type = DT_LNK; } else { dir->d_type = DT_REG; } diff --git a/fs/pseudofs/pseudofs.hh b/fs/pseudofs/pseudofs.hh index d31da2df13..c9409417fa 100644 --- a/fs/pseudofs/pseudofs.hh +++ b/fs/pseudofs/pseudofs.hh @@ -62,6 +62,27 @@ private: function _gen; }; +class pseudo_symlink_node : public pseudo_node { +public: + pseudo_symlink_node(uint64_t ino, function gen) + : pseudo_node(ino, VLNK), _target_path_gen(gen) {} + + virtual off_t size() const override { + return 0; + } + + virtual mode_t mode() const override { + return S_IRUSR | S_IRGRP | S_IROTH; + } + + string *target_path() const { + return new string(_target_path_gen()); + } + +private: + function _target_path_gen; +}; + class pseudo_dir_node : public pseudo_node { public: pseudo_dir_node(uint64_t ino) : pseudo_node(ino, VDIR) {} @@ -112,6 +133,8 @@ int close(vnode *vp, file *fp); int read(vnode *vp, file *fp, uio *uio, int ioflags); +int readlink(vnode *vp, uio *uio); + int write(vnode *vp, uio *uio, int ioflags); int ioctl(vnode *vp, file *fp, u_long cmd, void *arg);