Added support for O_TRUNC, file creation, and writing to files.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29689 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-03-25 01:07:00 +00:00
parent 2ce5b17258
commit d16ba4b957
2 changed files with 95 additions and 15 deletions
@@ -412,12 +412,12 @@ FUSEFileSystem::_InitCapabilities()
// fNodeCapabilities.Set(FS_VNODE_CAPABILITY_WRITE_STAT, fFS->ops.wstat);
// file operations
// fNodeCapabilities.Set(FS_VNODE_CAPABILITY_CREATE, fFS->ops.create);
fNodeCapabilities.Set(FS_VNODE_CAPABILITY_CREATE, fFS->ops.create);
fNodeCapabilities.Set(FS_VNODE_CAPABILITY_OPEN, fFS->ops.open);
fNodeCapabilities.Set(FS_VNODE_CAPABILITY_CLOSE, fFS->ops.flush);
fNodeCapabilities.Set(FS_VNODE_CAPABILITY_FREE_COOKIE, fFS->ops.release);
fNodeCapabilities.Set(FS_VNODE_CAPABILITY_READ, fFS->ops.read);
// fNodeCapabilities.Set(FS_VNODE_CAPABILITY_WRITE, fFS->ops.write);
fNodeCapabilities.Set(FS_VNODE_CAPABILITY_WRITE, fFS->ops.write);
// directory operations
// fNodeCapabilities.Set(FS_VNODE_CAPABILITY_CREATE_DIR, fFS->ops.mkdir);
@@ -870,11 +870,57 @@ FUSEVolume::WriteStat(void* node, const struct stat *st, uint32 mask)
status_t
FUSEVolume::Create(void* dir, const char* name, int openMode, int mode,
void** cookie, ino_t* vnid)
FUSEVolume::Create(void* _dir, const char* name, int openMode, int mode,
void** _cookie, ino_t* _vnid)
{
// TODO: Implement!
return B_UNSUPPORTED;
FUSENode* dir = (FUSENode*)_dir;
PRINT(("FUSEVolume::Create(%p (%lld), \"%s\", %#x, %#x)\n", dir, dir->id, name,
openMode, mode));
// lock the directory
NodeWriteLocker nodeLocker(this, dir, false);
if (nodeLocker.Status() != B_OK)
RETURN_ERROR(nodeLocker.Status());
// allocate a file cookie
FileCookie* cookie = new(std::nothrow) FileCookie(openMode);
if (cookie == NULL)
RETURN_ERROR(B_NO_MEMORY);
ObjectDeleter<FileCookie> cookieDeleter(cookie);
AutoLocker<Locker> locker(fLock);
// get a path for the node
char path[B_PATH_NAME_LENGTH];
size_t pathLen;
status_t error = _BuildPath(dir, name, path, pathLen);
if (error != B_OK)
RETURN_ERROR(error);
locker.Unlock();
// create the file
int fuseError = fuse_fs_create(fFS, path, mode, cookie);
if (fuseError != 0)
RETURN_ERROR(fuseError);
// get the node
FUSENode* node;
error = _GetNode(dir, name, &node);
if (error != B_OK) {
// This is bad. We've create the file successfully, but couldn't get
// the node. Close the file and delete the entry.
fuse_fs_flush(fFS, path, cookie);
fuse_fs_release(fFS, path, cookie);
fuse_fs_unlink(fFS, path);
RETURN_ERROR(error);
}
cookieDeleter.Detach();
*_cookie = cookie;
*_vnid = node->id;
return B_OK;
}
@@ -892,10 +938,6 @@ PRINT(("FUSEVolume::Open(%p (%lld), %#x)\n", node, node->id, openMode));
bool truncate = (openMode & O_TRUNC) != 0;
openMode &= ~O_TRUNC;
// TODO: Support truncation!
if (truncate)
RETURN_ERROR(B_NOT_ALLOWED);
// allocate a file cookie
FileCookie* cookie = new(std::nothrow) FileCookie(openMode);
if (cookie == NULL)
@@ -916,7 +958,17 @@ PRINT(("FUSEVolume::Open(%p (%lld), %#x)\n", node, node->id, openMode));
// open the file
int fuseError = fuse_fs_open(fFS, path, cookie);
if (fuseError != 0)
return fuseError;
RETURN_ERROR(fuseError);
// truncate the file, if requested
if (truncate) {
fuseError = fuse_fs_ftruncate(fFS, path, 0, cookie);
if (fuseError != 0) {
fuse_fs_flush(fFS, path, cookie);
fuse_fs_release(fFS, path, cookie);
RETURN_ERROR(fuseError);
}
}
cookieDeleter.Detach();
*_cookie = cookie;
@@ -1027,11 +1079,39 @@ FUSEVolume::Read(void* _node, void* _cookie, off_t pos, void* buffer,
status_t
FUSEVolume::Write(void* node, void* cookie, off_t pos, const void* buffer,
size_t bufferSize, size_t* bytesWritten)
FUSEVolume::Write(void* _node, void* _cookie, off_t pos, const void* buffer,
size_t bufferSize, size_t* _bytesWritten)
{
// TODO: Implement!
return B_UNSUPPORTED;
FUSENode* node = (FUSENode*)_node;
FileCookie* cookie = (FileCookie*)_cookie;
*_bytesWritten = 0;
// lock the directory
NodeReadLocker nodeLocker(this, node, true);
if (nodeLocker.Status() != B_OK)
RETURN_ERROR(nodeLocker.Status());
AutoLocker<Locker> locker(fLock);
// get a path for the node
char path[B_PATH_NAME_LENGTH];
size_t pathLen;
status_t error = _BuildPath(node, path, pathLen);
if (error != B_OK)
RETURN_ERROR(error);
locker.Unlock();
// read the file
int bytesWritten = fuse_fs_write(fFS, path, (const char*)buffer, bufferSize,
pos, cookie);
if (bytesWritten < 0)
return bytesWritten;
*_bytesWritten = bytesWritten;
return B_OK;
}