* 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
This commit is contained in:
parent
261fd618fe
commit
065e318429
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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<AttributeIterator> 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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 <driver_settings.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user