* VFS:
- Fixed vfs_get_vnode_from_fd() return type.
- Added vfs_open_vnode().
- Added a "bool traverseLeafLink" parameter to vfs_get_fs_node_from_path().
It was always resolving symlinks.
* device manager/devfs:
- devfs: get_node_for_path() no longer resolves leaf symlinks. That still
doesn't help with file disk devices, as creating partition wouldn't work
anyway.
- Pulled the module-related implementation part of BaseDevice into new class
AbstractModuleDevice and made all methods of BaseDevice virtual. Small
adjustments to devfs to be happy with the new BaseDevice interface.
- Added BaseDevice subclass FileDevice, which maps the interface to a file's
file descriptor. Still got a few TODOs, but should basically work.
- Use FileDevice for publishing file disk devices in devfs. Now those do
actually work, though there's some BFS trouble with one of the images I
tested.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33385 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -81,7 +81,7 @@ int vfs_getrlimit(int resource, struct rlimit *rlp);
|
|||||||
int vfs_setrlimit(int resource, const struct rlimit *rlp);
|
int vfs_setrlimit(int resource, const struct rlimit *rlp);
|
||||||
|
|
||||||
/* calls needed by the VM for paging and by the file cache */
|
/* calls needed by the VM for paging and by the file cache */
|
||||||
int vfs_get_vnode_from_fd(int fd, bool kernel, struct vnode **_vnode);
|
status_t vfs_get_vnode_from_fd(int fd, bool kernel, struct vnode **_vnode);
|
||||||
status_t vfs_get_vnode_from_path(const char *path, bool kernel,
|
status_t vfs_get_vnode_from_path(const char *path, bool kernel,
|
||||||
struct vnode **_vnode);
|
struct vnode **_vnode);
|
||||||
status_t vfs_get_vnode(dev_t mountID, ino_t vnodeID, bool canWait,
|
status_t vfs_get_vnode(dev_t mountID, ino_t vnodeID, bool canWait,
|
||||||
@@ -91,6 +91,7 @@ status_t vfs_entry_ref_to_vnode(dev_t mountID, ino_t directoryID,
|
|||||||
void vfs_vnode_to_node_ref(struct vnode *vnode, dev_t *_mountID,
|
void vfs_vnode_to_node_ref(struct vnode *vnode, dev_t *_mountID,
|
||||||
ino_t *_vnodeID);
|
ino_t *_vnodeID);
|
||||||
|
|
||||||
|
int vfs_open_vnode(struct vnode* vnode, int openMode, bool kernel);
|
||||||
status_t vfs_lookup_vnode(dev_t mountID, ino_t vnodeID,
|
status_t vfs_lookup_vnode(dev_t mountID, ino_t vnodeID,
|
||||||
struct vnode **_vnode);
|
struct vnode **_vnode);
|
||||||
void vfs_put_vnode(struct vnode *vnode);
|
void vfs_put_vnode(struct vnode *vnode);
|
||||||
@@ -114,7 +115,7 @@ status_t vfs_get_vnode_cache(struct vnode *vnode, struct VMCache **_cache,
|
|||||||
status_t vfs_get_file_map(struct vnode *vnode, off_t offset, size_t size,
|
status_t vfs_get_file_map(struct vnode *vnode, off_t offset, size_t size,
|
||||||
struct file_io_vec *vecs, size_t *_count);
|
struct file_io_vec *vecs, size_t *_count);
|
||||||
status_t vfs_get_fs_node_from_path(fs_volume *volume, const char *path,
|
status_t vfs_get_fs_node_from_path(fs_volume *volume, const char *path,
|
||||||
bool kernel, void **_node);
|
bool traverseLeafLink, bool kernel, void **_node);
|
||||||
status_t vfs_stat_vnode(struct vnode *vnode, struct stat *stat);
|
status_t vfs_stat_vnode(struct vnode *vnode, struct stat *stat);
|
||||||
status_t vfs_stat_node_ref(dev_t device, ino_t inode, struct stat *stat);
|
status_t vfs_stat_node_ref(dev_t device, ino_t inode, struct stat *stat);
|
||||||
status_t vfs_get_vnode_name(struct vnode *vnode, char *name,
|
status_t vfs_get_vnode_name(struct vnode *vnode, char *name,
|
||||||
|
|||||||
@@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Copyright 2008-2009, Axel Dörfler, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "AbstractModuleDevice.h"
|
||||||
|
|
||||||
|
|
||||||
|
AbstractModuleDevice::AbstractModuleDevice()
|
||||||
|
:
|
||||||
|
fNode(NULL),
|
||||||
|
fInitialized(0),
|
||||||
|
fDeviceModule(NULL),
|
||||||
|
fDeviceData(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AbstractModuleDevice::~AbstractModuleDevice()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
AbstractModuleDevice::HasSelect() const
|
||||||
|
{
|
||||||
|
return Module()->select != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
AbstractModuleDevice::HasDeselect() const
|
||||||
|
{
|
||||||
|
return Module()->deselect != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
AbstractModuleDevice::HasRead() const
|
||||||
|
{
|
||||||
|
return Module()->read != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
AbstractModuleDevice::HasWrite() const
|
||||||
|
{
|
||||||
|
return Module()->write != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
AbstractModuleDevice::HasIO() const
|
||||||
|
{
|
||||||
|
return Module()->io != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
AbstractModuleDevice::Open(const char* path, int openMode, void** _cookie)
|
||||||
|
{
|
||||||
|
return Module()->open(Data(), path, openMode, _cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
AbstractModuleDevice::Read(void* cookie, off_t pos, void* buffer, size_t* _length)
|
||||||
|
{
|
||||||
|
return Module()->read(cookie, pos, buffer, _length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
AbstractModuleDevice::Write(void* cookie, off_t pos, const void* buffer, size_t* _length)
|
||||||
|
{
|
||||||
|
return Module()->write(cookie, pos, buffer, _length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
AbstractModuleDevice::IO(void* cookie, io_request* request)
|
||||||
|
{
|
||||||
|
return Module()->io(cookie, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
AbstractModuleDevice::Control(void* cookie, int32 op, void* buffer, size_t length)
|
||||||
|
{
|
||||||
|
return Module()->control(cookie, op, buffer, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
AbstractModuleDevice::Select(void* cookie, uint8 event, selectsync* sync)
|
||||||
|
{
|
||||||
|
return Module()->select(cookie, event, sync);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
AbstractModuleDevice::Deselect(void* cookie, uint8 event, selectsync* sync)
|
||||||
|
{
|
||||||
|
return Module()->deselect(cookie, event, sync);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
AbstractModuleDevice::Close(void* cookie)
|
||||||
|
{
|
||||||
|
return Module()->close(cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
AbstractModuleDevice::Free(void* cookie)
|
||||||
|
{
|
||||||
|
return Module()->free(cookie);
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Copyright 2008-2009, Axel Dörfler, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef ABSTRACT_MODULE_DEVICE_H
|
||||||
|
#define ABSTRACT_MODULE_DEVICE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "BaseDevice.h"
|
||||||
|
|
||||||
|
|
||||||
|
class AbstractModuleDevice : public BaseDevice {
|
||||||
|
public:
|
||||||
|
AbstractModuleDevice();
|
||||||
|
virtual ~AbstractModuleDevice();
|
||||||
|
|
||||||
|
device_module_info* Module() const { return fDeviceModule; }
|
||||||
|
|
||||||
|
void* Data() const { return fDeviceData; }
|
||||||
|
device_node* Node() const { return fNode; }
|
||||||
|
|
||||||
|
virtual bool HasSelect() const;
|
||||||
|
virtual bool HasDeselect() const;
|
||||||
|
virtual bool HasRead() const;
|
||||||
|
virtual bool HasWrite() const;
|
||||||
|
virtual bool HasIO() const;
|
||||||
|
|
||||||
|
virtual status_t Open(const char* path, int openMode,
|
||||||
|
void** _cookie);
|
||||||
|
virtual status_t Read(void* cookie, off_t pos, void* buffer,
|
||||||
|
size_t* _length);
|
||||||
|
virtual status_t Write(void* cookie, off_t pos, const void* buffer,
|
||||||
|
size_t* _length);
|
||||||
|
virtual status_t IO(void* cookie, io_request* request);
|
||||||
|
virtual status_t Control(void* cookie, int32 op, void* buffer,
|
||||||
|
size_t length);
|
||||||
|
virtual status_t Select(void* cookie, uint8 event, selectsync* sync);
|
||||||
|
virtual status_t Deselect(void* cookie, uint8 event,
|
||||||
|
selectsync* sync);
|
||||||
|
|
||||||
|
virtual status_t Close(void* cookie);
|
||||||
|
virtual status_t Free(void* cookie);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
device_node* fNode;
|
||||||
|
int32 fInitialized;
|
||||||
|
device_module_info* fDeviceModule;
|
||||||
|
void* fDeviceData;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // ABSTRACT_MODULE_DEVICE_H
|
||||||
@@ -8,11 +8,6 @@
|
|||||||
|
|
||||||
|
|
||||||
BaseDevice::BaseDevice()
|
BaseDevice::BaseDevice()
|
||||||
:
|
|
||||||
fNode(NULL),
|
|
||||||
fInitialized(0),
|
|
||||||
fDeviceModule(NULL),
|
|
||||||
fDeviceData(NULL)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,3 +34,80 @@ void
|
|||||||
BaseDevice::Removed()
|
BaseDevice::Removed()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BaseDevice::HasSelect() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BaseDevice::HasDeselect() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BaseDevice::HasRead() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BaseDevice::HasWrite() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BaseDevice::HasIO() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BaseDevice::Read(void* cookie, off_t pos, void* buffer, size_t* _length)
|
||||||
|
{
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BaseDevice::Write(void* cookie, off_t pos, const void* buffer, size_t* _length)
|
||||||
|
{
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BaseDevice::IO(void* cookie, io_request* request)
|
||||||
|
{
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BaseDevice::Control(void* cookie, int32 op, void* buffer, size_t length)
|
||||||
|
{
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BaseDevice::Select(void* cookie, uint8 event, selectsync* sync)
|
||||||
|
{
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BaseDevice::Deselect(void* cookie, uint8 event, selectsync* sync)
|
||||||
|
{
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,112 +17,36 @@ public:
|
|||||||
void SetID(ino_t id) { fID = id; }
|
void SetID(ino_t id) { fID = id; }
|
||||||
ino_t ID() const { return fID; }
|
ino_t ID() const { return fID; }
|
||||||
|
|
||||||
device_node* Node() const { return fNode; }
|
|
||||||
|
|
||||||
virtual status_t InitDevice();
|
virtual status_t InitDevice();
|
||||||
virtual void UninitDevice();
|
virtual void UninitDevice();
|
||||||
|
|
||||||
virtual void Removed();
|
virtual void Removed();
|
||||||
|
|
||||||
device_module_info* Module() const { return fDeviceModule; }
|
virtual bool HasSelect() const;
|
||||||
void* Data() const { return fDeviceData; }
|
virtual bool HasDeselect() const;
|
||||||
|
virtual bool HasRead() const;
|
||||||
bool HasSelect() const
|
virtual bool HasWrite() const;
|
||||||
{ return Module()->select != NULL; }
|
virtual bool HasIO() const;
|
||||||
bool HasDeselect() const
|
|
||||||
{ return Module()->deselect != NULL; }
|
|
||||||
bool HasRead() const
|
|
||||||
{ return Module()->read != NULL; }
|
|
||||||
bool HasWrite() const
|
|
||||||
{ return Module()->write != NULL; }
|
|
||||||
bool HasIO() const
|
|
||||||
{ return Module()->io != NULL; }
|
|
||||||
|
|
||||||
virtual status_t Open(const char* path, int openMode,
|
virtual status_t Open(const char* path, int openMode,
|
||||||
void** _cookie);
|
void** _cookie) = 0;
|
||||||
status_t Read(void* cookie, off_t pos, void* buffer,
|
virtual status_t Read(void* cookie, off_t pos, void* buffer,
|
||||||
size_t* _length);
|
size_t* _length);
|
||||||
status_t Write(void* cookie, off_t pos, const void* buffer,
|
virtual status_t Write(void* cookie, off_t pos, const void* buffer,
|
||||||
size_t* _length);
|
size_t* _length);
|
||||||
status_t IO(void* cookie, io_request* request);
|
virtual status_t IO(void* cookie, io_request* request);
|
||||||
status_t Control(void* cookie, int32 op, void* buffer,
|
virtual status_t Control(void* cookie, int32 op, void* buffer,
|
||||||
size_t length);
|
size_t length);
|
||||||
virtual status_t Select(void* cookie, uint8 event, selectsync* sync);
|
virtual status_t Select(void* cookie, uint8 event, selectsync* sync);
|
||||||
status_t Deselect(void* cookie, uint8 event,
|
virtual status_t Deselect(void* cookie, uint8 event,
|
||||||
selectsync* sync);
|
selectsync* sync);
|
||||||
|
|
||||||
status_t Close(void* cookie);
|
virtual status_t Close(void* cookie) = 0;
|
||||||
status_t Free(void* cookie);
|
virtual status_t Free(void* cookie) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ino_t fID;
|
ino_t fID;
|
||||||
device_node* fNode;
|
|
||||||
int32 fInitialized;
|
|
||||||
device_module_info* fDeviceModule;
|
|
||||||
void* fDeviceData;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
inline status_t
|
|
||||||
BaseDevice::Open(const char* path, int openMode, void** _cookie)
|
|
||||||
{
|
|
||||||
return Module()->open(Data(), path, openMode, _cookie);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline status_t
|
|
||||||
BaseDevice::Read(void* cookie, off_t pos, void* buffer, size_t* _length)
|
|
||||||
{
|
|
||||||
return Module()->read(cookie, pos, buffer, _length);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline status_t
|
|
||||||
BaseDevice::Write(void* cookie, off_t pos, const void* buffer, size_t* _length)
|
|
||||||
{
|
|
||||||
return Module()->write(cookie, pos, buffer, _length);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline status_t
|
|
||||||
BaseDevice::IO(void* cookie, io_request* request)
|
|
||||||
{
|
|
||||||
return Module()->io(cookie, request);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline status_t
|
|
||||||
BaseDevice::Control(void* cookie, int32 op, void* buffer, size_t length)
|
|
||||||
{
|
|
||||||
return Module()->control(cookie, op, buffer, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline status_t
|
|
||||||
BaseDevice::Select(void* cookie, uint8 event, selectsync* sync)
|
|
||||||
{
|
|
||||||
return Module()->select(cookie, event, sync);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline status_t
|
|
||||||
BaseDevice::Deselect(void* cookie, uint8 event, selectsync* sync)
|
|
||||||
{
|
|
||||||
return Module()->deselect(cookie, event, sync);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline status_t
|
|
||||||
BaseDevice::Close(void* cookie)
|
|
||||||
{
|
|
||||||
return Module()->close(cookie);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline status_t
|
|
||||||
BaseDevice::Free(void* cookie)
|
|
||||||
{
|
|
||||||
return Module()->free(cookie);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // BASE_DEVICE_H
|
#endif // BASE_DEVICE_H
|
||||||
|
|||||||
@@ -0,0 +1,335 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "FileDevice.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include <fs_interface.h>
|
||||||
|
|
||||||
|
#include <vfs.h>
|
||||||
|
|
||||||
|
|
||||||
|
static const uint32 kBlockSize = 512;
|
||||||
|
|
||||||
|
|
||||||
|
struct FileDevice::Cookie {
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
Cookie(int fd)
|
||||||
|
:
|
||||||
|
fd(fd)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~Cookie()
|
||||||
|
{
|
||||||
|
if (fd >= 0)
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
FileDevice::FileDevice()
|
||||||
|
:
|
||||||
|
fFD(-1),
|
||||||
|
fFileSize(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FileDevice::~FileDevice()
|
||||||
|
{
|
||||||
|
if (fFD >= 0)
|
||||||
|
close(fFD);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
FileDevice::Init(const char* path)
|
||||||
|
{
|
||||||
|
fFD = open(path, O_RDONLY | O_NOTRAVERSE);
|
||||||
|
if (fFD < 0)
|
||||||
|
return errno;
|
||||||
|
|
||||||
|
struct stat st;
|
||||||
|
if (fstat(fFD, &st) != 0)
|
||||||
|
return errno;
|
||||||
|
|
||||||
|
if (!S_ISREG(st.st_mode))
|
||||||
|
return B_BAD_TYPE;
|
||||||
|
|
||||||
|
fFileSize = st.st_size / kBlockSize * kBlockSize;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
FileDevice::InitDevice()
|
||||||
|
{
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
FileDevice::UninitDevice()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
FileDevice::Removed()
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
FileDevice::HasSelect() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
FileDevice::HasDeselect() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
FileDevice::HasRead() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
FileDevice::HasWrite() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
FileDevice::HasIO() const
|
||||||
|
{
|
||||||
|
// TODO: Support!
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
FileDevice::Open(const char* path, int openMode, void** _cookie)
|
||||||
|
{
|
||||||
|
// get the vnode
|
||||||
|
struct vnode* vnode;
|
||||||
|
status_t error = vfs_get_vnode_from_fd(fFD, true, &vnode);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// open it
|
||||||
|
int fd = vfs_open_vnode(vnode, openMode, true);
|
||||||
|
if (fd < 0) {
|
||||||
|
vfs_put_vnode(vnode);
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
// our vnode reference does now belong to the FD
|
||||||
|
|
||||||
|
Cookie* cookie = new(std::nothrow) Cookie(fd);
|
||||||
|
if (cookie == NULL) {
|
||||||
|
close(fd);
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
*_cookie = cookie;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
FileDevice::Read(void* _cookie, off_t pos, void* buffer, size_t* _length)
|
||||||
|
{
|
||||||
|
Cookie* cookie = (Cookie*)_cookie;
|
||||||
|
|
||||||
|
ssize_t bytesRead = pread(cookie->fd, buffer, *_length, pos);
|
||||||
|
if (bytesRead < 0) {
|
||||||
|
*_length = 0;
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
*_length = bytesRead;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
FileDevice::Write(void* _cookie, off_t pos, const void* buffer, size_t* _length)
|
||||||
|
{
|
||||||
|
Cookie* cookie = (Cookie*)_cookie;
|
||||||
|
|
||||||
|
ssize_t bytesWritten = pwrite(cookie->fd, buffer, *_length, pos);
|
||||||
|
if (bytesWritten < 0) {
|
||||||
|
*_length = 0;
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
*_length = bytesWritten;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
FileDevice::IO(void* _cookie, io_request* request)
|
||||||
|
{
|
||||||
|
// Cookie* cookie = (Cookie*)_cookie;
|
||||||
|
// return do_fd_io(cookie->fd, request);
|
||||||
|
// TODO: The implementation is fine in principle, but do_fd_io() requires either
|
||||||
|
// the io() hook or the {read,write}_pages() hooks of the underlying FS to be
|
||||||
|
// implemented, which we can't guarantee. do_fd_io() should work around by using
|
||||||
|
// read() and write(), but it's all quite of a mess, since we mix up the io()
|
||||||
|
// hook -- which ATM has the semantics of uncached_io() hook (i.e. ignoring the
|
||||||
|
// file cache) -- with the actual io() hook semantics (i.e. using the file
|
||||||
|
// cache).
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename ResultType>
|
||||||
|
static status_t
|
||||||
|
set_ioctl_result(const ResultType& result, void* buffer, size_t length)
|
||||||
|
{
|
||||||
|
// NOTE: We omit the buffer size check for sake of callers (e.g. BFS) not
|
||||||
|
// specifying a length argument.
|
||||||
|
// if (sizeof(ResultType) < length)
|
||||||
|
// return B_BAD_VALUE;
|
||||||
|
|
||||||
|
if (buffer == NULL)
|
||||||
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
|
if (!IS_USER_ADDRESS(buffer))
|
||||||
|
return user_memcpy(buffer, &result, sizeof(ResultType));
|
||||||
|
|
||||||
|
memcpy(buffer, &result, sizeof(ResultType));
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
FileDevice::Control(void* _cookie, int32 op, void* buffer, size_t length)
|
||||||
|
{
|
||||||
|
Cookie* cookie = (Cookie*)_cookie;
|
||||||
|
|
||||||
|
switch (op) {
|
||||||
|
case B_GET_DEVICE_SIZE:
|
||||||
|
return set_ioctl_result(
|
||||||
|
fFileSize > ~(size_t)0 ? ~(size_t)0 : (size_t)fFileSize,
|
||||||
|
buffer, length);
|
||||||
|
|
||||||
|
case B_SET_BLOCKING_IO:
|
||||||
|
case B_SET_NONBLOCKING_IO:
|
||||||
|
// TODO: Translate to O_NONBLOCK and pass on!
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
case B_GET_READ_STATUS:
|
||||||
|
case B_GET_WRITE_STATUS:
|
||||||
|
// TODO: poll() the FD!
|
||||||
|
return set_ioctl_result(true, buffer, length);
|
||||||
|
|
||||||
|
case B_GET_ICON:
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
|
||||||
|
case B_GET_GEOMETRY:
|
||||||
|
case B_GET_BIOS_GEOMETRY:
|
||||||
|
{
|
||||||
|
// fill in the geometry
|
||||||
|
// Optimally we have only 1 block per sector and only one head.
|
||||||
|
// Since we have only a uint32 for the cylinder count, this won't
|
||||||
|
// work for files > 2TB. So, we set the head count to the minimally
|
||||||
|
// possible value.
|
||||||
|
off_t blocks = fFileSize / kBlockSize;
|
||||||
|
uint32 heads = (blocks + 0xfffffffe) / 0xffffffff;
|
||||||
|
if (heads == 0)
|
||||||
|
heads = 1;
|
||||||
|
|
||||||
|
device_geometry geometry;
|
||||||
|
geometry.bytes_per_sector = kBlockSize;
|
||||||
|
geometry.sectors_per_track = 1;
|
||||||
|
geometry.cylinder_count = blocks / heads;
|
||||||
|
geometry.head_count = heads;
|
||||||
|
geometry.device_type = B_DISK;
|
||||||
|
geometry.removable = false;
|
||||||
|
geometry.read_only = false;
|
||||||
|
geometry.write_once = false;
|
||||||
|
|
||||||
|
return set_ioctl_result(geometry, buffer, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
case B_GET_MEDIA_STATUS:
|
||||||
|
return set_ioctl_result((status_t)B_OK, buffer, length);
|
||||||
|
|
||||||
|
case B_SET_INTERRUPTABLE_IO:
|
||||||
|
case B_SET_UNINTERRUPTABLE_IO:
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
case B_FLUSH_DRIVE_CACHE:
|
||||||
|
return fsync(cookie->fd) == 0 ? B_OK : errno;
|
||||||
|
|
||||||
|
case B_GET_BIOS_DRIVE_ID:
|
||||||
|
return set_ioctl_result((uint8)0xf8, buffer, length);
|
||||||
|
|
||||||
|
case B_GET_DRIVER_FOR_DEVICE:
|
||||||
|
case B_SET_DEVICE_SIZE:
|
||||||
|
case B_SET_PARTITION:
|
||||||
|
case B_FORMAT_DEVICE:
|
||||||
|
case B_EJECT_DEVICE:
|
||||||
|
case B_LOAD_MEDIA:
|
||||||
|
case B_GET_NEXT_OPEN_DEVICE:
|
||||||
|
default:
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
FileDevice::Select(void* _cookie, uint8 event, selectsync* sync)
|
||||||
|
{
|
||||||
|
// TODO: Support (select_fd())!
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
FileDevice::Deselect(void* cookie, uint8 event, selectsync* sync)
|
||||||
|
{
|
||||||
|
// TODO: Support (deselect_fd())!
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
FileDevice::Close(void* cookie)
|
||||||
|
{
|
||||||
|
// TODO: This should probably really close the FD. Depending on the
|
||||||
|
// underlying FS operations could block and close() would be needed to
|
||||||
|
// unblock them.
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
FileDevice::Free(void* _cookie)
|
||||||
|
{
|
||||||
|
delete (Cookie*)_cookie;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef FILE_DEVICE_H
|
||||||
|
#define FILE_DEVICE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "BaseDevice.h"
|
||||||
|
|
||||||
|
|
||||||
|
class FileDevice : public BaseDevice {
|
||||||
|
public:
|
||||||
|
FileDevice();
|
||||||
|
virtual ~FileDevice();
|
||||||
|
|
||||||
|
status_t Init(const char* path);
|
||||||
|
|
||||||
|
virtual status_t InitDevice();
|
||||||
|
virtual void UninitDevice();
|
||||||
|
|
||||||
|
virtual void Removed();
|
||||||
|
|
||||||
|
virtual bool HasSelect() const;
|
||||||
|
virtual bool HasDeselect() const;
|
||||||
|
virtual bool HasRead() const;
|
||||||
|
virtual bool HasWrite() const;
|
||||||
|
virtual bool HasIO() const;
|
||||||
|
|
||||||
|
virtual status_t Open(const char* path, int openMode,
|
||||||
|
void** _cookie);
|
||||||
|
virtual status_t Read(void* cookie, off_t pos, void* buffer,
|
||||||
|
size_t* _length);
|
||||||
|
virtual status_t Write(void* cookie, off_t pos, const void* buffer,
|
||||||
|
size_t* _length);
|
||||||
|
virtual status_t IO(void* cookie, io_request* request);
|
||||||
|
virtual status_t Control(void* cookie, int32 op, void* buffer,
|
||||||
|
size_t length);
|
||||||
|
virtual status_t Select(void* cookie, uint8 event, selectsync* sync);
|
||||||
|
virtual status_t Deselect(void* cookie, uint8 event,
|
||||||
|
selectsync* sync);
|
||||||
|
|
||||||
|
virtual status_t Close(void* cookie);
|
||||||
|
virtual status_t Free(void* cookie);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Cookie;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int fFD;
|
||||||
|
off_t fFileSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // FILE_DEVICE_H
|
||||||
@@ -4,9 +4,11 @@ UsePrivateHeaders [ FDirName kernel boot platform $(TARGET_BOOT_PLATFORM) ] ;
|
|||||||
UsePrivateHeaders [ FDirName kernel util ] shared ;
|
UsePrivateHeaders [ FDirName kernel util ] shared ;
|
||||||
|
|
||||||
KernelMergeObject kernel_device_manager.o :
|
KernelMergeObject kernel_device_manager.o :
|
||||||
|
AbstractModuleDevice.cpp
|
||||||
BaseDevice.cpp
|
BaseDevice.cpp
|
||||||
device_manager.cpp
|
device_manager.cpp
|
||||||
devfs.cpp
|
devfs.cpp
|
||||||
|
FileDevice.cpp
|
||||||
id_generator.cpp
|
id_generator.cpp
|
||||||
io_resources.cpp
|
io_resources.cpp
|
||||||
IOScheduler.cpp
|
IOScheduler.cpp
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include <NodeMonitor.h>
|
#include <NodeMonitor.h>
|
||||||
|
|
||||||
#include <arch/cpu.h>
|
#include <arch/cpu.h>
|
||||||
|
#include <AutoDeleter.h>
|
||||||
#include <boot/kernel_args.h>
|
#include <boot/kernel_args.h>
|
||||||
#include <boot_device.h>
|
#include <boot_device.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
@@ -36,6 +37,7 @@
|
|||||||
#include <vm.h>
|
#include <vm.h>
|
||||||
|
|
||||||
#include "BaseDevice.h"
|
#include "BaseDevice.h"
|
||||||
|
#include "FileDevice.h"
|
||||||
#include "IORequest.h"
|
#include "IORequest.h"
|
||||||
#include "legacy_drivers.h"
|
#include "legacy_drivers.h"
|
||||||
|
|
||||||
@@ -484,7 +486,8 @@ static status_t
|
|||||||
get_node_for_path(struct devfs *fs, const char *path,
|
get_node_for_path(struct devfs *fs, const char *path,
|
||||||
struct devfs_vnode **_node)
|
struct devfs_vnode **_node)
|
||||||
{
|
{
|
||||||
return vfs_get_fs_node_from_path(fs->volume, path, true, (void **)_node);
|
return vfs_get_fs_node_from_path(fs->volume, path, false, true,
|
||||||
|
(void **)_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -508,21 +511,6 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
|
||||||
unpublish_node(struct devfs *fs, const char *path, mode_t type)
|
|
||||||
{
|
|
||||||
devfs_vnode *node;
|
|
||||||
status_t status = get_node_for_path(fs, path, &node);
|
|
||||||
if (status != B_OK)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
status = unpublish_node(fs, node, type);
|
|
||||||
|
|
||||||
put_vnode(fs->volume, node->id);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
publish_directory(struct devfs *fs, const char *path)
|
publish_directory(struct devfs *fs, const char *path)
|
||||||
{
|
{
|
||||||
@@ -818,7 +806,6 @@ dump_node(int argc, char **argv)
|
|||||||
kprintf(" symlink to: %s\n", vnode->stream.u.symlink.path);
|
kprintf(" symlink to: %s\n", vnode->stream.u.symlink.path);
|
||||||
} else {
|
} else {
|
||||||
kprintf(" device: %p\n", vnode->stream.u.dev.device);
|
kprintf(" device: %p\n", vnode->stream.u.dev.device);
|
||||||
kprintf(" node: %p\n", vnode->stream.u.dev.device->Node());
|
|
||||||
kprintf(" partition: %p\n", vnode->stream.u.dev.partition);
|
kprintf(" partition: %p\n", vnode->stream.u.dev.partition);
|
||||||
if (vnode->stream.u.dev.partition != NULL) {
|
if (vnode->stream.u.dev.partition != NULL) {
|
||||||
partition_info& info = vnode->stream.u.dev.partition->info;
|
partition_info& info = vnode->stream.u.dev.partition->info;
|
||||||
@@ -1622,6 +1609,7 @@ devfs_deselect(fs_volume* _volume, fs_vnode* _vnode, void* _cookie,
|
|||||||
static bool
|
static bool
|
||||||
devfs_can_page(fs_volume *_volume, fs_vnode *_vnode, void *cookie)
|
devfs_can_page(fs_volume *_volume, fs_vnode *_vnode, void *cookie)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
struct devfs_vnode *vnode = (devfs_vnode *)_vnode->private_node;
|
struct devfs_vnode *vnode = (devfs_vnode *)_vnode->private_node;
|
||||||
|
|
||||||
//TRACE(("devfs_canpage: vnode %p\n", vnode));
|
//TRACE(("devfs_canpage: vnode %p\n", vnode));
|
||||||
@@ -1633,6 +1621,9 @@ devfs_can_page(fs_volume *_volume, fs_vnode *_vnode, void *cookie)
|
|||||||
|
|
||||||
return vnode->stream.u.dev.device->HasRead()
|
return vnode->stream.u.dev.device->HasRead()
|
||||||
|| vnode->stream.u.dev.device->HasIO();
|
|| vnode->stream.u.dev.device->HasIO();
|
||||||
|
#endif
|
||||||
|
// TODO: Obsolete hook!
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1998,36 +1989,50 @@ file_system_module_info gDeviceFileSystem = {
|
|||||||
extern "C" status_t
|
extern "C" status_t
|
||||||
devfs_unpublish_file_device(const char *path)
|
devfs_unpublish_file_device(const char *path)
|
||||||
{
|
{
|
||||||
return unpublish_node(sDeviceFileSystem, path, S_IFLNK);
|
// get the device node
|
||||||
|
devfs_vnode* node;
|
||||||
|
status_t status = get_node_for_path(sDeviceFileSystem, path, &node);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
if (!S_ISCHR(node->stream.type)) {
|
||||||
|
put_vnode(sDeviceFileSystem->volume, node->id);
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if it is indeed a file device, unpublish it
|
||||||
|
FileDevice* device = dynamic_cast<FileDevice*>(node->stream.u.dev.device);
|
||||||
|
if (device == NULL) {
|
||||||
|
put_vnode(sDeviceFileSystem->volume, node->id);
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = unpublish_node(sDeviceFileSystem, node, S_IFCHR);
|
||||||
|
|
||||||
|
put_vnode(sDeviceFileSystem->volume, node->id);
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern "C" status_t
|
extern "C" status_t
|
||||||
devfs_publish_file_device(const char *path, const char *filePath)
|
devfs_publish_file_device(const char *path, const char *filePath)
|
||||||
{
|
{
|
||||||
struct devfs_vnode *node;
|
// create a FileDevice for the file
|
||||||
struct devfs_vnode *dirNode;
|
FileDevice* device = new(std::nothrow) FileDevice;
|
||||||
status_t status;
|
if (device == NULL)
|
||||||
|
|
||||||
filePath = strdup(filePath);
|
|
||||||
if (filePath == NULL)
|
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
ObjectDeleter<FileDevice> deviceDeleter(device);
|
||||||
|
|
||||||
RecursiveLocker locker(&sDeviceFileSystem->lock);
|
status_t error = device->Init(filePath);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
status = new_node(sDeviceFileSystem, path, &node, &dirNode);
|
// publish the device
|
||||||
if (status != B_OK) {
|
error = publish_device(sDeviceFileSystem, path, device);
|
||||||
free((char*)filePath);
|
if (error != B_OK)
|
||||||
return status;
|
return error;
|
||||||
}
|
|
||||||
|
|
||||||
// all went fine, let's initialize the node
|
deviceDeleter.Detach();
|
||||||
node->stream.type = S_IFLNK | 0644;
|
|
||||||
node->stream.u.symlink.path = filePath;
|
|
||||||
node->stream.u.symlink.length = strlen(filePath);
|
|
||||||
|
|
||||||
// the node is now fully valid and we may insert it into the dir
|
|
||||||
publish_node(sDeviceFileSystem, dirNode, node);
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
#include <util/DoublyLinkedList.h>
|
#include <util/DoublyLinkedList.h>
|
||||||
#include <util/Stack.h>
|
#include <util/Stack.h>
|
||||||
|
|
||||||
#include "BaseDevice.h"
|
#include "AbstractModuleDevice.h"
|
||||||
#include "devfs_private.h"
|
#include "devfs_private.h"
|
||||||
#include "id_generator.h"
|
#include "id_generator.h"
|
||||||
#include "IORequest.h"
|
#include "IORequest.h"
|
||||||
@@ -72,7 +72,8 @@ typedef struct io_resource_info {
|
|||||||
io_resource resource; // info about actual resource
|
io_resource resource; // info about actual resource
|
||||||
} io_resource_info;
|
} io_resource_info;
|
||||||
|
|
||||||
class Device : public BaseDevice, public DoublyLinkedListLinkImpl<Device> {
|
class Device : public AbstractModuleDevice,
|
||||||
|
public DoublyLinkedListLinkImpl<Device> {
|
||||||
public:
|
public:
|
||||||
Device(device_node* node, const char* moduleName);
|
Device(device_node* node, const char* moduleName);
|
||||||
virtual ~Device();
|
virtual ~Device();
|
||||||
@@ -1064,10 +1065,10 @@ device_attr_private::Compare(const device_attr* attrA, const device_attr *attrB)
|
|||||||
|
|
||||||
Device::Device(device_node* node, const char* moduleName)
|
Device::Device(device_node* node, const char* moduleName)
|
||||||
:
|
:
|
||||||
|
fModuleName(strdup(moduleName)),
|
||||||
fRemovedFromParent(false)
|
fRemovedFromParent(false)
|
||||||
{
|
{
|
||||||
fNode = node;
|
fNode = node;
|
||||||
fModuleName = strdup(moduleName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
#include <util/Stack.h>
|
#include <util/Stack.h>
|
||||||
#include <vfs.h>
|
#include <vfs.h>
|
||||||
|
|
||||||
#include "BaseDevice.h"
|
#include "AbstractModuleDevice.h"
|
||||||
#include "devfs_private.h"
|
#include "devfs_private.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
|
|
||||||
struct legacy_driver;
|
struct legacy_driver;
|
||||||
|
|
||||||
class LegacyDevice : public BaseDevice,
|
class LegacyDevice : public AbstractModuleDevice,
|
||||||
public DoublyLinkedListLinkImpl<LegacyDevice> {
|
public DoublyLinkedListLinkImpl<LegacyDevice> {
|
||||||
public:
|
public:
|
||||||
LegacyDevice(legacy_driver* driver,
|
LegacyDevice(legacy_driver* driver,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2005-2008, Ingo Weinhold, ingo_weinhold@gmx.de.
|
* Copyright 2005-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
* Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de.
|
* Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
@@ -518,6 +518,7 @@ static status_t dec_vnode_ref_count(struct vnode* vnode, bool alwaysFree,
|
|||||||
static inline void put_vnode(struct vnode* vnode);
|
static inline void put_vnode(struct vnode* vnode);
|
||||||
static status_t fs_unmount(char* path, dev_t mountID, uint32 flags,
|
static status_t fs_unmount(char* path, dev_t mountID, uint32 flags,
|
||||||
bool kernel);
|
bool kernel);
|
||||||
|
static int open_vnode(struct vnode* vnode, int openMode, bool kernel);
|
||||||
|
|
||||||
|
|
||||||
static struct fd_ops sFileOps = {
|
static struct fd_ops sFileOps = {
|
||||||
@@ -3944,7 +3945,7 @@ vfs_get_cookie_from_fd(int fd, void** _cookie)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern "C" int
|
extern "C" status_t
|
||||||
vfs_get_vnode_from_fd(int fd, bool kernel, struct vnode** vnode)
|
vfs_get_vnode_from_fd(int fd, bool kernel, struct vnode** vnode)
|
||||||
{
|
{
|
||||||
*vnode = get_vnode_from_fd(fd, kernel);
|
*vnode = get_vnode_from_fd(fd, kernel);
|
||||||
@@ -4009,6 +4010,17 @@ vfs_vnode_to_node_ref(struct vnode* vnode, dev_t* _mountID, ino_t* _vnodeID)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Calls fs_open() on the given vnode and returns a new
|
||||||
|
file descriptor for it
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
vfs_open_vnode(struct vnode* vnode, int openMode, bool kernel)
|
||||||
|
{
|
||||||
|
return open_vnode(vnode, openMode, kernel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Looks up a vnode with the given mount and vnode ID.
|
/*! Looks up a vnode with the given mount and vnode ID.
|
||||||
Must only be used with "in-use" vnodes as it doesn't grab a reference
|
Must only be used with "in-use" vnodes as it doesn't grab a reference
|
||||||
to the node.
|
to the node.
|
||||||
@@ -4030,8 +4042,8 @@ vfs_lookup_vnode(dev_t mountID, ino_t vnodeID, struct vnode** _vnode)
|
|||||||
|
|
||||||
|
|
||||||
extern "C" status_t
|
extern "C" status_t
|
||||||
vfs_get_fs_node_from_path(fs_volume* volume, const char* path, bool kernel,
|
vfs_get_fs_node_from_path(fs_volume* volume, const char* path,
|
||||||
void** _node)
|
bool traverseLeafLink, bool kernel, void** _node)
|
||||||
{
|
{
|
||||||
TRACE(("vfs_get_fs_node_from_path(volume = %p, path = \"%s\", kernel %d)\n",
|
TRACE(("vfs_get_fs_node_from_path(volume = %p, path = \"%s\", kernel %d)\n",
|
||||||
volume, path, kernel));
|
volume, path, kernel));
|
||||||
@@ -4051,12 +4063,12 @@ vfs_get_fs_node_from_path(fs_volume* volume, const char* path, bool kernel,
|
|||||||
struct vnode* vnode = mount->root_vnode;
|
struct vnode* vnode = mount->root_vnode;
|
||||||
|
|
||||||
if (buffer[0] == '/')
|
if (buffer[0] == '/')
|
||||||
status = path_to_vnode(buffer, true, &vnode, NULL, true);
|
status = path_to_vnode(buffer, traverseLeafLink, &vnode, NULL, kernel);
|
||||||
else {
|
else {
|
||||||
inc_vnode_ref_count(vnode);
|
inc_vnode_ref_count(vnode);
|
||||||
// vnode_path_to_vnode() releases a reference to the starting vnode
|
// vnode_path_to_vnode() releases a reference to the starting vnode
|
||||||
status = vnode_path_to_vnode(vnode, buffer, true, 0, kernel, &vnode,
|
status = vnode_path_to_vnode(vnode, buffer, traverseLeafLink, 0,
|
||||||
NULL);
|
kernel, &vnode, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
put_mount(mount);
|
put_mount(mount);
|
||||||
|
|||||||
Reference in New Issue
Block a user