Now maintains uid/gid/mode/mtime/crtime, added pipefs_write_stat().
Access permissions are not verified. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@8961 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Copyright 2003-2004, Axel Dörfler, [email protected]. All rights reserved.
|
** Copyright 2003-2004, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
** Distributed under the terms of the OpenBeOS License.
|
** Distributed under the terms of the Haiku License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@ class Volume {
|
|||||||
|
|
||||||
Inode *Lookup(vnode_id id);
|
Inode *Lookup(vnode_id id);
|
||||||
Inode *FindNode(const char *name);
|
Inode *FindNode(const char *name);
|
||||||
Inode *CreateNode(const char *name, int32 type);
|
Inode *CreateNode(Inode *parent, const char *name, int32 type);
|
||||||
status_t DeleteNode(Inode *inode, bool forceDelete = false);
|
status_t DeleteNode(Inode *inode, bool forceDelete = false);
|
||||||
status_t RemoveNode(Inode *directory, const char *name);
|
status_t RemoveNode(Inode *directory, const char *name);
|
||||||
|
|
||||||
@@ -116,13 +116,23 @@ class Volume {
|
|||||||
|
|
||||||
class Inode {
|
class Inode {
|
||||||
public:
|
public:
|
||||||
Inode(Volume *volume, const char *name, int32 type);
|
Inode(Volume *volume, Inode *parent, const char *name, int32 type);
|
||||||
~Inode();
|
~Inode();
|
||||||
|
|
||||||
status_t InitCheck();
|
status_t InitCheck();
|
||||||
vnode_id ID() const { return fID; }
|
vnode_id ID() const { return fID; }
|
||||||
const char *Name() const { return fName; }
|
const char *Name() const { return fName; }
|
||||||
|
|
||||||
int32 Type() const { return fType; }
|
int32 Type() const { return fType; }
|
||||||
|
void SetMode(mode_t mode) { fType = (fType & ~S_IUMSK) | (mode & S_IUMSK); }
|
||||||
|
gid_t GroupID() const { return fGroupID; }
|
||||||
|
void SetGroupID(gid_t gid) { fGroupID = gid; }
|
||||||
|
uid_t UserID() const { return fUserID; }
|
||||||
|
void SetUserID(uid_t uid) { fUserID = uid; }
|
||||||
|
time_t CreationTime() const { return fCreationTime; }
|
||||||
|
void SetCreationTime(time_t creationTime) { fCreationTime = creationTime; }
|
||||||
|
time_t ModificationTime() const { return fModificationTime; }
|
||||||
|
void SetModificationTime(time_t modificationTime) { fModificationTime = modificationTime; }
|
||||||
|
|
||||||
Inode *Next() const { return fNext; }
|
Inode *Next() const { return fNext; }
|
||||||
void SetNext(Inode *inode) { fNext = inode; }
|
void SetNext(Inode *inode) { fNext = inode; }
|
||||||
@@ -150,6 +160,10 @@ class Inode {
|
|||||||
vnode_id fID;
|
vnode_id fID;
|
||||||
int32 fType;
|
int32 fType;
|
||||||
const char *fName;
|
const char *fName;
|
||||||
|
gid_t fGroupID;
|
||||||
|
uid_t fUserID;
|
||||||
|
time_t fCreationTime;
|
||||||
|
time_t fModificationTime;
|
||||||
|
|
||||||
cbuf *fBufferChain;
|
cbuf *fBufferChain;
|
||||||
|
|
||||||
@@ -202,7 +216,7 @@ Volume::Volume(mount_id id)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// create the root vnode
|
// create the root vnode
|
||||||
fRootNode = CreateNode("", S_IFDIR);
|
fRootNode = CreateNode(NULL, "", S_IFDIR | 0777);
|
||||||
if (fRootNode == NULL)
|
if (fRootNode == NULL)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -258,9 +272,9 @@ Volume::Unlock()
|
|||||||
|
|
||||||
|
|
||||||
Inode *
|
Inode *
|
||||||
Volume::CreateNode(const char *name, int32 type)
|
Volume::CreateNode(Inode *parent, const char *name, int32 type)
|
||||||
{
|
{
|
||||||
Inode *inode = new Inode(this, name, type);
|
Inode *inode = new Inode(this, parent, name, type);
|
||||||
if (inode == NULL)
|
if (inode == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -269,12 +283,15 @@ Volume::CreateNode(const char *name, int32 type)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == S_IFIFO)
|
if (S_ISFIFO(type))
|
||||||
InsertNode(inode);
|
InsertNode(inode);
|
||||||
|
|
||||||
hash_insert(fNodeHash, inode);
|
hash_insert(fNodeHash, inode);
|
||||||
new_vnode(ID(), inode->ID(), inode);
|
new_vnode(ID(), inode->ID(), inode);
|
||||||
|
|
||||||
|
if (fRootNode != NULL)
|
||||||
|
fRootNode->SetModificationTime(time(NULL));
|
||||||
|
|
||||||
return inode;
|
return inode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,6 +302,9 @@ Volume::DeleteNode(Inode *inode, bool forceDelete)
|
|||||||
// remove it from the global hash table
|
// remove it from the global hash table
|
||||||
hash_remove(fNodeHash, inode);
|
hash_remove(fNodeHash, inode);
|
||||||
|
|
||||||
|
if (fRootNode != NULL)
|
||||||
|
fRootNode->SetModificationTime(time(NULL));
|
||||||
|
|
||||||
delete inode;
|
delete inode;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -394,7 +414,7 @@ Volume::RemoveNode(Inode *directory, const char *name)
|
|||||||
Inode *inode = FindNode(name);
|
Inode *inode = FindNode(name);
|
||||||
if (inode == NULL)
|
if (inode == NULL)
|
||||||
status = B_ENTRY_NOT_FOUND;
|
status = B_ENTRY_NOT_FOUND;
|
||||||
else if (inode->Type() == S_IFDIR)
|
else if (S_ISDIR(inode->Type()))
|
||||||
status = B_NOT_ALLOWED;
|
status = B_NOT_ALLOWED;
|
||||||
|
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
@@ -416,7 +436,7 @@ err:
|
|||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
Inode::Inode(Volume *volume, const char *name, int32 type)
|
Inode::Inode(Volume *volume, Inode *parent, const char *name, int32 type)
|
||||||
:
|
:
|
||||||
fNext(NULL),
|
fNext(NULL),
|
||||||
fHashNext(NULL),
|
fHashNext(NULL),
|
||||||
@@ -429,10 +449,15 @@ Inode::Inode(Volume *volume, const char *name, int32 type)
|
|||||||
fID = volume->GetNextNodeID();
|
fID = volume->GetNextNodeID();
|
||||||
fType = type;
|
fType = type;
|
||||||
|
|
||||||
if (type == S_IFIFO) {
|
if (S_ISFIFO(type)) {
|
||||||
fWriteLock = create_sem(1, "pipe write");
|
fWriteLock = create_sem(1, "pipe write");
|
||||||
benaphore_init(&fRequestLock, "pipe request");
|
benaphore_init(&fRequestLock, "pipe request");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fUserID = geteuid();
|
||||||
|
fGroupID = parent ? parent->GroupID() : getegid();
|
||||||
|
|
||||||
|
fCreationTime = fModificationTime = time(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -440,7 +465,7 @@ Inode::~Inode()
|
|||||||
{
|
{
|
||||||
free(const_cast<char *>(fName));
|
free(const_cast<char *>(fName));
|
||||||
|
|
||||||
if (fType == S_IFIFO) {
|
if (S_ISFIFO(fType)) {
|
||||||
delete_sem(fWriteLock);
|
delete_sem(fWriteLock);
|
||||||
benaphore_destroy(&fRequestLock);
|
benaphore_destroy(&fRequestLock);
|
||||||
}
|
}
|
||||||
@@ -451,7 +476,7 @@ status_t
|
|||||||
Inode::InitCheck()
|
Inode::InitCheck()
|
||||||
{
|
{
|
||||||
if (fName == NULL
|
if (fName == NULL
|
||||||
|| fType == S_IFIFO && (fRequestLock.sem < B_OK || fWriteLock < B_OK))
|
|| S_ISFIFO(fType) && (fRequestLock.sem < B_OK || fWriteLock < B_OK))
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -805,7 +830,7 @@ pipefs_lookup(fs_volume _volume, fs_vnode _dir, const char *name, vnode_id *_id,
|
|||||||
TRACE(("pipefs_lookup: entry dir %p, name '%s'\n", _dir, name));
|
TRACE(("pipefs_lookup: entry dir %p, name '%s'\n", _dir, name));
|
||||||
|
|
||||||
Inode *directory = (Inode *)_dir;
|
Inode *directory = (Inode *)_dir;
|
||||||
if (directory->Type() != S_IFDIR)
|
if (!S_ISDIR(directory->Type()))
|
||||||
return B_NOT_A_DIRECTORY;
|
return B_NOT_A_DIRECTORY;
|
||||||
|
|
||||||
volume->Lock();
|
volume->Lock();
|
||||||
@@ -909,7 +934,7 @@ pipefs_remove_vnode(fs_volume _volume, fs_vnode _node, bool reenter)
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
pipefs_create(fs_volume _volume, fs_vnode _dir, const char *name, int openMode, int perms,
|
pipefs_create(fs_volume _volume, fs_vnode _dir, const char *name, int openMode, int mode,
|
||||||
fs_cookie *_cookie, vnode_id *_newVnodeID)
|
fs_cookie *_cookie, vnode_id *_newVnodeID)
|
||||||
{
|
{
|
||||||
Volume *volume = (Volume *)_volume;
|
Volume *volume = (Volume *)_volume;
|
||||||
@@ -932,7 +957,7 @@ pipefs_create(fs_volume _volume, fs_vnode _dir, const char *name, int openMode,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
inode = volume->CreateNode(name, S_IFIFO);
|
inode = volume->CreateNode(directory, name, S_IFIFO | mode);
|
||||||
if (inode == NULL) {
|
if (inode == NULL) {
|
||||||
status = B_NO_MEMORY;
|
status = B_NO_MEMORY;
|
||||||
goto err;
|
goto err;
|
||||||
@@ -1096,7 +1121,7 @@ pipefs_open_dir(fs_volume _volume, fs_vnode _node, fs_cookie *_cookie)
|
|||||||
TRACE(("pipefs_open_dir(): vnode = %p\n", _node));
|
TRACE(("pipefs_open_dir(): vnode = %p\n", _node));
|
||||||
|
|
||||||
Inode *inode = (Inode *)_node;
|
Inode *inode = (Inode *)_node;
|
||||||
if (inode->Type() != S_IFDIR)
|
if (!S_ISDIR(inode->Type()))
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
if (inode != &volume->RootNode())
|
if (inode != &volume->RootNode())
|
||||||
@@ -1280,14 +1305,60 @@ pipefs_read_stat(fs_volume _volume, fs_vnode _node, struct stat *stat)
|
|||||||
Volume *volume = (Volume *)_volume;
|
Volume *volume = (Volume *)_volume;
|
||||||
Inode *inode = (Inode *)_node;
|
Inode *inode = (Inode *)_node;
|
||||||
|
|
||||||
TRACE(("pipefs_rstat: vnode %p (0x%Lx), stat %p\n", inode, inode->ID(), stat));
|
TRACE(("pipefs_read_stat: vnode %p (0x%Lx), stat %p\n", inode, inode->ID(), stat));
|
||||||
|
|
||||||
stat->st_dev = volume->ID();
|
stat->st_dev = volume->ID();
|
||||||
stat->st_ino = inode->ID();
|
stat->st_ino = inode->ID();
|
||||||
stat->st_size = inode->BytesInChain();
|
stat->st_size = inode->BytesInChain();
|
||||||
stat->st_mode = inode->Type() | 0777;
|
stat->st_mode = inode->Type();
|
||||||
|
|
||||||
return 0;
|
stat->st_nlink = 1;
|
||||||
|
stat->st_blksize = 4096;
|
||||||
|
|
||||||
|
stat->st_uid = inode->UserID();
|
||||||
|
stat->st_gid = inode->GroupID();
|
||||||
|
|
||||||
|
stat->st_atime = time(NULL);
|
||||||
|
stat->st_mtime = stat->st_ctime = inode->ModificationTime();
|
||||||
|
stat->st_crtime = inode->CreationTime();
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
pipefs_write_stat(fs_volume _volume, fs_vnode _node, const struct stat *stat, uint32 statMask)
|
||||||
|
{
|
||||||
|
Volume *volume = (Volume *)_volume;
|
||||||
|
Inode *inode = (Inode *)_node;
|
||||||
|
|
||||||
|
TRACE(("pipefs_write_stat: vnode %p (0x%Lx), stat %p\n", inode, inode->ID(), stat));
|
||||||
|
|
||||||
|
// we cannot change the size of anything
|
||||||
|
if (statMask & FS_WRITE_STAT_SIZE)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
volume->Lock();
|
||||||
|
// the inode's locks don't exist for the root node
|
||||||
|
// (but would be more appropriate to use here)
|
||||||
|
|
||||||
|
if (statMask & FS_WRITE_STAT_MODE)
|
||||||
|
inode->SetMode(stat->st_mode);
|
||||||
|
|
||||||
|
if (statMask & FS_WRITE_STAT_UID)
|
||||||
|
inode->SetUserID(stat->st_uid);
|
||||||
|
if (statMask & FS_WRITE_STAT_GID)
|
||||||
|
inode->SetGroupID(stat->st_gid);
|
||||||
|
|
||||||
|
if (statMask & FS_WRITE_STAT_MTIME)
|
||||||
|
inode->SetModificationTime(stat->st_mtime);
|
||||||
|
if (statMask & FS_WRITE_STAT_CRTIME)
|
||||||
|
inode->SetCreationTime(stat->st_crtime);
|
||||||
|
|
||||||
|
volume->Unlock();
|
||||||
|
|
||||||
|
notify_listener(B_STAT_CHANGED, volume->ID(), 0, 0, inode->ID(), NULL);
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1349,7 +1420,7 @@ file_system_info gPipeFileSystem = {
|
|||||||
|
|
||||||
NULL, // fs_access()
|
NULL, // fs_access()
|
||||||
&pipefs_read_stat,
|
&pipefs_read_stat,
|
||||||
NULL, // fs_write_stat()
|
&pipefs_write_stat,
|
||||||
|
|
||||||
/* file */
|
/* file */
|
||||||
&pipefs_create,
|
&pipefs_create,
|
||||||
|
|||||||
Reference in New Issue
Block a user