X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=blob.c;h=5905c9ad660cd93360fe77ef50ff81c4fe2a39df;hp=1742ac427c85e6e7cc35becc9cfbe508e45bf750;hb=a9126f461792a84c760162ecb25100f1593d427d;hpb=00e4d4da1b2c00da139b09d3ed4ab9ad9fba2691 diff --git a/blob.c b/blob.c index 1742ac42..5905c9ad 100644 --- a/blob.c +++ b/blob.c @@ -7,8 +7,11 @@ /** \file blob.c Macros and functions for blob handling. */ #include +#include + #include "para.h" #include "error.h" +#include "crypt.h" #include "string.h" #include "afh.h" #include "afs.h" @@ -67,13 +70,13 @@ static int print_blob(struct osl_table *table, struct osl_row *row, struct lsblob_action_data *lbad = data; struct osl_object obj; uint32_t id; - int ret, ret2; + int ret; if (!(lbad->flags & BLOB_LS_FLAG_LONG)) return para_printf(&lbad->pb, "%s\n", name); ret = osl_get_object(table, row, BLOBCOL_ID, &obj); if (ret < 0) { - ret2 = para_printf(&lbad->pb, "%s: %s\n", name, para_strerror(-ret)); + para_printf(&lbad->pb, "%s: %s\n", name, para_strerror(-ret)); return ret; } id = *(uint32_t *)obj.data; @@ -110,13 +113,13 @@ static void com_lsblob_callback(struct osl_table *table, pmd.loop_col_num = BLOBCOL_ID; ret = for_each_matching_row(&pmd); if (ret < 0) - ret = para_printf(&lbad.pb, "%s\n", para_strerror(-ret)); + para_printf(&lbad.pb, "%s\n", para_strerror(-ret)); if (lbad.pb.offset) pass_buffer_as_shm(lbad.pb.buf, lbad.pb.offset, &fd); free(lbad.pb.buf); } -static int com_lsblob(callback_function *f, int fd, int argc, char * const * const argv) +static int com_lsblob(callback_function *f, struct rc4_context *rc4c, int argc, char * const * const argv) { uint32_t flags = 0; struct osl_object options = {.data = &flags, .size = sizeof(flags)}; @@ -147,7 +150,7 @@ static int com_lsblob(callback_function *f, int fd, int argc, char * const * con // if (argc > i) // return -E_BLOB_SYNTAX; return send_option_arg_callback_request(&options, argc - i, - argv + i, f, send_result, &fd); + argv + i, f, rc4_send_result, rc4c); } static int cat_blob(struct osl_table *table, struct osl_row *row, @@ -180,12 +183,13 @@ static void com_catblob_callback(struct osl_table *table, int fd, for_each_matching_row(&pmd); } -static int com_catblob(callback_function *f, int fd, int argc, +static int com_catblob(callback_function *f, struct rc4_context *rc4c, int argc, char * const * const argv) { if (argc < 2) return -E_BLOB_SYNTAX; - return send_standard_callback_request(argc - 1, argv + 1, f, send_result, &fd); + return send_standard_callback_request(argc - 1, argv + 1, f, + rc4_send_result, rc4c); } /** Used for removing rows from a blob table. */ @@ -200,9 +204,9 @@ static int remove_blob(struct osl_table *table, struct osl_row *row, const char *name, void *data) { struct rmblob_data *rmbd = data; - int ret = osl_del_row(table, row), ret2; + int ret = osl_del_row(table, row); if (ret < 0) { - ret2 = para_printf(&rmbd->pb, "%s: %s\n", name, para_strerror(-ret)); + para_printf(&rmbd->pb, "%s: %s\n", name, para_strerror(-ret)); return ret; } rmbd->num_removed++; @@ -248,13 +252,13 @@ out: free(rmbd.pb.buf); } -static int com_rmblob(callback_function *f, int fd, int argc, +static int com_rmblob(callback_function *f, struct rc4_context *rc4c, int argc, char * const * const argv) { if (argc < 2) return -E_MOOD_SYNTAX; return send_option_arg_callback_request(NULL, argc - 1, argv + 1, f, - send_result, &fd); + rc4_send_result, rc4c); } static void com_addblob_callback(struct osl_table *table, __a_unused int fd, @@ -326,7 +330,82 @@ out: PARA_NOTICE_LOG("%s\n", para_strerror(-ret)); } -static int com_addblob(callback_function *f, int fd, int argc, +/* + * write input from fd to dynamically allocated buffer, + * but maximal max_size byte. + */ +static int fd2buf(struct rc4_context *rc4c, unsigned max_size, struct osl_object *obj) +{ + const size_t chunk_size = 1024; + size_t size = 2048, received = 0; + int ret; + char *buf = para_malloc(size); + + for (;;) { + ret = rc4_recv_bin_buffer(rc4c, buf + received, chunk_size); + if (ret <= 0) + break; + received += ret; + if (received + chunk_size >= size) { + size *= 2; + ret = -E_INPUT_TOO_LARGE; + if (size > max_size) + break; + buf = para_realloc(buf, size); + } + } + obj->data = buf; + obj->size = received; + if (ret < 0) + free(buf); + return ret; +} + +/* + * Read data from a file descriptor, and send it to the afs process. + * + * \param rc4c crypt context containing the file descriptor to read data from. + * \param arg_obj Pointer to the arguments to \a f. + * \param f The callback function. + * \param max_len Don't read more than that many bytes from stdin. + * \param result_handler See \ref send_callback_request. + * \param private_result_data See \ref send_callback_request. + * + * This function is used by commands that wish to let para_server store + * arbitrary data specified by the user (for instance the add_blob family of + * commands). First, at most \a max_len bytes are read and decrypted from the + * file descriptor given by \a rc4c. The result is concatenated with the buffer + * given by \a arg_obj, and the combined buffer is made available to the afs + * process via the callback method. See \ref send_callback_request for details. + * + * \return Negative on errors, the return value of the underlying call to + * send_callback_request() otherwise. + */ +static int stdin_command(struct rc4_context *rc4c, struct osl_object *arg_obj, + callback_function *f, unsigned max_len, + callback_result_handler *result_handler, + void *private_result_data) +{ + struct osl_object query, stdin_obj; + int ret; + + ret = rc4_send_buffer(rc4c, AWAITING_DATA_MSG); + if (ret < 0) + return ret; + ret = fd2buf(rc4c, max_len, &stdin_obj); + if (ret < 0) + return ret; + query.size = arg_obj->size + stdin_obj.size; + query.data = para_malloc(query.size); + memcpy(query.data, arg_obj->data, arg_obj->size); + memcpy((char *)query.data + arg_obj->size, stdin_obj.data, stdin_obj.size); + free(stdin_obj.data); + ret = send_callback_request(f, &query, result_handler, private_result_data); + free(query.data); + return ret; +} + +static int com_addblob(callback_function *f, struct rc4_context *rc4c, int argc, char * const * const argv) { struct osl_object arg_obj; @@ -337,7 +416,7 @@ static int com_addblob(callback_function *f, int fd, int argc, return -E_BLOB_SYNTAX; arg_obj.size = strlen(argv[1]) + 1; arg_obj.data = (char *)argv[1]; - return stdin_command(fd, &arg_obj, f, 10 * 1024 * 1024, NULL, NULL); + return stdin_command(rc4c, &arg_obj, f, 10 * 1024 * 1024, NULL, NULL); } /* FIXME: Print output to client, not to log file */ @@ -363,7 +442,7 @@ out: PARA_NOTICE_LOG("%s\n", para_strerror(-ret)); } -static int com_mvblob(callback_function *f, __a_unused int fd, +static int com_mvblob(callback_function *f, __a_unused struct rc4_context *rc4c, int argc, char * const * const argv) { if (argc != 3) @@ -377,9 +456,9 @@ static int com_mvblob(callback_function *f, __a_unused int fd, { \ return com_ ## cmd_name ## blob_callback(table_name ## _table, fd, query); \ } \ - int com_ ## cmd_name ## cmd_prefix(int fd, int argc, char * const * const argv) \ + int com_ ## cmd_name ## cmd_prefix(struct rc4_context *rc4c, int argc, char * const * const argv) \ { \ - return com_ ## cmd_name ## blob(com_ ## cmd_name ## cmd_prefix ## _callback, fd, argc, argv); \ + return com_ ## cmd_name ## blob(com_ ## cmd_name ## cmd_prefix ## _callback, rc4c, argc, argv); \ } static int blob_get_name_by_id(struct osl_table *table, uint32_t id,