Skip to content

Commit dbaa684

Browse files
committed
Unlink the temp file sooner
We only need the temp file to be present on the file system to run xdg-mime on it. Once we have done that, we can unlink it and simply use an fd to refer to it, seeking to the beginning each time. This makes us more robust against wl-copy crashing (or getting killed), in which case the file would be kept on the file system; this should no longer be the case with this patch. Related to #155
1 parent 065d6da commit dbaa684

File tree

3 files changed

+36
-23
lines changed

3 files changed

+36
-23
lines changed

src/types/copy-action.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ static void do_send(struct source *source, const char *mime_type, int fd) {
7171
/* Unset O_NONBLOCK */
7272
fcntl(fd, F_SETFL, 0);
7373

74-
if (self->file_to_copy != NULL) {
74+
if (self->fd_to_copy_from != -1) {
7575
/* Copy the file to the given file descriptor
7676
* by spawning an appropriate cat process.
7777
*/
@@ -82,9 +82,11 @@ static void do_send(struct source *source, const char *mime_type, int fd) {
8282
return;
8383
}
8484
if (pid == 0) {
85+
dup2(self->fd_to_copy_from, STDIN_FILENO);
86+
close(self->fd_to_copy_from);
8587
dup2(fd, STDOUT_FILENO);
8688
close(fd);
87-
execlp("cat", "cat", self->file_to_copy, NULL);
89+
execlp("cat", "cat", NULL);
8890
perror("exec cat");
8991
exit(1);
9092
}
@@ -97,6 +99,11 @@ static void do_send(struct source *source, const char *mime_type, int fd) {
9799
* instead.
98100
*/
99101
waitpid(pid, NULL, 0);
102+
/* Seek back to the beginning of the file */
103+
off_t rc = lseek(self->fd_to_copy_from, 0, SEEK_SET);
104+
if (rc < 0) {
105+
perror("lseek");
106+
}
100107
} else {
101108
/* We'll perform the copy ourselves */
102109
FILE *f = fdopen(fd, "w");

src/types/copy-action.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,9 @@ struct copy_action {
4040

4141
/* Exactly one of these fields must be non-null if the source
4242
* is non-null, otherwise all these fields must be null.
43+
* The null value for fd_to_copy_from is -1.
4344
*/
44-
const char *file_to_copy;
45+
int fd_to_copy_from;
4546
argv_t argv_to_copy;
4647
struct {
4748
const char *ptr;

src/wl-copy.c

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -81,29 +81,13 @@ static void did_set_selection_callback(struct copy_action *copy_action) {
8181
}
8282
}
8383

84-
static void cleanup_and_exit(struct copy_action *copy_action, int code) {
85-
/* We're done copying!
86-
* All that's left to do now is to
87-
* clean up after ourselves and exit.
88-
*/
89-
char *temp_file = (char *) copy_action->file_to_copy;
90-
if (temp_file != NULL) {
91-
/* Clean up our temporary file */
92-
execlp("rm", "rm", "-r", dirname(temp_file), NULL);
93-
perror("exec rm");
94-
exit(1);
95-
} else {
96-
exit(code);
97-
}
98-
}
99-
10084
static void cancelled_callback(struct copy_action *copy_action) {
101-
cleanup_and_exit(copy_action, 0);
85+
exit(0);
10286
}
10387

10488
static void pasted_callback(struct copy_action *copy_action) {
10589
if (options.paste_once) {
106-
cleanup_and_exit(copy_action, 0);
90+
exit(0);
10791
}
10892
}
10993

@@ -244,6 +228,7 @@ int main(int argc, argv_t argv) {
244228

245229
/* Create and initialize the copy action */
246230
struct copy_action *copy_action = calloc(1, sizeof(struct copy_action));
231+
copy_action->fd_to_copy_from = -1;
247232
copy_action->device = device;
248233
copy_action->primary = options.primary;
249234

@@ -266,7 +251,28 @@ int main(int argc, argv_t argv) {
266251
if (options.mime_type == NULL) {
267252
options.mime_type = infer_mime_type_from_contents(temp_file);
268253
}
269-
copy_action->file_to_copy = temp_file;
254+
copy_action->fd_to_copy_from = open(
255+
temp_file,
256+
O_RDONLY | O_CLOEXEC
257+
);
258+
if (copy_action->fd_to_copy_from < 0) {
259+
perror("Failed to open temp file");
260+
return 1;
261+
}
262+
/* Now, remove the temp file and its
263+
* containing directory. We still keep
264+
* access to the file through our open
265+
* file descriptor.
266+
*/
267+
int rc = unlink(temp_file);
268+
if (rc < 0) {
269+
perror("Failed to unlink temp file");
270+
}
271+
rc = rmdir(dirname(temp_file));
272+
if (rc < 0) {
273+
perror("Failed to remove temp file directory");
274+
}
275+
free(temp_file);
270276
}
271277

272278
/* Create the source */
@@ -300,6 +306,5 @@ int main(int argc, argv_t argv) {
300306
while (wl_display_dispatch(wl_display) >= 0);
301307

302308
perror("wl_display_dispatch");
303-
cleanup_and_exit(copy_action, 1);
304309
return 1;
305310
}

0 commit comments

Comments
 (0)