-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnewline.c
executable file
·137 lines (131 loc) · 4.08 KB
/
newline.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
129
130
131
132
133
134
135
136
137
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
#include <unistd.h>
#ifdef _WIN32
#include <io.h>
#include <fcntl.h>
#include <share.h>
#include <sys/stat.h>
#define delete(file) _wunlink(file)
#else
#define delete(file) unlink(file)
#endif // _WIN32
#include "args.h"
#include "tempfile.h"
#include "trim.h"
static FILE* open_file(const arg_char* name) {
#ifdef _WIN32
// Open the file allowing shared read, but not shared write
int fd;
_wsopen_s(
&fd, name, _O_RDWR | _O_BINARY | _O_NOINHERIT, _SH_DENYWR,
_S_IREAD | _S_IWRITE
);
if(fd == -1) {
return NULL;
}
FILE* file = _fdopen(fd, "r+b");
if(file == NULL) {
_close(fd);
return NULL;
}
setvbuf(file, NULL, _IOFBF, FileBufferLen);
return file;
#else
FILE* file = fopen(name, "r+b");
if(file != NULL) {
setvbuf(file, NULL, _IOFBF, FileBufferLen);
}
return file;
#endif // _WIN32
}
#ifdef _WIN32
int wmain(int argc, wchar_t** argv) {
_setmode(_fileno(stdout), _O_U16TEXT);
_setmode(_fileno(stderr), _O_U16TEXT);
#else
int main(int argc, char** argv) {
#endif
struct Arguments args = parse_args(argc, argv);
if(!args.valid) {
return EXIT_FAILURE;
}
bool success = true;
for(size_t i = 0; i < args.num_filenames; ++i) {
FILE* file = open_file(args.filenames[i]);
struct TempFile* temp_file = make_temp_file("newline_%.tmp");
if(file == NULL) {
arg_printerr(
arg_f arg_s(": ") arg_f arg_s(": ") arg_f,
argv[0], args.filenames[i], arg_strerror(errno)
);
if(temp_file != NULL) {
fclose(temp_file->file);
delete(temp_file->filename);
free_temp_file(temp_file);
}
success = false;
} else if(temp_file == NULL) {
arg_printerr(
arg_f arg_s(": ") arg_f arg_s(": Unable to create temporary ")
arg_s("file"), argv[0], args.filenames[i]
);
fclose(file);
success = false;
} else {
bool result = trim_file(
file, temp_file->file, args.newline_type,
args.trailing_newline, args.strip_whitespace
);
if(result) {
// Need to copy the temp file to original file. It would be
// faster to just rename() the temporary file to the original
// file, but this won't preserve file metadata such as
// permission bits or owners. ReplaceFile() does this on
// Windows, but an easy solution for Unix systems doesn't seem
// to exist.
fseeko(file, 0, SEEK_SET);
fseeko(temp_file->file, 0, SEEK_SET);
uint8_t* buffer = malloc(FileBufferLen);
size_t read_bytes = fread(
buffer, 1, FileBufferLen, temp_file->file
);
while(read_bytes) {
fwrite(buffer, 1, read_bytes, file);
read_bytes = fread(
buffer, 1, FileBufferLen, temp_file->file
);
}
free(buffer);
off_t file_len = ftello(file);
fflush(file);
ftruncate(fileno(file), file_len);
}
if(args.verbose) {
if(result) {
arg_print(
arg_s("Processed ") arg_f,
args.filenames[i]
);
} else {
arg_print(
arg_s("No changes made to ") arg_f,
args.filenames[i]
);
}
}
fclose(file);
fclose(temp_file->file);
delete(temp_file->filename);
free_temp_file(temp_file);
}
}
free_args(&args);
if(!success) {
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}