summaryrefslogtreecommitdiff
path: root/parsers/binary.c
blob: bea52c627aede920e99aaca1e0535aee78f63178 (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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
  stm32flash - Open Source ST STM32 flash program for *nix
  Copyright (C) 2010 Geoffrey McRae <geoff@spacevs.com>

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either version 2
  of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/


#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>

#include "binary.h"

typedef struct {
	int		fd;
	char		write;
	struct stat	stat;
} binary_t;

void* binary_init() {
	return calloc(sizeof(binary_t), 1);
}

parser_err_t binary_open(void *storage, const char *filename, const char write) {
	binary_t *st = storage;
	if (write) {
		if (filename[0] == '-' && filename[1] == '\0')
			st->fd = 1;
		else
			st->fd = open(
				filename,
#ifndef __WIN32__
				O_WRONLY | O_CREAT | O_TRUNC,
#else
				O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
#endif
#ifndef __WIN32__
				S_IRUSR  | S_IWUSR | S_IRGRP | S_IROTH
#else
				0
#endif
			);
		st->stat.st_size = 0;
	} else {
		if (filename[0] == '-' && filename[1] == '\0') {
			st->fd = 0;
		} else {
			if (stat(filename, &st->stat) != 0)
				return PARSER_ERR_INVALID_FILE;
			st->fd = open(filename,
#ifndef __WIN32__
				O_RDONLY
#else
				O_RDONLY | O_BINARY
#endif
			);
		}
	}

	st->write = write;
	return st->fd == -1 ? PARSER_ERR_SYSTEM : PARSER_ERR_OK;
}

parser_err_t binary_close(void *storage) {
	binary_t *st = storage;

	if (st->fd) close(st->fd);
	free(st);
	return PARSER_ERR_OK;
}

unsigned int binary_base(void *storage) {
	return 0;
}

unsigned int binary_size(void *storage) {
	binary_t *st = storage;
	return st->stat.st_size;
}

parser_err_t binary_read(void *storage, void *data, unsigned int *len) {
	binary_t *st = storage;
	unsigned int left = *len;
	unsigned char *d = data;

	if (st->write) return PARSER_ERR_WRONLY;

	ssize_t r;
	while(left > 0) {
		r = read(st->fd, d, left);
		if (r == 0)
			break ;
		else if ( r < 0)
			return PARSER_ERR_SYSTEM;

		left -= r;
		d += r;
	}

	*len = *len - left;
	return PARSER_ERR_OK;
}

parser_err_t binary_write(void *storage, void *data, unsigned int len) {
	binary_t *st = storage;
	unsigned char *d = data;

	if (!st->write) return PARSER_ERR_RDONLY;

	ssize_t r;
	while(len > 0) {
		r = write(st->fd, d, len);
		if (r < 1) return PARSER_ERR_SYSTEM;
		st->stat.st_size += r;

		len  -= r;
		d += r;
	}

	return PARSER_ERR_OK;
}

parser_t PARSER_BINARY = {
	"Raw BINARY",
	binary_init,
	binary_open,
	binary_close,
	binary_base,
	binary_size,
	binary_read,
	binary_write
};