Skip to content

Commit 4226137

Browse files
authored
Merge pull request #808 from ugexe/uv_fs_copyfile
Use uv_fs_copyfile api
2 parents 1849ae6 + 4ff0bad commit 4226137

File tree

1 file changed

+7
-67
lines changed

1 file changed

+7
-67
lines changed

src/io/fileops.c

Lines changed: 7 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -120,80 +120,20 @@ MVMnum64 MVM_file_time(MVMThreadContext *tc, MVMString *filename, MVMint64 statu
120120

121121
/* copy a file from one to another */
122122
void MVM_file_copy(MVMThreadContext *tc, MVMString *src, MVMString * dest) {
123-
/* TODO: on Windows we can use the CopyFile API, which is probaly
124-
more efficient, not to mention easier to use. */
123+
char * const a = MVM_string_utf8_c8_encode_C_string(tc, src);
124+
char * const b = MVM_string_utf8_c8_encode_C_string(tc, dest);
125125
uv_fs_t req;
126-
char * a, * b;
127-
uv_file in_fd = -1, out_fd = -1;
128-
MVMuint64 size, offset;
129-
130-
a = MVM_string_utf8_c8_encode_C_string(tc, src);
131-
b = MVM_string_utf8_c8_encode_C_string(tc, dest);
132-
133-
/* If the file cannot be stat(), there is little point in going any further. */
134-
if (uv_fs_stat(tc->loop, &req, a, NULL) < 0)
135-
goto failure;
136-
size = req.statbuf.st_size;
137-
138-
in_fd = uv_fs_open(tc->loop, &req, (const char *)a, O_RDONLY, 0, NULL);
139-
if (in_fd < 0) {
140-
goto failure;
141-
}
142-
143-
out_fd = uv_fs_open(tc->loop, &req, (const char *)b, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_MODE, NULL);
144-
if (out_fd < 0) {
145-
goto failure;
146-
}
147-
148-
offset = 0;
149-
do {
150-
/* sendfile() traditionally takes offset as a pointer argument
151-
* used a both input and output. libuv deviates by making
152-
* offset an integer and returning the number of bytes
153-
* sent. So it is necessary to add these explicitly. */
154-
MVMint64 sent = uv_fs_sendfile(tc->loop, &req, out_fd, in_fd, offset, size - offset, NULL);
155-
if (sent < 0) {
156-
goto failure;
157-
}
158-
offset += sent;
159-
} while (offset < size);
160126

161-
/* Cleanup */
162-
if(uv_fs_close(tc->loop, &req, in_fd, NULL) < 0) {
163-
goto failure;
164-
}
165-
in_fd = -1;
166-
167-
if (uv_fs_close(tc->loop, &req, out_fd, NULL) < 0) {
168-
goto failure;
127+
if(uv_fs_copyfile(tc->loop, &req, a, b, 0, NULL) < 0) {
128+
MVM_free(a);
129+
MVM_free(b);
130+
MVM_exception_throw_adhoc(tc, "Failed to copy file: %s", uv_strerror(req.result));
169131
}
170132

171-
MVM_free(b);
172133
MVM_free(a);
173-
return;
174-
175-
failure: {
176-
/* First get the error, since it may be overwritten further on. */
177-
const char * error = uv_strerror(req.result);
178-
/* Basic premise: dealing with all failure cases is hard.
179-
* So to simplify, a and b are allocated in all conditions.
180-
* Also to simplify, in_fd are nonnegative if open, negative
181-
* otherwise. */
182-
MVM_free(b);
183-
MVM_free(a);
184-
/* If any of these fail there is nothing
185-
* further to do, since we're already failing */
186-
if (in_fd >= 0)
187-
uv_fs_close(tc->loop, &req, in_fd, NULL);
188-
if (out_fd >= 0)
189-
uv_fs_close(tc->loop, &req, out_fd, NULL);
190-
/* This function only throws adhoc errors, so the message is for
191-
* progammer eyes only */
192-
MVM_exception_throw_adhoc(tc, "Failed to copy file: %s", error);
193-
}
134+
MVM_free(b);
194135
}
195136

196-
197137
/* rename one file to another. */
198138
void MVM_file_rename(MVMThreadContext *tc, MVMString *src, MVMString *dest) {
199139
char * const a = MVM_string_utf8_c8_encode_C_string(tc, src);

0 commit comments

Comments
 (0)