Now has a basic understanding of uid/gid/mode values and maintains it -
permissions are not tested, though. Removed the STREAM_TYPE_ constants. Now maintains a modification and creation time for all nodes. Implemented rootfs_write_stat() completely. rootfs_read_stat() now fills in all required values. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@8959 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+64
-29
@@ -28,13 +28,9 @@
|
|||||||
# define TRACE(x)
|
# define TRACE(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
STREAM_TYPE_DIR = S_IFDIR,
|
|
||||||
STREAM_TYPE_SYMLINK = S_IFLNK,
|
|
||||||
} stream_type;
|
|
||||||
|
|
||||||
struct rootfs_stream {
|
struct rootfs_stream {
|
||||||
stream_type type;
|
mode_t type;
|
||||||
struct stream_dir {
|
struct stream_dir {
|
||||||
struct rootfs_vnode *dir_head;
|
struct rootfs_vnode *dir_head;
|
||||||
struct rootfs_cookie *jar_head;
|
struct rootfs_cookie *jar_head;
|
||||||
@@ -47,8 +43,12 @@ struct rootfs_stream {
|
|||||||
|
|
||||||
struct rootfs_vnode {
|
struct rootfs_vnode {
|
||||||
struct rootfs_vnode *all_next;
|
struct rootfs_vnode *all_next;
|
||||||
vnode_id id;
|
vnode_id id;
|
||||||
char *name;
|
char *name;
|
||||||
|
time_t modification_time;
|
||||||
|
time_t creation_time;
|
||||||
|
uid_t uid;
|
||||||
|
gid_t gid;
|
||||||
struct rootfs_vnode *parent;
|
struct rootfs_vnode *parent;
|
||||||
struct rootfs_vnode *dir_next;
|
struct rootfs_vnode *dir_next;
|
||||||
struct rootfs_stream stream;
|
struct rootfs_stream stream;
|
||||||
@@ -109,7 +109,7 @@ rootfs_vnode_compare_func(void *_v, const void *_key)
|
|||||||
|
|
||||||
|
|
||||||
static struct rootfs_vnode *
|
static struct rootfs_vnode *
|
||||||
rootfs_create_vnode(struct rootfs *fs, const char *name, int type)
|
rootfs_create_vnode(struct rootfs *fs, struct rootfs_vnode *parent, const char *name, int type)
|
||||||
{
|
{
|
||||||
struct rootfs_vnode *vnode;
|
struct rootfs_vnode *vnode;
|
||||||
|
|
||||||
@@ -127,6 +127,10 @@ rootfs_create_vnode(struct rootfs *fs, const char *name, int type)
|
|||||||
|
|
||||||
vnode->id = fs->next_vnode_id++;
|
vnode->id = fs->next_vnode_id++;
|
||||||
vnode->stream.type = type;
|
vnode->stream.type = type;
|
||||||
|
vnode->creation_time = vnode->modification_time = time(NULL);
|
||||||
|
vnode->uid = geteuid();
|
||||||
|
vnode->gid = parent ? parent->gid : getegid();
|
||||||
|
// inherit group from parent if possible
|
||||||
|
|
||||||
return vnode;
|
return vnode;
|
||||||
}
|
}
|
||||||
@@ -215,7 +219,9 @@ rootfs_insert_in_dir(struct rootfs_vnode *dir, struct rootfs_vnode *v)
|
|||||||
{
|
{
|
||||||
v->dir_next = dir->stream.dir.dir_head;
|
v->dir_next = dir->stream.dir.dir_head;
|
||||||
dir->stream.dir.dir_head = v;
|
dir->stream.dir.dir_head = v;
|
||||||
return 0;
|
|
||||||
|
dir->modification_time = time(NULL);
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -235,10 +241,12 @@ rootfs_remove_from_dir(struct rootfs_vnode *dir, struct rootfs_vnode *findit)
|
|||||||
else
|
else
|
||||||
dir->stream.dir.dir_head = v->dir_next;
|
dir->stream.dir.dir_head = v->dir_next;
|
||||||
v->dir_next = NULL;
|
v->dir_next = NULL;
|
||||||
return 0;
|
|
||||||
|
dir->modification_time = time(NULL);
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return B_ENTRY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -260,9 +268,9 @@ rootfs_remove(struct rootfs *fs, struct rootfs_vnode *dir, const char *name, boo
|
|||||||
vnode = rootfs_find_in_dir(dir, name);
|
vnode = rootfs_find_in_dir(dir, name);
|
||||||
if (!vnode)
|
if (!vnode)
|
||||||
status = B_ENTRY_NOT_FOUND;
|
status = B_ENTRY_NOT_FOUND;
|
||||||
else if (isDirectory && vnode->stream.type != STREAM_TYPE_DIR)
|
else if (isDirectory && !S_ISDIR(vnode->stream.type))
|
||||||
status = B_NOT_A_DIRECTORY;
|
status = B_NOT_A_DIRECTORY;
|
||||||
else if (!isDirectory && vnode->stream.type == STREAM_TYPE_DIR)
|
else if (!isDirectory && S_ISDIR(vnode->stream.type))
|
||||||
status = B_IS_A_DIRECTORY;
|
status = B_IS_A_DIRECTORY;
|
||||||
else if (isDirectory && !rootfs_is_dir_empty(vnode))
|
else if (isDirectory && !rootfs_is_dir_empty(vnode))
|
||||||
status = B_DIRECTORY_NOT_EMPTY;
|
status = B_DIRECTORY_NOT_EMPTY;
|
||||||
@@ -314,7 +322,7 @@ rootfs_mount(mount_id id, const char *device, void *args, fs_volume *_fs, vnode_
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create the root vnode
|
// create the root vnode
|
||||||
vnode = rootfs_create_vnode(fs, ".", STREAM_TYPE_DIR);
|
vnode = rootfs_create_vnode(fs, NULL, ".", S_IFDIR | 0777);
|
||||||
if (vnode == NULL) {
|
if (vnode == NULL) {
|
||||||
err = B_NO_MEMORY;
|
err = B_NO_MEMORY;
|
||||||
goto err3;
|
goto err3;
|
||||||
@@ -385,7 +393,7 @@ rootfs_lookup(fs_volume _fs, fs_vnode _dir, const char *name, vnode_id *_id, int
|
|||||||
status_t status;
|
status_t status;
|
||||||
|
|
||||||
TRACE(("rootfs_lookup: entry dir %p, name '%s'\n", dir, name));
|
TRACE(("rootfs_lookup: entry dir %p, name '%s'\n", dir, name));
|
||||||
if (dir->stream.type != STREAM_TYPE_DIR)
|
if (!S_ISDIR(dir->stream.type))
|
||||||
return B_NOT_A_DIRECTORY;
|
return B_NOT_A_DIRECTORY;
|
||||||
|
|
||||||
mutex_lock(&fs->lock);
|
mutex_lock(&fs->lock);
|
||||||
@@ -556,7 +564,7 @@ rootfs_write(fs_volume fs, fs_vnode v, fs_cookie cookie, off_t pos, const void *
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
rootfs_create_dir(fs_volume _fs, fs_vnode _dir, const char *name, int perms, vnode_id *_newID)
|
rootfs_create_dir(fs_volume _fs, fs_vnode _dir, const char *name, int mode, vnode_id *_newID)
|
||||||
{
|
{
|
||||||
struct rootfs *fs = _fs;
|
struct rootfs *fs = _fs;
|
||||||
struct rootfs_vnode *dir = _dir;
|
struct rootfs_vnode *dir = _dir;
|
||||||
@@ -575,7 +583,7 @@ rootfs_create_dir(fs_volume _fs, fs_vnode _dir, const char *name, int perms, vno
|
|||||||
}
|
}
|
||||||
|
|
||||||
TRACE(("rootfs_create: creating new vnode\n"));
|
TRACE(("rootfs_create: creating new vnode\n"));
|
||||||
vnode = rootfs_create_vnode(fs, name, STREAM_TYPE_DIR);
|
vnode = rootfs_create_vnode(fs, dir, name, S_IFDIR | (mode & S_IUMSK));
|
||||||
if (vnode == NULL) {
|
if (vnode == NULL) {
|
||||||
status = B_NO_MEMORY;
|
status = B_NO_MEMORY;
|
||||||
goto err;
|
goto err;
|
||||||
@@ -621,7 +629,7 @@ rootfs_open_dir(fs_volume _fs, fs_vnode _v, fs_cookie *_cookie)
|
|||||||
|
|
||||||
TRACE(("rootfs_open: vnode %p\n", vnode));
|
TRACE(("rootfs_open: vnode %p\n", vnode));
|
||||||
|
|
||||||
if (vnode->stream.type != STREAM_TYPE_DIR)
|
if (!S_ISDIR(vnode->stream.type))
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
cookie = malloc(sizeof(struct rootfs_cookie));
|
cookie = malloc(sizeof(struct rootfs_cookie));
|
||||||
@@ -764,7 +772,7 @@ rootfs_read_link(fs_volume _fs, fs_vnode _link, char *buffer, size_t bufferSize)
|
|||||||
{
|
{
|
||||||
struct rootfs_vnode *link = _link;
|
struct rootfs_vnode *link = _link;
|
||||||
|
|
||||||
if (link->stream.type != STREAM_TYPE_SYMLINK)
|
if (!S_ISLNK(link->stream.type))
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
if (bufferSize < link->stream.symlink.length)
|
if (bufferSize < link->stream.symlink.length)
|
||||||
@@ -794,7 +802,7 @@ rootfs_symlink(fs_volume _fs, fs_vnode _dir, const char *name, const char *path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
TRACE(("rootfs_create: creating new symlink\n"));
|
TRACE(("rootfs_create: creating new symlink\n"));
|
||||||
vnode = rootfs_create_vnode(fs, name, STREAM_TYPE_SYMLINK);
|
vnode = rootfs_create_vnode(fs, dir, name, S_IFLNK | (mode & S_IUMSK));
|
||||||
if (vnode == NULL) {
|
if (vnode == NULL) {
|
||||||
status = B_NO_MEMORY;
|
status = B_NO_MEMORY;
|
||||||
goto err;
|
goto err;
|
||||||
@@ -914,28 +922,55 @@ rootfs_read_stat(fs_volume _fs, fs_vnode _v, struct stat *stat)
|
|||||||
struct rootfs *fs = _fs;
|
struct rootfs *fs = _fs;
|
||||||
struct rootfs_vnode *vnode = _v;
|
struct rootfs_vnode *vnode = _v;
|
||||||
|
|
||||||
TRACE(("rootfs_rstat: vnode %p (0x%Lx), stat %p\n", vnode, vnode->id, stat));
|
TRACE(("rootfs_read_stat: vnode %p (0x%Lx), stat %p\n", vnode, vnode->id, stat));
|
||||||
|
|
||||||
// stream exists, but we know to return size 0, since we can only hold directories
|
// stream exists, but we know to return size 0, since we can only hold directories
|
||||||
stat->st_dev = fs->id;
|
stat->st_dev = fs->id;
|
||||||
stat->st_ino = vnode->id;
|
stat->st_ino = vnode->id;
|
||||||
stat->st_size = 0;
|
stat->st_size = 0;
|
||||||
stat->st_mode = vnode->stream.type | DEFFILEMODE;
|
stat->st_mode = vnode->stream.type;
|
||||||
|
|
||||||
|
stat->st_nlink = 1;
|
||||||
|
stat->st_blksize = 65536;
|
||||||
|
|
||||||
|
stat->st_uid = vnode->uid;
|
||||||
|
stat->st_gid = vnode->gid;
|
||||||
|
|
||||||
|
stat->st_atime = time(NULL);
|
||||||
|
stat->st_mtime = stat->st_ctime = vnode->creation_time;
|
||||||
|
stat->st_crtime = vnode->creation_time;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
rootfs_write_stat(fs_volume _fs, fs_vnode _v, const struct stat *stat, uint32 statMask)
|
rootfs_write_stat(fs_volume _fs, fs_vnode _vnode, const struct stat *stat, uint32 statMask)
|
||||||
{
|
{
|
||||||
#ifdef TRACE_ROOTFS
|
struct rootfs *fs = _fs;
|
||||||
struct rootfs_vnode *v = _v;
|
struct rootfs_vnode *vnode = _vnode;
|
||||||
|
|
||||||
TRACE(("rootfs_wstat: vnode %p (0x%Lx), stat %p\n", v, v->id, stat));
|
TRACE(("rootfs_write_stat: vnode %p (0x%Lx), stat %p\n", vnode, vnode->id, stat));
|
||||||
#endif
|
|
||||||
// cannot change anything
|
// we cannot change the size of anything
|
||||||
return EINVAL;
|
if (statMask & FS_WRITE_STAT_SIZE)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
if (statMask & FS_WRITE_STAT_MODE)
|
||||||
|
vnode->stream.type = (vnode->stream.type & ~S_IUMSK) | (stat->st_mode & S_IUMSK);
|
||||||
|
|
||||||
|
if (statMask & FS_WRITE_STAT_UID)
|
||||||
|
vnode->uid = stat->st_uid;
|
||||||
|
if (statMask & FS_WRITE_STAT_GID)
|
||||||
|
vnode->gid = stat->st_gid;
|
||||||
|
|
||||||
|
if (statMask & FS_WRITE_STAT_MTIME)
|
||||||
|
vnode->modification_time = stat->st_mtime;
|
||||||
|
if (statMask & FS_WRITE_STAT_CRTIME)
|
||||||
|
vnode->creation_time = stat->st_crtime;
|
||||||
|
|
||||||
|
notify_listener(B_STAT_CHANGED, fs->id, 0, 0, vnode->id, NULL);
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user