Skip to content

Commit

Permalink
GUACAMOLE-1931: Merge allow writing to existing typescript files.
Browse files Browse the repository at this point in the history
  • Loading branch information
necouchman authored Mar 29, 2024
2 parents 7553e79 + a52177d commit f9d9dff
Show file tree
Hide file tree
Showing 13 changed files with 114 additions and 34 deletions.
3 changes: 2 additions & 1 deletion src/protocols/kubernetes/kubernetes.c
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,8 @@ void* guac_kubernetes_client_thread(void* data) {
guac_terminal_create_typescript(kubernetes_client->term,
settings->typescript_path,
settings->typescript_name,
settings->create_typescript_path);
settings->create_typescript_path,
settings->typescript_write_existing);
}

/* Init libwebsockets context creation parameters */
Expand Down
12 changes: 12 additions & 0 deletions src/protocols/kubernetes/settings.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ const char* GUAC_KUBERNETES_CLIENT_ARGS[] = {
"typescript-path",
"typescript-name",
"create-typescript-path",
"typescript-write-existing",
"recording-path",
"recording-name",
"recording-exclude-output",
Expand Down Expand Up @@ -167,6 +168,12 @@ enum KUBERNETES_ARGS_IDX {
*/
IDX_CREATE_TYPESCRIPT_PATH,

/**
* Whether existing files should be appended to when creating a new
* typescript. Disabled by default.
*/
IDX_TYPESCRIPT_WRITE_EXISTING,

/**
* The full absolute path to the directory in which screen recordings
* should be written.
Expand Down Expand Up @@ -366,6 +373,11 @@ guac_kubernetes_settings* guac_kubernetes_parse_args(guac_user* user,
guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS, argv,
IDX_CREATE_TYPESCRIPT_PATH, false);

/* Parse allow write existing file flag */
settings->typescript_write_existing =
guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS, argv,
IDX_TYPESCRIPT_WRITE_EXISTING, false);

/* Read recording path */
settings->recording_path =
guac_user_parse_args_string(user, GUAC_KUBERNETES_CLIENT_ARGS, argv,
Expand Down
6 changes: 6 additions & 0 deletions src/protocols/kubernetes/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,12 @@ typedef struct guac_kubernetes_settings {
*/
bool create_typescript_path;

/**
* Whether existing files should be appended to when creating a new
* typescript. Disabled by default.
*/
bool typescript_write_existing;

/**
* The path in which the screen recording should be saved, if enabled. If
* no screen recording should be saved, this will be NULL.
Expand Down
12 changes: 12 additions & 0 deletions src/protocols/ssh/settings.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ const char* GUAC_SSH_CLIENT_ARGS[] = {
"typescript-path",
"typescript-name",
"create-typescript-path",
"typescript-write-existing",
"recording-path",
"recording-name",
"recording-exclude-output",
Expand Down Expand Up @@ -198,6 +199,12 @@ enum SSH_ARGS_IDX {
*/
IDX_CREATE_TYPESCRIPT_PATH,

/**
* Whether existing files should be appended to when creating a new
* typescript. Disabled by default.
*/
IDX_TYPESCRIPT_WRITE_EXISTING,

/**
* The full absolute path to the directory in which screen recordings
* should be written.
Expand Down Expand Up @@ -472,6 +479,11 @@ guac_ssh_settings* guac_ssh_parse_args(guac_user* user,
guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv,
IDX_CREATE_TYPESCRIPT_PATH, false);

/* Parse allow write existing file flag */
settings->typescript_write_existing =
guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv,
IDX_TYPESCRIPT_WRITE_EXISTING, false);

/* Read recording path */
settings->recording_path =
guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv,
Expand Down
6 changes: 6 additions & 0 deletions src/protocols/ssh/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,12 @@ typedef struct guac_ssh_settings {
*/
bool create_typescript_path;

/**
* Whether existing files should be appended to when creating a new
* typescript. Disabled by default.
*/
bool typescript_write_existing;

/**
* The path in which the screen recording should be saved, if enabled. If
* no screen recording should be saved, this will be NULL.
Expand Down
3 changes: 2 additions & 1 deletion src/protocols/ssh/ssh.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,8 @@ void* ssh_client_thread(void* data) {
guac_terminal_create_typescript(ssh_client->term,
settings->typescript_path,
settings->typescript_name,
settings->create_typescript_path);
settings->create_typescript_path,
settings->typescript_write_existing);
}

/* Get user and credentials */
Expand Down
12 changes: 12 additions & 0 deletions src/protocols/telnet/settings.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ const char* GUAC_TELNET_CLIENT_ARGS[] = {
"typescript-path",
"typescript-name",
"create-typescript-path",
"typescript-write-existing",
"recording-path",
"recording-name",
"recording-exclude-output",
Expand Down Expand Up @@ -150,6 +151,12 @@ enum TELNET_ARGS_IDX {
*/
IDX_CREATE_TYPESCRIPT_PATH,

/**
* Whether existing files should be appended to when creating a new
* typescript. Disabled by default.
*/
IDX_TYPESCRIPT_WRITE_EXISTING,

/**
* The full absolute path to the directory in which screen recordings
* should be written.
Expand Down Expand Up @@ -463,6 +470,11 @@ guac_telnet_settings* guac_telnet_parse_args(guac_user* user,
guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv,
IDX_CREATE_TYPESCRIPT_PATH, false);

/* Parse allow write existing file flag */
settings->typescript_write_existing =
guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv,
IDX_TYPESCRIPT_WRITE_EXISTING, false);

/* Read recording path */
settings->recording_path =
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
Expand Down
6 changes: 6 additions & 0 deletions src/protocols/telnet/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,12 @@ typedef struct guac_telnet_settings {
*/
bool create_typescript_path;

/**
* Whether existing files should be appended to when creating a new
* typescript. Disabled by default.
*/
bool typescript_write_existing;

/**
* The path in which the screen recording should be saved, if enabled. If
* no screen recording should be saved, this will be NULL.
Expand Down
3 changes: 2 additions & 1 deletion src/protocols/telnet/telnet.c
Original file line number Diff line number Diff line change
Expand Up @@ -644,7 +644,8 @@ void* guac_telnet_client_thread(void* data) {
guac_terminal_create_typescript(telnet_client->term,
settings->typescript_path,
settings->typescript_name,
settings->create_typescript_path);
settings->create_typescript_path,
settings->typescript_write_existing);
}

/* Open telnet session */
Expand Down
5 changes: 3 additions & 2 deletions src/terminal/terminal.c
Original file line number Diff line number Diff line change
Expand Up @@ -2029,10 +2029,11 @@ void guac_terminal_pipe_stream_close(guac_terminal* term) {
}

int guac_terminal_create_typescript(guac_terminal* term, const char* path,
const char* name, int create_path) {
const char* name, int create_path, int allow_write_existing) {

/* Create typescript */
term->typescript = guac_terminal_typescript_alloc(path, name, create_path);
term->typescript = guac_terminal_typescript_alloc(
path, name, create_path, allow_write_existing);

/* Log failure */
if (term->typescript == NULL) {
Expand Down
25 changes: 17 additions & 8 deletions src/terminal/terminal/terminal.h
Original file line number Diff line number Diff line change
Expand Up @@ -747,13 +747,18 @@ void guac_terminal_clipboard_append(guac_terminal* terminal,
void guac_terminal_remove_user(guac_terminal* terminal, guac_user* user);

/**
* Requests that the terminal write all output to a new pair of typescript
* files within the given path and using the given base name. Terminal output
* will be written to these new files, along with timing information. If the
* create_path flag is non-zero, the given path will be created if it does not
* yet exist. If creation of the typescript files or path fails, error messages
* will automatically be logged, and no typescript will be written. The
* typescript will automatically be closed once the terminal is freed.
* Requests that the terminal write all output to a pair of typescript
* files within the given path and using the given base name. If
* allow_write_existing is non-zero, these may be existing files; otherwise,
* the existing files may not be written to, and a non-zero value will be
* returned.
*
* Terminal output will be written to the files, along with timing information.
* If the create_path flag is non-zero, the given path will be created if it
* does not yet exist. If creation of the typescript files or path fails,
* error messages will automatically be logged, and no typescript will be
* written. The typescript will automatically be closed once the terminal is
* freed.
*
* @param term
* The terminal whose output should be written to a typescript.
Expand All @@ -771,12 +776,16 @@ void guac_terminal_remove_user(guac_terminal* terminal, guac_user* user);
* written, or non-zero if the path should be created if it does not yet
* exist.
*
* @param allow_write_existing
* Non-zero if writing to existing files should be allowed, or zero
* otherwise.
*
* @return
* Zero if the typescript files have been successfully created and a
* typescript will be written, non-zero otherwise.
*/
int guac_terminal_create_typescript(guac_terminal* term, const char* path,
const char* name, int create_path);
const char* name, int create_path, int allow_write_existing);

/**
* Immediately applies the given color scheme to the given terminal, overriding
Expand Down
14 changes: 10 additions & 4 deletions src/terminal/terminal/typescript.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,13 @@ typedef struct guac_terminal_typescript {
} guac_terminal_typescript;

/**
* Creates a new pair of typescript files within the given path and using the
* Creates a pair of typescript files within the given path and using the
* given base name, returning an abstraction which represents those files.
* Terminal output will be written to these new files, along with timing
* Terminal output will be written to these files, along with timing
* information. If the create_path flag is non-zero, the given path will be
* created if it does not yet exist.
* created if it does not yet exist. If allow_write_existing is non-zero,
* these may be existing files; otherwise, any existing file will cause this
* function to fail, returning NULL.
*
* @param path
* The full absolute path to a directory in which the typescript files
Expand All @@ -144,12 +146,16 @@ typedef struct guac_terminal_typescript {
* written, or non-zero if the path should be created if it does not yet
* exist.
*
* @param allow_write_existing
* Non-zero if writing to existing files should be allowed, or zero
* otherwise.
*
* @return
* A new guac_terminal_typescript representing the typescript files
* requested, or NULL if creation of the typescript files failed.
*/
guac_terminal_typescript* guac_terminal_typescript_alloc(const char* path,
const char* name, int create_path);
const char* name, int create_path, int allow_write_existing);

/**
* Writes a single byte of terminal data to the typescript, flushing and
Expand Down
41 changes: 24 additions & 17 deletions src/terminal/typescript.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@
#include <fcntl.h>

/**
* Attempts to open a new typescript data file within the given path and having
* the given name. If such a file already exists, sequential numeric suffixes
* (.1, .2, .3, etc.) are appended until a filename is found which does not
* exist (or until the maximum number of numeric suffixes has been tried). If
* the file absolutely cannot be opened due to an error, -1 is returned and
* errno is set appropriately.
* Attempts to open a typescript data file within the given path and having
* the given name. If such a file already exists and allow_write_existing is
* zero, sequential numeric suffixes (.1, .2, .3, etc.) are appended until a
* filename is found which does not exist (or until the maximum number of
* numeric suffixes has been tried). If the file absolutely cannot be opened
* due to an error, -1 is returned and errno is set appropriately.
*
* @param path
* The full path to the directory in which the data file should be created.
Expand All @@ -55,12 +55,17 @@
* @param basename_size
* The number of bytes available within the provided basename buffer.
*
* @param allow_write_existing
* Non-zero if writing to an existing file should be allowed, or zero
* otherwise.
*
* @return
* The file descriptor of the open data file if open succeeded, or -1 on
* failure.
*/
static int guac_terminal_typescript_open_data_file(const char* path,
const char* name, char* basename, int basename_size) {
const char* name, char* basename, int basename_size,
int allow_write_existing) {

int i;

Expand All @@ -76,10 +81,11 @@ static int guac_terminal_typescript_open_data_file(const char* path,
return -1;
}

/* Require the file not exist already if allow_write_existing not set */
int file_flags = O_CREAT | O_WRONLY | (allow_write_existing ? 0 : O_EXCL);

/* Attempt to open typescript data file */
int data_fd = open(basename,
O_CREAT | O_EXCL | O_WRONLY,
S_IRUSR | S_IWUSR | S_IRGRP);
int data_fd = open(basename, file_flags, S_IRUSR | S_IWUSR | S_IRGRP);

/* Continuously retry with alternate names on failure */
if (data_fd == -1) {
Expand All @@ -96,9 +102,7 @@ static int guac_terminal_typescript_open_data_file(const char* path,
sprintf(suffix, "%i", i);

/* Retry with newly-suffixed filename */
data_fd = open(basename,
O_CREAT | O_EXCL | O_WRONLY,
S_IRUSR | S_IWUSR | S_IRGRP);
data_fd = open(basename, file_flags, S_IRUSR | S_IWUSR | S_IRGRP);

}

Expand All @@ -109,7 +113,7 @@ static int guac_terminal_typescript_open_data_file(const char* path,
}

guac_terminal_typescript* guac_terminal_typescript_alloc(const char* path,
const char* name, int create_path) {
const char* name, int create_path, int allow_write_existing) {

/* Create path if it does not exist, fail if impossible */
if (create_path && mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP)
Expand All @@ -124,7 +128,8 @@ guac_terminal_typescript* guac_terminal_typescript_alloc(const char* path,
typescript->data_fd = guac_terminal_typescript_open_data_file(
path, name, typescript->data_filename,
sizeof(typescript->data_filename)
- sizeof(GUAC_TERMINAL_TYPESCRIPT_TIMING_SUFFIX));
- sizeof(GUAC_TERMINAL_TYPESCRIPT_TIMING_SUFFIX),
allow_write_existing);
if (typescript->data_fd == -1) {
guac_mem_free(typescript);
return NULL;
Expand All @@ -139,10 +144,12 @@ guac_terminal_typescript* guac_terminal_typescript_alloc(const char* path,
return NULL;
}

/* Require the file not exist already if allow_write_existing not set */
int file_flags = O_CREAT | O_WRONLY | (allow_write_existing ? 0 : O_EXCL);

/* Attempt to open typescript timing file */
typescript->timing_fd = open(typescript->timing_filename,
O_CREAT | O_EXCL | O_WRONLY,
S_IRUSR | S_IWUSR | S_IRGRP);
file_flags, S_IRUSR | S_IWUSR | S_IRGRP);
if (typescript->timing_fd == -1) {
close(typescript->data_fd);
guac_mem_free(typescript);
Expand Down

0 comments on commit f9d9dff

Please sign in to comment.