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 0844df8091..a36ec43402 100644 --- a/src/add-ons/kernel/file_systems/ramfs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/ramfs/kernel_interface.cpp @@ -80,7 +80,6 @@ notify_if_stat_changed(Volume *volume, Node *node) // #pragma mark - FS -// ramfs_mount static status_t ramfs_mount(fs_volume* _volume, const char* /*device*/, uint32 flags, const char* /*args*/, ino_t* _rootID) @@ -113,7 +112,6 @@ ramfs_mount(fs_volume* _volume, const char* /*device*/, uint32 flags, } -// ramfs_unmount static status_t ramfs_unmount(fs_volume* _volume) { @@ -130,42 +128,44 @@ ramfs_unmount(fs_volume* _volume) } -// ramfs_read_fs_info static status_t ramfs_read_fs_info(fs_volume* _volume, struct fs_info *info) { FUNCTION_START(); Volume* volume = (Volume*)_volume->private_volume; - status_t error = B_OK; - if (VolumeReadLocker locker = volume) { - info->flags = B_FS_HAS_ATTR | B_FS_HAS_MIME | B_FS_HAS_QUERY - | B_FS_IS_REMOVABLE; - info->block_size = B_PAGE_SIZE; - info->io_size = kOptimalIOSize; - info->total_blocks = volume->CountBlocks(); - info->free_blocks = volume->CountFreeBlocks(); - info->device_name[0] = '\0'; - strlcpy(info->volume_name, volume->GetName(), - sizeof(info->volume_name)); - strcpy(info->fsh_name, "ramfs"); - } else - SET_ERROR(error, B_ERROR); - return error; + + VolumeReadLocker locker(volume); + if (!locker.IsLocked()) + RETURN_ERROR(B_ERROR); + + info->flags = B_FS_HAS_ATTR | B_FS_HAS_MIME | B_FS_HAS_QUERY + | B_FS_IS_REMOVABLE; + info->block_size = B_PAGE_SIZE; + info->io_size = kOptimalIOSize; + info->total_blocks = volume->CountBlocks(); + info->free_blocks = volume->CountFreeBlocks(); + info->device_name[0] = '\0'; + strlcpy(info->volume_name, volume->GetName(), + sizeof(info->volume_name)); + strcpy(info->fsh_name, "ramfs"); + return B_OK; } -// ramfs_write_fs_info static status_t ramfs_write_fs_info(fs_volume* _volume, const struct fs_info *info, uint32 mask) { FUNCTION_START(); Volume* volume = (Volume*)_volume->private_volume; + + VolumeWriteLocker locker(volume); + if (!locker.IsLocked()) + RETURN_ERROR(B_ERROR); + status_t error = B_OK; - if (VolumeWriteLocker locker = volume) { - if (mask & FS_WRITE_FSINFO_NAME) - error = volume->SetName(info->volume_name); - } else - SET_ERROR(error, B_ERROR); + if (mask & FS_WRITE_FSINFO_NAME) + error = volume->SetName(info->volume_name); + RETURN_ERROR(error); } @@ -182,7 +182,6 @@ ramfs_sync(fs_volume* /*fs*/) // #pragma mark - VNodes -// ramfs_lookup static status_t ramfs_lookup(fs_volume* _volume, fs_vnode* _dir, const char* entryName, ino_t* _vnodeID) @@ -195,65 +194,63 @@ ramfs_lookup(fs_volume* _volume, fs_vnode* _dir, const char* entryName, entryName)); // check for non-directories - if (!dir) + if (dir == NULL) RETURN_ERROR(B_NOT_A_DIRECTORY); + VolumeReadLocker locker(volume); + if (!locker.IsLocked()) + RETURN_ERROR(B_ERROR); + status_t error = B_OK; - if (VolumeReadLocker locker = volume) { - Node *node = NULL; + Node *node = NULL; - // special entries: "." and ".." - if (!strcmp(entryName, ".")) { - *_vnodeID = dir->GetID(); - if (volume->GetVNode(*_vnodeID, &node) != B_OK) - error = B_BAD_VALUE; - } else if (!strcmp(entryName, "..")) { - Directory *parent = dir->GetParent(); - if (parent && volume->GetVNode(parent->GetID(), &node) == B_OK) - *_vnodeID = node->GetID(); - else - error = B_BAD_VALUE; + // special entries: "." and ".." + if (!strcmp(entryName, ".")) { + *_vnodeID = dir->GetID(); + if (volume->GetVNode(*_vnodeID, &node) != B_OK) + error = B_BAD_VALUE; + } else if (!strcmp(entryName, "..")) { + Directory *parent = dir->GetParent(); + if (parent && volume->GetVNode(parent->GetID(), &node) == B_OK) + *_vnodeID = node->GetID(); + else + error = B_BAD_VALUE; - // ordinary entries - } else { - // find the entry - error = dir->FindAndGetNode(entryName, &node); -SET_ERROR(error, error); - if (error == B_OK) - *_vnodeID = node->GetID(); - } + // ordinary entries + } else { + // find the entry + error = dir->FindAndGetNode(entryName, &node); + if (error == B_OK) + *_vnodeID = node->GetID(); + } - } else - SET_ERROR(error, B_ERROR); RETURN_ERROR(error); } -// ramfs_get_vnode static status_t ramfs_get_vnode(fs_volume* _volume, ino_t vnid, fs_vnode* node, int* _type, uint32* _flags, bool reenter) { -// FUNCTION_START(); FUNCTION(("node: %lld\n", vnid)); Volume* volume = (Volume*)_volume->private_volume; Node *foundNode = NULL; - status_t error = B_OK; - if (VolumeReadLocker locker = volume) { - error = volume->FindNode(vnid, &foundNode); - if (error == B_OK) { - node->private_node = foundNode; - node->ops = &gRamFSVnodeOps; - *_type = foundNode->GetMode(); - *_flags = 0; - } - } else - SET_ERROR(error, B_ERROR); + + VolumeReadLocker locker(volume); + if (!locker.IsLocked()) + RETURN_ERROR(B_ERROR); + + status_t error = volume->FindNode(vnid, &foundNode); + if (error == B_OK) { + node->private_node = foundNode; + node->ops = &gRamFSVnodeOps; + *_type = foundNode->GetMode(); + *_flags = 0; + } RETURN_ERROR(error); } -// ramfs_write_vnode static status_t ramfs_write_vnode(fs_volume* /*fs*/, fs_vnode* DARG(_node), bool /*reenter*/) { @@ -269,7 +266,6 @@ ramfs_write_vnode(fs_volume* /*fs*/, fs_vnode* DARG(_node), bool /*reenter*/) } -// ramfs_remove_vnode static status_t ramfs_remove_vnode(fs_volume* _volume, fs_vnode* _node, bool /*reenter*/) { @@ -277,12 +273,13 @@ ramfs_remove_vnode(fs_volume* _volume, fs_vnode* _node, bool /*reenter*/) Volume* volume = (Volume*)_volume->private_volume; Node* node = (Node*)_node->private_node; + VolumeWriteLocker locker(volume); + if (!locker.IsLocked()) + RETURN_ERROR(B_ERROR); + status_t error = B_OK; - if (VolumeWriteLocker locker = volume) { - volume->NodeRemoved(node); - delete node; - } else - SET_ERROR(error, B_ERROR); + volume->NodeRemoved(node); + delete node; RETURN_ERROR(error); } @@ -290,7 +287,6 @@ ramfs_remove_vnode(fs_volume* _volume, fs_vnode* _node, bool /*reenter*/) // #pragma mark - Nodes -// ramfs_ioctl static status_t ramfs_ioctl(fs_volume* _volume, fs_vnode* /*node*/, void* /*cookie*/, uint32 cmd, void *buffer, size_t /*length*/) @@ -303,7 +299,8 @@ ramfs_ioctl(fs_volume* _volume, fs_vnode* /*node*/, void* /*cookie*/, case RAMFS_IOCTL_GET_ALLOCATION_INFO: { if (buffer) { - if (VolumeReadLocker locker = volume) { + VolumeReadLocker locker(volume); + if (!locker.IsLocked()) { AllocationInfo *info = (AllocationInfo*)buffer; volume->GetAllocationInfo(*info); } else @@ -315,7 +312,8 @@ ramfs_ioctl(fs_volume* _volume, fs_vnode* /*node*/, void* /*cookie*/, case RAMFS_IOCTL_DUMP_INDEX: { if (buffer) { - if (VolumeReadLocker locker = volume) { + VolumeReadLocker locker(volume); + if (!locker.IsLocked()) { const char *name = (const char*)buffer; PRINT(" RAMFS_IOCTL_DUMP_INDEX, `%s'\n", name); IndexDirectory *indexDir = volume->GetIndexDirectory(); @@ -340,7 +338,6 @@ PRINT(" RAMFS_IOCTL_DUMP_INDEX, `%s'\n", name); } -// ramfs_set_flags static status_t ramfs_set_flags(fs_volume* /*fs*/, fs_vnode* /*node*/, void* /*cookie*/, int /*flags*/) @@ -351,7 +348,6 @@ ramfs_set_flags(fs_volume* /*fs*/, fs_vnode* /*node*/, void* /*cookie*/, } -// ramfs_fsync static status_t ramfs_fsync(fs_volume* /*fs*/, fs_vnode* /*node*/) { @@ -360,7 +356,6 @@ ramfs_fsync(fs_volume* /*fs*/, fs_vnode* /*node*/) } -// ramfs_read_symlink static status_t ramfs_read_symlink(fs_volume* _volume, fs_vnode* _node, char *buffer, size_t *bufferSize) @@ -369,34 +364,34 @@ ramfs_read_symlink(fs_volume* _volume, fs_vnode* _node, char *buffer, Volume* volume = (Volume*)_volume->private_volume; Node* node = (Node*)_node->private_node; - status_t error = B_OK; - if (VolumeReadLocker locker = volume) { - // read symlinks only - if (!node->IsSymLink()) - error = B_BAD_VALUE; - if (error == B_OK) { - if (SymLink *symLink = dynamic_cast(node)) { - // copy the link contents - size_t toRead = min(*bufferSize, - symLink->GetLinkedPathLength()); - if (toRead > 0) - memcpy(buffer, symLink->GetLinkedPath(), - toRead); + VolumeReadLocker locker(volume); + if (!locker.IsLocked()) + RETURN_ERROR(B_ERROR); - *bufferSize = symLink->GetLinkedPathLength(); - } else { - FATAL("Node %" B_PRIdINO " pretends to be a SymLink, but isn't!\n", - node->GetID()); - error = B_BAD_VALUE; - } + status_t error = B_OK; + // read symlinks only + if (!node->IsSymLink()) + error = B_BAD_VALUE; + if (error == B_OK) { + if (SymLink *symLink = dynamic_cast(node)) { + // copy the link contents + size_t toRead = min(*bufferSize, + symLink->GetLinkedPathLength()); + if (toRead > 0) + memcpy(buffer, symLink->GetLinkedPath(), + toRead); + + *bufferSize = symLink->GetLinkedPathLength(); + } else { + FATAL("Node %" B_PRIdINO " pretends to be a SymLink, but isn't!\n", + node->GetID()); + error = B_BAD_VALUE; } - } else - SET_ERROR(error, B_ERROR); + } RETURN_ERROR(error); } -// ramfs_create_symlink static status_t ramfs_create_symlink(fs_volume* _volume, fs_vnode* _dir, const char *name, const char *path, int mode) @@ -405,56 +400,57 @@ ramfs_create_symlink(fs_volume* _volume, fs_vnode* _dir, const char *name, Volume* volume = (Volume*)_volume->private_volume; Directory* dir = dynamic_cast((Node*)_dir->private_node); + if (name == NULL || *name == '\0') + RETURN_ERROR(B_BAD_VALUE); + if (dir == NULL) + RETURN_ERROR(B_BAD_VALUE); + + VolumeWriteLocker locker(volume); + if (!locker.IsLocked()) + RETURN_ERROR(B_ERROR); + status_t error = B_OK; - // check name - if (!name || *name == '\0') { - SET_ERROR(error, B_BAD_VALUE); - // check directory - } else if (!dir) { - SET_ERROR(error, B_BAD_VALUE); - } else if (VolumeWriteLocker locker = volume) { - NodeMTimeUpdater mTimeUpdater(dir); - // directory deleted? - bool removed; - if (get_vnode_removed(volume->FSVolume(), dir->GetID(), &removed) + NodeMTimeUpdater mTimeUpdater(dir); + // directory deleted? + bool removed; + if (get_vnode_removed(volume->FSVolume(), dir->GetID(), &removed) != B_OK || removed) { - SET_ERROR(error, B_NOT_ALLOWED); - } - // check directory write permissions - error = dir->CheckPermissions(ACCESS_W); - Node *node = NULL; - if (error == B_OK) { - // check if entry does already exist - if (dir->FindNode(name, &node) == B_OK) { - SET_ERROR(error, B_FILE_EXISTS); - } else { - // entry doesn't exist: create a symlink - SymLink *symLink = NULL; - error = dir->CreateSymLink(name, path, &symLink); - if (error == B_OK) { - node = symLink; - // set permissions, owner and group - node->SetMode(mode); - node->SetUID(geteuid()); - node->SetGID(getegid()); - // put the node - volume->PutVNode(node); - } + SET_ERROR(error, B_NOT_ALLOWED); + } + + // check directory write permissions + error = dir->CheckPermissions(ACCESS_W); + Node *node = NULL; + if (error == B_OK) { + // check if entry does already exist + if (dir->FindNode(name, &node) == B_OK) { + SET_ERROR(error, B_FILE_EXISTS); + } else { + // entry doesn't exist: create a symlink + SymLink *symLink = NULL; + error = dir->CreateSymLink(name, path, &symLink); + if (error == B_OK) { + node = symLink; + // set permissions, owner and group + node->SetMode(mode); + node->SetUID(geteuid()); + node->SetGID(getegid()); + // put the node + volume->PutVNode(node); } } - NodeMTimeUpdater mTimeUpdater2(node); - // notify listeners - if (error == B_OK) { - notify_entry_created(volume->GetID(), dir->GetID(), name, - node->GetID()); - } - } else - SET_ERROR(error, B_ERROR); + } + NodeMTimeUpdater mTimeUpdater2(node); + // notify listeners + if (error == B_OK) { + notify_entry_created(volume->GetID(), dir->GetID(), name, + node->GetID()); + } + RETURN_ERROR(error); } -// ramfs_link static status_t ramfs_link(fs_volume* _volume, fs_vnode* _dir, const char *name, fs_vnode* _node) @@ -464,42 +460,43 @@ ramfs_link(fs_volume* _volume, fs_vnode* _dir, const char *name, Directory* dir = dynamic_cast((Node*)_dir->private_node); Node* node = (Node*)_node->private_node; + if (dir == NULL) + RETURN_ERROR(B_BAD_VALUE); + + VolumeWriteLocker locker(volume); + if (!locker.IsLocked()) + RETURN_ERROR(B_ERROR); + status_t error = B_OK; - // check directory - if (!dir) { - SET_ERROR(error, B_BAD_VALUE); - } else if (VolumeWriteLocker locker = volume) { - NodeMTimeUpdater mTimeUpdater(dir); - // directory deleted? - bool removed; - if (get_vnode_removed(volume->FSVolume(), dir->GetID(), &removed) + NodeMTimeUpdater mTimeUpdater(dir); + // directory deleted? + bool removed; + if (get_vnode_removed(volume->FSVolume(), dir->GetID(), &removed) != B_OK || removed) { - SET_ERROR(error, B_NOT_ALLOWED); + SET_ERROR(error, B_NOT_ALLOWED); + } + // check directory write permissions + error = dir->CheckPermissions(ACCESS_W); + Entry *entry = NULL; + if (error == B_OK) { + // check if entry does already exist + if (dir->FindEntry(name, &entry) == B_OK) { + SET_ERROR(error, B_FILE_EXISTS); + } else { + // entry doesn't exist: create a link + error = dir->CreateEntry(node, name); } - // check directory write permissions - error = dir->CheckPermissions(ACCESS_W); - Entry *entry = NULL; - if (error == B_OK) { - // check if entry does already exist - if (dir->FindEntry(name, &entry) == B_OK) { - SET_ERROR(error, B_FILE_EXISTS); - } else { - // entry doesn't exist: create a link - error = dir->CreateEntry(node, name); - } - } - // notify listeners - if (error == B_OK) { - notify_entry_created(volume->GetID(), dir->GetID(), name, - node->GetID()); - } - } else - SET_ERROR(error, B_ERROR); + } + // notify listeners + if (error == B_OK) { + notify_entry_created(volume->GetID(), dir->GetID(), name, + node->GetID()); + } + RETURN_ERROR(error); } -// ramfs_unlink static status_t ramfs_unlink(fs_volume* _volume, fs_vnode* _dir, const char *name) { @@ -508,43 +505,43 @@ ramfs_unlink(fs_volume* _volume, fs_vnode* _dir, const char *name) Directory* dir = dynamic_cast((Node*)_dir->private_node); status_t error = B_OK; - // check name - if (!name || *name == '\0' || !strcmp(name, ".") || !strcmp(name, "..")) { - SET_ERROR(error, B_BAD_VALUE); - // check node - } else if (!dir) { - SET_ERROR(error, B_BAD_VALUE); - } else if (VolumeWriteLocker locker = volume) { - NodeMTimeUpdater mTimeUpdater(dir); - // check directory write permissions - error = dir->CheckPermissions(ACCESS_W); - ino_t nodeID = -1; - if (error == B_OK) { - // check if entry exists - Node *node = NULL; - Entry *entry = NULL; - if (dir->FindAndGetNode(name, &node, &entry) == B_OK) { - nodeID = node->GetID(); - // unlink the entry, if it isn't a non-empty directory - if (node->IsDirectory() - && !dynamic_cast(node)->IsEmpty()) { - SET_ERROR(error, B_DIRECTORY_NOT_EMPTY); - } else - error = dir->DeleteEntry(entry); - volume->PutVNode(node); + if (name == NULL || *name == '\0' || strcmp(name, ".") == 0 || strcmp(name, "..") == 0) + RETURN_ERROR(B_BAD_VALUE); + if (dir == NULL) + RETURN_ERROR(B_BAD_VALUE); + + VolumeWriteLocker locker(volume); + if (!locker.IsLocked()) + RETURN_ERROR(B_ERROR); + + NodeMTimeUpdater mTimeUpdater(dir); + // check directory write permissions + error = dir->CheckPermissions(ACCESS_W); + ino_t nodeID = -1; + if (error == B_OK) { + // check if entry exists + Node *node = NULL; + Entry *entry = NULL; + if (dir->FindAndGetNode(name, &node, &entry) == B_OK) { + nodeID = node->GetID(); + // unlink the entry, if it isn't a non-empty directory + if (node->IsDirectory() + && !dynamic_cast(node)->IsEmpty()) { + SET_ERROR(error, B_DIRECTORY_NOT_EMPTY); } else - SET_ERROR(error, B_ENTRY_NOT_FOUND); - } - // notify listeners - if (error == B_OK) - notify_entry_removed(volume->GetID(), dir->GetID(), name, nodeID); - } else - SET_ERROR(error, B_ERROR); + error = dir->DeleteEntry(entry); + volume->PutVNode(node); + } else + SET_ERROR(error, B_ENTRY_NOT_FOUND); + } + // notify listeners + if (error == B_OK) + notify_entry_removed(volume->GetID(), dir->GetID(), name, nodeID); + RETURN_ERROR(error); } -// ramfs_rename static status_t ramfs_rename(fs_volume* _volume, fs_vnode* _oldDir, const char *oldName, fs_vnode* _newDir, const char *newName) @@ -553,115 +550,116 @@ ramfs_rename(fs_volume* _volume, fs_vnode* _oldDir, const char *oldName, Directory* oldDir = dynamic_cast((Node*)_oldDir->private_node); Directory* newDir = dynamic_cast((Node*)_newDir->private_node); + + FUNCTION(("old dir: %lld, old name: `%s', new dir: %lld, new name: `%s'\n", + oldDir->GetID(), oldName, newDir->GetID(), newName)); + + VolumeWriteLocker locker(volume); + if (!locker.IsLocked()) + RETURN_ERROR(B_ERROR); + status_t error = B_OK; - if (VolumeWriteLocker locker = volume) { -FUNCTION(("old dir: %lld, old name: `%s', new dir: %lld, new name: `%s'\n", -oldDir->GetID(), oldName, newDir->GetID(), newName)); - NodeMTimeUpdater mTimeUpdater1(oldDir); - NodeMTimeUpdater mTimeUpdater2(newDir); + NodeMTimeUpdater mTimeUpdater1(oldDir); + NodeMTimeUpdater mTimeUpdater2(newDir); - // target directory deleted? - bool removed; - if (get_vnode_removed(volume->FSVolume(), newDir->GetID(), &removed) - != B_OK || removed) { - SET_ERROR(error, B_NOT_ALLOWED); - } + // target directory deleted? + bool removed; + if (get_vnode_removed(volume->FSVolume(), newDir->GetID(), &removed) + != B_OK || removed) { + SET_ERROR(error, B_NOT_ALLOWED); + } - // check directory write permissions - if (error == B_OK) - error = oldDir->CheckPermissions(ACCESS_W); - if (error == B_OK) - error = newDir->CheckPermissions(ACCESS_W); + // check directory write permissions + if (error == B_OK) + error = oldDir->CheckPermissions(ACCESS_W); + if (error == B_OK) + error = newDir->CheckPermissions(ACCESS_W); - Node *node = NULL; - Entry *entry = NULL; - if (error == B_OK) { - // check if entry exists - if (oldDir->FindAndGetNode(oldName, &node, &entry) != B_OK) { - SET_ERROR(error, B_ENTRY_NOT_FOUND); - } else { - if (oldDir != newDir) { - // check whether the entry is a descendent of the target - // directory - for (Directory *parent = newDir; - parent; + Node *node = NULL; + Entry *entry = NULL; + if (error == B_OK) { + // check if entry exists + if (oldDir->FindAndGetNode(oldName, &node, &entry) != B_OK) { + SET_ERROR(error, B_ENTRY_NOT_FOUND); + } else { + if (oldDir != newDir) { + // check whether the entry is a descendent of the target + // directory + for (Directory *parent = newDir; parent != NULL; parent = parent->GetParent()) { - if (parent == node) { - error = B_BAD_VALUE; - break; - } else if (parent == oldDir) - break; - } + if (parent == node) { + error = B_BAD_VALUE; + break; + } else if (parent == oldDir) + break; } } - - // check the target directory situation - Node *clobberNode = NULL; - Entry *clobberEntry = NULL; - if (error == B_OK) { - if (newDir->FindAndGetNode(newName, &clobberNode, - &clobberEntry) == B_OK) { - if (clobberNode->IsDirectory() - && !dynamic_cast(clobberNode)->IsEmpty()) { - SET_ERROR(error, B_NAME_IN_USE); - } - } - } - - // do the job - if (error == B_OK) { - // temporarily acquire an additional reference to make - // sure the node isn't deleted when we remove the entry - error = node->AddReference(); - if (error == B_OK) { - // delete the original entry - error = oldDir->DeleteEntry(entry); - if (error == B_OK) { - // create the new one/relink the target entry - if (clobberEntry) - error = clobberEntry->Link(node); - else - error = newDir->CreateEntry(node, newName); - - if (error == B_OK) { - // send a "removed" notification for the clobbered - // entry - if (clobberEntry) { - notify_entry_removed(volume->GetID(), - newDir->GetID(), newName, - clobberNode->GetID()); - } - } else { - // try to recreate the original entry, in case of - // failure - newDir->CreateEntry(node, oldName); - } - } - node->RemoveReference(); - } - } - - // release the entries - if (clobberEntry) - volume->PutVNode(clobberNode); - if (entry) - volume->PutVNode(node); } - // notify listeners + // check the target directory situation + Node *clobberNode = NULL; + Entry *clobberEntry = NULL; if (error == B_OK) { - notify_entry_moved(volume->GetID(), oldDir->GetID(), oldName, - newDir->GetID(), newName, node->GetID()); + if (newDir->FindAndGetNode(newName, &clobberNode, + &clobberEntry) == B_OK) { + if (clobberNode->IsDirectory() + && !dynamic_cast(clobberNode)->IsEmpty()) { + SET_ERROR(error, B_NAME_IN_USE); + } + } } - } else - SET_ERROR(error, B_ERROR); + + // do the job + if (error == B_OK) { + // temporarily acquire an additional reference to make + // sure the node isn't deleted when we remove the entry + error = node->AddReference(); + if (error == B_OK) { + // delete the original entry + error = oldDir->DeleteEntry(entry); + if (error == B_OK) { + // create the new one/relink the target entry + if (clobberEntry) + error = clobberEntry->Link(node); + else + error = newDir->CreateEntry(node, newName); + + if (error == B_OK) { + // send a "removed" notification for the clobbered + // entry + if (clobberEntry) { + notify_entry_removed(volume->GetID(), + newDir->GetID(), newName, + clobberNode->GetID()); + } + } else { + // try to recreate the original entry, in case of + // failure + newDir->CreateEntry(node, oldName); + } + } + node->RemoveReference(); + } + } + + // release the entries + if (clobberEntry) + volume->PutVNode(clobberNode); + if (entry) + volume->PutVNode(node); + } + + // notify listeners + if (error == B_OK) { + notify_entry_moved(volume->GetID(), oldDir->GetID(), oldName, + newDir->GetID(), newName, node->GetID()); + } RETURN_ERROR(error); } -// ramfs_access static status_t ramfs_access(fs_volume* _volume, fs_vnode* _node, int mode) { @@ -669,16 +667,15 @@ ramfs_access(fs_volume* _volume, fs_vnode* _node, int mode) Volume* volume = (Volume*)_volume->private_volume; Node* node = (Node*)_node->private_node; - status_t error = B_OK; - if (VolumeReadLocker locker = volume) { - error = node->CheckPermissions(mode); - } else - SET_ERROR(error, B_ERROR); + VolumeReadLocker locker(volume); + if (!locker.IsLocked()) + RETURN_ERROR(B_ERROR); + + status_t error = node->CheckPermissions(mode); RETURN_ERROR(error); } -// ramfs_read_stat static status_t ramfs_read_stat(fs_volume* _volume, fs_vnode* _node, struct stat *st) { @@ -687,68 +684,73 @@ ramfs_read_stat(fs_volume* _volume, fs_vnode* _node, struct stat *st) Node* node = (Node*)_node->private_node; FUNCTION(("node: %lld\n", node->GetID())); - status_t error = B_OK; - if (VolumeReadLocker locker = volume) { - st->st_dev = volume->GetID(); - st->st_ino = node->GetID(); - st->st_mode = node->GetMode(); - st->st_nlink = node->GetRefCount(); - st->st_uid = node->GetUID(); - st->st_gid = node->GetGID(); - st->st_size = node->GetSize(); - st->st_blksize = kOptimalIOSize; - st->st_blocks = (st->st_size + st->st_blksize - 1) / st->st_blksize; - st->st_atime = node->GetATime(); - st->st_mtime = node->GetMTime(); - st->st_ctime = node->GetCTime(); - st->st_crtime = node->GetCrTime(); - } else - SET_ERROR(error, B_ERROR); - RETURN_ERROR(error); + + VolumeReadLocker locker(volume); + if (!locker.IsLocked()) + RETURN_ERROR(B_ERROR); + + st->st_dev = volume->GetID(); + st->st_ino = node->GetID(); + st->st_mode = node->GetMode(); + st->st_nlink = node->GetRefCount(); + st->st_uid = node->GetUID(); + st->st_gid = node->GetGID(); + st->st_size = node->GetSize(); + st->st_blksize = kOptimalIOSize; + st->st_blocks = (st->st_size + st->st_blksize - 1) / st->st_blksize; + st->st_atime = node->GetATime(); + st->st_mtime = node->GetMTime(); + st->st_ctime = node->GetCTime(); + st->st_crtime = node->GetCrTime(); + + RETURN_ERROR(B_OK); } -// ramfs_write_stat static status_t ramfs_write_stat(fs_volume* _volume, fs_vnode* _node, const struct stat *st, uint32 mask) { + FUNCTION(("mask: %lx\n", mask)); + Volume* volume = (Volume*)_volume->private_volume; Node* node = (Node*)_node->private_node; - FUNCTION(("mask: %lx\n", mask)); + VolumeWriteLocker locker(volume); + if (!locker.IsLocked()) + RETURN_ERROR(B_ERROR); + status_t error = B_OK; - if (VolumeWriteLocker locker = volume) { - NodeMTimeUpdater mTimeUpdater(node); - // check permissions - error = node->CheckPermissions(ACCESS_W); - // size - if (error == B_OK && (mask & B_STAT_SIZE)) - error = node->SetSize(st->st_size); - if (error == B_OK) { - // permissions - if (mask & B_STAT_MODE) { - node->SetMode((node->GetMode() & ~S_IUMSK) - | (st->st_mode & S_IUMSK)); - } - // UID - if (mask & B_STAT_UID) - node->SetUID(st->st_uid); - // GID - if (mask & B_STAT_GID) - node->SetGID(st->st_gid); - // mtime - if (mask & B_STAT_MODIFICATION_TIME) - node->SetMTime(st->st_mtime); - // crtime - if (mask & B_STAT_CREATION_TIME) - node->SetCrTime(st->st_crtime); + NodeMTimeUpdater mTimeUpdater(node); + // check permissions + error = node->CheckPermissions(ACCESS_W); + // size + if (error == B_OK && (mask & B_STAT_SIZE)) + error = node->SetSize(st->st_size); + if (error == B_OK) { + // permissions + if (mask & B_STAT_MODE) { + node->SetMode((node->GetMode() & ~S_IUMSK) + | (st->st_mode & S_IUMSK)); } - // notify listeners - if (error == B_OK) - notify_if_stat_changed(volume, node); - } else - SET_ERROR(error, B_ERROR); + // UID + if (mask & B_STAT_UID) + node->SetUID(st->st_uid); + // GID + if (mask & B_STAT_GID) + node->SetGID(st->st_gid); + // mtime + if (mask & B_STAT_MODIFICATION_TIME) + node->SetMTime(st->st_mtime); + // crtime + if (mask & B_STAT_CREATION_TIME) + node->SetCrTime(st->st_crtime); + } + + // notify listeners + if (error == B_OK) + notify_if_stat_changed(volume, node); + RETURN_ERROR(error); } @@ -756,7 +758,6 @@ ramfs_write_stat(fs_volume* _volume, fs_vnode* _node, const struct stat *st, // #pragma mark - Files -// FileCookie class FileCookie { public: FileCookie(int openMode) : fOpenMode(openMode), fLastNotificationTime(0) {} @@ -782,101 +783,99 @@ private: }; -// ramfs_create static status_t ramfs_create(fs_volume* _volume, fs_vnode* _dir, const char *name, int openMode, int mode, void** _cookie, ino_t *vnid) { -// FUNCTION_START(); FUNCTION(("name: `%s', open mode: %x, mode: %x\n", name, openMode, mode)); Volume* volume = (Volume*)_volume->private_volume; Directory* dir = dynamic_cast((Node*)_dir->private_node); - status_t error = B_OK; - // check name - if (!name || *name == '\0') { - SET_ERROR(error, B_BAD_VALUE); - // check directory - } else if (!dir) { - SET_ERROR(error, B_BAD_VALUE); - // check special names - } else if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { - SET_ERROR(error, B_FILE_EXISTS); - } else if (VolumeWriteLocker locker = volume) { - NodeMTimeUpdater mTimeUpdater(dir); - // directory deleted? - bool removed; - if (get_vnode_removed(volume->FSVolume(), dir->GetID(), &removed) - != B_OK || removed) { - SET_ERROR(error, B_NOT_ALLOWED); - } - // create the file cookie - FileCookie *cookie = NULL; - if (error == B_OK) { - cookie = new(nothrow) FileCookie(openMode); - if (!cookie) - SET_ERROR(error, B_NO_MEMORY); - } - Node *node = NULL; - if (error == B_OK) { - // check if entry does already exist - if (dir->FindNode(name, &node) == B_OK) { - // entry does already exist - // fail, if we shall fail, when the file exists - if (openMode & O_EXCL) { - SET_ERROR(error, B_FILE_EXISTS); - // don't create a file over an existing directory or symlink - } else if (!node->IsFile()) { - SET_ERROR(error, B_NOT_ALLOWED); - // the user must have write permission for an existing entry - } else if ((error = node->CheckPermissions(ACCESS_W)) == B_OK) { - // truncate, if requested - if (openMode & O_TRUNC) - error = node->SetSize(0); - // we ignore the supplied permissions in this case - // get vnode - if (error == B_OK) { - *vnid = node->GetID(); - error = volume->GetVNode(node->GetID(), &node); - } - } - // the user must have dir write permission to create a new entry - } else if ((error = dir->CheckPermissions(ACCESS_W)) == B_OK) { - // entry doesn't exist: create a file - File *file = NULL; - error = dir->CreateFile(name, &file); - if (error == B_OK) { - node = file; - *vnid = node->GetID(); - // set permissions, owner and group - node->SetMode(mode); - node->SetUID(geteuid()); - node->SetGID(getegid()); + if (name == NULL || *name == '\0') + RETURN_ERROR(B_BAD_VALUE); + if (dir == NULL) + RETURN_ERROR(B_BAD_VALUE); + if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) + RETURN_ERROR(B_FILE_EXISTS); - // set cache in vnode - struct vnode* vnode; - if (vfs_lookup_vnode(_volume->id, node->GetID(), &vnode) == B_OK) { - vfs_set_vnode_cache(vnode, file->GetCache(vnode)); - } + 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); + } + // create the file cookie + FileCookie *cookie = NULL; + if (error == B_OK) { + cookie = new(nothrow) FileCookie(openMode); + if (!cookie) + SET_ERROR(error, B_NO_MEMORY); + } + Node *node = NULL; + if (error == B_OK) { + // check if entry does already exist + if (dir->FindNode(name, &node) == B_OK) { + // entry does already exist + // fail, if we shall fail, when the file exists + if (openMode & O_EXCL) { + SET_ERROR(error, B_FILE_EXISTS); + // don't create a file over an existing directory or symlink + } else if (!node->IsFile()) { + SET_ERROR(error, B_NOT_ALLOWED); + // the user must have write permission for an existing entry + } else if ((error = node->CheckPermissions(ACCESS_W)) == B_OK) { + // truncate, if requested + if (openMode & O_TRUNC) + error = node->SetSize(0); + // we ignore the supplied permissions in this case + // get vnode + if (error == B_OK) { + *vnid = node->GetID(); + error = volume->GetVNode(node->GetID(), &node); + } + } + // the user must have dir write permission to create a new entry + } else if ((error = dir->CheckPermissions(ACCESS_W)) == B_OK) { + // entry doesn't exist: create a file + File *file = NULL; + error = dir->CreateFile(name, &file); + if (error == B_OK) { + node = file; + *vnid = node->GetID(); + // set permissions, owner and group + node->SetMode(mode); + node->SetUID(geteuid()); + node->SetGID(getegid()); + + // set cache in vnode + struct vnode* vnode; + if (vfs_lookup_vnode(_volume->id, node->GetID(), &vnode) == B_OK) { + vfs_set_vnode_cache(vnode, file->GetCache(vnode)); } } - // set result / cleanup on failure - if (error == B_OK) - *_cookie = cookie; - else if (cookie) - delete cookie; } - NodeMTimeUpdater mTimeUpdater2(node); - // notify listeners + // set result / cleanup on failure if (error == B_OK) - notify_entry_created(volume->GetID(), dir->GetID(), name, *vnid); - } else - SET_ERROR(error, B_ERROR); + *_cookie = cookie; + else if (cookie) + delete cookie; + } + NodeMTimeUpdater mTimeUpdater2(node); + // notify listeners + if (error == B_OK) + notify_entry_created(volume->GetID(), dir->GetID(), name, *vnid); + RETURN_ERROR(error); } -// ramfs_open static status_t ramfs_open(fs_volume* _volume, fs_vnode* _node, int openMode, void** _cookie) { @@ -885,44 +884,46 @@ ramfs_open(fs_volume* _volume, fs_vnode* _node, int openMode, void** _cookie) Node* node = (Node*)_node->private_node; FUNCTION(("node: %lld\n", node->GetID())); - status_t error = B_OK; - if (VolumeReadLocker locker = volume) { - // directory can be opened read-only - if (node->IsDirectory() && (openMode & O_RWMASK) != O_RDONLY) - error = B_IS_A_DIRECTORY; - if (error == B_OK && (openMode & O_DIRECTORY) != 0 && !node->IsDirectory()) - error = B_NOT_A_DIRECTORY; - int accessMode = open_mode_to_access(openMode); - // truncating requires write permission - if (error == B_OK && (openMode & O_TRUNC)) - accessMode |= ACCESS_W; - // check open mode against permissions - if (error == B_OK) - error = node->CheckPermissions(accessMode); - // create the cookie - FileCookie *cookie = NULL; - if (error == B_OK) { - cookie = new(nothrow) FileCookie(openMode); - if (!cookie) - SET_ERROR(error, B_NO_MEMORY); - } - // truncate if requested - if (error == B_OK && (openMode & O_TRUNC)) - error = node->SetSize(0); - NodeMTimeUpdater mTimeUpdater(node); - // set result / cleanup on failure - if (error == B_OK) - *_cookie = cookie; - else if (cookie) - delete cookie; - } else - SET_ERROR(error, B_ERROR); + VolumeReadLocker locker(volume); + if (!locker.IsLocked()) + RETURN_ERROR(B_ERROR); + + status_t error = B_OK; + // directory can be opened read-only + if (node->IsDirectory() && (openMode & O_RWMASK) != O_RDONLY) + error = B_IS_A_DIRECTORY; + if (error == B_OK && (openMode & O_DIRECTORY) != 0 && !node->IsDirectory()) + error = B_NOT_A_DIRECTORY; + + int accessMode = open_mode_to_access(openMode); + // truncating requires write permission + if (error == B_OK && (openMode & O_TRUNC)) + accessMode |= ACCESS_W; + // check open mode against permissions + if (error == B_OK) + error = node->CheckPermissions(accessMode); + // create the cookie + FileCookie *cookie = NULL; + if (error == B_OK) { + cookie = new(nothrow) FileCookie(openMode); + if (!cookie) + SET_ERROR(error, B_NO_MEMORY); + } + // truncate if requested + if (error == B_OK && (openMode & O_TRUNC)) + error = node->SetSize(0); + NodeMTimeUpdater mTimeUpdater(node); + // set result / cleanup on failure + if (error == B_OK) + *_cookie = cookie; + else if (cookie) + delete cookie; + RETURN_ERROR(error); } -// ramfs_close static status_t ramfs_close(fs_volume* _volume, fs_vnode* _node, void* /*cookie*/) { @@ -931,18 +932,19 @@ ramfs_close(fs_volume* _volume, fs_vnode* _node, void* /*cookie*/) Node* node = (Node*)_node->private_node; FUNCTION(("node: %lld\n", node->GetID())); + + VolumeReadLocker locker(volume); + if (!locker.IsLocked()) + RETURN_ERROR(B_ERROR); + status_t error = B_OK; // notify listeners - if (VolumeReadLocker locker = volume) { - notify_if_stat_changed(volume, node); - } else - SET_ERROR(error, B_ERROR); - return error; + notify_if_stat_changed(volume, node); + return error; } -// ramfs_free_cookie static status_t ramfs_free_cookie(fs_volume* /*fs*/, fs_vnode* /*_node*/, void* _cookie) { @@ -953,7 +955,6 @@ ramfs_free_cookie(fs_volume* /*fs*/, fs_vnode* /*_node*/, void* _cookie) } -// ramfs_read static status_t ramfs_read(fs_volume* _volume, fs_vnode* _node, void* _cookie, off_t pos, void *buffer, size_t *bufferSize) @@ -965,32 +966,36 @@ ramfs_read(fs_volume* _volume, fs_vnode* _node, void* _cookie, off_t pos, // FUNCTION(("((%lu, %lu), %lld, %p, %lu)\n", node->GetDirID(), // node->GetObjectID(), pos, buffer, *bufferSize)); + + VolumeReadLocker locker(volume); + if (!locker.IsLocked()) + RETURN_ERROR(B_ERROR); + status_t error = B_OK; - if (VolumeReadLocker locker = volume) { - // don't read anything but files - if (!node->IsFile()) - SET_ERROR(error, B_BAD_VALUE); - // check, if reading is allowed - int rwMode = cookie->GetOpenMode() & O_RWMASK; - if (error == B_OK && rwMode != O_RDONLY && rwMode != O_RDWR) - SET_ERROR(error, B_FILE_ERROR); - // read - if (error == B_OK) { - if (File *file = dynamic_cast(node)) - error = file->ReadAt(pos, buffer, *bufferSize, bufferSize); - else { - FATAL("Node %" B_PRIdINO " pretends to be a File, but isn't!\n", - node->GetID()); - error = B_BAD_VALUE; - } + // don't read anything but files + if (!node->IsFile()) + SET_ERROR(error, B_BAD_VALUE); + + // check, if reading is allowed + int rwMode = cookie->GetOpenMode() & O_RWMASK; + if (error == B_OK && rwMode != O_RDONLY && rwMode != O_RDWR) + SET_ERROR(error, B_FILE_ERROR); + + // read + if (error == B_OK) { + if (File *file = dynamic_cast(node)) { + error = file->ReadAt(pos, buffer, *bufferSize, bufferSize); + } else { + FATAL("Node %" B_PRIdINO " pretends to be a File, but isn't!\n", + node->GetID()); + error = B_BAD_VALUE; } - } else - SET_ERROR(error, B_ERROR); + } + RETURN_ERROR(error); } -// ramfs_write static status_t ramfs_write(fs_volume* _volume, fs_vnode* _node, void* _cookie, off_t pos, const void *buffer, size_t *bufferSize) @@ -1002,37 +1007,39 @@ ramfs_write(fs_volume* _volume, fs_vnode* _node, void* _cookie, off_t pos, FileCookie *cookie = (FileCookie*)_cookie; // FUNCTION(("((%lu, %lu), %lld, %p, %lu)\n", node->GetDirID(), // node->GetObjectID(), pos, buffer, *bufferSize)); + + VolumeWriteLocker locker(volume); + if (!locker.IsLocked()) + RETURN_ERROR(B_ERROR); + status_t error = B_OK; - if (VolumeWriteLocker locker = volume) { - // don't write anything but files - if (!node->IsFile()) - SET_ERROR(error, B_BAD_VALUE); + // don't write anything but files + if (!node->IsFile()) + SET_ERROR(error, B_BAD_VALUE); + if (error == B_OK) { + // check, if reading is allowed + int rwMode = cookie->GetOpenMode() & O_RWMASK; + if (error == B_OK && rwMode != O_WRONLY && rwMode != O_RDWR) + SET_ERROR(error, B_FILE_ERROR); if (error == B_OK) { - // check, if reading is allowed - int rwMode = cookie->GetOpenMode() & O_RWMASK; - if (error == B_OK && rwMode != O_WRONLY && rwMode != O_RDWR) - SET_ERROR(error, B_FILE_ERROR); - if (error == B_OK) { - // reset the position, if opened in append mode - if (cookie->GetOpenMode() & O_APPEND) - pos = node->GetSize(); - // write - if (File *file = dynamic_cast(node)) { - error = file->WriteAt(pos, buffer, *bufferSize, - bufferSize); - } else { - FATAL("Node %" B_PRIdINO " pretends to be a File, but isn't!\n", - node->GetID()); - error = B_BAD_VALUE; - } + // reset the position, if opened in append mode + if (cookie->GetOpenMode() & O_APPEND) + pos = node->GetSize(); + // write + if (File *file = dynamic_cast(node)) { + error = file->WriteAt(pos, buffer, *bufferSize, + bufferSize); + } else { + FATAL("Node %" B_PRIdINO " pretends to be a File, but isn't!\n", + node->GetID()); + error = B_BAD_VALUE; } } - // notify listeners - if (error == B_OK && cookie->NotificationIntervalElapsed(true)) - notify_if_stat_changed(volume, node); - NodeMTimeUpdater mTimeUpdater(node); - } else - SET_ERROR(error, B_ERROR); + } + // notify listeners + if (error == B_OK && cookie->NotificationIntervalElapsed(true)) + notify_if_stat_changed(volume, node); + NodeMTimeUpdater mTimeUpdater(node); RETURN_ERROR(error); } @@ -1040,7 +1047,6 @@ ramfs_write(fs_volume* _volume, fs_vnode* _node, void* _cookie, off_t pos, // #pragma mark - Directories -// DirectoryCookie class DirectoryCookie { public: DirectoryCookie(Directory *directory = NULL) @@ -1122,7 +1128,6 @@ private: int32 DirectoryCookie::fNextIteratorID = 0; -// ramfs_create_dir static status_t ramfs_create_dir(fs_volume* _volume, fs_vnode* _dir, const char *name, int mode) { @@ -1130,104 +1135,103 @@ ramfs_create_dir(fs_volume* _volume, fs_vnode* _dir, const char *name, int mode) Volume* volume = (Volume*)_volume->private_volume; Directory* dir = dynamic_cast((Node*)_dir->private_node); + if (name == NULL || *name == '\0') + RETURN_ERROR(B_BAD_VALUE); + if (dir == NULL) + RETURN_ERROR(B_BAD_VALUE); + 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); + // directory deleted? + bool removed; status_t error = B_OK; - // check name - if (!name || *name == '\0') { - SET_ERROR(error, B_BAD_VALUE); - // check directory - } else if (!dir) { - SET_ERROR(error, B_BAD_VALUE); - // check special names - } else if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { - SET_ERROR(error, B_FILE_EXISTS); - } else if (VolumeWriteLocker locker = volume) { - NodeMTimeUpdater mTimeUpdater(dir); - // directory deleted? - bool removed; - if (get_vnode_removed(volume->FSVolume(), dir->GetID(), &removed) + if (get_vnode_removed(volume->FSVolume(), dir->GetID(), &removed) != B_OK || removed) { - SET_ERROR(error, B_NOT_ALLOWED); - } - // check directory write permissions - error = dir->CheckPermissions(ACCESS_W); - Node *node = NULL; - if (error == B_OK) { - // check if entry does already exist - if (dir->FindNode(name, &node) == B_OK) { - SET_ERROR(error, B_FILE_EXISTS); - } else { - // entry doesn't exist: create a directory - Directory *newDir = NULL; - error = dir->CreateDirectory(name, &newDir); - if (error == B_OK) { - node = newDir; - // set permissions, owner and group - node->SetMode(mode); - node->SetUID(geteuid()); - node->SetGID(getegid()); - // put the node - volume->PutVNode(node); - } + SET_ERROR(error, B_NOT_ALLOWED); + } + + // check directory write permissions + error = dir->CheckPermissions(ACCESS_W); + Node *node = NULL; + if (error == B_OK) { + // check if entry does already exist + if (dir->FindNode(name, &node) == B_OK) { + SET_ERROR(error, B_FILE_EXISTS); + } else { + // entry doesn't exist: create a directory + Directory *newDir = NULL; + error = dir->CreateDirectory(name, &newDir); + if (error == B_OK) { + node = newDir; + // set permissions, owner and group + node->SetMode(mode); + node->SetUID(geteuid()); + node->SetGID(getegid()); + // put the node + volume->PutVNode(node); } } - NodeMTimeUpdater mTimeUpdater2(node); - // notify listeners - if (error == B_OK) { - notify_entry_created(volume->GetID(), dir->GetID(), name, - node->GetID()); - } - } else - SET_ERROR(error, B_ERROR); + } + NodeMTimeUpdater mTimeUpdater2(node); + // notify listeners + if (error == B_OK) { + notify_entry_created(volume->GetID(), dir->GetID(), name, + node->GetID()); + } + RETURN_ERROR(error); } -// ramfs_remove_dir static status_t ramfs_remove_dir(fs_volume* _volume, fs_vnode* _dir, const char *name) { FUNCTION(("name: `%s'\n", name)); Volume* volume = (Volume*)_volume->private_volume; Directory* dir = dynamic_cast((Node*)_dir->private_node); - status_t error = B_OK; - // check name - if (!name || *name == '\0' || !strcmp(name, ".") || !strcmp(name, "..")) { - SET_ERROR(error, B_BAD_VALUE); - // check node - } else if (!dir) { - SET_ERROR(error, B_BAD_VALUE); - } else if (VolumeWriteLocker locker = volume) { - NodeMTimeUpdater mTimeUpdater(dir); - // check directory write permissions - error = dir->CheckPermissions(ACCESS_W); - ino_t nodeID = -1; - if (error == B_OK) { - // check if entry exists - Node *node = NULL; - Entry *entry = NULL; - if (dir->FindAndGetNode(name, &node, &entry) == B_OK) { - nodeID = node->GetID(); - if (!node->IsDirectory()) { - SET_ERROR(error, B_NOT_A_DIRECTORY); - } else if (!dynamic_cast(node)->IsEmpty()) { - SET_ERROR(error, B_DIRECTORY_NOT_EMPTY); - } else - error = dir->DeleteEntry(entry); - volume->PutVNode(node); + if (name == NULL || *name == '\0' || !strcmp(name, ".") || !strcmp(name, "..")) + RETURN_ERROR(B_BAD_VALUE); + if (dir == NULL) + RETURN_ERROR(B_BAD_VALUE); + + VolumeWriteLocker locker(volume); + if (!locker.IsLocked()) + RETURN_ERROR(B_ERROR); + + NodeMTimeUpdater mTimeUpdater(dir); + // check directory write permissions + status_t error = dir->CheckPermissions(ACCESS_W); + ino_t nodeID = -1; + if (error == B_OK) { + // check if entry exists + Node *node = NULL; + Entry *entry = NULL; + if (dir->FindAndGetNode(name, &node, &entry) == B_OK) { + nodeID = node->GetID(); + if (!node->IsDirectory()) { + SET_ERROR(error, B_NOT_A_DIRECTORY); + } else if (!dynamic_cast(node)->IsEmpty()) { + SET_ERROR(error, B_DIRECTORY_NOT_EMPTY); } else - SET_ERROR(error, B_ENTRY_NOT_FOUND); - } - // notify listeners - if (error == B_OK) - notify_entry_removed(volume->GetID(), dir->GetID(), name, nodeID); - } else - SET_ERROR(error, B_ERROR); + error = dir->DeleteEntry(entry); + volume->PutVNode(node); + } else + SET_ERROR(error, B_ENTRY_NOT_FOUND); + } + // notify listeners + if (error == B_OK) + notify_entry_removed(volume->GetID(), dir->GetID(), name, nodeID); + RETURN_ERROR(error); } -// ramfs_open_dir static status_t ramfs_open_dir(fs_volume* /*fs*/, fs_vnode* _node, void** _cookie) { @@ -1236,17 +1240,19 @@ ramfs_open_dir(fs_volume* /*fs*/, fs_vnode* _node, void** _cookie) Node* node = (Node*)_node->private_node; FUNCTION(("dir: (%Lu)\n", node->GetID())); + + if (!node->IsDirectory()) + RETURN_ERROR(B_NOT_A_DIRECTORY); + // get the Directory - status_t error = (node->IsDirectory() ? B_OK : B_NOT_A_DIRECTORY); - Directory *dir = NULL; - if (error == B_OK) { - dir = dynamic_cast(node); - if (!dir) { - FATAL("Node %" B_PRIdINO " pretends to be a Directory, but isn't!\n", - node->GetID()); - error = B_NOT_A_DIRECTORY; - } + Directory *dir = dynamic_cast(node); + status_t error = B_OK; + if (dir == NULL) { + FATAL("Node %" B_PRIdINO " pretends to be a Directory, but isn't!\n", + node->GetID()); + error = B_NOT_A_DIRECTORY; } + // create a DirectoryCookie if (error == B_OK) { DirectoryCookie *cookie = new(nothrow) DirectoryCookie(dir); @@ -1264,7 +1270,6 @@ ramfs_open_dir(fs_volume* /*fs*/, fs_vnode* _node, void** _cookie) } -// ramfs_close_dir static status_t ramfs_close_dir(fs_volume* /*fs*/, fs_vnode* DARG(_node), void* _cookie) { @@ -1278,7 +1283,6 @@ ramfs_close_dir(fs_volume* /*fs*/, fs_vnode* DARG(_node), void* _cookie) } -// ramfs_free_dir_cookie static status_t ramfs_free_dir_cookie(fs_volume* /*fs*/, fs_vnode* /*_node*/, void* _cookie) { @@ -1289,7 +1293,6 @@ ramfs_free_dir_cookie(fs_volume* /*fs*/, fs_vnode* /*_node*/, void* _cookie) } -// ramfs_read_dir static status_t ramfs_read_dir(fs_volume* _volume, fs_vnode* DARG(_node), void* _cookie, struct dirent *buffer, size_t bufferSize, uint32 *count) @@ -1300,42 +1303,42 @@ ramfs_read_dir(fs_volume* _volume, fs_vnode* DARG(_node), void* _cookie, FUNCTION(("dir: (%Lu)\n", node->GetID())); DirectoryCookie *cookie = (DirectoryCookie*)_cookie; - status_t error = B_OK; - if (VolumeReadLocker locker = volume) { - error = cookie->Resume(); - if (error == B_OK) { - // read one entry - ino_t nodeID = -1; - const char *name = NULL; - if (cookie->GetNext(&nodeID, &name) == B_OK) { - PRINT(" entry: `%s'\n", name); - size_t nameLen = strlen(name); - // check, whether the entry fits into the buffer, - // and fill it in - size_t length = (buffer->d_name + nameLen + 1) - (char*)buffer; - if (length <= bufferSize) { - buffer->d_dev = volume->GetID(); - buffer->d_ino = nodeID; - memcpy(buffer->d_name, name, nameLen); - buffer->d_name[nameLen] = '\0'; - buffer->d_reclen = length; - *count = 1; - } else { - SET_ERROR(error, B_BUFFER_OVERFLOW); - } - } else - *count = 0; - cookie->Suspend(); - } - } else - SET_ERROR(error, B_ERROR); + VolumeReadLocker locker(volume); + if (!locker.IsLocked()) + RETURN_ERROR(B_ERROR); + + status_t error = cookie->Resume(); + if (error == B_OK) { + // read one entry + ino_t nodeID = -1; + const char *name = NULL; + if (cookie->GetNext(&nodeID, &name) == B_OK) { + PRINT(" entry: `%s'\n", name); + size_t nameLen = strlen(name); + // check, whether the entry fits into the buffer, + // and fill it in + size_t length = (buffer->d_name + nameLen + 1) - (char*)buffer; + if (length <= bufferSize) { + buffer->d_dev = volume->GetID(); + buffer->d_ino = nodeID; + memcpy(buffer->d_name, name, nameLen); + buffer->d_name[nameLen] = '\0'; + buffer->d_reclen = length; + *count = 1; + } else { + SET_ERROR(error, B_BUFFER_OVERFLOW); + } + } else + *count = 0; + + cookie->Suspend(); + } RETURN_ERROR(error); } -// ramfs_rewind_dir static status_t ramfs_rewind_dir(fs_volume* /*fs*/, fs_vnode* /*_node*/, void* _cookie) { @@ -1352,7 +1355,6 @@ ramfs_rewind_dir(fs_volume* /*fs*/, fs_vnode* /*_node*/, void* _cookie) // #pragma mark - Attribute Directories -// ramfs_open_attr_dir static status_t ramfs_open_attr_dir(fs_volume* _volume, fs_vnode* _node, void** _cookie) { @@ -1360,31 +1362,31 @@ ramfs_open_attr_dir(fs_volume* _volume, fs_vnode* _node, void** _cookie) Volume* volume = (Volume*)_volume->private_volume; Node* node = (Node*)_node->private_node; + VolumeReadLocker locker(volume); + if (!locker.IsLocked()) + RETURN_ERROR(B_ERROR); + status_t error = B_OK; - if (VolumeReadLocker locker = volume) { - // check permissions - error = node->CheckPermissions(ACCESS_R); - // create iterator - AttributeIterator *iterator = NULL; - if (error == B_OK) { - iterator = new(nothrow) AttributeIterator(node); - if (iterator) - error = iterator->Suspend(); - else - SET_ERROR(error, B_NO_MEMORY); - } - // set result / cleanup on failure - if (error == B_OK) - *_cookie = iterator; + // check permissions + error = node->CheckPermissions(ACCESS_R); + // create iterator + AttributeIterator *iterator = NULL; + if (error == B_OK) { + iterator = new(nothrow) AttributeIterator(node); + if (iterator) + error = iterator->Suspend(); else - delete iterator; - } else - SET_ERROR(error, B_ERROR); + SET_ERROR(error, B_NO_MEMORY); + } + // set result / cleanup on failure + if (error == B_OK) + *_cookie = iterator; + else + delete iterator; RETURN_ERROR(error); } -// ramfs_close_attr_dir static status_t ramfs_close_attr_dir(fs_volume* /*fs*/, fs_vnode* /*_node*/, void* _cookie) { @@ -1397,7 +1399,6 @@ ramfs_close_attr_dir(fs_volume* /*fs*/, fs_vnode* /*_node*/, void* _cookie) } -// ramfs_free_attr_dir_cookie static status_t ramfs_free_attr_dir_cookie(fs_volume* /*fs*/, fs_vnode* /*_node*/, void* _cookie) @@ -1411,7 +1412,6 @@ ramfs_free_attr_dir_cookie(fs_volume* /*fs*/, fs_vnode* /*_node*/, } -// ramfs_read_attr_dir static status_t ramfs_read_attr_dir(fs_volume* _volume, fs_vnode* _node, void* _cookie, struct dirent *buffer, size_t bufferSize, uint32 *count) @@ -1420,41 +1420,41 @@ ramfs_read_attr_dir(fs_volume* _volume, fs_vnode* _node, void* _cookie, Volume* volume = (Volume*)_volume->private_volume; AttributeIterator *iterator = (AttributeIterator*)_cookie; - status_t error = B_OK; - if (VolumeReadLocker locker = volume) { - error = iterator->Resume(); - if (error == B_OK) { - // get next attribute - Attribute *attribute = NULL; - if (iterator->GetNext(&attribute) == B_OK) { - const char *name = attribute->GetName(); - size_t nameLen = strlen(name); - // check, whether the entry fits into the buffer, - // and fill it in - size_t length = (buffer->d_name + nameLen + 1) - (char*)buffer; - if (length <= bufferSize) { - buffer->d_dev = volume->GetID(); - buffer->d_ino = -1; // attributes don't have a node ID - memcpy(buffer->d_name, name, nameLen); - buffer->d_name[nameLen] = '\0'; - buffer->d_reclen = length; - *count = 1; - } else { - SET_ERROR(error, B_BUFFER_OVERFLOW); - } - } else - *count = 0; - iterator->Suspend(); - } - } else - SET_ERROR(error, B_ERROR); + VolumeReadLocker locker(volume); + if (!locker.IsLocked()) + RETURN_ERROR(B_ERROR); + + status_t error = iterator->Resume(); + if (error == B_OK) { + // get next attribute + Attribute *attribute = NULL; + if (iterator->GetNext(&attribute) == B_OK) { + const char *name = attribute->GetName(); + size_t nameLen = strlen(name); + // check, whether the entry fits into the buffer, + // and fill it in + size_t length = (buffer->d_name + nameLen + 1) - (char*)buffer; + if (length <= bufferSize) { + buffer->d_dev = volume->GetID(); + buffer->d_ino = -1; // attributes don't have a node ID + memcpy(buffer->d_name, name, nameLen); + buffer->d_name[nameLen] = '\0'; + buffer->d_reclen = length; + *count = 1; + } else { + SET_ERROR(error, B_BUFFER_OVERFLOW); + } + } else + *count = 0; + + iterator->Suspend(); + } RETURN_ERROR(error); } -// ramfs_rewind_attr_dir static status_t ramfs_rewind_attr_dir(fs_volume* /*fs*/, fs_vnode* /*_node*/, void* _cookie) { @@ -1471,7 +1471,6 @@ ramfs_rewind_attr_dir(fs_volume* /*fs*/, fs_vnode* /*_node*/, void* _cookie) // #pragma mark - Attributes -// AttributeCookie class AttributeCookie { public: AttributeCookie() : fOpenMode(0), fLastNotificationTime(0) {} @@ -2297,4 +2296,3 @@ module_info *modules[] = { (module_info *)&sRamFSModuleInfo, NULL, }; -