fs: ext2: File operations
Introduced functions: - read - write - seek - tell Signed-off-by: Franciszek Zdobylak <fzdobylak@antmicro.com>
This commit is contained in:
parent
7b7b334bc3
commit
a87cc6c0b6
|
@ -549,6 +549,88 @@ static int64_t find_dir_entry(struct ext2_inode *inode, const char *name, size_t
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Inode operations --------------------------------------------------------- */
|
||||
|
||||
ssize_t ext2_inode_read(struct ext2_inode *inode, void *buf, uint32_t offset, size_t nbytes)
|
||||
{
|
||||
int rc = 0;
|
||||
ssize_t read = 0;
|
||||
uint32_t block_size = inode->i_fs->block_size;
|
||||
|
||||
while (read < nbytes && offset < inode->i_size) {
|
||||
|
||||
uint32_t block = offset / block_size;
|
||||
uint32_t block_off = offset % block_size;
|
||||
|
||||
rc = ext2_fetch_inode_block(inode, block);
|
||||
if (rc < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t left_on_blk = block_size - block_off;
|
||||
uint32_t left_in_file = inode->i_size - offset;
|
||||
size_t to_read = MIN(nbytes, MIN(left_on_blk, left_in_file));
|
||||
|
||||
memcpy((uint8_t *)buf + read, inode_current_block_mem(inode) + block_off, to_read);
|
||||
|
||||
read += to_read;
|
||||
offset += to_read;
|
||||
}
|
||||
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
}
|
||||
return read;
|
||||
}
|
||||
|
||||
ssize_t ext2_inode_write(struct ext2_inode *inode, const void *buf, uint32_t offset, size_t nbytes)
|
||||
{
|
||||
int rc = 0;
|
||||
ssize_t written = 0;
|
||||
uint32_t block_size = inode->i_fs->block_size;
|
||||
|
||||
while (written < nbytes) {
|
||||
uint32_t block = offset / block_size;
|
||||
uint32_t block_off = offset % block_size;
|
||||
|
||||
LOG_DBG("inode:%d Write to block %d (offset: %d-%zd/%d)",
|
||||
inode->i_id, block, offset, offset + nbytes, inode->i_size);
|
||||
|
||||
rc = ext2_fetch_inode_block(inode, block);
|
||||
if (rc < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
size_t to_write = MIN(nbytes, block_size - block_off);
|
||||
|
||||
memcpy(inode_current_block_mem(inode) + block_off, (uint8_t *)buf + written,
|
||||
to_write);
|
||||
LOG_DBG("Written %zd bytes at offset %d in block i%d", to_write, block_off, block);
|
||||
|
||||
rc = ext2_commit_inode_block(inode);
|
||||
if (rc < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
written += to_write;
|
||||
}
|
||||
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (offset + written > inode->i_size) {
|
||||
LOG_DBG("New inode size: %d -> %zd", inode->i_size, offset + written);
|
||||
inode->i_size = offset + written;
|
||||
rc = ext2_commit_inode(inode);
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
int ext2_get_direntry(struct ext2_dir *dir, struct fs_dirent *ent)
|
||||
{
|
||||
if (dir->d_off >= dir->d_inode->i_size) {
|
||||
|
|
|
@ -156,6 +156,36 @@ struct ext2_lookup_args {
|
|||
*/
|
||||
int ext2_lookup_inode(struct ext2_data *fs, struct ext2_lookup_args *args);
|
||||
|
||||
/* Inode operations */
|
||||
|
||||
/**
|
||||
* @brief Read from inode at given offset
|
||||
*
|
||||
* @param inode Inode
|
||||
* @param buf Buffer to hold read data
|
||||
* @param offset Offset in inode
|
||||
* @param nbytes Number of bytes to read
|
||||
*
|
||||
* @retval >=0 number of bytes read on success
|
||||
* @retval <0 error code
|
||||
*/
|
||||
ssize_t ext2_inode_read(struct ext2_inode *inode, void *buf, uint32_t offset,
|
||||
size_t nbytes);
|
||||
|
||||
/**
|
||||
* @brief Write to inode at given offset
|
||||
*
|
||||
* @param inode Inode
|
||||
* @param buf Buffer with data to write
|
||||
* @param offset Offset in inode
|
||||
* @param nbytes Number of bytes to write
|
||||
*
|
||||
* @retval >=0 number of bytes read on success
|
||||
* @retval <0 error code
|
||||
*/
|
||||
ssize_t ext2_inode_write(struct ext2_inode *inode, const void *buf,
|
||||
uint32_t offset, size_t nbytes);
|
||||
|
||||
/* Directory operations */
|
||||
|
||||
/**
|
||||
|
|
|
@ -125,6 +125,83 @@ out:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t ext2_read(struct fs_file_t *filp, void *dest, size_t nbytes)
|
||||
{
|
||||
struct ext2_file *f = filp->filep;
|
||||
|
||||
if ((f->f_flags & FS_O_READ) == 0) {
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
ssize_t r = ext2_inode_read(f->f_inode, dest, f->f_off, nbytes);
|
||||
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
f->f_off += r;
|
||||
return r;
|
||||
}
|
||||
|
||||
static ssize_t ext2_write(struct fs_file_t *filp, const void *src, size_t nbytes)
|
||||
{
|
||||
struct ext2_file *f = filp->filep;
|
||||
|
||||
if ((f->f_flags & FS_O_WRITE) == 0) {
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
if (f->f_flags & FS_O_APPEND) {
|
||||
f->f_off = f->f_inode->i_size;
|
||||
}
|
||||
|
||||
ssize_t r = ext2_inode_write(f->f_inode, src, f->f_off, nbytes);
|
||||
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
f->f_off += r;
|
||||
return r;
|
||||
}
|
||||
|
||||
static int ext2_lseek(struct fs_file_t *filp, off_t off, int whence)
|
||||
{
|
||||
struct ext2_file *f = filp->filep;
|
||||
|
||||
uint32_t new_off = 0;
|
||||
|
||||
switch (whence) {
|
||||
case FS_SEEK_SET:
|
||||
new_off = off;
|
||||
break;
|
||||
|
||||
case FS_SEEK_CUR:
|
||||
new_off = f->f_off + off;
|
||||
break;
|
||||
|
||||
case FS_SEEK_END:
|
||||
new_off = f->f_inode->i_size + off;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* New offset not inside the file. */
|
||||
if (new_off < 0 || new_off > f->f_inode->i_size) {
|
||||
return -EINVAL;
|
||||
}
|
||||
f->f_off = new_off;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static off_t ext2_tell(struct fs_file_t *filp)
|
||||
{
|
||||
struct ext2_file *f = filp->filep;
|
||||
|
||||
return f->f_off;
|
||||
}
|
||||
|
||||
/* Directory operations */
|
||||
|
||||
static int ext2_mkdir(struct fs_mount_t *mountp, const char *name)
|
||||
|
@ -375,6 +452,10 @@ static int ext2_statvfs(struct fs_mount_t *mountp, const char *path, struct fs_s
|
|||
static const struct fs_file_system_t ext2_fs = {
|
||||
.open = ext2_open,
|
||||
.close = ext2_close,
|
||||
.read = ext2_read,
|
||||
.write = ext2_write,
|
||||
.lseek = ext2_lseek,
|
||||
.tell = ext2_tell,
|
||||
.mkdir = ext2_mkdir,
|
||||
.mount = ext2_mount,
|
||||
.unmount = ext2_unmount,
|
||||
|
|
Loading…
Reference in a new issue