-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathrewrite-inplace.c
129 lines (104 loc) · 3.41 KB
/
rewrite-inplace.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
128
/*********************************************************************
Rewrites the contents of the file given on the command line. For details, see
https://yktoo.com/en/blog/post/2015/07/20-fixing-samsung-ssd-840-evo-performance-issues-in-linux/
WARNING:
This program comes with ABSOLUTELY NO WARRANTY whatsoever, use
it entirely at your own risk! The author shall never be held
responsible for loss of your data, ruining your hard drive, PC,
house, city or planet, including but not limited to wars,
hurricanes, famines, global warming or alien invasions, arising
from using it.
Author:
Dmitry Kann, https://yktoo.com/
License:
LGPL 3.0
Compile with:
gcc rewrite-inplace.c -o rewrite-inplace
*********************************************************************/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
volatile sig_atomic_t interrupted = 0;
void handle_sigint(int sig){
interrupted = 1;
}
int main(int argc, char **argv) {
int file_desc;
char buf[1000000];
int chunk_num = 0;
size_t read_size;
size_t write_size;
size_t buf_size = sizeof(buf);
off_t file_pos;
off_t file_size;
char* file_name;
// Check command-line arguments
if (argc != 2) {
fprintf(stderr, "Usage: %s <file_name>\n", argv[0]);
exit(1);
}
// Try to open the file
file_name = argv[1];
if ((file_desc = open(file_name, O_RDWR)) == -1) {
perror("Could not open the file");
exit(2);
}
// Get file length
if ((file_size = lseek(file_desc, 0, SEEK_END)) == (off_t)-1) {
perror("Could not get file position");
exit(3);
}
printf("File %s is open, size %zu bytes\n", file_name, file_size);
// Register the signal
signal(SIGINT, handle_sigint);
// Iterate through the file contents
file_pos = 0;
while (file_pos<file_size && !interrupted) {
// Progress display
if (chunk_num++ % 10 == 0) {
printf("%zu/%zu bytes written\r", file_pos, file_size);
}
// Position the file pointer for reading
if (lseek(file_desc, file_pos, SEEK_SET) == -1) {
perror("Reading: lseek() failed");
exit(4);
}
// Fill in the buffer with bytes
if ((read_size = read(file_desc, buf, buf_size)) < 0) {
perror("Reading: read() failed");
exit(5);
}
if (read_size == 0)
break;
// Position the file pointer for writing
if (lseek(file_desc, file_pos, SEEK_SET) == -1) {
perror("Writing: lseek() failed");
exit(6);
}
// Write the bytes
if ((write_size = write(file_desc, buf, read_size)) == -1) {
perror("Writing: write() failed");
exit(7);
}
if (write_size < read_size) {
perror("Writing: write() wrote less bytes than required");
exit(7);
}
// Advance the pointer
file_pos += read_size;
}
// Close the file
close(file_desc);
if (interrupted) {
fprintf(stderr, "File writing has been interrupted; %zu/%zu bytes written\n", file_pos, file_size);
exit(15);
} else {
printf("File has been rewritten successfully; %zu bytes written\n", file_size);
exit(0);
}
}