diff --git a/src/add-ons/kernel/file_systems/ramfs/Jamfile b/src/add-ons/kernel/file_systems/ramfs/Jamfile index 6ff1044467..41cd5a2e37 100644 --- a/src/add-ons/kernel/file_systems/ramfs/Jamfile +++ b/src/add-ons/kernel/file_systems/ramfs/Jamfile @@ -30,6 +30,7 @@ KernelAddon ramfs NodeListener.cpp NodeTable.cpp Query.cpp + SpecialNode.cpp SizeIndex.cpp SymLink.cpp Volume.cpp diff --git a/src/add-ons/kernel/file_systems/ramfs/Node.cpp b/src/add-ons/kernel/file_systems/ramfs/Node.cpp index 2d1ce1748a..5b756af02c 100644 --- a/src/add-ons/kernel/file_systems/ramfs/Node.cpp +++ b/src/add-ons/kernel/file_systems/ramfs/Node.cpp @@ -15,20 +15,21 @@ Node::Node(Volume *volume, uint8 type) - : fVolume(volume), - fID(fVolume->NextNodeID()), - fRefCount(0), - fMode(0), - fUID(0), - fGID(0), - fATime(0), - fMTime(0), - fCTime(0), - fCrTime(0), - fModified(0), - fIsKnownToVFS(false), - fAttributes(), - fReferrers() + : + fVolume(volume), + fID(fVolume->NextNodeID()), + fRefCount(0), + fMode(0), + fUID(0), + fGID(0), + fATime(0), + fMTime(0), + fCTime(0), + fCrTime(0), + fModified(0), + fIsKnownToVFS(false), + fAttributes(), + fReferrers() { // set file type switch (type) { diff --git a/src/add-ons/kernel/file_systems/ramfs/Node.h b/src/add-ons/kernel/file_systems/ramfs/Node.h index a1b966275e..327774f4b6 100644 --- a/src/add-ons/kernel/file_systems/ramfs/Node.h +++ b/src/add-ons/kernel/file_systems/ramfs/Node.h @@ -22,6 +22,7 @@ enum { NODE_TYPE_DIRECTORY, NODE_TYPE_FILE, NODE_TYPE_SYMLINK, + NODE_TYPE_SPECIAL, }; // access modes @@ -115,6 +116,8 @@ private: Volume *fVolume; ino_t fID; int32 fRefCount; + +protected: mode_t fMode; uid_t fUID; uid_t fGID; diff --git a/src/add-ons/kernel/file_systems/ramfs/SpecialNode.cpp b/src/add-ons/kernel/file_systems/ramfs/SpecialNode.cpp new file mode 100644 index 0000000000..3361514f16 --- /dev/null +++ b/src/add-ons/kernel/file_systems/ramfs/SpecialNode.cpp @@ -0,0 +1,35 @@ +/* + * Copyright 2025, Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT license. + */ + +#include "SpecialNode.h" + +#include "Volume.h" + + +SpecialNode::SpecialNode(Volume *volume, mode_t mode) + : + Node(volume, NODE_TYPE_SPECIAL) +{ + fMode = mode; +} + + +SpecialNode::~SpecialNode() +{ +} + + +status_t +SpecialNode::SetSize(off_t newSize) +{ + return B_UNSUPPORTED; +} + + +off_t +SpecialNode::GetSize() const +{ + return 0; +} diff --git a/src/add-ons/kernel/file_systems/ramfs/SpecialNode.h b/src/add-ons/kernel/file_systems/ramfs/SpecialNode.h new file mode 100644 index 0000000000..61369e2bb5 --- /dev/null +++ b/src/add-ons/kernel/file_systems/ramfs/SpecialNode.h @@ -0,0 +1,22 @@ +/* + * Copyright 2025, Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT license. + */ +#ifndef SPECIAL_NODE_H +#define SPECIAL_NODE_H + + +#include "Node.h" + + +class SpecialNode : public Node { +public: + SpecialNode(Volume *volume, mode_t mode); + virtual ~SpecialNode(); + + virtual status_t SetSize(off_t newSize); + virtual off_t GetSize() const; +}; + + +#endif // SPECIAL_NODE_H diff --git a/src/add-ons/kernel/file_systems/ramfs/kernel_interface.cpp b/src/add-ons/kernel/file_systems/ramfs/kernel_interface.cpp index a36ec43402..454207fda9 100644 --- a/src/add-ons/kernel/file_systems/ramfs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/ramfs/kernel_interface.cpp @@ -58,6 +58,7 @@ #include "Node.h" #include "Query.h" #include "ramfs_ioctl.h" +#include "SpecialNode.h" #include "SymLink.h" #include "Volume.h" @@ -876,6 +877,71 @@ ramfs_create(fs_volume* _volume, fs_vnode* _dir, const char *name, int openMode, } +static status_t +ramfs_create_special_node(fs_volume *_volume, fs_vnode *_dir, const char *name, + fs_vnode *subVnode, mode_t mode, uint32 flags, fs_vnode *_superVnode, + ino_t *vnid) +{ + FUNCTION(("name: `%s', mode: %x\n", name, mode)); + Volume* volume = (Volume*)_volume->private_volume; + Directory* dir = dynamic_cast((Node*)_dir->private_node); + + if (name == NULL || subVnode != NULL) + RETURN_ERROR(B_UNSUPPORTED); + if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) + RETURN_ERROR(B_FILE_EXISTS); + + VolumeWriteLocker locker(volume); + if (!locker.IsLocked()) + RETURN_ERROR(B_ERROR); + + NodeMTimeUpdater mTimeUpdater(dir); + status_t error = B_OK; + + // directory deleted? + bool removed; + if (get_vnode_removed(volume->FSVolume(), dir->GetID(), &removed) + != B_OK || removed) { + SET_ERROR(error, B_NOT_ALLOWED); + } + + Node *existingNode = NULL; + if (dir->FindNode(name, &existingNode) == B_OK) + RETURN_ERROR(B_FILE_EXISTS); + + error = dir->CheckPermissions(ACCESS_W); + if (error != B_OK) + RETURN_ERROR(error); + + SpecialNode* node = new(std::nothrow) SpecialNode(volume, mode); + if (node == NULL) + RETURN_ERROR(B_NO_MEMORY); + + *vnid = node->GetID(); + + node->SetUID(geteuid()); + node->SetGID(getegid()); + + Entry* entry; + error = node->InitCheck(); + if (error == B_OK) { + // add node to directory + error = dir->CreateEntry(node, name, &entry); + } + if (error != B_OK) { + delete node; + RETURN_ERROR(error); + } + + NodeMTimeUpdater mTimeUpdater2(node); + + // notify listeners + notify_entry_created(volume->GetID(), dir->GetID(), name, *vnid); + + return B_OK; +} + + static status_t ramfs_open(fs_volume* _volume, fs_vnode* _node, int openMode, void** _cookie) { @@ -2248,7 +2314,7 @@ fs_vnode_ops gRamFSVnodeOps = { &ramfs_remove_attr, /* special nodes */ - NULL // create_special_node + &ramfs_create_special_node, }; static file_system_module_info sRamFSModuleInfo = {