summaryrefslogtreecommitdiffstats
path: root/src/ufo-roof-read-file.c
blob: de8391e0b184f8d51d53fb8e02941e00ae696177 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <stdio.h>
#include <errno.h>
#include <stdint.h>

#include "glib.h"

#include "ufo-roof.h"
#include "ufo-roof-read-file.h"

typedef struct {
    UfoRoofReadInterface iface;

    UfoRoofConfig *cfg;
    
    gchar *fname;
    FILE *fd;
} UfoRoofReadFile;

static void ufo_roof_read_file_free(UfoRoofReadInterface *iface) {
    UfoRoofReadFile *reader = (UfoRoofReadFile*)iface;
    
    if (reader) {
        if (reader->fname)
            g_free(reader->fname);

        if (reader->fd >= 0) 
            fclose(reader->fd);
    
        free(reader);
    }
}

static guint ufo_roof_read_file(UfoRoofReadInterface *iface, void *buffers, GError **error) {
    UfoRoofReadFile *reader = (UfoRoofReadFile*)iface;
    UfoRoofConfig *cfg = reader->cfg;

    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(buffers + 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");
    }
        
    return packets;
}


UfoRoofReadInterface *ufo_roof_read_file_new(UfoRoofConfig *cfg, guint id, GError **error) {
    UfoRoofReadFile *reader = (UfoRoofReadFile*)calloc(1, sizeof(UfoRoofReadFile));
    if (!reader) roof_new_error(error, "Can't allocate UfoRoofReadFile");
    
        // 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 UfoRoofReadFile is used", cfg->header_size + cfg->payload_size, cfg->max_packet_size);

    reader->cfg = cfg;
    reader->iface.close = ufo_roof_read_file_free;
    reader->iface.read =ufo_roof_read_file;
    
    reader->fname = g_strdup_printf(cfg->path, id + cfg->first_file_number);
    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 %s", reader->fname);
    }

    return (UfoRoofReadInterface*)reader;
}