📄 target.c
字号:
// Replace old seghead with a new and remove all old segments
journal_begin(i);
if ((i = object_create(name, 0, 0, -dir)) < 0)
return i;
// Do not link child
fs.link_child = 0;
journal_end(0);
// If any further segments exist then remove them now
if (fs.i_backup > 0)
if ((error = object_remove(fs.i_backup)) < 0)
return error;
tw(tr_bstat());
}
else {
// Get total size of the file.
fs.fd[fdi].size = segfile_seek(i, INT_MAX, &dummy, 0);
}
if (is_open_option(option, FFS_O_APPEND)) {
fs.fd[fdi].fp = fs.fd[fdi].size;
}
}
if (is_open_option(option, FFS_O_WRONLY)) {
#if (TARGET == 1)
if ((fs.fd[fdi].buf = (char *) target_malloc(fs.fd_buf_size)) == 0)
return EFFS_MEMORY;
#else
if ((fs.fd[fdi].buf = malloc(fs.fd_buf_size)) == 0)
return EFFS_MEMORY;
#endif
}
// Save data in file descriptor
fs.fd[fdi].seghead = i;
fs.fd[fdi].options = option;
return fdi + FFS_FD_OFFSET;
#undef pathname
#undef option
}
fd_t ffs_open(const char *pathname, ffs_options_t option)
{
FFS_BLOCKING_CALL_BEGIN();
result = ffs_open_b(pathname, option, 0, &fb);
FFS_BLOCKING_CALL_END();
return result;
}
req_id_t ffs_open_nb(const char *pathname, ffs_options_t option,
T_RV_RETURN *cp)
{
return ffs_open_b(pathname, option, cp, 0);
}
req_id_t ffs_close_b(fd_t fdi, T_RV_RETURN *cp, struct ffs_blocking_s *fb)
{
int error;
tw(tr(TR_FUNC, TrApi, "ffs_close(%d) ?\n", fdi));
ttw(ttr(TTrApi, "ffs_close(%d) ?" NL, fdi));
{
struct ffs_req_s *req;
MSG_ALLOC(req);
req->fdi = fdi;
req->request_id = request_id_get();
req->fb = fb;
req->cp = cp;
req->cmd = CLOSE;
MSG_SEND(req);
return req->request_id;
}
}
effs_t task_close(struct ffs_req_s *p)
{
iref_t i;
int error;
#define fdi p->fdi
if (fs.initerror)
return fs.initerror;
fdi -= FFS_FD_OFFSET;
if (!is_fd_valid(fdi))
return EFFS_BADFD;
if (is_open_option(fs.fd[fdi].options, FFS_O_WRONLY )) {
if ((error = datasync(fdi)) < 0)
return error;
#if (TARGET == 1)
target_free(fs.fd[fdi].buf);
#else
free(fs.fd[fdi].buf);
#endif
}
// Clear all data in file descriptor
fs.fd[fdi].seghead = 0;
fs.fd[fdi].options = fs.fd[fdi].fp = 0;
return EFFS_OK;
#undef fdi
}
effs_t ffs_close(fd_t fdi)
{
FFS_BLOCKING_CALL_BEGIN();
result = ffs_close_b(fdi, 0, &fb);
FFS_BLOCKING_CALL_END();
return result;
}
req_id_t ffs_close_nb(fd_t fdi, T_RV_RETURN *cp)
{
return ffs_close_b( fdi, cp, 0);
}
req_id_t ffs_write_b(fd_t fdi, void *src, int amount,
T_RV_RETURN *cp, struct ffs_blocking_s *fb)
{
effs_t error;
iref_t i;
int size_remaining, fp_offset;
int size, size_done;
offset_t chunk_offset;
tw(tr(TR_BEGIN, TrApi, "ffs_write_b(%d, 0x%x, %d) ?{\n", fdi, src, amount));
ttw(ttr(TTrApi, "ffs_write_b(%d, 0x%x, %d) ?" NL, fdi, src, amount));
{
struct ffs_req_s *req;
MSG_ALLOC(req);
req->fdi = fdi;
req->src = (char *) src;
req->size = amount;
req->request_id = request_id_get();
req->fb = fb;
req->cp = cp;
req->cmd = WRITE;
MSG_SEND(req);
return req->request_id;
}
}
int task_write(struct ffs_req_s *p)
{
effs_t error;
iref_t i;
int size_remaining, fp_offset;
int size, size_done;
offset_t chunk_offset;
;
#define fdi p->fdi
#define src p->src
#define amount p->size
if (fs.initerror)
return fs.initerror;
if (amount < 0 || src == NULL)
return EFFS_INVALID;
fdi -= FFS_FD_OFFSET;
if (!is_fd_valid(fdi))
return EFFS_BADFD;
if (!is_open_option(fs.fd[fdi].options, FFS_O_WRONLY ))
return EFFS_INVALID; // not opened with write flag
// If FFS_O_APPEEND is specified move fp to eof
if (is_open_option(fs.fd[fdi].options, FFS_O_APPEND ))
fs.fd[fdi].fp = fs.fd[fdi].size;
// If fp has been moved outside the write buf (by a read) then flush the
// write buffer.
if (fs.fd[fdi].fp >= (fs.fd[fdi].wfp + fs.chunk_size_max)) {
if ((error = datasync(fdi)) < 0)
return error;
}
size_done = 0;
size_remaining = amount;
do {
if (!fs.fd[fdi].dirty ) {
// Buffer is not dirty so find the chunk that fp points to.
segfile_seek(fs.fd[fdi].seghead, fs.fd[fdi].fp, &i,
&chunk_offset);
if ((fs.fd[fdi].size == fs.fd[fdi].fp &&
chunk_offset == fs.chunk_size_max) || fs.fd[fdi].size == 0 ) {
// End of file and last chunk is full or empty seghead.
fs.fd[fdi].wfp = fs.fd[fdi].size;
fs.fd[fdi].wch = 0; // Create new chunk (not update).
}
else {
// Work on this chunk and update it later by datasyns
segment_read(i, fs.fd[fdi].buf, fs.fd_buf_size, 0);
fs.fd[fdi].wfp = fs.fd[fdi].fp - chunk_offset;
fs.fd[fdi].wch = i;
}
}
fs.fd[fdi].dirty = 1;
fp_offset = fs.fd[fdi].fp - fs.fd[fdi].wfp;
// Fill the buffer to max or just add the rest
size = fs.chunk_size_max - fp_offset;
if (size_remaining <= fs.chunk_size_max - fp_offset)
size = size_remaining;
tw(tr(TR_FUNC, TrApi, "Copy data to buffer (size: %d)\n", size));
memcpy(fs.fd[fdi].buf + fp_offset, src + size_done,
size);
fs.fd[fdi].fp += size;
if (fs.fd[fdi].fp > fs.fd[fdi].size)
fs.fd[fdi].size = fs.fd[fdi].fp;
size_done += size; // FIXME: remove size_done or size_remaining
size_remaining -= size;
// If wrbuf is full (size = chunk_size_max) so create a chunk.
if (fs.fd[fdi].fp >= (fs.fd[fdi].wfp + fs.chunk_size_max)) {
if ((error = datasync(fdi)) < 0)
return error;
}
} while(size_remaining > 0);
tw(tr(TR_END, TrApi, "} %d\n", amount));
return amount;
#undef fdi
#undef src
#undef amount
}
int ffs_write(fd_t fdi, void *src, int amount)
{
FFS_BLOCKING_CALL_BEGIN();
result = ffs_write_b(fdi, src, amount, 0, &fb);
FFS_BLOCKING_CALL_END();
return result;
}
req_id_t ffs_write_nb(fd_t fdi, void *src, int amount, T_RV_RETURN *cp)
{
tw(tr(TR_FUNC, TrApi, "ffs_write_nb(%d, 0x%x, %d) ?\n", fdi, src, amount));
return ffs_write_b(fdi, src, amount, cp, 0);
}
int ffs_read(fd_t fdi, void *src, int size)
{
int error;
tw(tr(TR_BEGIN, TrApi, "ffs_read(%d, 0x%x, %d) {\n", fdi, src, size));
ttw(ttr(TTrApi, "ffs_read(%d, 0x%x, %d) ?" NL, fdi, src, size));
if ((error = ffs_begin()) == EFFS_OK)
{
error = stream_read(fdi - FFS_FD_OFFSET, src, size);
}
tw(tr(TR_END, TrApi, "} %d\n", error));
return ffs_end(error); // number of bytes read
}
// The seek function will not allow the file offset to be set beyond the end
// of the existing data in the file or the final offset to be negative.
req_id_t ffs_seek_b(fd_t fdi, int offset, int whence, T_RV_RETURN *cp,
struct ffs_blocking_s *fb)
{
effs_t error;
int fp_new;
tw(tr(TR_FUNC, TrApi, "ffs_seek(%d, %d, %d) ?\n", fdi, offset, whence));
ttw(ttr(TTrApi, "ffs_seek(%d, %d, %d) ?" NL, fdi, offset, whence));
{
struct ffs_req_s *req;
MSG_ALLOC(req);
req->fdi = fdi;
req->size = offset;
req->value16 = whence;
req->request_id = request_id_get();
req->fb = fb;
req->cp = cp;
req->cmd = SEEK;
MSG_SEND(req);
return req->request_id;
}
}
int task_seek(struct ffs_req_s *p)
{
effs_t error;
iref_t i;
int fp_new, foffset;
#define fdi p->fdi
#define offset p->size
#define whence p->value16
if (fs.initerror)
return fs.initerror;
fdi -= FFS_FD_OFFSET;
if (!is_fd_valid(fdi))
return EFFS_BADFD;
switch(whence) {
case FFS_SEEK_SET:
if (offset < 0 || offset > fs.fd[fdi].size)
return EFFS_INVALID;
fp_new = offset;
break;
case FFS_SEEK_CUR:
if (fs.fd[fdi].fp + offset < 0 ||
fs.fd[fdi].fp + offset > fs.fd[fdi].size)
return EFFS_INVALID;
fp_new = fs.fd[fdi].fp + offset;
break;
case FFS_SEEK_END:
if (offset > 0 || fs.fd[fdi].size < -offset)
return EFFS_INVALID;
fp_new = (offset + fs.fd[fdi].size);
break;
default:
return EFFS_INVALID;
}
if (!is_offset_in_buf(fp_new, fdi))
if ((error = datasync(fdi)) < 0)
return error;
return fs.fd[fdi].fp = fp_new;
#undef fdi
#undef offset
#undef whence
}
int ffs_seek(fd_t fdi, int offset, int whence)
{
FFS_BLOCKING_CALL_BEGIN();
result = ffs_seek_b(fdi, offset, whence, 0, &fb);
FFS_BLOCKING_CALL_END();
return result;
}
req_id_t ffs_seek_nb(fd_t fdi, int offset, int whence, T_RV_RETURN *cp)
{
return ffs_seek_b(fdi, offset, whence, cp, 0);
}
req_id_t ffs_truncate_b(const char *path, offset_t length, T_RV_RETURN *cp,
struct ffs_blocking_s *fb)
{
tw(tr(TR_FUNC, TrApi, "ffs_truncate('%s', %d) \n", path, length));
ttw(ttr(TTrApi, "ffs_ftruncate('%s', %d) ?" NL, path, length));
{
struct ffs_req_s *req;
MSG_ALLOC(req);
req->path = path;
req->size = length;
req->request_id = request_id_get();
req->fb = fb;
req->cp = cp;
req->cmd = TRUNC;
MSG_SEND(req);
return req->request_id;
}
}
effs_t task_trunc(struct ffs_req_s *p)
{
iref_t i;
#define path p->path
#define length p->size
if (fs.initerror)
return fs.initerror;
if (path == NULL)
return EFFS_BADNAME;
return object_truncate(path, -1, length);
#undef path
#undef length
}
effs_t ffs_truncate(const char *path, offset_t length)
{
FFS_BLOCKING_CALL_BEGIN();
result = ffs_truncate_b(path, length, 0, &fb);
FFS_BLOCKING_CALL_END();
return result;
}
req_id_t ffs_truncate_nb(const char *path, offset_t length, T_RV_RETURN *cp)
{
return ffs_truncate_b(path, length, cp, 0);
}
req_id_t ffs_ftruncate_b(fd_t fdi, offset_t length, T_RV_RETURN *cp,
struct ffs_blocking_s *fb)
{
tw(tr(TR_FUNC, TrApi, "ffs_ftruncate(%d, %d) \n", fdi, length));
ttw(ttr(TTrApi, "ffs_ftruncate(%d, %d) ?" NL, fdi, length));
{
struct ffs_req_s *req;
MSG_ALLOC(req);
req->fdi = fdi;
req->size = length;
req->request_id = request_id_get();
req->fb = fb;
req->cp = cp;
req->cmd = FTRUNC;
MSG_SEND(req);
return req->request_id;
}
}
effs_t task_ftrunc(struct ffs_req_s *p)
{
iref_t i;
#define fdi p->fdi
#define length p->size
if (fs.initerror)
return fs.initerror;
return object_truncate(0, fdi - FFS_FD_OFFSET, length);
#undef fdi
#undef length
}
effs_t ffs_ftruncate(fd_t fdi, offset_t length)
{
FFS_BLOCKING_CALL_BEGIN();
result = ffs_ftruncate_b(fdi, length, 0, &fb);
FFS_BLOCKING_CALL_END();
return result;
}
req_id_t ffs_ftruncate_nb(fd_t fdi, offset_t length, T_RV_RETURN *cp)
{
return ffs_ftruncate_b(fdi, length, cp, 0);
}
req_id_t ffs_fdatasync_b(fd_t fdi, T_RV_RETURN *cp, struct ffs_blocking_s *fb)
{
tw(tr(TR_FUNC, TrApi, "ffs_fdatasync(%d) \n", fdi));
ttw(ttr(TTrApi, "ffs_fdatasync(%d) ?" NL, fdi));
{
struct ffs_req_s *req;
MSG_ALLOC(req);
req->fdi = fdi;
req->request_id = request_id_get();
req->fb = fb;
req->cp = cp;
req->cmd = FDATASYNC;
MSG_SEND(req);
return req->request_id;
}
}
effs_t task_fdatasync(struct ffs_req_s *p)
{
effs_t error;
#define fdi p->fdi
if (fs.initerror)
return fs.initerror;
return datasync(fdi - FFS_FD_OFFSET);
#undef fdi
}
effs_t ffs_fdatasync(fd_t fdi)
{
FFS_BLOCKING_CALL_BEGIN();
result = ffs_fdatasync_b(fdi, 0, &fb);
FFS_BLOCKING_CALL_END();
return result;
}
req_id_t ffs_fdatasync_nb(fd_t fdi, T_RV_RETURN *cp)
{
return ffs_fdatasync_b(fdi, cp, 0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -