mirror of
https://github.com/genodelabs/genode.git
synced 2025-03-27 22:29:16 +00:00
parent
430bde3636
commit
ead59325c7
@ -74,21 +74,6 @@ class Fatfs::File_system : public Vfs::File_system
|
|||||||
File *f = Genode::Avl_node<File>::child(cmp);
|
File *f = Genode::Avl_node<File>::child(cmp);
|
||||||
return f ? f->lookup(path_str) : nullptr;
|
return f ? f->lookup(path_str) : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Recursive flush to block device
|
|
||||||
*/
|
|
||||||
void flush()
|
|
||||||
{
|
|
||||||
/* flush the cache for this open file */
|
|
||||||
f_sync(&fil);
|
|
||||||
|
|
||||||
/* flush child nodes */
|
|
||||||
if (File *f = Genode::Avl_node<File>::child(-1))
|
|
||||||
f->flush();
|
|
||||||
if (File *f = Genode::Avl_node<File>::child( 1))
|
|
||||||
f->flush();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Fatfs_handle : Vfs_handle
|
struct Fatfs_handle : Vfs_handle
|
||||||
@ -197,23 +182,6 @@ class Fatfs::File_system : public Vfs::File_system
|
|||||||
/* Pre-allocated FIL */
|
/* Pre-allocated FIL */
|
||||||
File *_next_file = nullptr;
|
File *_next_file = nullptr;
|
||||||
|
|
||||||
/**
|
|
||||||
* Flush pending writes on open files to blocks
|
|
||||||
*/
|
|
||||||
void _flush_open(Genode::Duration time)
|
|
||||||
{
|
|
||||||
if (_open_files.first())
|
|
||||||
_open_files.first()->flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Timeout to schedule after writes
|
|
||||||
*/
|
|
||||||
Timer::Connection _timer { _env, "vfs_fatfs" };
|
|
||||||
|
|
||||||
Timer::One_shot_timeout<Fatfs::File_system> _flush_timeout {
|
|
||||||
_timer, *this, &File_system::_flush_open };
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an open FatFS file matching path or null.
|
* Return an open FatFS file matching path or null.
|
||||||
*/
|
*/
|
||||||
@ -333,6 +301,7 @@ class Fatfs::File_system : public Vfs::File_system
|
|||||||
Allocator &alloc) override
|
Allocator &alloc) override
|
||||||
{
|
{
|
||||||
Fatfs_file_handle *handle;
|
Fatfs_file_handle *handle;
|
||||||
|
|
||||||
File *file = _opened_file(path);
|
File *file = _opened_file(path);
|
||||||
bool create = vfs_mode & OPEN_MODE_CREATE;
|
bool create = vfs_mode & OPEN_MODE_CREATE;
|
||||||
|
|
||||||
@ -341,6 +310,11 @@ class Fatfs::File_system : public Vfs::File_system
|
|||||||
return OPEN_ERR_EXISTS;
|
return OPEN_ERR_EXISTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (file && f_error(&file->fil)) {
|
||||||
|
Genode::error("FatFS: hard error on file '", path, "'");
|
||||||
|
return OPEN_ERR_NO_PERM;
|
||||||
|
};
|
||||||
|
|
||||||
/* attempt allocation before modifying blocks */
|
/* attempt allocation before modifying blocks */
|
||||||
if (!_next_file)
|
if (!_next_file)
|
||||||
_next_file = new (_alloc) File();
|
_next_file = new (_alloc) File();
|
||||||
@ -442,17 +416,6 @@ class Fatfs::File_system : public Vfs::File_system
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Sync_result complete_sync(Vfs_handle *vfs_handle) override
|
|
||||||
{
|
|
||||||
Fatfs_file_handle *handle = static_cast<Fatfs_file_handle *>(vfs_handle);
|
|
||||||
|
|
||||||
File *file = handle->file;
|
|
||||||
if (file)
|
|
||||||
f_sync(&file->fil);
|
|
||||||
|
|
||||||
return SYNC_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
Genode::Dataspace_capability dataspace(char const *path) override
|
Genode::Dataspace_capability dataspace(char const *path) override
|
||||||
{
|
{
|
||||||
Genode::warning(__func__, " not implemented in FAT plugin");
|
Genode::warning(__func__, " not implemented in FAT plugin");
|
||||||
@ -496,7 +459,7 @@ class Fatfs::File_system : public Vfs::File_system
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Stat_result stat(char const *path, Stat &stat)
|
Stat_result stat(char const *path, Stat &stat) override
|
||||||
{
|
{
|
||||||
stat = Stat();
|
stat = Stat();
|
||||||
|
|
||||||
@ -593,21 +556,34 @@ class Fatfs::File_system : public Vfs::File_system
|
|||||||
if ((handle->status_flags()&OPEN_MODE_ACCMODE) == OPEN_MODE_RDONLY)
|
if ((handle->status_flags()&OPEN_MODE_ACCMODE) == OPEN_MODE_RDONLY)
|
||||||
return WRITE_ERR_INVALID;
|
return WRITE_ERR_INVALID;
|
||||||
|
|
||||||
FRESULT fres;
|
FRESULT fres = FR_OK;
|
||||||
FIL *fil = &handle->file->fil;
|
FIL *fil = &handle->file->fil;
|
||||||
|
FSIZE_t const wpos = handle->seek();
|
||||||
|
|
||||||
|
/* seek file pointer */
|
||||||
|
if (f_tell(fil) != wpos) {
|
||||||
|
/*
|
||||||
|
* seeking beyond the EOF will expand the file size
|
||||||
|
* and is not the expected behavior
|
||||||
|
*/
|
||||||
|
if (f_size(fil) < wpos)
|
||||||
|
return WRITE_ERR_INVALID;
|
||||||
|
|
||||||
|
fres = f_lseek(fil, wpos);
|
||||||
|
/* check the seek again */
|
||||||
|
if (f_tell(fil) != handle->seek())
|
||||||
|
return WRITE_ERR_IO;
|
||||||
|
}
|
||||||
|
|
||||||
fres = f_lseek(fil, handle->seek());
|
|
||||||
if (fres == FR_OK) {
|
if (fres == FR_OK) {
|
||||||
UINT bw = 0;
|
UINT bw = 0;
|
||||||
fres = f_write(fil, buf, buf_size, &bw);
|
fres = f_write(fil, buf, buf_size, &bw);
|
||||||
|
f_sync(fil);
|
||||||
out_count = bw;
|
out_count = bw;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (fres) {
|
switch (fres) {
|
||||||
case FR_OK:
|
case FR_OK: return WRITE_OK;
|
||||||
/* flush to blocks after ~1 seconds of inactivity */
|
|
||||||
_flush_timeout.schedule(Genode::Microseconds(1 << 20));
|
|
||||||
return WRITE_OK;
|
|
||||||
case FR_INVALID_OBJECT: return WRITE_ERR_INVALID;
|
case FR_INVALID_OBJECT: return WRITE_ERR_INVALID;
|
||||||
case FR_TIMEOUT: return WRITE_ERR_WOULD_BLOCK;
|
case FR_TIMEOUT: return WRITE_ERR_WOULD_BLOCK;
|
||||||
default: return WRITE_ERR_IO;
|
default: return WRITE_ERR_IO;
|
||||||
@ -619,25 +595,28 @@ class Fatfs::File_system : public Vfs::File_system
|
|||||||
file_size &out_count) override
|
file_size &out_count) override
|
||||||
{
|
{
|
||||||
Fatfs_file_handle *handle = static_cast<Fatfs_file_handle *>(vfs_handle);
|
Fatfs_file_handle *handle = static_cast<Fatfs_file_handle *>(vfs_handle);
|
||||||
|
|
||||||
return handle->complete_read(buf, buf_size, out_count);
|
return handle->complete_read(buf, buf_size, out_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ftruncate_result ftruncate(Vfs_handle *vfs_handle, file_size len) override
|
Ftruncate_result ftruncate(Vfs_handle *vfs_handle, file_size len) override
|
||||||
{
|
{
|
||||||
FRESULT res;
|
|
||||||
Fatfs_file_handle *handle = static_cast<Fatfs_file_handle *>(vfs_handle);
|
Fatfs_file_handle *handle = static_cast<Fatfs_file_handle *>(vfs_handle);
|
||||||
|
|
||||||
if (!handle->file)
|
if (!handle->file)
|
||||||
return FTRUNCATE_ERR_NO_PERM;
|
return FTRUNCATE_ERR_NO_PERM;
|
||||||
if ((handle->status_flags()&OPEN_MODE_ACCMODE) == OPEN_MODE_RDONLY)
|
if ((handle->status_flags()&OPEN_MODE_ACCMODE) == OPEN_MODE_RDONLY)
|
||||||
return FTRUNCATE_ERR_NO_PERM;
|
return FTRUNCATE_ERR_NO_PERM;
|
||||||
|
|
||||||
FIL *fil = &handle->file->fil;
|
FIL *fil = &handle->file->fil;
|
||||||
|
FRESULT res = FR_OK;
|
||||||
|
|
||||||
/* f_lseek will exapand a file */
|
/* f_lseek will expand a file... */
|
||||||
res = f_lseek(fil, len);
|
res = f_lseek(fil, len);
|
||||||
|
if (f_tell(fil) != len)
|
||||||
|
return f_size(fil) < len ?
|
||||||
|
FTRUNCATE_ERR_NO_SPACE : FTRUNCATE_ERR_NO_PERM;
|
||||||
|
|
||||||
/* otherwise truncate will shorten the file to its seek position */
|
/* ... otherwise truncate will shorten to the seek position */
|
||||||
if ((res == FR_OK) && (len < f_size(fil))) {
|
if ((res == FR_OK) && (len < f_size(fil))) {
|
||||||
res = f_truncate(fil);
|
res = f_truncate(fil);
|
||||||
if (res == FR_OK && len < handle->seek())
|
if (res == FR_OK && len < handle->seek())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user