-
Notifications
You must be signed in to change notification settings - Fork 0
/
go-sn.c
127 lines (117 loc) · 3.1 KB
/
go-sn.c
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
#define _GNU_SOURCE //enable the strcasestr function from string.h
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#define BLOCK_SIZE 512
#define SN_LEN 19
#ifndef VERSION
#error "VERSION must be passed in by command: -DVERSION=<version>"
#endif
#define stringify_(x) #x
#define stringify(x) stringify_(x)
const char* usage =
"GOcontroll serial number utility v" stringify(VERSION) "\n"
"Usage:\n"
"go-sn [command] \'serial-number\'\n"
"\n"
"Available commands:\n"
"[r]ead Read the serial number from memory\n"
"[w]rite Write the 'serial-number' to memory\n"
"\n"
"'serial-number' must be a total of 19 characters long, and be segmented into 4 parts of 4 seperated by '-'\n"
"\n"
"Examples:\n"
"go-sn read\n"
"go-sn write 1234-5678-9012-3456\n";
int get_disk() {
int disk;
if ((disk = open("/dev/mmcblk0", O_RDWR)) < 0) {
fprintf(stderr, "Unable to open block device:\n%s\n", strerror(errno));
return -1;
}
if (lseek(disk, -BLOCK_SIZE, SEEK_END) < 0) {
close(disk);
fprintf(stderr, "Could not seek to serial number address:\n%s\n", strerror(errno));
return -1;
}
return disk;
}
int validate_serial(char* sn) {
if (strlen(sn) != SN_LEN) {
fprintf(stderr, "The serial number has to be 19 characters long.\n");
return -1;
}
for (int i = 0; i < SN_LEN; i++) { // sn is already verified to be SN_LEN long
if ((sn[i] == '-') && (((i+1) % 5) != 0)) { //check if every - is at the proper position
fprintf(stderr, "Each segment of the of the serial number should contain 4 characters\n");
return -1;
}
if ((sn[i] != '-') && (((i+1) % 5) == 0)) { //check if every - position contains a -
fprintf(stderr, "Each segment of the of the serial number should contain 4 characters\n");
return -1;
}
}
return 0;
}
int read_serial() {
int disk;
if ((disk = get_disk()) < 0) {
return -1;
}
char buffer[SN_LEN+1]; //buffer with null terminator
ssize_t bytes;
if ((bytes = read(disk, buffer, SN_LEN)) < 0) {
close(disk);
fprintf(stderr, "Could not read the serial number:\n%s\n", strerror(errno));
return -1;
}
if (bytes != 19) {
fprintf(stderr, "Could not read full serial number, only %d bytes read.\n", bytes);
return -1;
}
buffer[SN_LEN] = 0; //add null terminator
if (validate_serial(buffer)) {
return -1;
}
printf("%s\n",buffer); //print the sn to stdout
close(disk);
return 0;
}
int write_serial(char* sn) {
if (validate_serial(sn)) {
return -1;
}
int disk;
if ((disk = get_disk()) < 0) {
return -1;
}
char buffer[BLOCK_SIZE] = {0};
strncpy(buffer, sn, SN_LEN);
if (write(disk, buffer, BLOCK_SIZE) < 0) {
close(disk);
fprintf(stderr,"Could not write the serial number to memory:\n%s\n", strerror(errno));
return -1;
}
close(disk);
return 0;
}
int main (int argc, char *argv[]) {
if (argc < 2) {
fprintf(stderr,"%s",usage);
return 0;
}
if (strcasestr("read", argv[1]) != NULL) {
return read_serial();
} else if (strcasestr("write", argv[1]) != NULL) {
if (argc != 3) {
fprintf(stderr,"%s", usage);
return -1;
}
return write_serial(argv[2]);
}
}