* Implemented create/create dir/create symlink and remove/remove dir in the

write_overlay and add the necessary infrastructure for it.
* Fix setting permissions through write stat.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29268 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz
2009-02-21 02:35:55 +00:00
parent 69fc3a4e4d
commit f9e9051d3e
@@ -36,11 +36,28 @@
namespace write_overlay {
status_t publish_overlay_vnode(fs_volume *volume, ino_t inodeNumber,
void *privateNode, int type);
class OverlayInode;
struct open_cookie {
int open_mode;
void * super_cookie;
};
struct open_dir_cookie {
uint32 index;
};
struct overlay_dirent {
ino_t inode_number;
char * name;
};
struct write_buffer {
write_buffer * next;
off_t position;
@@ -57,27 +74,38 @@ public:
fs_volume * Volume() { return fVolume; }
fs_volume * SuperVolume() { return fVolume->super_volume; }
ino_t BuildInodeNumber() { return fCurrentInodeNumber++; }
private:
fs_volume * fVolume;
ino_t fCurrentInodeNumber;
};
class OverlayInode {
public:
OverlayInode(OverlayVolume *volume,
fs_vnode *superVnode, ino_t inodeNumber);
fs_vnode *superVnode, ino_t inodeNumber,
OverlayInode *parentDir = NULL,
mode_t mode = 0);
~OverlayInode();
status_t InitCheck();
bool IsVirtual() { return fIsVirtual; }
fs_volume * Volume() { return fVolume->Volume(); }
fs_volume * SuperVolume() { return fVolume->SuperVolume(); }
fs_vnode * SuperVnode() { return &fSuperVnode; }
ino_t InodeNumber() { return fInodeNumber; }
status_t Lookup(const char *name, ino_t *inodeNumber);
status_t ReadStat(struct stat *stat);
status_t WriteStat(const struct stat *stat, uint32 statMask);
status_t Create(const char *name, int openMode, int perms,
void **cookie, ino_t *newInodeNumber);
status_t Open(int openMode, void **cookie);
status_t Close(void *cookie);
status_t FreeCookie(void *cookie);
@@ -86,14 +114,41 @@ public:
status_t Write(void *cookie, off_t position,
const void *buffer, size_t *length);
status_t CreateDir(const char *name,
int perms, ino_t *newInodeNumber);
status_t RemoveDir(const char *name);
status_t OpenDir(void **cookie);
status_t CloseDir(void *cookie);
status_t FreeDirCookie(void *cookie);
status_t ReadDir(void *cookie, struct dirent *buffer,
size_t bufferSize, uint32 *num);
status_t RewindDir(void *cookie);
status_t CreateSymlink(const char *name, const char *path,
int mode);
status_t ReadSymlink(char *buffer, size_t *bufferSize);
status_t AddEntry(overlay_dirent *entry);
status_t RemoveEntry(const char *name,
overlay_dirent **entry);
private:
status_t _PopulateDirents();
status_t _CreateCommon(const char *name, int type, int perms,
ino_t *newInodeNumber, OverlayInode **node);
OverlayVolume * fVolume;
OverlayInode * fParentDir;
fs_vnode fSuperVnode;
ino_t fInodeNumber;
write_buffer * fWriteBuffers;
off_t fOriginalNodeLength;
overlay_dirent ** fDirents;
uint32 fDirentCount;
struct stat fStat;
bool fHasStat;
bool fHasDirents;
bool fIsVirtual;
};
@@ -101,7 +156,8 @@ private:
OverlayVolume::OverlayVolume(fs_volume *volume)
: fVolume(volume)
: fVolume(volume),
fCurrentInodeNumber((ino_t)1 << 32)
{
}
@@ -115,27 +171,53 @@ OverlayVolume::~OverlayVolume()
OverlayInode::OverlayInode(OverlayVolume *volume, fs_vnode *superVnode,
ino_t inodeNumber)
ino_t inodeNumber, OverlayInode *parentDir, mode_t mode)
: fVolume(volume),
fSuperVnode(*superVnode),
fParentDir(parentDir),
fInodeNumber(inodeNumber),
fWriteBuffers(NULL),
fOriginalNodeLength(-1),
fHasStat(false)
fDirents(NULL),
fDirentCount(0),
fHasStat(false),
fHasDirents(false),
fIsVirtual(superVnode == NULL)
{
TRACE("inode created\n");
TRACE("inode created %lld\n", fInodeNumber);
if (superVnode != NULL)
fSuperVnode = *superVnode;
else {
fStat.st_dev = SuperVolume()->id;
fStat.st_ino = fInodeNumber;
fStat.st_mode = mode;
fStat.st_nlink = 1;
fStat.st_uid = 0;
fStat.st_gid = 0;
fStat.st_size = 0;
fStat.st_rdev = 0;
fStat.st_blksize = 1024;
fStat.st_atime = fStat.st_mtime = fStat.st_ctime = fStat.st_crtime
= time(NULL);
fStat.st_type = 0;
fHasStat = true;
}
}
OverlayInode::~OverlayInode()
{
TRACE("inode destroyed\n");
TRACE("inode destroyed %lld\n", fInodeNumber);
write_buffer *element = fWriteBuffers;
while (element) {
write_buffer *next = element->next;
free(element);
element = next;
}
for (uint32 i = 0; i < fDirentCount; i++)
free(fDirents[i]);
free(fDirents);
}
@@ -146,6 +228,35 @@ OverlayInode::InitCheck()
}
status_t
OverlayInode::Lookup(const char *name, ino_t *inodeNumber)
{
if (strcmp(name, ".") == 0) {
*inodeNumber = fInodeNumber;
return get_vnode(SuperVolume(), *inodeNumber, NULL);
}
if (fIsVirtual && strcmp(name, "..") == 0) {
*inodeNumber = fParentDir->InodeNumber();
return get_vnode(Volume(), *inodeNumber, NULL);
}
for (uint32 i = 0; i < fDirentCount; i++) {
if (strcmp(fDirents[i]->name, name) == 0) {
*inodeNumber = fDirents[i]->inode_number;
return get_vnode(SuperVolume(), *inodeNumber, NULL);
}
}
if (!fHasDirents && !fIsVirtual && fSuperVnode.ops->lookup != NULL) {
return fSuperVnode.ops->lookup(SuperVolume(), &fSuperVnode, name,
inodeNumber);
}
return B_ENTRY_NOT_FOUND;
}
status_t
OverlayInode::ReadStat(struct stat *stat)
{
@@ -180,7 +291,7 @@ OverlayInode::WriteStat(const struct stat *stat, uint32 statMask)
fStat.st_size = stat->st_size;
if (statMask & B_STAT_MODE)
fStat.st_mode = stat->st_mode;
fStat.st_mode = (fStat.st_mode & ~S_IUMSK) | (stat->st_mode & S_IUMSK);
if (statMask & B_STAT_UID)
fStat.st_uid = stat->st_uid;
if (statMask & B_STAT_GID)
@@ -202,9 +313,31 @@ OverlayInode::WriteStat(const struct stat *stat, uint32 statMask)
}
status_t
OverlayInode::Create(const char *name, int openMode, int perms, void **cookie,
ino_t *newInodeNumber)
{
OverlayInode *newNode = NULL;
status_t result = _CreateCommon(name, S_IFREG, perms, newInodeNumber,
&newNode);
if (result != B_OK)
return result;
return newNode->Open(openMode, cookie);
}
status_t
OverlayInode::Open(int openMode, void **_cookie)
{
if (fIsVirtual) {
if (openMode & O_TRUNC)
fStat.st_size = 0;
*_cookie = NULL;
return B_OK;
}
if (fSuperVnode.ops->open == NULL)
return B_UNSUPPORTED;
@@ -243,6 +376,9 @@ OverlayInode::Open(int openMode, void **_cookie)
status_t
OverlayInode::Close(void *_cookie)
{
if (fIsVirtual)
return B_OK;
open_cookie *cookie = (open_cookie *)_cookie;
return fSuperVnode.ops->close(SuperVolume(), &fSuperVnode,
cookie->super_cookie);
@@ -252,6 +388,9 @@ OverlayInode::Close(void *_cookie)
status_t
OverlayInode::FreeCookie(void *_cookie)
{
if (fIsVirtual)
return B_OK;
open_cookie *cookie = (open_cookie *)_cookie;
status_t result = fSuperVnode.ops->free_cookie(SuperVolume(),
&fSuperVnode, cookie->super_cookie);
@@ -396,12 +535,325 @@ OverlayInode::Write(void *_cookie, off_t position, const void *buffer,
}
status_t
OverlayInode::CreateDir(const char *name, int perms, ino_t *newInodeNumber)
{
return _CreateCommon(name, S_IFDIR, perms, newInodeNumber, NULL);
}
status_t
OverlayInode::RemoveDir(const char *name)
{
return RemoveEntry(name, NULL);
}
status_t
OverlayInode::OpenDir(void **cookie)
{
if (!fHasDirents)
_PopulateDirents();
open_dir_cookie *dirCookie = (open_dir_cookie *)malloc(
sizeof(open_dir_cookie));
if (dirCookie == NULL)
return B_NO_MEMORY;
dirCookie->index = 0;
*cookie = dirCookie;
return B_OK;
}
status_t
OverlayInode::CloseDir(void *cookie)
{
return B_OK;
}
status_t
OverlayInode::FreeDirCookie(void *cookie)
{
free(cookie);
return B_OK;
}
status_t
OverlayInode::ReadDir(void *cookie, struct dirent *buffer, size_t bufferSize,
uint32 *num)
{
open_dir_cookie *dirCookie = (open_dir_cookie *)cookie;
if (dirCookie->index >= fDirentCount) {
*num = 0;
return B_OK;
}
overlay_dirent *dirent = fDirents[dirCookie->index++];
size_t nameLength = MIN(strlen(dirent->name),
bufferSize - sizeof(struct dirent)) + 1;
buffer->d_dev = SuperVolume()->id;
buffer->d_pdev = 0;
buffer->d_ino = dirent->inode_number;
buffer->d_pino = 0;
buffer->d_reclen = sizeof(struct dirent) + nameLength;
strlcpy(buffer->d_name, dirent->name, nameLength);
*num = 1;
return B_OK;
}
status_t
OverlayInode::RewindDir(void *cookie)
{
open_dir_cookie *dirCookie = (open_dir_cookie *)cookie;
dirCookie->index = 0;
return B_OK;
}
status_t
OverlayInode::CreateSymlink(const char *name, const char *path, int perms)
{
OverlayInode *newNode = NULL;
status_t result = _CreateCommon(name, S_IFLNK, perms, NULL, &newNode);
if (result != B_OK)
return result;
size_t writeLength = strlen(path);
return newNode->Write(NULL, 0, path, &writeLength);
}
status_t
OverlayInode::ReadSymlink(char *buffer, size_t *bufferSize)
{
if (fIsVirtual) {
if (!S_ISLNK(fStat.st_mode))
return B_BAD_VALUE;
return Read(NULL, 0, buffer, bufferSize);
}
if (fSuperVnode.ops->read_symlink == NULL)
return B_UNSUPPORTED;
return fSuperVnode.ops->read_symlink(SuperVolume(), &fSuperVnode, buffer,
bufferSize);
}
status_t
OverlayInode::AddEntry(overlay_dirent *entry)
{
if (!fHasDirents)
_PopulateDirents();
for (uint32 i = 0; i < fDirentCount; i++)
if (strcmp(fDirents[i]->name, entry->name) == 0)
return B_FILE_EXISTS;
overlay_dirent **newDirents = (overlay_dirent **)realloc(fDirents,
sizeof(overlay_dirent *) * (fDirentCount + 1));
if (newDirents == NULL)
return B_NO_MEMORY;
fDirents = newDirents;
fDirents[fDirentCount++] = entry;
notify_entry_created(SuperVolume()->id, fInodeNumber, entry->name,
entry->inode_number);
return B_OK;
}
status_t
OverlayInode::RemoveEntry(const char *name, overlay_dirent **_entry)
{
if (!fHasDirents)
_PopulateDirents();
for (uint32 i = 0; i < fDirentCount; i++) {
overlay_dirent *entry = fDirents[i];
if (strcmp(entry->name, name) == 0) {
for (uint32 j = i + 1; j < fDirentCount; j++)
fDirents[j - 1] = fDirents[j];
fDirentCount--;
notify_entry_removed(SuperVolume()->id, fInodeNumber, entry->name,
entry->inode_number);
if (_entry != NULL)
*_entry = entry;
else {
free(entry->name);
free(entry);
}
return B_OK;
}
}
return B_ENTRY_NOT_FOUND;
}
status_t
OverlayInode::_PopulateDirents()
{
if (fHasDirents)
return B_OK;
if (fIsVirtual || fSuperVnode.ops->open_dir == NULL
|| fSuperVnode.ops->read_dir == NULL) {
fDirents = (overlay_dirent **)malloc(sizeof(overlay_dirent *) * 2);
if (fDirents == NULL)
return B_NO_MEMORY;
const char *names[] = { ".", ".." };
ino_t inodes[] = { fInodeNumber,
fParentDir != NULL ? fParentDir->InodeNumber() : 0 };
for (uint32 i = 0; i < 2; i++) {
fDirents[i] = (overlay_dirent *)malloc(sizeof(overlay_dirent));
if (fDirents[i] == NULL)
return B_NO_MEMORY;
fDirents[i]->inode_number = inodes[i];
fDirents[i]->name = strdup(names[i]);
if (fDirents[i]->name == NULL) {
free(fDirents[i]);
return B_NO_MEMORY;
}
fDirentCount++;
}
fHasDirents = true;
return B_OK;
}
fHasDirents = true;
void *superCookie = NULL;
status_t result = fSuperVnode.ops->open_dir(SuperVolume(),
&fSuperVnode, &superCookie);
if (result != B_OK)
return result;
size_t bufferSize = sizeof(struct dirent) + B_FILE_NAME_LENGTH;
struct dirent *buffer = (struct dirent *)malloc(bufferSize);
if (buffer == NULL)
return B_NO_MEMORY;
while (result == B_OK) {
uint32 num = 1;
result = fSuperVnode.ops->read_dir(SuperVolume(),
&fSuperVnode, superCookie, buffer, bufferSize, &num);
if (result != B_OK || num == 0)
break;
overlay_dirent **newDirents = (overlay_dirent **)realloc(fDirents,
sizeof(overlay_dirent *) * (fDirentCount + num));
if (newDirents == NULL)
break;
fDirents = newDirents;
struct dirent *dirent = buffer;
for (uint32 i = 0; i < num; i++) {
overlay_dirent *entry = (overlay_dirent *)malloc(
sizeof(overlay_dirent));
if (entry == NULL)
break;
entry->inode_number = dirent->d_ino;
entry->name = strdup(dirent->d_name);
if (entry->name == NULL) {
free(entry);
break;
}
fDirents[fDirentCount++] = entry;
dirent = (struct dirent *)((uint8 *)dirent + dirent->d_reclen);
}
}
if (fSuperVnode.ops->close_dir != NULL)
fSuperVnode.ops->close_dir(SuperVolume(), &fSuperVnode, superCookie);
if (fSuperVnode.ops->free_dir_cookie != NULL)
fSuperVnode.ops->free_dir_cookie(SuperVolume(), &fSuperVnode, superCookie);
free(buffer);
return B_OK;
}
status_t
OverlayInode::_CreateCommon(const char *name, int type, int perms,
ino_t *newInodeNumber, OverlayInode **_node)
{
if (!fHasStat)
ReadStat(NULL);
if (!S_ISDIR(fStat.st_mode))
return B_NOT_A_DIRECTORY;
overlay_dirent *entry = (overlay_dirent *)malloc(sizeof(overlay_dirent));
if (entry == NULL)
return B_NO_MEMORY;
entry->name = strdup(name);
if (entry->name == NULL) {
free(entry);
return B_NO_MEMORY;
}
entry->inode_number = fVolume->BuildInodeNumber();
OverlayInode *node = new(std::nothrow) OverlayInode(fVolume, NULL,
entry->inode_number, this, perms | type);
if (node == NULL) {
free(entry->name);
free(entry);
return B_NO_MEMORY;
}
status_t result = AddEntry(entry);
if (result != B_OK) {
free(entry->name);
free(entry);
delete node;
}
result = publish_overlay_vnode(fVolume->Volume(), entry->inode_number,
node, type);
if (result != B_OK) {
RemoveEntry(entry->name, NULL);
delete node;
return result;
}
if (newInodeNumber != NULL)
*newInodeNumber = entry->inode_number;
if (_node != NULL)
*_node = node;
return B_OK;
}
// #pragma mark - vnode ops
#define OVERLAY_CALL(op, params...) \
TRACE("relaying op: " #op "\n"); \
OverlayInode *node = (OverlayInode *)vnode->private_node; \
if (node->IsVirtual()) \
return B_UNSUPPORTED; \
fs_vnode *superVnode = node->SuperVnode(); \
if (superVnode->ops->op != NULL) \
return superVnode->ops->op(volume->super_volume, superVnode, params);
@@ -410,10 +862,15 @@ OverlayInode::Write(void *_cookie, off_t position, const void *buffer,
static status_t
overlay_put_vnode(fs_volume *volume, fs_vnode *vnode, bool reenter)
{
TRACE("put_vnode\n");
OverlayInode *node = (OverlayInode *)vnode->private_node;
fs_vnode *superVnode = node->SuperVnode();
if (node->IsVirtual()) {
delete node;
return B_OK;
}
status_t result = B_OK;
fs_vnode *superVnode = node->SuperVnode();
if (superVnode->ops->put_vnode != NULL) {
result = superVnode->ops->put_vnode(volume->super_volume, superVnode,
reenter);
@@ -427,10 +884,15 @@ overlay_put_vnode(fs_volume *volume, fs_vnode *vnode, bool reenter)
static status_t
overlay_remove_vnode(fs_volume *volume, fs_vnode *vnode, bool reenter)
{
TRACE("remove_vnode\n");
OverlayInode *node = (OverlayInode *)vnode->private_node;
fs_vnode *superVnode = node->SuperVnode();
if (node->IsVirtual()) {
delete node;
return B_OK;
}
status_t result = B_OK;
fs_vnode *superVnode = node->SuperVnode();
if (superVnode->ops->remove_vnode != NULL) {
result = superVnode->ops->remove_vnode(volume->super_volume, superVnode,
reenter);
@@ -451,8 +913,12 @@ overlay_get_super_vnode(fs_volume *volume, fs_vnode *vnode,
}
OverlayInode *node = (OverlayInode *)vnode->private_node;
fs_vnode *superVnode = node->SuperVnode();
if (node->IsVirtual()) {
*_superVnode = *vnode;
return B_OK;
}
fs_vnode *superVnode = node->SuperVnode();
if (superVnode->ops->get_super_vnode != NULL) {
return superVnode->ops->get_super_vnode(volume->super_volume,
superVnode, superVolume, _superVnode);
@@ -466,8 +932,8 @@ overlay_get_super_vnode(fs_volume *volume, fs_vnode *vnode,
static status_t
overlay_lookup(fs_volume *volume, fs_vnode *vnode, const char *name, ino_t *id)
{
OVERLAY_CALL(lookup, name, id)
return B_UNSUPPORTED;
TRACE("lookup: \"%s\"\n", name);
return ((OverlayInode *)vnode->private_node)->Lookup(name, id);
}
@@ -574,12 +1040,6 @@ overlay_deselect(fs_volume *volume, fs_vnode *vnode, void *cookie, uint8 event,
static status_t
overlay_fsync(fs_volume *volume, fs_vnode *vnode)
{
OverlayInode *node = (OverlayInode *)vnode->private_node;
fs_vnode *superVnode = node->SuperVnode();
if (superVnode->ops->fsync != NULL)
return superVnode->ops->fsync(volume->super_volume, superVnode);
return B_OK;
}
@@ -588,8 +1048,9 @@ static status_t
overlay_read_symlink(fs_volume *volume, fs_vnode *vnode, char *buffer,
size_t *bufferSize)
{
OVERLAY_CALL(read_symlink, buffer, bufferSize)
return B_UNSUPPORTED;
TRACE("read_symlink\n");
return ((OverlayInode *)vnode->private_node)->ReadSymlink(buffer,
bufferSize);
}
@@ -597,8 +1058,9 @@ static status_t
overlay_create_symlink(fs_volume *volume, fs_vnode *vnode, const char *name,
const char *path, int mode)
{
OVERLAY_CALL(create_symlink, name, path, mode)
return B_UNSUPPORTED;
TRACE("create_symlink: \"%s\" -> \"%s\"\n", name, path);
return ((OverlayInode *)vnode->private_node)->CreateSymlink(name, path,
mode);
}
@@ -606,7 +1068,6 @@ static status_t
overlay_link(fs_volume *volume, fs_vnode *vnode, const char *name,
fs_vnode *target)
{
OVERLAY_CALL(link, name, target)
return B_UNSUPPORTED;
}
@@ -614,31 +1075,64 @@ overlay_link(fs_volume *volume, fs_vnode *vnode, const char *name,
static status_t
overlay_unlink(fs_volume *volume, fs_vnode *vnode, const char *name)
{
OVERLAY_CALL(unlink, name)
return B_UNSUPPORTED;
TRACE("unlink: \"%s\"\n", name);
return ((OverlayInode *)vnode->private_node)->RemoveEntry(name, NULL);
}
static status_t
overlay_rename(fs_volume *volume, fs_vnode *vnode,
const char *fromName, fs_vnode *toDir, const char *toName)
const char *fromName, fs_vnode *toVnode, const char *toName)
{
OVERLAY_CALL(rename, fromName, toDir, toName)
return B_UNSUPPORTED;
TRACE("rename: \"%s\" -> \"%s\"\n", fromName, toName);
OverlayInode *fromNode = (OverlayInode *)vnode->private_node;
OverlayInode *toNode = (OverlayInode *)toVnode->private_node;
overlay_dirent *entry = NULL;
status_t result = fromNode->RemoveEntry(fromName, &entry);
if (result != B_OK)
return result;
char *oldName = entry->name;
entry->name = strdup(toName);
if (entry->name == NULL) {
entry->name = oldName;
if (fromNode->AddEntry(entry) != B_OK) {
free(entry->name);
free(entry);
}
return B_NO_MEMORY;
}
result = toNode->AddEntry(entry);
if (result != B_OK) {
free(entry->name);
entry->name = oldName;
if (fromNode->AddEntry(entry) != B_OK) {
free(entry->name);
free(entry);
}
return result;
}
return B_OK;
}
static status_t
overlay_access(fs_volume *volume, fs_vnode *vnode, int mode)
{
OVERLAY_CALL(access, mode)
return B_UNSUPPORTED;
// TODO: implement
return B_OK;
}
static status_t
overlay_read_stat(fs_volume *volume, fs_vnode *vnode, struct stat *stat)
{
TRACE("read_stat\n");
return ((OverlayInode *)vnode->private_node)->ReadStat(stat);
}
@@ -647,6 +1141,7 @@ static status_t
overlay_write_stat(fs_volume *volume, fs_vnode *vnode, const struct stat *stat,
uint32 statMask)
{
TRACE("write_stat\n");
return ((OverlayInode *)vnode->private_node)->WriteStat(stat, statMask);
}
@@ -655,14 +1150,16 @@ static status_t
overlay_create(fs_volume *volume, fs_vnode *vnode, const char *name,
int openMode, int perms, void **cookie, ino_t *newVnodeID)
{
OVERLAY_CALL(create, name, openMode, perms, cookie, newVnodeID)
return B_UNSUPPORTED;
TRACE("create: \"%s\"\n", name);
return ((OverlayInode *)vnode->private_node)->Create(name, openMode,
perms, cookie, newVnodeID);
}
static status_t
overlay_open(fs_volume *volume, fs_vnode *vnode, int openMode, void **cookie)
{
TRACE("open\n");
return ((OverlayInode *)vnode->private_node)->Open(openMode, cookie);
}
@@ -670,6 +1167,7 @@ overlay_open(fs_volume *volume, fs_vnode *vnode, int openMode, void **cookie)
static status_t
overlay_close(fs_volume *volume, fs_vnode *vnode, void *cookie)
{
TRACE("close\n");
return ((OverlayInode *)vnode->private_node)->Close(cookie);
}
@@ -677,6 +1175,7 @@ overlay_close(fs_volume *volume, fs_vnode *vnode, void *cookie)
static status_t
overlay_free_cookie(fs_volume *volume, fs_vnode *vnode, void *cookie)
{
TRACE("free_cookie\n");
return ((OverlayInode *)vnode->private_node)->FreeCookie(cookie);
}
@@ -685,6 +1184,7 @@ static status_t
overlay_read(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos,
void *buffer, size_t *length)
{
TRACE("read\n");
return ((OverlayInode *)vnode->private_node)->Read(cookie, pos, buffer,
length);
}
@@ -694,6 +1194,7 @@ static status_t
overlay_write(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos,
const void *buffer, size_t *length)
{
TRACE("write\n");
return ((OverlayInode *)vnode->private_node)->Write(cookie, pos, buffer,
length);
}
@@ -703,40 +1204,41 @@ static status_t
overlay_create_dir(fs_volume *volume, fs_vnode *vnode, const char *name,
int perms, ino_t *newVnodeID)
{
OVERLAY_CALL(create_dir, name, perms, newVnodeID)
return B_UNSUPPORTED;
TRACE("create_dir: \"%s\"\n", name);
return ((OverlayInode *)vnode->private_node)->CreateDir(name, perms,
newVnodeID);
}
static status_t
overlay_remove_dir(fs_volume *volume, fs_vnode *vnode, const char *name)
{
OVERLAY_CALL(remove_dir, name)
return B_UNSUPPORTED;
TRACE("remove_dir: \"%s\"\n", name);
return ((OverlayInode *)vnode->private_node)->RemoveDir(name);
}
static status_t
overlay_open_dir(fs_volume *volume, fs_vnode *vnode, void **cookie)
{
OVERLAY_CALL(open_dir, cookie)
return B_UNSUPPORTED;
TRACE("open_dir\n");
return ((OverlayInode *)vnode->private_node)->OpenDir(cookie);
}
static status_t
overlay_close_dir(fs_volume *volume, fs_vnode *vnode, void *cookie)
{
OVERLAY_CALL(close_dir, cookie)
return B_UNSUPPORTED;
TRACE("close_dir\n");
return ((OverlayInode *)vnode->private_node)->CloseDir(cookie);
}
static status_t
overlay_free_dir_cookie(fs_volume *volume, fs_vnode *vnode, void *cookie)
{
OVERLAY_CALL(free_dir_cookie, cookie)
return B_UNSUPPORTED;
TRACE("free_dir_cookie\n");
return ((OverlayInode *)vnode->private_node)->FreeDirCookie(cookie);
}
@@ -744,16 +1246,17 @@ static status_t
overlay_read_dir(fs_volume *volume, fs_vnode *vnode, void *cookie,
struct dirent *buffer, size_t bufferSize, uint32 *num)
{
OVERLAY_CALL(read_dir, cookie, buffer, bufferSize, num)
return B_UNSUPPORTED;
TRACE("read_dir\n");
return ((OverlayInode *)vnode->private_node)->ReadDir(cookie, buffer,
bufferSize, num);
}
static status_t
overlay_rewind_dir(fs_volume *volume, fs_vnode *vnode, void *cookie)
{
OVERLAY_CALL(rewind_dir, cookie)
return B_UNSUPPORTED;
TRACE("rewind_dir\n");
return ((OverlayInode *)vnode->private_node)->RewindDir(cookie);
}
@@ -1312,6 +1815,15 @@ static file_system_module_info sOverlayFileSystem = {
NULL // initialize
};
status_t
publish_overlay_vnode(fs_volume *volume, ino_t inodeNumber, void *privateNode,
int type)
{
return publish_vnode(volume, inodeNumber, privateNode, &sOverlayVnodeOps,
type, 0);
}
} // namespace write_overlay
using namespace write_overlay;