From 26470029ecff8baa9b7a5a8162618c51e891fc8b Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Fri, 18 Mar 2016 10:22:18 -0300 Subject: [PATCH] Exit before transmission if receipt file cannot be created. If opening the receipt file fails after transmission, it's too late to tell the user about the failure. Reviewed-by: Gabriel F. T. Gomes --- rnetclient.c | 68 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/rnetclient.c b/rnetclient.c index 5d56ac1..3561b45 100644 --- a/rnetclient.c +++ b/rnetclient.c @@ -72,6 +72,9 @@ struct rnetclient_args { /* Output directory to save the receipt. */ char *output_dir; + + /* Output filename. */ + char output_file[PATH_MAX]; }; /* Parser for command line arguments. */ @@ -343,12 +346,10 @@ static int rnet_recv(gnutls_session_t session, struct rnet_message **message) return 0; } -static void save_rec_file(char *cpf, char *buffer, int len, const struct rnetclient_args *args) +static int open_rec_file(char *cpf, struct rnetclient_args *args) { int fd; - char *path, *fname, *tmp; - size_t fname_len; - ssize_t r; + char *path, *tmp; path = args->output_dir; @@ -371,47 +372,53 @@ static void save_rec_file(char *cpf, char *buffer, int len, const struct rnetcli just have to change one letter. */ tmp = strstr(p, ".DEC"); tmp[1] = 'R'; - fname_len = strlen(p) + strlen(path) + 2; - fname = alloca(fname_len); - snprintf(fname, fname_len, "%s/%s", path, p); + snprintf(args->output_file, PATH_MAX, "%s/%s", path, p); free(p); } else { /* The declaration filename does not follow the convention, so we will not use it as a template. We just generate a filename using "$CPF.REC". */ - fname_len = strlen(cpf) + strlen(path) + sizeof(".REC") + 2; - fname = alloca(fname_len); - snprintf(fname, fname_len, "%s/%s.REC", path, cpf); + snprintf(args->output_file, PATH_MAX, "%s/%s.REC", path, cpf); } /* Now, open the file and write. */ - fd = open(fname, O_CREAT | O_WRONLY | O_EXCL, S_IRUSR | S_IWUSR); + fd = open(args->output_file, O_CREAT | O_WRONLY | O_EXCL, S_IRUSR | S_IWUSR); if (fd < 0) { - fprintf(stderr, "Could not create receipt file \"%s\": %s\n", fname, strerror(errno)); - return; + fprintf(stderr, "Could not create receipt file \"%s\": %s\n", + args->output_file, strerror(errno)); } + return fd; +} + +static int save_rec_file(int fd, char *buffer, int len, const struct rnetclient_args *args) +{ + ssize_t r; + do { r = write(fd, buffer, len); } while (r < 0 && errno == EAGAIN); - if (r != len) - fprintf(stderr, "Could not write to receipt file: %s", strerror(errno)); - else - fprintf(stderr, "Wrote the receipt file to %s.\n", fname); - close(fd); + if (r != len) { + fprintf(stderr, "Could not write to receipt file: %s", + strerror(errno)); + } else { + fprintf(stderr, "Wrote the receipt file to %s.\n", + args->output_file); + } + return r; } -static void handle_response_text_and_file(char *cpf, struct rnet_message *message, const struct rnetclient_args *args) +static void handle_response_text_and_file(int fd, struct rnet_message *message, const struct rnetclient_args *args) { char *value; int vlen; if (!rnet_message_parse(message, "texto", &value, &vlen)) fprintf(stderr, "%.*s\n", vlen, value); if (!rnet_message_parse(message, "arquivo", &value, &vlen)) - save_rec_file(cpf, value, vlen, args); + save_rec_file(fd, value, vlen, args); } -static void handle_response_already_found(char *cpf, struct rnet_message *message, const struct rnetclient_args *args) +static void handle_response_already_found(int fd, struct rnet_message *message, const struct rnetclient_args *args) { - handle_response_text_and_file(cpf, message, args); + handle_response_text_and_file(fd, message, args); } static void handle_response_error(struct rnet_message *message) @@ -435,6 +442,7 @@ int main(int argc, char **argv) char *cpf; error_t err; char cwd[PATH_MAX]; + int outfd; /* Parsing the command line arguments. The argp_parse function calls exit() if there is some error during the @@ -476,6 +484,12 @@ int main(int argc, char **argv) cpf = rnet_decfile_get_header_field(decfile, "cpf"); + outfd = open_rec_file(cpf, &rnet_args); + if (outfd < 0) { + r = 1; + goto out_rec; + } + gnutls_global_init(); session_new(&session); @@ -518,19 +532,19 @@ int main(int argc, char **argv) } switch (message->buffer[0]) { case 1: /* go ahead */ - handle_response_text_and_file(cpf, message, &rnet_args); + handle_response_text_and_file(outfd, message, &rnet_args); break; case 3: /* error */ handle_response_error(message); finish = 1; break; case 4: - handle_response_already_found(cpf, message, &rnet_args); + handle_response_already_found(outfd, message, &rnet_args); finish = 1; break; case 2: case 5: - handle_response_text_and_file(cpf, message, &rnet_args); + handle_response_text_and_file(outfd, message, &rnet_args); finish = 1; break; } @@ -557,7 +571,7 @@ int main(int argc, char **argv) case 4: case 5: case 1: - handle_response_text_and_file(cpf, message, &rnet_args); + handle_response_text_and_file(outfd, message, &rnet_args); break; } @@ -567,6 +581,8 @@ out_handshake: close(c); out_connect: gnutls_global_deinit(); + close(outfd); +out_rec: rnet_decfile_close(decfile); return r; -- 2.20.1