#include #include #include #include #include "glib.h" #include "ufo-roof.h" #include "ufo-roof-read-file.h" typedef struct { RoofReadInterface iface; RoofConfig *cfg; gchar *fname; FILE *fd; uint8_t *buf; } RoofReadFile; static void roof_read_file_free(RoofReadInterface *iface) { RoofReadFile *reader = (RoofReadFile*)iface; if (reader) { if (reader->fname) g_free(reader->fname); if (reader->fd) fclose(reader->fd); if (reader->buf) free(reader->buf); free(reader); } } static guint roof_read_file(RoofReadInterface *iface, uint8_t **buffers, GError **error) { RoofReadFile *reader = (RoofReadFile*)iface; RoofConfig *cfg = reader->cfg; assert(iface); assert(buffers); size_t bytes = 0; size_t packet_size = cfg->header_size + cfg->payload_size; size_t expected = cfg->max_packets * packet_size; while ((!feof(reader->fd))&&(!ferror(reader->fd))&&(bytes < expected)) { size_t ret = fread(reader->buf + bytes, 1, expected - bytes, reader->fd); bytes += ret; } guint packets = bytes / packet_size; if (ferror(reader->fd)) { roof_network_error_with_retval(error, 0, "read failed, error %i", ferror(reader->fd)); } else if ((feof(reader->fd))&&(bytes % packet_size)) { roof_network_error_with_retval(error, packets, "extra data in the end of input"); } *buffers = reader->buf; return packets; } RoofReadInterface *roof_read_file_new(RoofConfig *cfg, const char *path, guint file_id, GError **error) { RoofReadFile *reader = (RoofReadFile*)calloc(1, sizeof(RoofReadFile)); if (!reader) roof_new_error(error, "Can't allocate RoofReadFile"); // FIXME: Shall we jump if max_packet_size > header+payload (or will be extra data included in the data files)? Report error for now. if ((cfg->header_size + cfg->payload_size) != cfg->max_packet_size) roof_new_error(error, "packet_size (%u) should be equal to max_packet_size (%u) if RoofReadFile is used", cfg->header_size + cfg->payload_size, cfg->max_packet_size); reader->cfg = cfg; reader->iface.close = roof_read_file_free; reader->iface.read =roof_read_file; reader->fname = g_strdup_printf(path, file_id); if (!reader->fname) { free(reader); roof_new_error(error, "Can't build file name"); } reader->fd = fopen(reader->fname, "rb"); if (!reader->fd) { g_free(reader->fname); g_free(reader); roof_new_error(error, "Can't open file %i at path %s", file_id, path); } reader->buf = (uint8_t*)malloc(cfg->max_packets * (cfg->header_size + cfg->payload_size)); if (!reader->buf) { roof_read_file_free((RoofReadInterface*)reader); roof_new_error(error, "Can't allocate file buffer"); } return (RoofReadInterface*)reader; }