aboutsummaryrefslogtreecommitdiff
path: root/src/linux/mockfile.c
blob: 3fdd6bfaf371e25a42fcacccce38569b17507761 (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
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <errno.h>

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

#if !CPUINFO_MOCK
	#error This file should be built only in mock mode
#endif

#include <cpuinfo-mock.h>
#include <arm/linux/api.h>
#include <arm/midr.h>
#include <cpuinfo/log.h>


static struct cpuinfo_mock_file* cpuinfo_mock_files = NULL;
static uint32_t cpuinfo_mock_file_count = 0;


void CPUINFO_ABI cpuinfo_mock_filesystem(struct cpuinfo_mock_file* files) {
	cpuinfo_log_info("filesystem mocking enabled");
	uint32_t file_count = 0;
	while (files[file_count].path != NULL) {
		/* Indicate that file is not opened */
		files[file_count].offset = SIZE_MAX;
		file_count += 1;
	}
	cpuinfo_mock_files = files;
	cpuinfo_mock_file_count = file_count;	
}

int CPUINFO_ABI cpuinfo_mock_open(const char* path, int oflag) {
	if (cpuinfo_mock_files == NULL) {
		cpuinfo_log_warning("cpuinfo_mock_open called without mock filesystem; redictering to open");
		return open(path, oflag);
	}

	for (uint32_t i = 0; i < cpuinfo_mock_file_count; i++) {
		if (strcmp(cpuinfo_mock_files[i].path, path) == 0) {
			if (oflag != O_RDONLY) {
				errno = EACCES;
				return -1;
			}
			if (cpuinfo_mock_files[i].offset != SIZE_MAX) {
				errno = ENFILE;
				return -1;
			}
			cpuinfo_mock_files[i].offset = 0;
			return (int) i;
		}
	}
	errno = ENOENT;
	return -1;
}

int CPUINFO_ABI cpuinfo_mock_close(int fd) {
	if (cpuinfo_mock_files == NULL) {
		cpuinfo_log_warning("cpuinfo_mock_close called without mock filesystem; redictering to close");
		return close(fd);
	}

	if ((unsigned int) fd >= cpuinfo_mock_file_count) {
		errno = EBADF;
		return -1;
	}
	if (cpuinfo_mock_files[fd].offset == SIZE_MAX) {
		errno = EBADF;
		return -1;
	}
	cpuinfo_mock_files[fd].offset = SIZE_MAX;
	return 0;
}

ssize_t CPUINFO_ABI cpuinfo_mock_read(int fd, void* buffer, size_t capacity) {
	if (cpuinfo_mock_files == NULL) {
		cpuinfo_log_warning("cpuinfo_mock_read called without mock filesystem; redictering to read");
		return read(fd, buffer, capacity);
	}

	if ((unsigned int) fd >= cpuinfo_mock_file_count) {
		errno = EBADF;
		return -1;
	}
	if (cpuinfo_mock_files[fd].offset == SIZE_MAX) {
		errno = EBADF;
		return -1;
	}

	const size_t offset = cpuinfo_mock_files[fd].offset;
	size_t count = cpuinfo_mock_files[fd].size - offset;
	if (count > capacity) {
		count = capacity;
	}
	memcpy(buffer, (void*) cpuinfo_mock_files[fd].content + offset, count);
	cpuinfo_mock_files[fd].offset += count;
	return (ssize_t) count;
}