Skip to content

Commit

Permalink
ext2: Add ability to mount devices and filesystems
Browse files Browse the repository at this point in the history
Fix setting attributes of newly created file
Fixes phoenix-rtos/phoenix-rtos-project#114

DONE: RTOS-675
  • Loading branch information
jmaksymowicz committed Nov 23, 2023
1 parent 7f2d478 commit 5d0b12e
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 86 deletions.
7 changes: 4 additions & 3 deletions ext2/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,6 @@ int _ext2_dir_read(ext2_t *fs, ext2_obj_t *dir, offs_t offs, struct dirent *res,
res->d_name[entry->len] = '\0';
free(entry);

if ((dir->flags & OFLAG_MOUNTPOINT) && !strncmp(res->d_name, "..", 2))
res->d_ino = (ino_t)dir->mnt.id;

dir->inode->atime = time(NULL);

return res->d_reclen;
Expand Down Expand Up @@ -251,6 +248,10 @@ int _ext2_dir_add(ext2_t *fs, ext2_obj_t *dir, const char *name, size_t len, uin
entry->type = DIRENT_CHRDEV;
else if (S_ISBLK(mode))
entry->type = DIRENT_BLKDEV;
else if (S_ISFIFO(mode))
entry->type = DIRENT_FIFO;
else if (S_ISSOCK(mode))
entry->type = DIRENT_SOCK;
else if (S_ISREG(mode))
entry->type = DIRENT_FILE;
else
Expand Down
90 changes: 54 additions & 36 deletions ext2/ext2.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,10 @@ int ext2_create(ext2_t *fs, id_t id, const char *name, size_t len, oid_t *dev, u
if (ext2_link(fs, id, name, len, obj->id) < 0)
return ext2_obj_destroy(fs, obj);

/* FIXME: FIFO */
if (S_ISCHR(obj->inode->mode) || S_ISBLK(obj->inode->mode))
if (EXT2_ISDEV(obj->inode->mode)) {
memcpy(&obj->dev, dev, sizeof(oid_t));
obj->flags |= OFLAG_MOUNTPOINT;
}

*res = obj->id;
ext2_obj_put(fs, obj);
Expand Down Expand Up @@ -81,22 +82,25 @@ int ext2_lookup(ext2_t *fs, id_t id, const char *name, size_t len, oid_t *res, o
int err;

res->port = fs->port;
if (!len || (name == NULL))
if ((len == 0) || (name == NULL)) {
return -EINVAL;
}

if ((dir = ext2_obj_get(fs, id)) == NULL)
if ((dir = ext2_obj_get(fs, id)) == NULL) {
return -ENOENT;
}

mutexLock(dir->lock);
for (i = 0, j = 0; i < len; i = j + 1, dir = obj) {
while ((i < len) && (name[i] == '/'))
while ((i < len) && (name[i] == '/')) {
i++;
}

j = i + 1;

while ((j < len) && (name[j] != '/'))
while ((j < len) && (name[j] != '/')) {
j++;

mutexLock(dir->lock);
}

do {
if (i >= len) {
Expand All @@ -109,10 +113,13 @@ int ext2_lookup(ext2_t *fs, id_t id, const char *name, size_t len, oid_t *res, o
break;
}

if ((err = _ext2_dir_search(fs, dir, name + i, j - i, &res->id)) < 0)
err = _ext2_dir_search(fs, dir, name + i, j - i, &res->id);
if (err < 0) {
break;
}

if ((obj = ext2_obj_get(fs, res->id)) == NULL) {
obj = ext2_obj_get(fs, res->id);
if (obj == NULL) {
ext2_unlink(fs, dir->id, name + i, j - i);
err = -ENOENT;
break;
Expand All @@ -122,20 +129,18 @@ int ext2_lookup(ext2_t *fs, id_t id, const char *name, size_t len, oid_t *res, o
mutexUnlock(dir->lock);
ext2_obj_put(fs, dir);

if (err < 0)
if (err < 0) {
return err;
}

mutexLock(obj->lock);
}

if (S_ISCHR(obj->inode->mode) || S_ISBLK(obj->inode->mode)) {
memcpy(dev, &obj->dev, sizeof(oid_t));
}
else {
dev->port = fs->port;
dev->id = res->id;
mutexLock(obj->lock);
if (EXT2_IS_MOUNTPOINT(obj) && S_ISDIR(obj->inode->mode)) {
break;
}
}

*dev = EXT2_IS_MOUNTPOINT(obj) ? obj->dev : *res;

mutexUnlock(obj->lock);
ext2_obj_put(fs, obj);

Expand Down Expand Up @@ -189,17 +194,15 @@ ssize_t ext2_read(ext2_t *fs, id_t id, offs_t offs, char *buff, size_t len)
mutexLock(obj->lock);

if (S_ISDIR(obj->inode->mode)) {
if ((obj->flags & (OFLAG_MOUNT | OFLAG_MOUNTPOINT)) && (len >= sizeof(oid_t))) {
ret = sizeof(oid_t);
memcpy(buff, &obj->mnt, ret);
if (EXT2_IS_MOUNTPOINT(obj)) {
ret = -EINVAL;
}
else {
ret = _ext2_dir_read(fs, obj, offs, (struct dirent *)buff, len);
}
}
else if ((S_ISCHR(obj->inode->mode) || S_ISBLK(obj->inode->mode)) && (len >= sizeof(oid_t))) {
ret = sizeof(oid_t);
memcpy(buff, &obj->dev, ret);
else if (EXT2_ISDEV(obj->inode->mode)) {
ret = -EINVAL;
}
else {
ret = _ext2_file_read(fs, obj, offs, buff, len);
Expand All @@ -222,10 +225,12 @@ ssize_t ext2_write(ext2_t *fs, id_t id, offs_t offs, const char *buff, size_t le

mutexLock(obj->lock);

if (S_ISDIR(obj->inode->mode) || S_ISCHR(obj->inode->mode) || S_ISBLK(obj->inode->mode))
if (S_ISDIR(obj->inode->mode) || EXT2_ISDEV(obj->inode->mode)) {
ret = -EINVAL;
else
}
else {
ret = _ext2_file_write(fs, obj, offs, buff, len);
}

mutexUnlock(obj->lock);
ext2_obj_put(fs, obj);
Expand Down Expand Up @@ -317,7 +322,7 @@ int ext2_getattr(ext2_t *fs, id_t id, int type, long long *attr)
else if (S_ISREG(obj->inode->mode)) {
*attr = otFile;
}
else if (S_ISCHR(obj->inode->mode) || S_ISBLK(obj->inode->mode) || S_ISFIFO(obj->inode->mode)) {
else if (EXT2_ISDEV(obj->inode->mode)) {
*attr = otDev;
}
else if (S_ISLNK(obj->inode->mode)) {
Expand Down Expand Up @@ -360,7 +365,7 @@ int ext2_getattr(ext2_t *fs, id_t id, int type, long long *attr)
}


int ext2_setattr(ext2_t *fs, id_t id, int type, long long attr)
int ext2_setattr(ext2_t *fs, id_t id, int type, long long attr, void *data, size_t len)
{
ext2_obj_t *obj;
int err = EOK;
Expand Down Expand Up @@ -402,6 +407,24 @@ int ext2_setattr(ext2_t *fs, id_t id, int type, long long attr)
obj->inode->atime = attr;
break;

case atDev:
if (data != NULL && len == sizeof(oid_t)) {
oid_t dev;
memcpy(&dev, data, len);
if ((dev.port == fs->port) && (dev.id == id)) {
obj->flags &= ~OFLAG_MOUNTPOINT;
}
else {
obj->dev = dev;
obj->flags |= OFLAG_MOUNTPOINT;
}
}
else {
err = -EINVAL;
}
break;


default:
/* unknown / invalid attribute to set */
err = -EINVAL;
Expand Down Expand Up @@ -530,12 +553,7 @@ int ext2_unlink(ext2_t *fs, id_t id, const char *name, size_t len)
mutexLock(obj->lock);

do {
if (obj->flags & (OFLAG_MOUNTPOINT | OFLAG_MOUNT)) {
err = -EBUSY;
break;
}

if (S_ISDIR(obj->inode->mode) && !_ext2_dir_empty(fs, obj)) {
if (S_ISDIR(obj->inode->mode) && (EXT2_IS_MOUNTPOINT(obj) || !_ext2_dir_empty(fs, obj))) {
err = -ENOTEMPTY;
break;
}
Expand Down
5 changes: 4 additions & 1 deletion ext2/ext2.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
#define MAX_OBJECTS 512 /* Max number of filesystem objects in use */


#define EXT2_ISDEV(x) (S_ISCHR(x) || S_ISBLK(x) || S_ISFIFO(x) || S_ISSOCK(x))


/* Filesystem common data types forward declaration */
typedef struct _ext2_sb_t ext2_sb_t; /* SuperBlock */
typedef struct _ext2_gd_t ext2_gd_t; /* Group Descriptor*/
Expand Down Expand Up @@ -108,7 +111,7 @@ extern int ext2_getattr(ext2_t *fs, id_t id, int type, long long *attr);


/* Sets file attributes */
extern int ext2_setattr(ext2_t *fs, id_t id, int type, long long attr);
extern int ext2_setattr(ext2_t *fs, id_t id, int type, long long attr, void *data, size_t len);


/* Adds a link */
Expand Down
63 changes: 36 additions & 27 deletions ext2/libext2.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,48 +25,62 @@
#include "libext2.h"


static int libext2_create(void *info, oid_t *oid, const char *name, oid_t *dev, unsigned mode, int type, oid_t *res)
static int libext2_create(void *info, oid_t *dir, const char *name, oid_t *oid, unsigned mode, int type, oid_t *dev)
{
ext2_t *fs = (ext2_t *)info;
ext2_obj_t *obj;
oid_t devOther;
int ret;
dev->port = fs->port;
oid->port = fs->port;

switch (type) {
case otDir:
mode |= S_IFDIR;
if (!S_ISDIR(mode)) {
mode &= ALLPERMS;
mode |= S_IFDIR;
}
break;

case otFile:
mode |= S_IFREG;
if (!S_ISREG(mode)) {
mode &= ALLPERMS;
mode |= S_IFREG;
}
break;

case otDev:
mode &= 0x1ff;
mode |= S_IFCHR;
if (!EXT2_ISDEV(mode)) {
mode &= ALLPERMS;
mode |= S_IFCHR;
}
break;

case otSymlink:
mode |= S_IFLNK;
if (!S_ISLNK(mode)) {
mode &= ALLPERMS;
mode |= S_IFLNK;
}
break;
}

size_t namelen = strlen(name);

if (ext2_lookup(fs, oid->id, name, namelen, dev, &devOther) > 0) {
if ((obj = ext2_obj_get(fs, dev->id)) == NULL) {
if (ext2_lookup(fs, dir->id, name, namelen, oid, &devOther) > 0) {
if ((obj = ext2_obj_get(fs, oid->id)) == NULL) {
return -EINVAL;
}

mutexLock(obj->lock);

if (S_ISCHR(obj->inode->mode) || S_ISBLK(obj->inode->mode)) {
if (!devOther.port && !devOther.id && (S_ISCHR(mode) || S_ISBLK(mode))) {
memcpy(&obj->dev, res, sizeof(oid_t));
if (EXT2_ISDEV(obj->inode->mode) && !EXT2_IS_MOUNTPOINT(obj)) {
/* This can happen if we have a device file stored in filesystem
* but no device oid is associated with it at the moment
*/
if (EXT2_ISDEV(mode)) {
memcpy(&obj->dev, dev, sizeof(oid_t));
obj->inode->mode = mode;
obj->flags |= OFLAG_DIRTY;
dev->id = obj->id;
obj->flags |= OFLAG_DIRTY | OFLAG_MOUNTPOINT;
oid->id = obj->id;
ret = _ext2_obj_sync(fs, obj);

mutexUnlock(obj->lock);
Expand All @@ -77,12 +91,7 @@ static int libext2_create(void *info, oid_t *oid, const char *name, oid_t *dev,
mutexUnlock(obj->lock);
ext2_obj_put(fs, obj);

if ((devOther.port == fs->port) && (devOther.id == dev->id)) {
if (ext2_unlink(fs, oid->id, name, namelen) < 0) {
return -EEXIST;
}
}
else {
if (ext2_unlink(fs, dir->id, name, namelen) < 0) {
return -EEXIST;
}
}
Expand All @@ -94,19 +103,19 @@ static int libext2_create(void *info, oid_t *oid, const char *name, oid_t *dev,
}
}

ret = ext2_create(fs, oid->id, name, namelen, res, mode, &dev->id);
ret = ext2_create(fs, dir->id, name, namelen, dev, mode, &oid->id);

if (ret >= 0 && type == otSymlink) {
const char *target = name + namelen + 1;
size_t targetlen = strlen(target);
int retWrite;

/* not writing trailing '\0', readlink() does not append it */
retWrite = ext2_write(fs, dev->id, 0, target, targetlen);
retWrite = ext2_write(fs, oid->id, 0, target, targetlen);
if (retWrite < 0) {
ret = retWrite;
ext2_destroy(fs, dev->id);
dev->id = 0;
ext2_destroy(fs, oid->id);
oid->id = 0;
}
}

Expand Down Expand Up @@ -140,7 +149,7 @@ static ssize_t libext2_write(void *info, oid_t *oid, offs_t offs, const void *da

static int libext2_setattr(void *info, oid_t *oid, int type, long long attr, void *data, size_t len)
{
return ext2_setattr((ext2_t *)info, oid->id, type, attr);
return ext2_setattr((ext2_t *)info, oid->id, type, attr, data, len);
}


Expand Down Expand Up @@ -168,9 +177,9 @@ static int libext2_lookup(void *info, oid_t *oid, const char *name, oid_t *res,
}


static int libext2_link(void *info, oid_t *oid, const char *name, oid_t *res)
static int libext2_link(void *info, oid_t *dir, const char *name, oid_t *oid)
{
return ext2_link((ext2_t *)info, oid->id, name, strlen(name), res->id);
return ext2_link((ext2_t *)info, dir->id, name, strlen(name), oid->id);
}


Expand Down
Loading

0 comments on commit 5d0b12e

Please sign in to comment.