From 065e31842971a008888c578c2c1f1a35c75de40e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Tue, 22 May 2007 13:19:44 +0000 Subject: [PATCH] * Inode::Create() now has a "_created" parameter that will be set to true in case a node has been created - this is now used in bfs_create() to suppress the new entry notification in case the file already existed. * Implemented parameter parsing in bfs_initialize() - does not work in the new bfs_shell though, as it currently misses driver_settings functionality. * Attribute::Create() and Attribute::Open() will now honour O_TRUNC correctly. * Note: Inode::WriteAttribute() still follows R5 semantics for small_data attributes in this regard and must be fixed (I've opened ticket #1242 for this). * Some cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21204 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/file_systems/bfs/Attribute.cpp | 44 +++++- .../kernel/file_systems/bfs/Attribute.h | 5 +- src/add-ons/kernel/file_systems/bfs/Index.cpp | 2 +- src/add-ons/kernel/file_systems/bfs/Inode.cpp | 29 ++-- src/add-ons/kernel/file_systems/bfs/Inode.h | 116 ++++++++------ .../kernel/file_systems/bfs/Volume.cpp | 26 ++-- .../file_systems/bfs/kernel_interface.cpp | 147 +++++++----------- 7 files changed, 204 insertions(+), 165 deletions(-) diff --git a/src/add-ons/kernel/file_systems/bfs/Attribute.cpp b/src/add-ons/kernel/file_systems/bfs/Attribute.cpp index 101937294a..58edeaab9c 100644 --- a/src/add-ons/kernel/file_systems/bfs/Attribute.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Attribute.cpp @@ -1,9 +1,10 @@ -/* Attribute - connection between pure inode and kernel_interface attributes - * - * Copyright 2004, Axel Dörfler, axeld@pinc-software.de. +/* + * Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de. * This file may be used under the terms of the MIT License. */ +//! connection between pure inode and kernel_interface attributes + #include "Attribute.h" @@ -128,6 +129,11 @@ Attribute::Create(const char *name, type_code type, int openMode, attr_cookie ** cookie->open_mode = openMode; cookie->create = true; + if (Get(name) == B_OK) { + // attribute already exists + if ((openMode & O_TRUNC) != 0) + _Truncate(); + } *_cookie = cookie; return B_OK; } @@ -154,9 +160,8 @@ Attribute::Open(const char *name, int openMode, attr_cookie **_cookie) cookie->create = false; // Should we truncate the attribute? - if (openMode & O_TRUNC) { - // ToDo! - } + if ((openMode & O_TRUNC) != 0) + _Truncate(); *_cookie = cookie; return B_OK; @@ -206,3 +211,30 @@ Attribute::Write(Transaction &transaction, attr_cookie *cookie, pos, buffer, _length); } + +status_t +Attribute::_Truncate() +{ + if (fSmall != NULL) { + // TODO: as long as Inode::_AddSmallData() works like it does, + // we've got nothing to do here + return B_OK; + } + + if (fAttribute != NULL) { + WriteLocked locked(fAttribute->Lock()); + Transaction transaction(fAttribute->GetVolume(), fAttribute->BlockNumber()); + + status_t status = fAttribute->SetFileSize(transaction, 0); + if (status >= B_OK) + status = fAttribute->WriteBack(transaction); + + if (status < B_OK) + return status; + + transaction.Done(); + } + + return B_OK; +} + diff --git a/src/add-ons/kernel/file_systems/bfs/Attribute.h b/src/add-ons/kernel/file_systems/bfs/Attribute.h index ef9a0cd058..d4c08d2396 100644 --- a/src/add-ons/kernel/file_systems/bfs/Attribute.h +++ b/src/add-ons/kernel/file_systems/bfs/Attribute.h @@ -30,7 +30,8 @@ class Attribute { status_t Get(const char *name); void Put(); - status_t Create(const char *name, type_code type, int openMode, attr_cookie **_cookie); + status_t Create(const char *name, type_code type, int openMode, + attr_cookie **_cookie); status_t Open(const char *name, int openMode, attr_cookie **_cookie); status_t Stat(struct stat &stat); @@ -40,6 +41,8 @@ class Attribute { off_t pos, const uint8 *buffer, size_t *_length); private: + status_t _Truncate(); + NodeGetter fNodeGetter; Inode *fInode; small_data *fSmall; diff --git a/src/add-ons/kernel/file_systems/bfs/Index.cpp b/src/add-ons/kernel/file_systems/bfs/Index.cpp index f66fb90ba0..2b50c4efc8 100644 --- a/src/add-ons/kernel/file_systems/bfs/Index.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Index.cpp @@ -209,7 +209,7 @@ Index::Create(Transaction &transaction, const char *name, uint32 type) // Inode::Create() will keep the inode locked for us return Inode::Create(transaction, fVolume->IndicesNode(), name, - S_INDEX_DIR | S_DIRECTORY | mode, 0, type, NULL, &fNode); + S_INDEX_DIR | S_DIRECTORY | mode, 0, type, NULL, NULL, &fNode); } diff --git a/src/add-ons/kernel/file_systems/bfs/Inode.cpp b/src/add-ons/kernel/file_systems/bfs/Inode.cpp index ecf659841f..f79184553a 100644 --- a/src/add-ons/kernel/file_systems/bfs/Inode.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Inode.cpp @@ -498,6 +498,7 @@ status_t Inode::_AddSmallData(Transaction &transaction, NodeGetter &nodeGetter, const char *name, uint32 type, const uint8 *data, size_t length, bool force) { + // TODO: support new write attr semantics and write offset! bfs_inode *node = nodeGetter.WritableNode(); if (node == NULL || name == NULL || data == NULL) @@ -1047,7 +1048,7 @@ Inode::CreateAttribute(Transaction &transaction, const char *name, uint32 type, // Inode::Create() locks the inode for us return Inode::Create(transaction, attributes, name, - S_ATTR | S_FILE | 0666, 0, type, NULL, attribute); + S_ATTR | S_FILE | 0666, 0, type, NULL, NULL, attribute); } @@ -2122,7 +2123,7 @@ Inode::Sync() status_t -Inode::Remove(Transaction &transaction, const char *name, off_t *_id, +Inode::Remove(Transaction &transaction, const char *name, vnode_id *_id, bool isDirectory) { BPlusTree *tree; @@ -2205,18 +2206,22 @@ Inode::Remove(Transaction &transaction, const char *name, off_t *_id, /*! Creates the inode with the specified parent directory, and automatically adds the created inode to that parent directory. If an attribute directory - is created, it will also automatically added to the parent inode as such. - However, the indices root node, and the regular root node won't be added - to the super block. + is created, it will also automatically be added to the parent inode as + such. However, the indices root node, and the regular root node won't be + added to the super block. It will also create the initial B+tree for the inode if it's a directory of any kind. - If the "_id" or "_inode" variable is given and non-NULL to store the inode's - ID, the inode stays locked - you have to call put_vnode() if you don't use it - anymore. + If the "_id" or "_inode" variable is given and non-NULL to store the + inode's ID, the inode stays locked - you have to call put_vnode() if you + don't use it anymore. + If the node already exists, this method will fail if O_EXCL is set, or it's + a directory or a symlink. Otherwise, it will just be returned. If O_TRUNC + has been specified, the file will also be truncated. */ status_t Inode::Create(Transaction &transaction, Inode *parent, const char *name, - int32 mode, int openMode, uint32 type, off_t *_id, Inode **_inode) + int32 mode, int openMode, uint32 type, bool *_created, vnode_id *_id, + Inode **_inode) { FUNCTION_START(("name = %s, mode = %ld\n", name, mode)); @@ -2274,8 +2279,10 @@ Inode::Create(Transaction &transaction, Inode *parent, const char *name, return status; } + if (_created) + *_created = false; if (_id) - *_id = offset; + *_id = inode->ID(); if (_inode) *_inode = inode; @@ -2395,6 +2402,8 @@ Inode::Create(Transaction &transaction, Inode *parent, const char *name, inode->Size(), volume->Device())); } + if (_created) + *_created = true; if (_id != NULL) *_id = inode->ID(); if (_inode != NULL) diff --git a/src/add-ons/kernel/file_systems/bfs/Inode.h b/src/add-ons/kernel/file_systems/bfs/Inode.h index 2790b232dc..bf377feb92 100644 --- a/src/add-ons/kernel/file_systems/bfs/Inode.h +++ b/src/add-ons/kernel/file_systems/bfs/Inode.h @@ -8,10 +8,6 @@ #include "system_dependencies.h" -#ifndef _IMPEXP_KERNEL -# define _IMPEXP_KERNEL -#endif - #include "Volume.h" #include "Journal.h" #include "Lock.h" @@ -40,7 +36,8 @@ enum inode_type { class Inode { public: Inode(Volume *volume, vnode_id id); - Inode(Volume *volume, Transaction &transaction, vnode_id id, mode_t mode, block_run &run); + Inode(Volume *volume, Transaction &transaction, vnode_id id, + mode_t mode, block_run &run); //Inode(CachedBlock *cached); ~Inode(); @@ -52,17 +49,27 @@ class Inode { SimpleLock &SmallDataLock() { return fSmallDataLock; } status_t WriteBack(Transaction &transaction); - bool IsContainer() const { return Mode() & (S_DIRECTORY | S_INDEX_DIR | S_ATTR_DIR); } - // note, that this test will also be true for S_IFBLK (not that it's used in the fs :) - bool IsDirectory() const { return (Mode() & (S_DIRECTORY | S_INDEX_DIR | S_ATTR_DIR)) == S_DIRECTORY; } - bool IsIndex() const { return (Mode() & (S_INDEX_DIR | 0777)) == S_INDEX_DIR; } - // that's a stupid check, but AFAIK the only possible method... + bool IsContainer() const + { return Mode() & (S_DIRECTORY | S_INDEX_DIR | S_ATTR_DIR); } + // note, that this test will also be true for S_IFBLK + // (not that it's used in the fs :) + bool IsDirectory() const + { return (Mode() & (S_DIRECTORY | S_INDEX_DIR | S_ATTR_DIR)) + == S_DIRECTORY; } + bool IsIndex() const + { return (Mode() & (S_INDEX_DIR | 0777)) == S_INDEX_DIR; } + // that's a stupid check, but AFAIK the only possible method... - bool IsAttributeDirectory() const { return (Mode() & S_ATTR_DIR) != 0; } - bool IsAttribute() const { return (Mode() & S_ATTR) != 0; } - bool IsFile() const { return (Mode() & (S_IFMT | S_ATTR)) == S_FILE; } - bool IsRegularNode() const { return (Mode() & (S_ATTR_DIR | S_INDEX_DIR | S_ATTR)) == 0; } - // a regular node in the standard namespace (i.e. not an index or attribute) + bool IsAttributeDirectory() const + { return (Mode() & S_ATTR_DIR) != 0; } + bool IsAttribute() const + { return (Mode() & S_ATTR) != 0; } + bool IsFile() const + { return (Mode() & (S_IFMT | S_ATTR)) == S_FILE; } + bool IsRegularNode() const + { return (Mode() & (S_ATTR_DIR | S_INDEX_DIR | S_ATTR)) == 0; } + // a regular node in the standard namespace + // (i.e. not an index or attribute) bool IsSymLink() const { return S_ISLNK(Mode()); } bool HasUserAccessableStream() const { return IsFile(); } // currently only files can be accessed with bfs_read()/bfs_write() @@ -87,30 +94,36 @@ class Inode { status_t CheckPermissions(int accessMode) const; // small_data access methods - small_data *FindSmallData(const bfs_inode *node, const char *name) const; + small_data *FindSmallData(const bfs_inode *node, + const char *name) const; const char *Name(const bfs_inode *node) const; - status_t GetName(char *buffer, size_t bufferSize = B_FILE_NAME_LENGTH) const; + status_t GetName(char *buffer, + size_t bufferSize = B_FILE_NAME_LENGTH) const; status_t SetName(Transaction &transaction, const char *name); // high-level attribute methods - status_t ReadAttribute(const char *name, int32 type, off_t pos, uint8 *buffer, size_t *_length); - status_t WriteAttribute(Transaction &transaction, const char *name, int32 type, off_t pos, const uint8 *buffer, size_t *_length); + status_t ReadAttribute(const char *name, int32 type, off_t pos, + uint8 *buffer, size_t *_length); + status_t WriteAttribute(Transaction &transaction, const char *name, + int32 type, off_t pos, const uint8 *buffer, size_t *_length); status_t RemoveAttribute(Transaction &transaction, const char *name); // attribute methods status_t GetAttribute(const char *name, Inode **attribute); void ReleaseAttribute(Inode *attribute); - status_t CreateAttribute(Transaction &transaction, const char *name, uint32 type, Inode **attribute); + status_t CreateAttribute(Transaction &transaction, const char *name, + uint32 type, Inode **attribute); // for directories only: - status_t GetTree(BPlusTree **); + status_t GetTree(BPlusTree **_tree); bool IsEmpty(); // manipulating the data stream status_t FindBlockRun(off_t pos, block_run &run, off_t &offset); status_t ReadAt(off_t pos, uint8 *buffer, size_t *length); - status_t WriteAt(Transaction &transaction, off_t pos, const uint8 *buffer, size_t *length); + status_t WriteAt(Transaction &transaction, off_t pos, + const uint8 *buffer, size_t *length); status_t FillGapWithZeros(off_t oldSize, off_t newSize); status_t SetFileSize(Transaction &transaction, off_t size); @@ -124,16 +137,21 @@ class Inode { bfs_inode &Node() { return fNode; } // create/remove inodes - status_t Remove(Transaction &transaction, const char *name, off_t *_id = NULL, - bool isDirectory = false); - static status_t Create(Transaction &transaction, Inode *parent, const char *name, - int32 mode, int omode, uint32 type, off_t *_id = NULL, Inode **_inode = NULL); + status_t Remove(Transaction &transaction, const char *name, + vnode_id *_id = NULL, bool isDirectory = false); + static status_t Create(Transaction &transaction, Inode *parent, + const char *name, int32 mode, int openMode, uint32 type, + bool *_created = NULL, vnode_id *_id = NULL, Inode **_inode = NULL); // index maintaining helper - void UpdateOldSize() { fOldSize = Size(); } - void UpdateOldLastModified() { fOldLastModified = Node().LastModifiedTime(); } - off_t OldSize() { return fOldSize; } - off_t OldLastModified() { return fOldLastModified; } + void UpdateOldSize() + { fOldSize = Size(); } + void UpdateOldLastModified() + { fOldLastModified = Node().LastModifiedTime(); } + off_t OldSize() + { return fOldSize; } + off_t OldLastModified() + { return fOldLastModified; } // file cache void *FileCache() const { return fCache; } @@ -148,17 +166,19 @@ class Inode { friend class InodeAllocator; // small_data access methods - status_t _MakeSpaceForSmallData(Transaction &transaction, bfs_inode *node, - const char *name, int32 length); + status_t _MakeSpaceForSmallData(Transaction &transaction, + bfs_inode *node, const char *name, int32 length); status_t _RemoveSmallData(Transaction &transaction, NodeGetter &node, - const char *name); + const char *name); status_t _AddSmallData(Transaction &transaction, NodeGetter &node, - const char *name, uint32 type, const uint8 *data, size_t length, - bool force = false); - status_t _GetNextSmallData(bfs_inode *node, small_data **_smallData) const; - status_t _RemoveSmallData(bfs_inode *node, small_data *item, int32 index); + const char *name, uint32 type, const uint8 *data, size_t length, + bool force = false); + status_t _GetNextSmallData(bfs_inode *node, + small_data **_smallData) const; + status_t _RemoveSmallData(bfs_inode *node, small_data *item, + int32 index); status_t _RemoveAttribute(Transaction &transaction, const char *name, - bool hasIndex, Index *index); + bool hasIndex, Index *index); void _AddIterator(AttributeIterator *iterator); void _RemoveIterator(AttributeIterator *iterator); @@ -179,8 +199,11 @@ class Inode { Inode *fAttributes; void *fCache; bfs_inode fNode; - off_t fOldSize; // we need those values to ensure we will remove - off_t fOldLastModified; // the correct keys from the indices + + off_t fOldSize; + off_t fOldLastModified; + // we need those values to ensure we will remove + // the correct keys from the indices mutable SimpleLock fSmallDataLock; Chain fIterators; @@ -200,7 +223,8 @@ class NodeGetter : public CachedBlock { SetTo(volume->VnodeToBlock(inode->ID())); } - NodeGetter(Volume *volume, Transaction &transaction, const Inode *inode, bool empty = false) + NodeGetter(Volume *volume, Transaction &transaction, + const Inode *inode, bool empty = false) : CachedBlock(volume) { SetToWritable(transaction, volume->VnodeToBlock(inode->ID()), empty); @@ -293,11 +317,11 @@ class AttributeIterator { }; -/** Converts the open mode, the open flags given to bfs_open(), into - * access modes, e.g. since O_RDONLY requires read access to the - * file, it will be converted to R_OK. - */ - +/*! + Converts the open mode, the open flags given to bfs_open(), into + access modes, e.g. since O_RDONLY requires read access to the + file, it will be converted to R_OK. +*/ inline int openModeToAccess(int openMode) { diff --git a/src/add-ons/kernel/file_systems/bfs/Volume.cpp b/src/add-ons/kernel/file_systems/bfs/Volume.cpp index 2952056fb7..af6e577f59 100644 --- a/src/add-ons/kernel/file_systems/bfs/Volume.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Volume.cpp @@ -455,7 +455,8 @@ Volume::CreateIndicesRoot(Transaction &transaction) { off_t id; status_t status = Inode::Create(transaction, NULL, NULL, - S_INDEX_DIR | S_STR_INDEX | S_DIRECTORY | 0700, 0, 0, &id, &fIndicesNode); + S_INDEX_DIR | S_STR_INDEX | S_DIRECTORY | 0700, 0, 0, NULL, &id, + &fIndicesNode); if (status < B_OK) RETURN_ERROR(status); @@ -496,12 +497,12 @@ Volume::UpdateLiveQueries(Inode *inode, const char *attribute, int32 type, const } -/** Checks if there is a live query whose results depend on the presence - * or value of the specified attribute. - * Don't use it if you already have all the data together to evaluate - * the queries - it wouldn't safe you anything in this case. - */ - +/*! + Checks if there is a live query whose results depend on the presence + or value of the specified attribute. + Don't use it if you already have all the data together to evaluate + the queries - it wouldn't safe you anything in this case. +*/ bool Volume::CheckForLiveQuery(const char *attribute) { @@ -534,8 +535,7 @@ Volume::RemoveQuery(Query *query) } -// #pragma mark - -// Disk scanning and initialization +// #pragma mark - Disk scanning and initialization status_t @@ -572,7 +572,8 @@ Volume::Initialize(const char *device, const char *name, uint32 blockSize, if (strchr(name, '/') != NULL) return B_BAD_VALUE; - if (blockSize != 1024 && blockSize != 2048 && blockSize != 4096 && blockSize != 8192) + if (blockSize != 1024 && blockSize != 2048 && blockSize != 4096 + && blockSize != 8192) return B_BAD_VALUE; DeviceOpener opener(device, O_RDWR); @@ -603,7 +604,8 @@ Volume::Initialize(const char *device, const char *name, uint32 blockSize, * fSuperBlock.BlocksPerAllocationGroup() + 1); fSuperBlock.log_blocks.length = HOST_ENDIAN_TO_BFS_INT16(2048); // ToDo: set the log size depending on the disk size - fSuperBlock.log_start = fSuperBlock.log_end = HOST_ENDIAN_TO_BFS_INT64(ToBlock(Log())); + fSuperBlock.log_start = fSuperBlock.log_end = HOST_ENDIAN_TO_BFS_INT64( + ToBlock(Log())); // set the current log pointers, so that journaling will work correctly fLogStart = fSuperBlock.LogStart(); @@ -628,7 +630,7 @@ Volume::Initialize(const char *device, const char *name, uint32 blockSize, off_t id; status_t status = Inode::Create(transaction, NULL, NULL, - S_DIRECTORY | 0755, 0, 0, &id, &fRootNode); + S_DIRECTORY | 0755, 0, 0, NULL, &id, &fRootNode); if (status < B_OK) RETURN_ERROR(status); diff --git a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp index dd3e845ebd..ee6d0afd8b 100644 --- a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp @@ -1,9 +1,10 @@ -/* kernel_interface - file system interface to Haiku's vnode layer - * +/* * Copyright 2001-2007, Axel Dörfler, axeld@pinc-software.de. * This file may be used under the terms of the MIT License. */ +//! file system interface to Haiku's vnode layer + #include "Debug.h" #include "Volume.h" @@ -14,6 +15,9 @@ #include "Attribute.h" #include "bfs_control.h" +#ifndef BFS_SHELL +# include +#endif #define BFS_IO_SIZE 65536 @@ -79,7 +83,8 @@ bfs_scan_partition(int fd, partition_data *partition, void *_cookie) partition->status = B_PARTITION_VALID; partition->flags |= B_PARTITION_FILE_SYSTEM; - partition->content_size = cookie->super_block.NumBlocks() * cookie->super_block.BlockSize(); + partition->content_size = cookie->super_block.NumBlocks() + * cookie->super_block.BlockSize(); partition->block_size = cookie->super_block.BlockSize(); partition->content_name = strdup(cookie->super_block.name); if (partition->content_name == NULL) @@ -441,11 +446,6 @@ bfs_get_file_map(fs_volume _fs, fs_vnode _node, off_t offset, size_t size, // #pragma mark - -/** the walk function just "walks" through a directory looking for the - * specified file. It calls get_vnode() on its vnode-id to init it - * for the kernel. - */ - static status_t bfs_lookup(void *_ns, void *_directory, const char *file, vnode_id *_vnodeID, int *_type) { @@ -487,7 +487,8 @@ bfs_lookup(void *_ns, void *_directory, const char *file, vnode_id *_vnodeID, in static status_t -bfs_get_vnode_name(fs_volume _fs, fs_vnode _node, char *buffer, size_t bufferSize) +bfs_get_vnode_name(fs_volume _fs, fs_vnode _node, char *buffer, + size_t bufferSize) { Inode *inode = (Inode *)_node; @@ -496,9 +497,11 @@ bfs_get_vnode_name(fs_volume _fs, fs_vnode _node, char *buffer, size_t bufferSiz static status_t -bfs_ioctl(void *_fs, void *_node, void *_cookie, ulong cmd, void *buffer, size_t bufferLength) +bfs_ioctl(void *_fs, void *_node, void *_cookie, ulong cmd, void *buffer, + size_t bufferLength) { - FUNCTION_START(("node = %p, cmd = %lu, buf = %p, len = %ld\n", _node, cmd, buffer, bufferLength)); + FUNCTION_START(("node = %p, cmd = %lu, buf = %p, len = %ld\n", _node, cmd, + buffer, bufferLength)); Volume *volume = (Volume *)_fs; Inode *inode = (Inode *)_node; @@ -552,7 +555,8 @@ bfs_ioctl(void *_fs, void *_node, void *_cookie, ulong cmd, void *buffer, size_t CachedBlock cached(volume); block_run run; while (allocator.AllocateBlocks(transaction, 8, 0, 64, 1, run) == B_OK) { - PRINT(("write block_run(%ld, %d, %d)\n", run.allocation_group, run.start, run.length)); + PRINT(("write block_run(%ld, %d, %d)\n", run.allocation_group, + run.start, run.length)); for (int32 i = 0;i < run.length;i++) { uint8 *block = cached.SetToWritable(transaction, run); if (block != NULL) @@ -739,7 +743,7 @@ bfs_write_stat(void *_ns, void *_node, const struct stat *stat, uint32 mask) status_t bfs_create(void *_ns, void *_directory, const char *name, int openMode, int mode, - void **_cookie, vnode_id *vnodeID) + void **_cookie, vnode_id *_vnodeID) { FUNCTION_START(("name = \"%s\", perms = %d, openMode = %d\n", name, mode, openMode)); @@ -766,8 +770,9 @@ bfs_create(void *_ns, void *_directory, const char *name, int openMode, int mode Transaction transaction(volume, directory->BlockNumber()); - status_t status = Inode::Create(transaction, directory, name, S_FILE | (mode & S_IUMSK), - openMode, 0, vnodeID); + bool created; + status_t status = Inode::Create(transaction, directory, name, + S_FILE | (mode & S_IUMSK), openMode, 0, &created, _vnodeID); if (status >= B_OK) { transaction.Done(); @@ -775,7 +780,8 @@ bfs_create(void *_ns, void *_directory, const char *name, int openMode, int mode // register the cookie *_cookie = cookie; - notify_entry_created(volume->ID(), directory->ID(), name, *vnodeID); + if (created) + notify_entry_created(volume->ID(), directory->ID(), name, *_vnodeID); } else free(cookie); @@ -784,7 +790,8 @@ bfs_create(void *_ns, void *_directory, const char *name, int openMode, int mode static status_t -bfs_create_symlink(void *_ns, void *_directory, const char *name, const char *path, int mode) +bfs_create_symlink(void *_ns, void *_directory, const char *name, + const char *path, int mode) { FUNCTION_START(("name = \"%s\", path = \"%s\"\n", name, path)); @@ -806,7 +813,8 @@ bfs_create_symlink(void *_ns, void *_directory, const char *name, const char *pa Inode *link; off_t id; - status = Inode::Create(transaction, directory, name, S_SYMLINK | 0777, 0, 0, &id, &link); + status = Inode::Create(transaction, directory, name, S_SYMLINK | 0777, + 0, 0, NULL, &id, &link); if (status < B_OK) RETURN_ERROR(status); @@ -814,10 +822,12 @@ bfs_create_symlink(void *_ns, void *_directory, const char *name, const char *pa if (length < SHORT_SYMLINK_NAME_LENGTH) { strcpy(link->Node().short_symlink, path); } else { - link->Node().flags |= HOST_ENDIAN_TO_BFS_INT32(INODE_LONG_SYMLINK | INODE_LOGGED); - + link->Node().flags |= HOST_ENDIAN_TO_BFS_INT32(INODE_LONG_SYMLINK + | INODE_LOGGED); + // links usually don't have a file cache attached - but we now need one - link->SetFileCache(file_cache_create(volume->ID(), link->ID(), 0, volume->Device())); + link->SetFileCache(file_cache_create(volume->ID(), link->ID(), 0, + volume->Device())); // The following call will have to write the inode back, so // we don't have to do that here... @@ -827,7 +837,8 @@ bfs_create_symlink(void *_ns, void *_directory, const char *name, const char *pa if (status == B_OK) status = link->WriteBack(transaction); - // Inode::Create() left the inode locked in memory, and also doesn't publish links + // Inode::Create() left the inode locked in memory, and also doesn't + // publish links publish_vnode(volume->ID(), id, link); put_vnode(volume->ID(), id); @@ -1348,7 +1359,8 @@ bfs_read_link(void *_ns, void *_node, char *buffer, size_t *_bufferSize) static status_t -bfs_create_dir(void *_ns, void *_directory, const char *name, int mode, vnode_id *_newVnodeID) +bfs_create_dir(void *_ns, void *_directory, const char *name, int mode, + vnode_id *_newVnodeID) { FUNCTION_START(("name = \"%s\", perms = %d\n", name, mode)); @@ -1371,7 +1383,8 @@ bfs_create_dir(void *_ns, void *_directory, const char *name, int mode, vnode_id // Inode::Create() locks the inode if we pass the "id" parameter, but we // need it anyway off_t id; - status = Inode::Create(transaction, directory, name, S_DIRECTORY | (mode & S_IUMSK), 0, 0, &id); + status = Inode::Create(transaction, directory, name, + S_DIRECTORY | (mode & S_IUMSK), 0, 0, NULL, &id); if (status == B_OK) { *_newVnodeID = id; put_vnode(volume->ID(), id); @@ -1742,7 +1755,7 @@ bfs_remove_attr(fs_volume _fs, fs_vnode _node, const char *name) notify_attribute_changed(volume->ID(), inode->ID(), name, B_ATTR_REMOVED); } - RETURN_ERROR(status); + return status; } @@ -2033,57 +2046,40 @@ bfs_initialize(const char *partition, const char *name, const char *parameters, { if (partition == NULL) return B_BAD_VALUE; - -// TODO: Handle parameters! -// char **argv = (char**)parms; uint32 blockSize = 1024; uint32 flags = 0; bool verbose = false; -#if 0 - while (argv && *++argv) { - char *arg = *argv; - if (*arg == '-') { - if (arg[1] == '-') { - if (!strcmp(arg, "--noindex")) - flags |= VOLUME_NO_INDICES; - else - return B_BAD_VALUE; - } +// TODO: driver_settings are not yet supported by the fsshell +#ifndef BFS_SHELL + void *handle = parse_driver_settings_string(parameters); + if (handle != NULL) { + if (get_driver_boolean_parameter(handle, "noindex", false, true)) + flags |= VOLUME_NO_INDICES; + if (get_driver_boolean_parameter(handle, "verbose", false, true)) + verbose = true; - while (*++arg && *arg >= 'a' && *arg <= 'z') { - switch (*arg) { - case 'v': - verbose = true; - break; - case 'b': - if (*++argv == NULL || !(**argv >= '0' && **argv <= '9')) - return B_BAD_VALUE; + const char *string = get_driver_parameter(handle, "block_size", + NULL, NULL); + if (string != NULL) + blockSize = strtoul(string, NULL, 0); - blockSize = atol(*argv); - break; - case 'n': - flags |= VOLUME_NO_INDICES; - break; - } - } - } - else - break; + delete_driver_settings(handle); } -#endif // 0 - if (blockSize != 1024 && blockSize != 2048 && blockSize != 4096 && blockSize != 8192) { - FATAL(("valid block sizes are: 1024, 2048, 4096, and 8192\n")); - return -1; + if (blockSize != 1024 && blockSize != 2048 && blockSize != 4096 + && blockSize != 8192) { + INFORM(("valid block sizes are: 1024, 2048, 4096, and 8192\n")); + return B_BAD_VALUE; } +#endif Volume volume(-1); status_t status = volume.Initialize(partition, name, blockSize, flags); if (status < B_OK) { - FATAL(("Initializing volume failed: %s\n", strerror(status))); - return -1; + INFORM(("Initializing volume failed: %s\n", strerror(status))); + return status; } if (verbose) { @@ -2101,33 +2097,6 @@ bfs_initialize(const char *partition, const char *name, const char *parameters, INFORM(("\tlog size: %u blocks\n", super.log_blocks.Length())); } - // make the disk image bootable - -// TODO: Check whether this is necessary. Actually makebootable should do the -// trick anyway. -#if 0 - int device = open(partition, O_RDWR); - if (device < 0) { - FATAL(("Could not make image bootable: Failed to open \"%s\"\n", - partition)); - return B_FILE_ERROR; - } - - // change BIOS drive and partition offset - // TODO: for now, this will only work for images only - - sBootBlockData1[kBIOSDriveOffset] = 0x80; - // for now, this should be replaced by the real thing - uint32 *offset = (uint32 *)&sBootBlockData1[kPartitionDataOffset]; - *offset = 0; - - write_pos(device, 0, sBootBlockData1, kBootBlockData1Size); - write_pos(device, kBootBlockData2Offset, sBootBlockData2, - kBootBlockData2Size); - - close(device); -#endif // 0 - return B_OK; }