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:
Axel Dörfler
2004-09-15 00:15:52 +00:00
parent e4a0232cc7
commit 31a726883b
+91 -20
View File
@@ -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,