summaryrefslogtreecommitdiff
path: root/util/amdfwtool/handle_file.c
blob: c37bb2c8eb552dedef060d75a2ef5b8c3667be8a (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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/* SPDX-License-Identifier: GPL-2.0-only */

#include <fcntl.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

#include "amdfwtool.h"

void write_or_fail(int fd, void *ptr, size_t size)
{
	ssize_t written;

	written = write_from_buf_to_file(fd, ptr, size);
	if (written < 0 || (size_t)written != size) {
		fprintf(stderr, "%s: Error writing %zu bytes - written %zd bytes\n",
								__func__, size, written);
		exit(-1);
	}
}

ssize_t read_from_file_to_buf(int fd, void *buf, size_t buf_size)
{
	ssize_t bytes;
	size_t total_bytes = 0;

	do {
		bytes = read(fd, buf + total_bytes, buf_size - total_bytes);
		if (bytes == 0) {
			fprintf(stderr, "Reached EOF probably\n");
			break;
		}

		if (bytes < 0 && errno == EAGAIN)
			bytes = 0;

		if (bytes < 0) {
			fprintf(stderr, "Read failure %s\n", strerror(errno));
			return bytes;
		}

		total_bytes += bytes;
	} while (total_bytes < buf_size);

	if (total_bytes != buf_size) {
		fprintf(stderr, "Read data size(%zu) != buffer size(%zu)\n",
								total_bytes, buf_size);
		return -1;
	}
	return buf_size;
}

ssize_t write_from_buf_to_file(int fd, const void *buf, size_t buf_size)
{
	ssize_t bytes;
	size_t total_bytes = 0;

	do {
		bytes = write(fd, buf + total_bytes, buf_size - total_bytes);
		if (bytes < 0 && errno == EAGAIN)
			bytes = 0;

		if (bytes < 0) {
			fprintf(stderr, "Write failure %s\n", strerror(errno));
			lseek(fd, SEEK_CUR, -total_bytes);
			return bytes;
		}

		total_bytes += bytes;
	} while (total_bytes < buf_size);

	if (total_bytes != buf_size) {
		fprintf(stderr, "Wrote more data(%zu) than buffer size(%zu)\n",
								total_bytes, buf_size);
		lseek(fd, SEEK_CUR, -total_bytes);
		return -1;
	}

	return buf_size;
}

ssize_t write_body(char *output, void *body_offset, ssize_t body_size)
{
	char body_name[PATH_MAX], body_tmp_name[PATH_MAX];
	int ret;
	int fd;
	ssize_t bytes = -1;

	/* Create a tmp file and rename it at the end so that make does not get confused
	   if amdfwtool is killed for some unexpected reasons. */
	ret = snprintf(body_tmp_name, sizeof(body_tmp_name), "%s%s%s",
			output, BODY_FILE_SUFFIX, TMP_FILE_SUFFIX);
	if (ret < 0) {
		fprintf(stderr, "Error %s forming BODY tmp file name: %d\n",
							strerror(errno), ret);
		return -1;
	} else if ((unsigned int)ret >= sizeof(body_tmp_name)) {
		fprintf(stderr, "BODY File name %d  > %zu\n", ret, sizeof(body_tmp_name));
		return -1;
	}

	fd = open(body_tmp_name, O_RDWR | O_CREAT | O_TRUNC, 0666);
	if (fd < 0) {
		fprintf(stderr, "Error: Opening %s file: %s\n", body_tmp_name, strerror(errno));
		return -1;
	}

	bytes = write_from_buf_to_file(fd, body_offset, body_size);
	if (bytes != body_size) {
		fprintf(stderr, "Error: Writing to file %s failed\n", body_tmp_name);
		return -1;
	}
	close(fd);

	/* Rename the tmp file */
	ret = snprintf(body_name, sizeof(body_name), "%s%s", output, BODY_FILE_SUFFIX);
	if (ret < 0) {
		fprintf(stderr, "Error %s forming BODY file name: %d\n", strerror(errno), ret);
		return -1;
	}

	if (rename(body_tmp_name, body_name)) {
		fprintf(stderr, "Error: renaming file %s to %s\n", body_tmp_name, body_name);
		return -1;
	}

	return bytes;
}

ssize_t copy_blob(void *dest, const char *src_file, size_t room)
{
	int fd;
	struct stat fd_stat;
	ssize_t bytes;

	fd = open(src_file, O_RDONLY);
	if (fd < 0) {
		fprintf(stderr, "Error opening file: %s: %s\n",
		       src_file, strerror(errno));
		return -1;
	}

	if (fstat(fd, &fd_stat)) {
		fprintf(stderr, "fstat error: %s\n", strerror(errno));
		close(fd);
		return -2;
	}

	if ((size_t)fd_stat.st_size > room) {
		fprintf(stderr, "Error: %s will not fit.  Exiting.\n", src_file);
		close(fd);
		return -3;
	}

	bytes = read(fd, dest, (size_t)fd_stat.st_size);
	close(fd);
	if (bytes != (ssize_t)fd_stat.st_size) {
		fprintf(stderr, "Error while reading %s\n", src_file);
		return -4;
	}

	return bytes;
}