-
Notifications
You must be signed in to change notification settings - Fork 5
/
dev_one.c
122 lines (103 loc) · 2.46 KB
/
dev_one.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
/*
vi:noexpandtab:ts=2:sw=2
*/
#define _LARGEFILE64_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include "util.h"
unsigned int BLOCK_SIZE = 0;
u8 *buf;
u8 *buf_r;
u64 writedata(char *file, u64 start, int read_before_write)
{
u64 pos = start;
u64 size = dev_size(file);
ssize_t count;
int mode;
int fp;
if (read_before_write)
mode = O_RDWR;
else
mode = O_WRONLY;
fp = open(file, mode | O_LARGEFILE | O_CREAT | O_SYNC, S_IWUSR|S_IRUSR);
struct showstatus_state stat;
showstatus_init(&stat, pos, size, read_before_write);
if (pos) {
if (lseek64(fp, pos, SEEK_SET) != pos) {
perror("[1;31mFailed to lseek64[0m");
return 0;
}
}
while (!size || pos < size) {
if (!size || size - pos >= BLOCK_SIZE) {
if (read_before_write) {
count = read(fp, buf_r, BLOCK_SIZE);
if (memcmp(buf, buf_r, count)) {
if (lseek64(fp, pos, SEEK_SET) != pos) {
perror("[1;31mFailed to lseek64[0m");
return 0;
}
count = write(fp, buf, count);
stat.written += count;
}
} else
count = write(fp, buf, BLOCK_SIZE);
} else
count = write(fp, buf, size - pos);
if (count == -1) {
if (errno != ENOSPC)
perror("write");
goto out;
}
pos += count;
showstatus_timed(pos, &stat, "");
}
out:
showstatus(pos);
fprintf(stderr, "\n");
fsync(fp);
close(fp);
return pos-start;
}
void alloc_bufs(unsigned int size) {
BLOCK_SIZE = size;
buf = malloc(BLOCK_SIZE);
buf_r = malloc(BLOCK_SIZE);
if (!buf || !buf_r) {
perror("malloc");
exit(1);
}
return;
}
int main(int argc, char *argv[])
{
u64 written, start = 0;
double start_human;
char *start_units;
char *filename;
int read_before_write;
if (argc < 2 || argc > 4) {
fprintf(stderr, "Usage: %s device [ [ start ] read_before_write ]\nWARNING - all data on device will be destroyed!\n", argv[0]);
return 1;
}
filename = argv[1];
alloc_bufs(sd_erase_size(filename)); /* BLOCK_SIZE set here */
if (argc > 2) {
start = interpret_number(argv[2]);
start = start - start % BLOCK_SIZE;
}
start_human = human_size(start, &start_units);
fprintf(stderr, "Starting at %#llx (%.2f %s)\n", start, start_human, start_units);
read_before_write = argc > 3;
memset(buf, 0xff, BLOCK_SIZE);
written = writedata(argv[1], start, read_before_write);
fprintf(stderr, "\x1b[36m%llu bytes written to %s.\x1b[0m\n", written, filename);
sync();
return 0;
}