Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shorten temporary files lifetime, various fixes/refactoring #155

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
15 changes: 14 additions & 1 deletion src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ foreach protocol : protocols
protocol_deps += lib
endforeach

inc = include_directories('.')

lib = static_library(
'wl-clipboard',
[
Expand Down Expand Up @@ -124,22 +126,33 @@ lib = static_library(
'types/registry.c',
'types/copy-action.h',
'types/copy-action.c',
'types/buffer.h',
'types/buffer.c',
'types/copy-source-argv.h',
'types/copy-source-argv.c',
'types/copy-source-buffer.h',
'types/copy-source-buffer.c',
'types/sensitive-section.h',
'types/sensitive-section.c',
],
dependencies: wayland,
link_with: protocol_deps
link_with: protocol_deps,
include_directories: [inc]
)

executable(
'wl-copy',
['wl-copy.c', protocol_headers],
dependencies: wayland,
link_with: lib,
include_directories: [inc],
install: true
)
executable(
'wl-paste',
['wl-paste.c', protocol_headers],
dependencies: wayland,
link_with: lib,
include_directories: [inc],
install: true
)
33 changes: 33 additions & 0 deletions src/types/buffer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* wl-clipboard
*
* Copyright © 2019 Sergey Bugaev <bugaevc@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/


#include <string.h>

#include "buffer.h"

static void noop(struct buffer*) {
/* intentionally left blank */
}

void buffer_steal(struct buffer* dest, struct buffer* src) {
memcpy(dest, src, sizeof(*src));
src->destroy = noop;
src->ptr = NULL;
src->len = 0;
}
38 changes: 38 additions & 0 deletions src/types/buffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/* wl-clipboard
*
* Copyright © 2019 Sergey Bugaev <bugaevc@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef TYPES_OWNED_SLICE_H
#define TYPES_OWNED_SLICE_H

#include <stddef.h>

struct buffer {
void (*destroy)(struct buffer*);

char* ptr;
size_t len;
};

/// @brief Steal buffer to dest from src, leaving the latter empty
/// @param[out] dest Uninitialised (or empty) buffer
/// @param[in] src Initialised and valid buffer
/// @note It is safe to call .destroy on src after stealing
/// @warning Does not check anything
void buffer_steal(struct buffer* dest, struct buffer* src);

#endif /* UTIL_FILES_H */
63 changes: 4 additions & 59 deletions src/types/copy-action.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,66 +68,10 @@ static void on_focus(
static void do_send(struct source *source, const char *mime_type, int fd) {
struct copy_action *self = source->data;

/* Unset O_NONBLOCK */
/* Unset O_NONBLOCK */
fcntl(fd, F_SETFL, 0);

if (self->file_to_copy != NULL) {
/* Copy the file to the given file descriptor
* by spawning an appropriate cat process.
*/
pid_t pid = fork();
if (pid < 0) {
perror("fork");
close(fd);
return;
}
if (pid == 0) {
dup2(fd, STDOUT_FILENO);
close(fd);
execlp("cat", "cat", self->file_to_copy, NULL);
perror("exec cat");
exit(1);
}
close(fd);
/* Wait for the cat process to exit. This effectively
* means waiting for the other side to read the whole
* file. In theory, a malicious client could perform a
* denial-of-serivice attack against us. Perhaps we
* should switch to an asynchronous child waiting scheme
* instead.
*/
wait(NULL);
} else {
/* We'll perform the copy ourselves */
FILE *f = fdopen(fd, "w");
if (f == NULL) {
perror("fdopen");
close(fd);
return;
}

if (self->data_to_copy.ptr != NULL) {
/* Just copy the given chunk of data */
fwrite(self->data_to_copy.ptr, 1, self->data_to_copy.len, f);
} else if (self->argv_to_copy != NULL) {
/* Copy an argv-style string array,
* inserting spaces between items.
*/
int is_first = 1;
for (argv_t word = self->argv_to_copy; *word != NULL; word++) {
if (!is_first) {
fwrite(" ", 1, 1, f);
}
is_first = 0;
fwrite(*word, 1, strlen(*word), f);
}
} else {
bail("Unreachable: nothing to copy");
}

fclose(f);
}

self->src->copy(fd, self->src);

if (self->pasted_callback != NULL) {
self->pasted_callback(self);
Expand All @@ -141,7 +85,8 @@ static void forward_cancel(struct source *source) {
}
}

void copy_action_init(struct copy_action *self) {
void copy_action_init(struct copy_action *self, struct copy_source* src) {
self->src = src;
if (self->source != NULL) {
self->source->send_callback = do_send;
self->source->cancelled_callback = forward_cancel;
Expand Down
14 changes: 4 additions & 10 deletions src/types/copy-action.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#ifndef TYPES_COPY_ACTION_H
#define TYPES_COPY_ACTION_H

#include <types/copy-source.h>
#include "util/string.h"

#include <stddef.h>
Expand All @@ -38,17 +39,10 @@ struct copy_action {
void (*pasted_callback)(struct copy_action *self);
void (*cancelled_callback)(struct copy_action *self);

/* Exactly one of these fields must be non-null if the source
* is non-null, otherwise all these fields must be null.
*/
const char *file_to_copy;
argv_t argv_to_copy;
struct {
const char *ptr;
size_t len;
} data_to_copy;
struct copy_source* src;
};

void copy_action_init(struct copy_action *self);
/// @brief Initialise copy action from specified copy source
void copy_action_init(struct copy_action *self, struct copy_source* src);

#endif /* TYPES_COPY_ACTION_H */
57 changes: 57 additions & 0 deletions src/types/copy-source-argv.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/* wl-clipboard
*
* Copyright © 2019 Sergey Bugaev <bugaevc@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/


#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include <types/copy-source-argv.h>

static void copy(int fd, struct copy_source* self) {
struct copy_source_argv* self2 = (struct copy_source_argv*)self;

FILE* file = fdopen(fd, "w");
if (!file) {
perror("copy_source_argv/copy: fdopen");
close(fd);
return;
}

argv_t word = self2->argv;
if (*word) {
fwrite(*word, 1, strlen(*word), file);
++word;
}
for (; *word; ++word) {
fputc(' ', file);
fwrite(*word, 1, strlen(*word), file);
}
fclose(file);
}


int copy_source_argv_init(struct copy_source_argv* self, argv_t argv) {
self->impl.copy = copy;
if (!argv) {
return -1;
}
self->argv = argv;
return 0;
}

41 changes: 41 additions & 0 deletions src/types/copy-source-argv.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/* wl-clipboard
*
* Copyright © 2019 Sergey Bugaev <bugaevc@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef TYPES_COPY_SOURCE_ARGV_H
#define TYPES_COPY_SOURCE_ARGV_H

#include <util/string.h>
#include <types/copy-source.h>

#include <stddef.h>

/// @brief Copy source, serving data from the argv-like array of strings
struct copy_source_argv {
struct copy_source impl;

argv_t argv;
};

/// @brief Initialise copy source from argv-like array of (unowned) array of strings,
/// terminated with empty string
/// @param[out] self Uninitialised copy source
/// @param[in] argv argv-like array of strings
/// @return 0 on success, negative value otherwise
int copy_source_argv_init(struct copy_source_argv* self, argv_t argv);

#endif /* TYPES_COPY_ACTION_H */
67 changes: 67 additions & 0 deletions src/types/copy-source-buffer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/* wl-clipboard
*
* Copyright © 2019 Sergey Bugaev <bugaevc@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <types/copy-source-buffer.h>

static void copy(int fd, struct copy_source* self) {
struct copy_source_buffer* self2 = (struct copy_source_buffer*)self;

const char* ptr = self2->slice.ptr;
size_t len = self2->slice.len;

for (;;) {
ssize_t bytes = write(fd, ptr, len);
if (bytes < 0) {
perror("copy_source_slice/copy: write");
close(fd);
exit(1);
}
len -= bytes;
if (!bytes || !len) {
break;
}
ptr += bytes;
}

if (close(fd)) {
perror("copy_source_slice/copy: close");
}
}

static void destroy(struct copy_source* self) {
struct copy_source_buffer* self2 = (struct copy_source_buffer*)self;
self2->slice.destroy(&self2->slice);
}


int copy_source_buffer_init(struct copy_source_buffer* self, struct buffer* slice) {
if (!slice || !slice->ptr || !slice->len) {
return -1;
}

self->impl.copy = copy;
self->impl.destroy = destroy;

buffer_steal(&self->slice, slice);
return 0;
}

Loading