static gboolean _rawx_update_chunk_attrs(chunk_id_t *cid, GSList *attrs, GError **err) { ne_session *s = NULL; ne_request *r = NULL; int ne_rc; gboolean result = FALSE; gchar dst[128]; guint16 port = 0; GString *req_str = NULL; char idstr[65]; if (!addr_info_get_addr(&(cid->addr), dst, sizeof(dst), &port)) return result; s = ne_session_create("http", dst, port); if (!s) { GSETERROR(err, "Failed to create session to rawx %s:%d", dst, port); return result; } ne_set_connect_timeout(s, 10); ne_set_read_timeout(s, 30); req_str =g_string_new("/rawx/chunk/set/"); oio_str_bin2hex (&(cid->id), sizeof(cid->id), idstr, sizeof(idstr)); req_str = g_string_append(req_str, idstr); GRID_TRACE("Calling %s", req_str->str); r = ne_request_create (s, "GET", req_str->str); if (!r) { goto end_attr; } for (; attrs != NULL; attrs = attrs->next) { struct chunk_attr_s *attr = attrs->data; ne_add_request_header(r, attr->key, attr->val); } switch (ne_rc = ne_request_dispatch(r)) { case NE_OK: result = TRUE; break; case NE_ERROR: GSETCODE(err, CODE_INTERNAL_ERROR, "Request NE_ERROR"); break; case NE_TIMEOUT: GSETCODE(err, CODE_INTERNAL_ERROR, "Request Timeout"); break; case NE_CONNECT: GSETCODE(err, CODE_INTERNAL_ERROR, "Request Connection timeout"); break; default: GSETCODE(err, CODE_INTERNAL_ERROR, "Request failed"); break; } end_attr: if (NULL != req_str) g_string_free(req_str, TRUE); if (NULL != r) ne_request_destroy (r); if (NULL != s) ne_session_destroy (s); return result; }
int get_idx_of_service(const char *service_type, struct grid_service_data *service, GError **error) { char file_name[strlen(IDX_STORE_PATH) + strlen(service_type) +1]; struct stat file_stat; int rc; GArray *known_services = NULL; struct grid_service_data *known_service = NULL; gboolean idx_found = FALSE; int last_idx = 0; memset(file_name, '\0', strlen(IDX_STORE_PATH) + strlen(service_type) +1); memset(&file_stat, 0, sizeof(struct stat)); sprintf(file_name, "%s%s_snmp_idx.dat", IDX_STORE_PATH, service_type); rc = stat(file_name, &file_stat); if (rc < 0 && errno != ENOENT && errno != ENOTDIR) { GSETERROR(error, "Failed to stat file [%s] : %s", file_name, strerror(errno)); return(0); } known_services = g_array_new(TRUE, TRUE, sizeof(struct grid_service_data)); if (rc < 0) { service->idx = 0; g_array_append_val(known_services, *service); if (!save_known_service_to_file(known_services, file_name, error)) { GSETERROR(error, "Failed to save known services to file [%s]", file_name); g_array_free(known_services, TRUE); return(0); } } else { guint i; read_known_service_from_file(known_services, file_name, error); for (i = 0; i < known_services->len; i++) { known_service = &g_array_index(known_services, struct grid_service_data, i); if (0 == g_ascii_strcasecmp(service->desc, known_service->desc)) { service->idx = known_service->idx; idx_found = TRUE; break; } else if (known_service->idx > last_idx) last_idx = known_service->idx; } if (!idx_found) { service->idx = last_idx+1; g_array_append_val(known_services, *service); if (!save_known_service_to_file(known_services, file_name, error)) { GSETERROR(error, "Failed to save known sevices to file [%s]", file_name); g_array_free(known_services, TRUE); return(0); } } } g_array_free(known_services, TRUE); return(1); }
int compress_chunk(const gchar* path, const gchar* algo, const gint64 blocksize, gboolean preserve, GError ** error) { GError *local_error = NULL; int status = 0; gchar *tmp_path = NULL; gulong tmp_len; guint32 compressed_size = 0; struct compression_ctx_s* comp_ctx = NULL; guint8* buf = NULL; gsize nb_read; gsize nb_write; GByteArray *gba = NULL; gulong checksum = 0; FILE *src = NULL; FILE *dst = NULL; /* Sanity check */ if(!path || ! algo) { GSETERROR(error, "Invalid parameter %p\n", path); return status; } if (!check_uncompressed_chunk(path, &local_error)) { if(local_error) { GSETERROR(error, "Chunk check failed :\n%s", local_error->message); g_clear_error(&local_error); } else GSETERROR(error, "Chunk check failed : no error\n"); return status; } tmp_len = strlen(path) +sizeof(".pending"); tmp_path = g_malloc0(tmp_len); g_snprintf(tmp_path, tmp_len, "%s.pending", path); comp_ctx = g_malloc0(sizeof(struct compression_ctx_s)); if(!init_compression_ctx(comp_ctx, algo)) { GSETERROR(error, "Failed to init compression context\n"); goto end; } if(!comp_ctx->checksum_initiator(&checksum)) { GSETERROR(error, "Failed to init compression checksum\n"); goto end; } do { int fd; if ((fd = open(tmp_path, O_WRONLY|O_CREAT|O_EXCL, 0644)) == -1) { GSETERROR(error, "Failed to create pending chunk file (%s)\n", strerror(errno)); goto end; } metautils_pclose(&fd); } while (0); if (!copy_fattr(path, tmp_path, &local_error)) { if(local_error) { GSETERROR(error, "Failed to copy extended attributes to destination file:\n%s",local_error->message); g_clear_error(&local_error); } else GSETERROR(error, "Failed to copy extended attributes to destination file\n"); goto end; } DEBUG("Extended attributes copied from src to dst\n"); if(!set_compress_attr(tmp_path, algo, blocksize, &local_error)) { if(local_error) { GSETERROR(error, "Error while adding compression attibutes :\n %s", local_error->message); g_clear_error(&local_error); } goto end; } DEBUG("Compression extended attributes successfully added\n"); src = fopen(path, "r"); dst = fopen(tmp_path, "w"); guint32 bsize32 = blocksize; if(comp_ctx->header_writer(dst, bsize32, &checksum, &compressed_size) != 0) { GSETERROR(error, "Failed to compress source file\n"); goto end; } int src_fd = fileno(src); gsize bsize = blocksize; buf = g_malloc0(blocksize); while(1) { nb_read = 0; nb_read = read(src_fd, buf, bsize); if(nb_read != bsize) { /* check if we hit eof */ if(!feof(src) && ferror(src)) { GSETERROR(error, "An error occured while reading data from source file\n"); goto end; } else { if(nb_read > 0) { gba = g_byte_array_new(); /* process data */ if(0 != comp_ctx->data_compressor(buf, nb_read, gba, &checksum)) { GSETERROR(error, "Error while compressing data\n"); goto end; } /* write compressed data */ nb_write = 0; if ((nb_write = fwrite(gba->data, gba->len, 1, dst)) != 1) { GSETERROR(error, "An error occured while writing data in destination file\n"); goto end; } compressed_size+=gba->len; if(gba) { g_byte_array_free(gba, TRUE); gba = NULL; } } break; } } else { gba = g_byte_array_new(); /* process data */ if(0 != comp_ctx->data_compressor(buf, nb_read, gba, &checksum)) { GSETERROR(error, "Error while compressing data\n"); goto end; } /* write compressed data */ nb_write = 0; if ((nb_write = fwrite(gba->data, gba->len, 1, dst)) != 1) { GSETERROR(error, "An error occured while writing data in destination file\n"); goto end; } compressed_size+=gba->len; if(gba) { g_byte_array_free(gba, TRUE); gba = NULL; } } } DEBUG("Chunk compressed"); if(comp_ctx->eof_writer(dst, checksum, &compressed_size) != 0) { GSETERROR(error, "Failed to write compressed file EOF marker and checksum\n"); goto end; } if(!set_chunk_compressed_size_in_attr(tmp_path, error, compressed_size)) { GSETERROR(error, "Failed to set compression information in extended attributes\n"); goto end; } DEBUG("Compression footers successfully wrote"); status = 1; end: if(src) { if(fclose(src) != 0) WARN("Failed to fclose source file"); src = NULL; } if(dst) { if(fclose(dst) != 0) WARN("Failed to fclose destination file"); dst = NULL; } if(status == 1) { /* TODO: stat old file, rename, paste stat*/ if(preserve) { /* Need to set old file info in new file */ TRACE("Renaming and setting good informations to new file..."); struct stat stat_buf = {0}; if(stat(path, &stat_buf) == -1) { GSETERROR (error, "Failed to stat old file, cannot keep old file information, abort\n"); /* remove tmp file */ DEBUG("Removing failed file"); if(remove(tmp_path) != 0) WARN("Failed to remove tmp file [%s]", tmp_path); status = 0; } else { TRACE("Updating Access / Modify / Change informations"); struct utimbuf ut = {0}; ut.actime = stat_buf.st_atime; ut.modtime = stat_buf.st_mtime; if (0 > chown(tmp_path, stat_buf.st_uid, stat_buf.st_gid)) { GSETERROR(error, "chown error: (%d) %s", errno, strerror(errno)); status = 0; } if (utime(tmp_path, &ut) != 0) { GSETERROR(error, "Failed to set correct access time to new file"); status = 0; } if(status == 1) { if(rename(tmp_path, path) != 0) { GSETERROR(error, "Failed to rename tmp file"); status = 0; } } else { /* remove tmp file */ DEBUG("Removing failed file"); if(remove(tmp_path) != 0) WARN("Failed to remove tmp file [%s]", tmp_path); } } } else { TRACE("Renaming pending file..."); if(rename(tmp_path, path) != 0) { GSETERROR(error, "Failed to rename tmp file"); status = 0; } TRACE("Renaming done"); } } else { /* remove tmp file */ DEBUG("Removing failed file"); if(remove(tmp_path) != 0) WARN("Failed to remove tmp file [%s]", tmp_path); } if(buf) g_free(buf); if(gba) g_byte_array_free(gba, TRUE); if(tmp_path) g_free(tmp_path); return status; }
int uncompress_chunk2(const gchar* path, gboolean preserve, gboolean keep_pending, GError ** error) { GError *local_error = NULL; int status = 0; TRACE("Uncompressing [%s]", path); gchar *tmp_path = NULL; gulong tmp_len; gint64 total_read; guint8* data = NULL; gint64 bufsize, nb_read; gint64 current_read; struct compressed_chunk_s *cp_chunk = NULL; struct compression_ctx_s *comp_ctx = NULL; GHashTable *compress_opt = NULL; FILE *dst = NULL; /* Check chunk exists */ DEBUG("Checking chunk exists"); struct stat buf = {0}; if(stat(path, &buf) == -1) { GSETERROR (error, "stat() failed, chunk not found\n"); goto end; } DEBUG("File [%s] found", path); compress_opt = g_hash_table_new_full( g_str_hash, g_str_equal, g_free, g_free); if (!get_compression_info_in_attr(path, error, compress_opt)) { GSETERROR(error, "Failed to get compression info in attr, chunk may be not compressed"); goto end; } gchar * compression = NULL; compression = (gchar*) g_hash_table_lookup(compress_opt, NS_COMPRESSION_OPTION); if (compression != NULL && g_ascii_strncasecmp(compression, NS_COMPRESSION_ON, strlen(compression)) != 0) { GSETERROR(error, "Chunk not compressed, cannot nothing to do"); goto end; } /* init compression method according to algo choice */ comp_ctx = g_malloc0(sizeof(struct compression_ctx_s)); init_compression_ctx(comp_ctx, g_hash_table_lookup(compress_opt, NS_COMPRESS_ALGO_OPTION)); cp_chunk = g_malloc0(sizeof(struct compressed_chunk_s)); if (comp_ctx->chunk_initiator(cp_chunk, path) != 0) { GSETERROR(error, "Failed to init compressed chunk context"); goto end; } DEBUG("Chunk check done"); tmp_len = strlen(path) +sizeof(".pending"); tmp_path = g_malloc0(tmp_len); g_snprintf(tmp_path, tmp_len, "%s.pending", path); DEBUG("Checking chunk not busy"); if(stat(tmp_path, &buf) != -1) { DEBUG("Stats failed"); GSETERROR (error, "stat() success on pending file, cannot process : busy chunk\n"); goto end; } do { int fd; if((fd = open(tmp_path, O_WRONLY|O_CREAT|O_EXCL, 0644)) == -1) { GSETERROR(error, "Failed to create pending chunk file (%s)\n", strerror(errno)); goto end; } metautils_pclose(&fd); } while (0); if(!copy_fattr(path, tmp_path, error)) { GSETERROR(error, "Failed to copy extended attributes to destination file\n"); goto end; } TRACE("xattr copied from src to dst"); dst = fopen(tmp_path, "w"); TRACE("Destination file opened"); gint64 chunk_size; chunk_size = g_ascii_strtoll(cp_chunk->uncompressed_size, NULL, 10); total_read = 0; DEBUG("Starting, total_read = %"G_GINT64_FORMAT", chunk_size = %"G_GINT64_FORMAT, total_read, chunk_size); while(total_read < chunk_size) { bufsize = MIN(DECOMPRESSION_MAX_BUFSIZE, (chunk_size - total_read)); data = g_malloc0(bufsize); DEBUG("New buffer allocated sized %"G_GINT64_FORMAT" bytes", bufsize); nb_read = 0; current_read = 0; while(nb_read < bufsize) { current_read = comp_ctx->data_uncompressor(cp_chunk, 0, data + nb_read, bufsize - nb_read, &local_error); DEBUG("Currently read %"G_GINT64_FORMAT" bytes", current_read); if(current_read < 0) { if(local_error) { GSETERROR(error, "An error occured while decompressing chunk : %s", local_error->message); g_clear_error(&local_error); } else GSETERROR(error, "An error occured while decompressing chunk\n"); goto end; } else if (current_read == 0) { /* Premature end of file, will still write to pending */ WARN("Read 0 bytes, original chunk may have been truncated"); break; } nb_read += current_read; } TRACE("buffer filled"); errno = 0; /* write buf to dst file */ if(nb_read > 0 && fwrite(data, nb_read, 1, dst) != 1) { GSETERROR(error, "An error occured while writing data in destination file: %s", strerror(errno)); goto end; } if (data) { g_free(data); data = NULL; } if (nb_read > 0) total_read += nb_read; else break; } if(!comp_ctx->integrity_checker(cp_chunk)) { GSETERROR(error, "Seems there is an error in decompression, invalid checksum\n"); goto end; } status = 1; end: if(dst) { if(fclose(dst) != 0) WARN("Failed to fclose destination file"); dst = NULL; } if(status == 1) { if(preserve) { /* Need to set old file info in new file */ TRACE("Updating Access / Modify / Change informations"); struct utimbuf ut = {0}; ut.actime = buf.st_atime; ut.modtime = buf.st_mtime; if (0 > chown(tmp_path, buf.st_uid, buf.st_gid)) { GSETERROR(error, "chown error: (%d) %s", errno, strerror(errno)); status = 0; } if(utime(tmp_path, &ut) != 0) { GSETERROR(error, "Failed to set correct access time to new file"); status = 0; } if(status == 1) { if(rename(tmp_path, path) != 0) { GSETERROR(error, "Failed to rename tmp file"); status = 0; } } else if (keep_pending) { INFO("Temporary file kept: %s", tmp_path); } else { /* remove tmp file */ DEBUG("Removing failed file"); if(remove(tmp_path) != 0) WARN("Failed to remove tmp file [%s]", tmp_path); } } else { DEBUG("Renaming pending file\n"); if(rename(tmp_path, path) != 0) { GSETERROR(error, "Failed to rename tmp file"); status = 0; } } } else if (keep_pending) { INFO("Temporary file kept: %s", tmp_path); } else { /* remove tmp file */ DEBUG("Removing pending file\n"); if(remove(tmp_path) != 0) WARN("Failed to remove tmp file [%s]", tmp_path); } if(compress_opt) g_hash_table_destroy(compress_opt); if(data) g_free(data); if(tmp_path) g_free(tmp_path); return status; }
int read_content_length(worker_t *worker, GError **error) { ssize_t rl; worker_data_t *data = NULL; http_session_t *http_session = NULL; unsigned int content_length; char *header_end = NULL; char *content_length_line = NULL; char *buffer = NULL; TRACE("Executing read_content_length worker"); data = &(worker->data); http_session = (http_session_t*)data->session; header_end = strstr(data->buffer, "\r\n\r\n"); content_length_line = strstr(data->buffer, "Content-Length"); if (content_length_line && header_end) { if (sscanf(content_length_line, CONTENT_LENGTH_PATTERN, &content_length) == 1) { DEBUG("Found a Content-Length header with value %u", content_length); /* Prepare the buffer */ buffer = g_strdup(header_end + 4); CLEAR_WORKER_DATA(data); data->buffer_size = content_length; data->buffer = g_try_malloc0(data->buffer_size+1); if (data->buffer == NULL) { GSETERROR(error, "Memory allocation failure"); g_free(buffer); goto error_alloc_buffer; } strcpy(data->buffer, buffer); data->done = strlen(buffer); g_free(buffer); worker->func = read_response_body; return(1); } } else if (header_end) { GSETERROR(error, "Header Content-Length was not found in headers"); goto error_content_length_not_found; } if (data->done >= data->buffer_size) { data->buffer_size += DEFAULT_BUFFER_SIZE; data->buffer = g_try_realloc(data->buffer, data->buffer_size+1); /* Allocate 1 byte for \0 */ if (data->buffer == NULL) { GSETERROR(error, "Memory allocation failure"); goto error_alloc_buffer; } else { /* Init newly alloced memory */ memset(data->buffer + (data->buffer_size - DEFAULT_BUFFER_SIZE), 0, DEFAULT_BUFFER_SIZE + 1); } } rl = read(data->fd, data->buffer + data->done, data->buffer_size - data->done); if (rl < 0) { GSETERROR(error, "Read on socket failed with error : %s", strerror(errno)); goto error_read; } if (rl == 0 && data->done < data->buffer_size) { GSETERROR(error, "Connection closed while reading Content-Length"); goto error_read; } data->done += rl; return(1); error_content_length_not_found: error_read: g_free(data->buffer); error_alloc_buffer: return(http_session->error_handler(worker, error)); }
int write_request(worker_t *worker, GError **error) { ssize_t wl; worker_data_t *data = NULL; http_session_t *http_session; char request[HTTP_REQ_MAX_SIZE]; TRACE("Executing write_request worker"); data = &(worker->data); http_session = (http_session_t*)data->session; memset(request, '\0', HTTP_REQ_MAX_SIZE); if (data->buffer == NULL) { switch (http_session->method) { case E_GET : snprintf(request, HTTP_REQ_MAX_SIZE, "GET %s HTTP/1.0%s%s", http_session->url, EOL, EOL); break; case E_POST : break; default : break; } DEBUG("Sending HTTP request [%s]", request); data->buffer_size = strlen(request); data->buffer = g_try_malloc0(data->buffer_size); if (data->buffer == NULL) { GSETERROR(error, "Memory allocation failure"); goto error_alloc_buffer; } memcpy(data->buffer, request, data->buffer_size); } wl = write(data->fd, data->buffer + data->done, data->buffer_size - data->done); if (wl < 0) { GSETERROR(error, "Write on socket failed with error : %s", strerror(errno)); goto error_write; } data->done += wl; if (data->done >= data->buffer_size) { g_free(data->buffer); data->buffer = NULL; data->buffer_size = 0; data->done = 0; /* Schedule next worker */ worker->func = read_http_status; if (!change_fd_events_in_io_scheduler(worker, EPOLLIN, error)) { GSETERROR(error, "Failed to change polling event on fd %d", data->fd); goto error_sched; } } return(1); error_sched: error_write: g_free(data->buffer); error_alloc_buffer: return(http_session->error_handler(worker, error)); }
int read_http_status(worker_t *worker, GError **error) { ssize_t rl; worker_data_t *data = NULL; http_session_t *http_session = NULL; unsigned int http_status; TRACE("Executing read_http_status worker"); data = &(worker->data); http_session = (http_session_t*)data->session; if (data->buffer == NULL) { data->buffer_size = DEFAULT_BUFFER_SIZE; data->buffer = g_try_malloc0(data->buffer_size+1); /* Allocate 1 byte for \0 */ if (data->buffer == NULL) { GSETERROR(error, "Memory allocation failure"); goto error_alloc_buffer; } } else if (data->done >= data->buffer_size) { data->buffer_size += DEFAULT_BUFFER_SIZE; data->buffer = g_try_realloc(data->buffer, data->buffer_size+1); /* Allocate 1 byte for \0 */ if (data->buffer == NULL) { GSETERROR(error, "Memory allocation failure"); goto error_alloc_buffer; } else { /* Init newly alloced memory */ memset(data->buffer + (data->buffer_size - DEFAULT_BUFFER_SIZE), 0, DEFAULT_BUFFER_SIZE + 1); } } rl = read(data->fd, data->buffer + data->done, data->buffer_size - data->done); if (rl < 0) { GSETERROR(error, "Read on socket failed with error : %s", strerror(errno)); goto error_read; } data->done += rl; /* Make sure we read the first line completely */ if (strstr((char*)data->buffer, EOL)) { if (sscanf((char*)data->buffer, HTTP_STATUS_PATTERN, &http_status) == 1) { DEBUG("Found HTTP status %u", http_status); if (http_status == HTTP_STATUS_OK) { worker->func = read_content_length; } else { GSETERROR(error, "HTTP request failed with status %d", http_status); goto error_status; } } else { GSETERROR(error, "Failed to read HTTP status"); goto error_status; } } else if (rl == 0) { GSETERROR(error, "Connection closed while reading HTTP status"); goto error_read; } return(1); error_read: error_status: g_free(data->buffer); error_alloc_buffer: return(http_session->error_handler(worker, error)); }
gint accept_add_local (ACCEPT_POOL ap, const gchar *l, GError **err) { struct working_parameter_s wrkParam; struct sockaddr_un sun; int srv = -1; if (!l || !(*l)) { GSETERROR(err,"invalid parameter"); goto errorLabel; } /*parse the URL*/ init_socket_options_defaults( l, &wrkParam ); parse_socket_options( &wrkParam ); /*try to stat the file*/ if (-1 == check_socket_is_absent( &wrkParam, err )) { GSETERROR(err,"A socket seems already present at [%s]", wrkParam.path.ptr); } /*open and bind the socket*/ if (-1==(srv=socket(PF_UNIX, SOCK_STREAM, 0))) { GSETERROR(err,"Cannot open a new socket PF_UNIX : %s", strerror(errno)); goto errorLabel; } if (!sock_set_reuseaddr(srv, TRUE)) { GSETERROR(err,"Cannot set SO_REUSEADDR on %d [%s] (%s)", srv, l, strerror(errno)); goto errorLabel; } fcntl(srv, F_SETFL, O_NONBLOCK|fcntl(srv, F_GETFL)); sun.sun_family = PF_LOCAL; strncpy(sun.sun_path, wrkParam.path.ptr, sizeof(sun.sun_path)); if (-1==bind (srv, (struct sockaddr*) &sun, sizeof(struct sockaddr_un))) { GSETERROR(err,"cannot bind srv=%d to %s (%s)", srv, l, strerror(errno)); goto errorLabel; } if (-1==listen (srv,AP_BACKLOG)) { GSETERROR(err,"cannot listen to inbound connections : %s", strerror(errno)); goto errorLabel; } if (!accept_add_any(ap,srv,err)) { GSETERROR(err,"Cannot monitor the local server"); goto errorLabel; } /*change socket rights*/ if (0 != chmod(wrkParam.path.ptr,wrkParam.mode)) { int errsav = errno; ERROR("Failed to set mode [%o] on UNIX socket [%s] : %s", wrkParam.mode, wrkParam.path.ptr, strerror(errsav)); SRV_SEND_WARNING("server","UNIX socket might be not accessible : failed to set mode [%o] on UNIX socket [%s] (%s)", wrkParam.mode, wrkParam.path.ptr, strerror(errsav)); } INFO("socket srv=%d %s now monitored", srv, _get_family_name(FAMILY(&sun))); return 1; errorLabel: if (srv>=0) metautils_pclose(&srv); return 0; }
int send_request(request_t *req, response_t *resp, GError **error) { int fd; size_t size_to_send, u_size_sent, u_size_read; gint size_sent, size_read; message_t message; void *buff = NULL; memset(&message, 0, sizeof(message_t)); if (!build_message_from_request(&message, req, error)) { GSETERROR(error, "Failed to build message"); return(0); } if (0 > (fd = gridagent_connect(error))) { GSETERROR(error, "Connection to agent failed"); goto error_connect; } size_to_send = message.length + sizeof(message.length); buff = g_malloc0(size_to_send); memcpy(buff, &(message.length), sizeof(message.length)); memcpy(buff + sizeof(message.length), message.data, message.length); size_sent = sock_to_write(fd, CONNECT_TIMEOUT, buff, size_to_send, error); if (size_sent<0) { GSETERROR(error, "Failed to send all data to agent"); goto error_write; } if ((u_size_sent=size_sent) < size_to_send) { GSETERROR(error, "Failed to send all data to agent"); goto error_write; } /* Clean message to reuse it */ message_clean( &message); size_read = sock_to_read_size(fd, SOCKET_TIMEOUT, &(message.length), sizeof(message.length), error); if ((u_size_read=size_read) < sizeof(message.length)) { GSETERROR(error, "Failed to read message size"); goto error_read_size; } message.data = g_malloc0(message.length); size_read = sock_to_read_size(fd, SOCKET_TIMEOUT, message.data, message.length, error); if ((u_size_read=size_read) < message.length) { GSETERROR(error, "Failed to read all data from agent"); goto error_read; } if (!read_response_from_message(resp, &message, error)) { GSETERROR(error, "Failed to extract response from message"); goto error_read_resp; } metautils_pclose(&fd); g_free(buff); message_clean( &message); return(1); error_read_resp: error_read: error_read_size: error_write: if (buff) g_free(buff); metautils_pclose(&fd); error_connect: message_clean( &message); return(0); }
gint sock_to_read(int fd, gint ms, void *buf, gsize bufSize, GError ** err) { if (VTABLE.to_read) return VTABLE.to_read(fd, ms, buf, bufSize, err); #define READ() do { \ rc = metautils_syscall_read(fd, buf, bufSize); \ if (rc > 0) \ return rc; \ if (rc == 0) { \ GSETCODE(err, ERRCODE_CONN_CLOSED, "Socket %d closed", fd); \ return 0; \ } \ if (errno != EAGAIN && errno != EINTR) { \ GSETCODE(err, errno_to_errcode(errno), "Read error (%s)", strerror(errno)); \ return -1; \ } \ } while (0) gint rc; if (fd < 0 || !buf || bufSize <= 0) { GSETERROR(err, "invalid parameter"); return -1; } /* on tente un premier READ, qui s'il reussit, nous epargne un appel a POLL */ READ(); /* pas de data en attente, donc attente protegee par le poll */ for (;;) { struct pollfd p; p.fd = fd; p.events = POLLIN; p.revents = 0; /*wait for something to happen */ rc = metautils_syscall_poll(&p, 1, ms); if (rc == 0) { /*timeout */ GSETCODE(err, ERRCODE_CONN_TIMEOUT, "Socket timeout"); return -1; } if (rc < 0 && errno != EINTR) { /*error */ GSETCODE(err, errno_to_errcode(errno), "Socket error (%s)", strerror(errno)); return -1; } if (rc == 1) { if (p.revents & POLLHUP && !(p.revents & POLLIN)) { GSETCODE(err, ERRCODE_CONN_CLOSED, "Socket %d closed", fd); return 0; } if (p.revents & POLLERR) { int sock_err = socket_get_errcode(fd); GSETCODE(err, ERRCODE_CONN_CLOSED, "Socket %d error : (%d) %s", fd, sock_err, strerror(sock_err)); return 0; } READ(); } } }
gint sock_to_write(int fd, gint ms, void *buf, gsize bufSize, GError ** err) { if (VTABLE.to_write) return VTABLE.to_write(fd, ms, buf, bufSize, err); #define WRITE() do { \ written = metautils_syscall_write(fd, ((guint8 *)buf) + nbSent, bufSize - nbSent); \ if (written > 0) { \ ui_written = written; \ nbSent += ui_written; \ } \ if (written < 0) { \ if (errno != EAGAIN && errno != EINTR) { \ GSETERROR(err, "Write error (%s)", strerror(errno)); \ return -1; \ } \ } \ } while (0) gsize ui_written; ssize_t written; gsize nbSent = 0; if (fd < 0 || !buf || bufSize <= 0) { GSETERROR(err, "invalid parameter"); return -1; } WRITE(); while (nbSent < bufSize) { int rc_poll; struct pollfd p; p.fd = fd; p.events = POLLOUT | POLLERR | POLLHUP | POLLNVAL; p.revents = 0; errno = 0; rc_poll = metautils_syscall_poll(&p, 1, ms); if (rc_poll == 0) { /*timeout */ GSETCODE(err, ERRCODE_CONN_TIMEOUT, "Socket timeout"); return (-1); } if (rc_poll == -1) { /*poll error */ if (errno != EINTR) { GSETERROR(err, "Socket error (%s) after %"G_GSIZE_FORMAT" bytes written", strerror(errno), nbSent); return (-1); } else { TRACE("poll interrupted (%s)", strerror(errno)); continue; } } /*poll success */ if (p.revents & POLLNVAL) { GSETERROR(err, "Socket (%d) is invalid after %"G_GSIZE_FORMAT" bytes sent", fd, nbSent); return -1; } if (p.revents & POLLERR) { int sock_err = socket_get_errcode(fd); GSETERROR(err, "Socket (%d) error after %"G_GSIZE_FORMAT" bytes written : (%d) %s", fd, nbSent, sock_err, strerror(sock_err)); return -1; } if ((p.revents & POLLHUP)) { GSETCODE(err, ERRCODE_CONN_CLOSED, "Socket (%d) closed after %"G_GSIZE_FORMAT" bytes written", fd, nbSent); return -1; } WRITE(); } return nbSent; }