diff --git a/ce/ce.c b/ce/ce.c index fbf2cbd..5316eb4 100644 --- a/ce/ce.c +++ b/ce/ce.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -386,7 +387,6 @@ static void mkfile (struct context* context, char** file_paths, size_t files_cou } static void cat (struct context* context, char** file_paths, size_t files_count) { - struct desc desc; char volume[VOLUME_MAX]; const char* path; int ret; @@ -399,29 +399,39 @@ static void cat (struct context* context, char** file_paths, size_t files_count) continue; } - if ((ret = volume_open (volume)) < 0) { - cprintf (context, "ERROR could not open volume '%s': %s\n", volume, str_status[-ret]); - continue; + struct filereader fr; + if ((ret = filereader_init (&fr, volume, path)) < 0) { + cprintf (context, "ERROR could not initialize filereader for '%s:%s'\n", volume, path); + return; } - describe (path, &desc); + size_t chunk_size = 1024; + char* buffer = arena_malloc (&arena, chunk_size); - if (desc.type != FS_FILE) - goto close; + size_t chunks = fr.file_size / chunk_size; + size_t rem = fr.file_size % chunk_size; - char* buffer = malloc (desc.size + 1); + for (size_t chunk = 0; chunk < chunks; chunk++) { + if ((ret = filereader_read (&fr, (uint8_t*)buffer, chunk_size)) < 0) { + filereader_fini (&fr); + cprintf (context, "ERROR filereader failed to read from '%s:%s'\n", volume, path); + return; + } - if (buffer == NULL) - goto close; + mail_send (e_pgid, buffer, chunk_size); + } - memset (buffer, 0, desc.size + 1); - read_file (path, 0, (uint8_t*)buffer, desc.size); - cprintf (context, "%s\n", buffer); + if (rem > 0) { + if ((ret = filereader_read (&fr, (uint8_t*)buffer, rem)) < 0) { + filereader_fini (&fr); + cprintf (context, "ERROR filereader failed to read from '%s:%s'\n", volume, path); + return; + } - close: - if (buffer != NULL) - free (buffer); - volume_close (); + mail_send (e_pgid, buffer, rem); + } + + filereader_fini (&fr); } } @@ -566,11 +576,13 @@ static void execute_redir (struct ast_redir* redir, struct context* context) { } } - if ((ret = filewriter_write (&fw, (uint8_t*)&context->strbuf.items[chunks * chunk_size], rem)) < - 0) { - filewriter_fini (&fw); - cprintf (context, "ERROR filewriter failed to write to '%s:%s'\n", volume, path); - return; + if (rem > 0) { + if ((ret = filewriter_write (&fw, (uint8_t*)&context->strbuf.items[chunks * chunk_size], rem)) < + 0) { + filewriter_fini (&fw); + cprintf (context, "ERROR filewriter failed to write to '%s:%s'\n", volume, path); + return; + } } filewriter_fini (&fw); diff --git a/libioutil/filereader.c b/libioutil/filereader.c new file mode 100644 index 0000000..c1bc466 --- /dev/null +++ b/libioutil/filereader.c @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +int filereader_init (struct filereader* fw, const char* volume, const char* path) { + memset (fw, 0, sizeof (*fw)); + strncpy (fw->volume, volume, VOLUME_MAX); + strncpy (fw->path, path, PATH_MAX); + + int ret; + struct desc desc; + + if ((ret = volume_open (fw->volume)) < 0) + return -FR_VOLUME_OPEN_ERROR; + + if ((ret = describe (fw->path, &desc)) < 0) { + volume_close (); + return -FR_DESC_ERROR; + } + + if (desc.type != FS_FILE) + return -FR_NOT_FILE; + + fw->file_size = desc.size; + fw->flags |= FR_OPEN; + + return FR_OK; +} + +int filereader_fini (struct filereader* fw) { + if ((fw->flags & FR_OPEN)) { + volume_close (); + fw->flags &= ~FR_OPEN; + } + + return FR_OK; +} + +int filereader_read (struct filereader* fw, uint8_t* buffer, size_t buffer_size) { + if (!(fw->flags & FR_OPEN)) + return -FR_VOLUME_NOT_OPENED; + + int ret; + + if (buffer_size > 0) { + if (!(fw->read_cursor + buffer_size <= fw->file_size)) + return -FR_CURSOR_OOB; + + if ((ret = read_file (fw->path, fw->read_cursor, buffer, buffer_size)) < 0) + return -FR_READ_ERROR; + + fw->read_cursor += buffer_size; + } + + return FR_OK; +} diff --git a/libioutil/filereader.h b/libioutil/filereader.h new file mode 100644 index 0000000..1517748 --- /dev/null +++ b/libioutil/filereader.h @@ -0,0 +1,33 @@ +#ifndef _LIBIOUTIL_FILEREADER_H +#define _LIBIOUTIL_FILEREADER_H + +#include +#include +#include +#include + +#define FR_OK 0 +#define FR_VOLUME_OPEN_ERROR 1 +#define FR_DESC_ERROR 2 +#define FR_NOT_FILE 3 +#define FR_VOLUME_NOT_OPENED 4 +#define FR_READ_ERROR 5 +#define FR_CURSOR_OOB 6 + +#define FR_OPEN (1 << 31) + +struct filereader { + char volume[VOLUME_MAX]; + char path[PATH_MAX]; + size_t read_cursor; + size_t file_size; + uint32_t flags; +}; + +int filereader_init (struct filereader* fw, const char* volume, const char* path); + +int filereader_fini (struct filereader* fw); + +int filereader_read (struct filereader* fw, uint8_t* buffer, size_t buffer_size); + +#endif // _LIBIOUTIL_FILEREADER_H diff --git a/libioutil/src.mk b/libioutil/src.mk index f4eb992..8cce3f7 100644 --- a/libioutil/src.mk +++ b/libioutil/src.mk @@ -1,3 +1,5 @@ -c += filewriter.c +c += filewriter.c \ + filereader.c -o += filewriter.o +o += filewriter.o \ + filereader.o