static void cli_read_cb(int sd, short type, void *arg) { struct cli *cli = arg; uint32_t cmdlen; uint8_t *msg = NULL; if (read_fully(sd, &cmdlen, sizeof(cmdlen)) != 0) goto error; msg = btpd_malloc(cmdlen); if (read_fully(sd, msg, cmdlen) != 0) goto error; if (!(benc_validate(msg, cmdlen) == 0 && benc_islst(msg) && benc_first(msg) != NULL && benc_isstr(benc_first(msg)))) goto error; if (cmd_dispatch(cli, msg) != 0) goto error; free(msg); return; error: btpd_ev_del(&cli->read); close(cli->sd); free(cli); if (msg != NULL) free(msg); }
/* Initializes 'buffer' with 'n' bytes of high-quality random numbers. Returns * 0 if successful, otherwise a positive errno value or EOF on error. */ int get_entropy(void *buffer, size_t n) { #ifndef _WIN32 size_t bytes_read; int error; int fd; fd = open(urandom, O_RDONLY); if (fd < 0) { VLOG_ERR("%s: open failed (%s)", urandom, ovs_strerror(errno)); return errno ? errno : EINVAL; } error = read_fully(fd, buffer, n, &bytes_read); close(fd); if (error) { VLOG_ERR("%s: read error (%s)", urandom, ovs_retval_to_string(error)); } #else int error = 0; HCRYPTPROV crypt_prov = 0; CryptAcquireContext(&crypt_prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); if (!CryptGenRandom(crypt_prov, n, buffer)) { VLOG_ERR("CryptGenRandom: read error (%s)", ovs_lasterror_to_string()); error = EINVAL; } CryptReleaseContext(crypt_prov, 0); #endif return error; }
static void stream_read(struct stream *s) { if (s->fds[0] < 0) { return; } for (;;) { char buffer[512]; int error; size_t n; error = read_fully(s->fds[0], buffer, sizeof buffer, &n); ds_put_buffer(&s->log, buffer, n); if (error) { if (error == EAGAIN || error == EWOULDBLOCK) { return; } else { if (error != EOF) { VLOG_WARN("error reading subprocess pipe: %s", strerror(error)); } break; } } else if (s->log.length > PROCESS_MAX_CAPTURE) { VLOG_WARN("subprocess output overflowed %d-byte buffer", PROCESS_MAX_CAPTURE); break; } } close(s->fds[0]); s->fds[0] = -1; }
static void read_and_push( XferElementGlue *self) { XferElement *elt = XFER_ELEMENT(self); int fd = get_read_fd(self); XMsg *msg; crc32_init(&elt->crc); while (!elt->cancelled) { char *buf = g_malloc(GLUE_BUFFER_SIZE); gsize len; int read_error; /* read a buffer from upstream */ len = read_fully(fd, buf, GLUE_BUFFER_SIZE, &read_error); if (len < GLUE_BUFFER_SIZE) { if (read_error) { if (!elt->cancelled) { xfer_cancel_with_error(elt, _("Error reading from fd %d: %s"), fd, strerror(read_error)); g_debug("element-glue: error reading from fd %d: %s", fd, strerror(read_error)); wait_until_xfer_cancelled(elt->xfer); } amfree(buf); break; } else if (len == 0) { /* we only count a zero-length read as EOF */ amfree(buf); break; } } crc32_add((uint8_t *)buf, len, &elt->crc); xfer_element_push_buffer(elt->downstream, buf, len); } if (elt->cancelled && elt->expect_eof) xfer_element_drain_fd(fd); /* send an EOF indication downstream */ xfer_element_push_buffer(elt->downstream, NULL, 0); /* close the read fd, since it's at EOF */ close_read_fd(self); g_debug("sending XMSG_CRC message"); g_debug("read_and_push CRC: %08x size %lld", crc32_finish(&elt->crc), (long long)elt->crc.size); msg = xmsg_new(elt->upstream, XMSG_CRC, 0); msg->crc = crc32_finish(&elt->crc); msg->size = elt->crc.size; xfer_queue_message(elt->xfer, msg); }
/* Forks, then: * * - In the parent, waits for the child to signal that it has completed its * startup sequence. Then stores -1 in '*fdp' and returns the child's * pid in '*child_pid' argument. * * - In the child, stores a fd in '*fdp' and returns 0 through '*child_pid' * argument. The caller should pass the fd to fork_notify_startup() after * it finishes its startup sequence. * * Returns 0 on success. If something goes wrong and child process was not * able to signal its readiness by calling fork_notify_startup(), then this * function returns -1. However, even in case of failure it still sets child * process id in '*child_pid'. */ static int fork_and_wait_for_startup(int *fdp, pid_t *child_pid) { int fds[2]; pid_t pid; int ret = 0; xpipe(fds); pid = fork_and_clean_up(); if (pid > 0) { /* Running in parent process. */ size_t bytes_read; char c; close(fds[1]); if (read_fully(fds[0], &c, 1, &bytes_read) != 0) { int retval; int status; do { retval = waitpid(pid, &status, 0); } while (retval == -1 && errno == EINTR); if (retval == pid) { if (WIFEXITED(status) && WEXITSTATUS(status)) { /* Child exited with an error. Convey the same error * to our parent process as a courtesy. */ exit(WEXITSTATUS(status)); } else { char *status_msg = process_status_msg(status); //VLOG_ERR("fork child died before signaling startup (%s)", // status_msg); printf("fork child died before signaling startup (%s)", status_msg); ret = -1; } } else if (retval < 0) { //VLOG_FATAL("waitpid failed (%s)", ovs_strerror(errno)); printf("waitpid failed (%d)", errno); } else { abort(); } } close(fds[0]); *fdp = -1; } else if (!pid) { /* Running in child process. */ close(fds[0]); *fdp = fds[1]; } *child_pid = pid; return ret; }
static pid_t fork_and_wait_for_startup(int *fdp) { int fds[2]; pid_t pid; xpipe(fds); pid = fork(); if (pid > 0) { /* Running in parent process. */ size_t bytes_read; char c; close(fds[1]); fatal_signal_fork(); if (read_fully(fds[0], &c, 1, &bytes_read) != 0) { int retval; int status; do { retval = waitpid(pid, &status, 0); } while (retval == -1 && errno == EINTR); if (retval == pid && WIFEXITED(status) && WEXITSTATUS(status)) { /* Child exited with an error. Convey the same error to * our parent process as a courtesy. */ exit(WEXITSTATUS(status)); } VLOG_FATAL("fork child failed to signal startup (%s)", strerror(errno)); } close(fds[0]); *fdp = -1; } else if (!pid) { /* Running in child process. */ close(fds[0]); time_postfork(); lockfile_postfork(); *fdp = fds[1]; } else { VLOG_FATAL("fork failed (%s)", strerror(errno)); } return pid; }
/* Initializes 'buffer' with 'n' bytes of high-quality random numbers. Returns * 0 if successful, otherwise a positive errno value or EOF on error. */ int get_entropy(void *buffer, size_t n) { #ifndef _WIN32 size_t bytes_read; int error; int fd; fd = open(urandom, O_RDONLY); if (fd < 0) { VLOG_ERR("%s: open failed (%s)", urandom, ovs_strerror(errno)); return errno ? errno : EINVAL; } error = read_fully(fd, buffer, n, &bytes_read); close(fd); if (error) { VLOG_ERR("%s: read error (%s)", urandom, ovs_retval_to_string(error)); } #else int error = 0; HCRYPTPROV crypt_prov = 0; LPVOID msg_buf; CryptAcquireContext(&crypt_prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); if (!CryptGenRandom(crypt_prov, n, buffer)) { error = EINVAL; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), 0, (LPTSTR)&msg_buf, 0, NULL ); VLOG_ERR("CryptGenRandom: read error (%s)", msg_buf); LocalFree(msg_buf); } CryptReleaseContext(crypt_prov, 0); #endif return error; }
void holding_set_from_driver( char *holding_file, off_t orig_size, crc_t native_crc, crc_t client_crc, crc_t server_crc) { int fd; size_t buflen; char buffer[DISK_BLOCK_BYTES]; char *read_buffer; dumpfile_t file; if((fd = robust_open(holding_file, O_RDWR, 0)) == -1) { dbprintf(_("holding_set_origsize: open of %s failed: %s\n"), holding_file, strerror(errno)); return; } buflen = read_fully(fd, buffer, sizeof(buffer), NULL); if (buflen <= 0) { dbprintf(_("holding_set_origsize: %s: empty file?\n"), holding_file); close(fd); return; } parse_file_header(buffer, &file, (size_t)buflen); lseek(fd, (off_t)0, SEEK_SET); file.orig_size = orig_size; file.native_crc = native_crc; file.client_crc = client_crc; file.server_crc = server_crc; read_buffer = build_header(&file, NULL, DISK_BLOCK_BYTES); full_write(fd, read_buffer, DISK_BLOCK_BYTES); dumpfile_free_data(&file); amfree(read_buffer); close(fd); }
int holding_file_get_dumpfile( char * fname, dumpfile_t *file) { char buffer[DISK_BLOCK_BYTES]; int fd; memset(buffer, 0, sizeof(buffer)); fh_init(file); file->type = F_UNKNOWN; if((fd = robust_open(fname, O_RDONLY, 0)) == -1) return 0; if(read_fully(fd, buffer, sizeof(buffer), NULL) != sizeof(buffer)) { aclose(fd); return 0; } aclose(fd); parse_file_header(buffer, file, sizeof(buffer)); return 1; }
int process_ihexfile(const char *ihexfile, struct record **rec_p) { int fd; int rc; int i; int len; uint8_t *ptr; uint8_t c; uint8_t ih_count; uint16_t ih_address; uint8_t ih_type; uint8_t ih_data[256]; uint8_t ih_checksum; uint32_t ip = 0; struct record *rec; fd = open(ihexfile, O_RDONLY); if (fd < 0) { fprintf(stderr, "process_ihexfile: open failed (%s) :%s\n", ihexfile, strerror(errno)); return -1; } while (1) { ptr = io_buffer; len = read_fully(fd, ptr, 1); if (len < 0) goto read_error; else if (len == 0) break; c = *(ptr++); if (c == '\n') continue; else if (c == '\r') continue; if (c != ':') goto data_error; ptr = io_buffer; len = read_fully(fd, ptr, 8); if (len < 0) goto read_error; else if (len == 0) goto data_error; if (hex2(&ptr, &ih_count) < 0) goto data_error; if (hex4(&ptr, &ih_address) < 0) goto data_error; if (hex2(&ptr, &ih_type) < 0) goto data_error; if (ih_count > 0) { ptr = io_buffer; len = read_fully(fd, ptr, (ih_count * 2)); if (len < 0) goto read_error; else if (len == 0) goto data_error; for (i = 0; i < ih_count; i++) { if (hex2(&ptr, &ih_data[i]) < 0) goto data_error; } } ptr = io_buffer; len = read_fully(fd, ptr, 2); if (len < 0) goto read_error; else if (len == 0) goto data_error; if (hex2(&ptr, &ih_checksum) < 0) goto data_error; if (ih_type == 0x00) { rec = malloc(sizeof(struct record) + (sizeof(uint8_t) * ih_count)); if (rec == NULL) goto memory_error; rec->next = NULL; rec->count = ih_count; rec->address = ip + ih_address; memcpy(rec->data, ih_data, ih_count); *(rec_p) = rec; rec_p = &rec->next; } else if (ih_type == 0x02) { ip = (((ih_data[0] << 8) | (ih_data[1] << 0)) << 4); } else if (ih_type == 0x04) { ip = (((ih_data[0] << 8) | (ih_data[1] << 0)) << 16); } } rc = 0; goto close; memory_error: fprintf(stderr, "process_ihexfile: memory error\n"); rc = -1; goto close; read_error: fprintf(stderr, "process_ihexfile: read error\n"); rc = -1; goto close; data_error: fprintf(stderr, "process_ihexfile: data error\n"); rc = -1; goto close; close: if (close(fd) < 0) { fprintf(stderr, "process_ihexfile: close failed %s\n", strerror(errno)); return -1; } return rc; }
static void read_and_write(XferElementGlue *self) { XferElement *elt = XFER_ELEMENT(self); /* dynamically allocate a buffer, in case this thread has * a limited amount of stack allocated */ char *buf = g_malloc(GLUE_BUFFER_SIZE); int rfd = get_read_fd(self); int wfd = get_write_fd(self); XMsg *msg; crc32_init(&elt->crc); g_debug("read_and_write: read from %d, write to %d", rfd, wfd); while (!elt->cancelled) { size_t len; /* read from upstream */ len = read_fully(rfd, buf, GLUE_BUFFER_SIZE, NULL); if (len < GLUE_BUFFER_SIZE) { if (errno) { if (!elt->cancelled) { xfer_cancel_with_error(elt, _("Error reading from fd %d: %s"), rfd, strerror(errno)); wait_until_xfer_cancelled(elt->xfer); } break; } else if (len == 0) { /* we only count a zero-length read as EOF */ break; } } /* write the buffer fully */ if (!elt->downstream->drain_mode && full_write(wfd, buf, len) < len) { if (elt->downstream->must_drain) { g_debug("Could not write to fd %d: %s", wfd, strerror(errno)); } else if (elt->downstream->ignore_broken_pipe && errno == EPIPE) { } else { if (!elt->cancelled) { xfer_cancel_with_error(elt, _("Could not write to fd %d: %s"), wfd, strerror(errno)); wait_until_xfer_cancelled(elt->xfer); } break; } } crc32_add((uint8_t *)buf, len, &elt->crc); } if (elt->cancelled && elt->expect_eof) xfer_element_drain_fd(rfd); /* close the read fd. If it's not at EOF, then upstream will get EPIPE, which will hopefully * kill it and complete the cancellation */ close_read_fd(self); /* close the fd we've been writing, as an EOF signal to downstream */ close_write_fd(self); g_debug("read_and_write upstream CRC: %08x size %lld", crc32_finish(&elt->crc), (long long)elt->crc.size); g_debug("sending XMSG_CRC message"); msg = xmsg_new(elt->upstream, XMSG_CRC, 0); msg->crc = crc32_finish(&elt->crc); msg->size = elt->crc.size; xfer_queue_message(elt->xfer, msg); g_debug("read_and_write downstream CRC: %08x size %lld", crc32_finish(&elt->crc), (long long)elt->crc.size); g_debug("sending XMSG_CRC message"); msg = xmsg_new(elt->downstream, XMSG_CRC, 0); msg->crc = crc32_finish(&elt->crc); msg->size = elt->crc.size; xfer_queue_message(elt->xfer, msg); amfree(buf); }
static gpointer pull_buffer_impl( XferElement *elt, size_t *size) { XferElementGlue *self = XFER_ELEMENT_GLUE(elt); /* accept first, if required */ if (self->on_pull & PULL_ACCEPT_FIRST) { /* don't accept the next time around */ self->on_pull &= ~PULL_ACCEPT_FIRST; if (elt->cancelled) { *size = 0; return NULL; } if ((self->input_data_socket = do_directtcp_accept(self, &self->input_listen_socket)) == -1) { /* do_directtcp_accept already signalled an error; xfer * is cancelled */ *size = 0; return NULL; } /* read from this new socket */ self->read_fdp = &self->input_data_socket; } else if (self->on_pull & PULL_CONNECT_FIRST) { /* or connect first, if required */ /* don't connect the next time around */ self->on_pull &= ~PULL_CONNECT_FIRST; if (elt->cancelled) { *size = 0; return NULL; } if ((self->input_data_socket = do_directtcp_connect(self, elt->upstream->output_listen_addrs)) == -1) { /* do_directtcp_connect already signalled an error; xfer * is cancelled */ *size = 0; return NULL; } /* read from this new socket */ self->read_fdp = &self->input_data_socket; } switch (self->on_pull) { case PULL_FROM_RING_BUFFER: { gpointer buf; if (elt->cancelled) { /* the finalize method will empty the ring buffer */ *size = 0; return NULL; } /* make sure there's at least one element available */ amsemaphore_down(self->ring_used_sem); /* get it */ buf = self->ring[self->ring_tail].buf; *size = self->ring[self->ring_tail].size; self->ring_tail = (self->ring_tail + 1) % GLUE_RING_BUFFER_SIZE; /* and mark this element as free to be overwritten */ amsemaphore_up(self->ring_free_sem); return buf; } case PULL_FROM_FD: { int fd = get_read_fd(self); char *buf; ssize_t len; /* if the fd is already closed, it's possible upstream bailed out * so quickly that we didn't even get a look at the fd */ if (elt->cancelled || fd == -1) { if (fd != -1) { if (elt->expect_eof) xfer_element_drain_fd(fd); close_read_fd(self); } *size = 0; return NULL; } buf = g_malloc(GLUE_BUFFER_SIZE); /* read from upstream */ len = read_fully(fd, buf, GLUE_BUFFER_SIZE, NULL); if (len < GLUE_BUFFER_SIZE) { if (errno) { if (!elt->cancelled) { xfer_cancel_with_error(elt, _("Error reading from fd %d: %s"), fd, strerror(errno)); wait_until_xfer_cancelled(elt->xfer); } /* return an EOF */ amfree(buf); len = 0; /* and finish off the upstream */ if (elt->expect_eof) { xfer_element_drain_fd(fd); } close_read_fd(self); } else if (len == 0) { /* EOF */ g_free(buf); buf = NULL; *size = 0; /* signal EOF to downstream */ close_read_fd(self); } } *size = (size_t)len; return buf; } default: case PULL_INVALID: g_assert_not_reached(); return NULL; } }
int rename_tmp_holding( char * holding_file, int complete) { int fd; size_t buflen; char buffer[DISK_BLOCK_BYTES]; dumpfile_t file; char *filename; char *filename_tmp = NULL; memset(buffer, 0, sizeof(buffer)); filename = g_strdup(holding_file); while(filename != NULL && filename[0] != '\0') { g_free(filename_tmp); filename_tmp = g_strconcat(filename, ".tmp", NULL); if((fd = robust_open(filename_tmp,O_RDONLY, 0)) == -1) { dbprintf(_("rename_tmp_holding: open of %s failed: %s\n"),filename_tmp,strerror(errno)); amfree(filename); amfree(filename_tmp); return 0; } buflen = read_fully(fd, buffer, sizeof(buffer), NULL); close(fd); if(rename(filename_tmp, filename) != 0) { dbprintf(_("rename_tmp_holding: could not rename \"%s\" to \"%s\": %s"), filename_tmp, filename, strerror(errno)); } if (buflen <= 0) { dbprintf(_("rename_tmp_holding: %s: empty file?\n"), filename); amfree(filename); amfree(filename_tmp); return 0; } parse_file_header(buffer, &file, (size_t)buflen); if(complete == 0 ) { char * header; if((fd = robust_open(filename, O_RDWR, 0)) == -1) { dbprintf(_("rename_tmp_holdingX: open of %s failed: %s\n"), filename, strerror(errno)); dumpfile_free_data(&file); amfree(filename); amfree(filename_tmp); return 0; } file.is_partial = 1; if (debug_holding > 1) dump_dumpfile_t(&file); header = build_header(&file, NULL, DISK_BLOCK_BYTES); if (!header) /* this shouldn't happen */ error(_("header does not fit in %zd bytes"), (size_t)DISK_BLOCK_BYTES); if (full_write(fd, header, DISK_BLOCK_BYTES) != DISK_BLOCK_BYTES) { dbprintf(_("rename_tmp_holding: writing new header failed: %s"), strerror(errno)); dumpfile_free_data(&file); amfree(filename); amfree(filename_tmp); free(header); close(fd); return 0; } free(header); close(fd); } g_free(filename); filename = g_strdup(file.cont_filename); dumpfile_free_data(&file); } amfree(filename); amfree(filename_tmp); return 1; }
void read_global_pools() { int total_length, i; uchar *poolp; // Read the overal length of the five global pools. total_length = read_swapped_int(); // Read the sizes of each of the global pools. utf_pool_size = read_swapped_short(); class_pool_size = read_swapped_short(); ref_pool_size = read_swapped_short(); type_pool_size = read_swapped_short(); value_pool_size = read_swapped_short(); raw_pool = malloc(total_length); if (raw_pool == 0) { fprintf(stderr, "Couldn't allocate %d byte for pools\n", total_length); fflush(stderr); exit(5); } poolp = raw_pool; // printf("UTF pool size = %d\n", utf_pool_size); // printf("CLASS pool size = %d\n", class_pool_size); // printf("REF pool size = %d\n", ref_pool_size); // printf("TYPE pool size = %d\n", type_pool_size); // printf("VALUE pool size = %d\n", value_pool_size); // printf("Reading %d bytes of pool\n", total_length); // fflush(stdout); read_fully(raw_pool, total_length); // printf("done read\n"); // fflush(stdout); // Allocate the indexes for the four string tables. utf_pool = calloc(utf_pool_size, sizeof(uchar *)); class_pool = calloc(class_pool_size, sizeof(uchar *)); type_pool = calloc(type_pool_size, sizeof(uchar *)); value_pool = calloc(value_pool_size, sizeof(uchar *)); if (utf_pool == 0 || class_pool == 0 || type_pool == 0 || value_pool == 0) { fprintf(stderr, "Couldn't allocate space for global pools\n"); exit(6); } // Setup the utf pool. utf_pool[0] = 0; for (i = 1; i < utf_pool_size; i++) { ushort len = strlen(poolp); utf_pool[i] = poolp; poolp += (1 + len); } // Setup the class pool. class_pool[0] = 0; for (i = 1; i < class_pool_size; i++) { ushort len; class_pool[i] = poolp; if (*poolp == '%') { poolp += 3; } len = strlen(poolp); poolp += (1 + len); } // The ref_pool simply points at the raw data. // We have to offset for the missing entry at zero. ref_pool = (poolp - 6); poolp = poolp + (6 * (ref_pool_size-1)); // Setup the type pool. type_pool[0] = 0; for (i = 1; i < type_pool_size; i++) { type_pool[i] = poolp; for (;;) { char ch = *poolp++; if (ch == 0) { break; } if (ch == 'L') { poolp += 2; } } } // Setup the value pool. value_pool[0] = 0; for (i = 1; i < value_pool_size; i++) { ushort len; uchar tag = *poolp; value_pool[i] = poolp; switch (tag) { case CONSTANT_INTEGER: poolp += 5; break; case CONSTANT_FLOAT: poolp += 5; break; case CONSTANT_LONG: poolp += 9; break; case CONSTANT_DOUBLE: poolp += 9; break; case CONSTANT_STRING: len = strlen(poolp+1); poolp += (len + 2); break; default: fprintf(stderr, "Unexpected tag %d in value pool\n", tag); exit(4); } } if (poolp != (raw_pool + total_length)) { fprintf(stderr, "Size mismatch when processing global pools\n"); } // printf("Setup global pools OK\n"); }
int file_lock_lock( file_lock *lock) { int rv = -2; int fd = -1; int saved_errno; struct flock lock_buf; struct stat stat_buf; g_assert(!lock->locked); /* protect from overlapping lock operations within a process */ g_static_mutex_lock(&lock_lock); if (!locally_locked_files) { locally_locked_files = g_hash_table_new(g_str_hash, g_str_equal); } /* if this filename is in the hash table, then some other thread in this * process has locked it */ if (g_hash_table_lookup(locally_locked_files, lock->filename)) { rv = 1; errno = EBUSY; goto done; } /* The locks are advisory, so an error here never means the lock is already * taken. */ lock->fd = fd = open(lock->filename, O_CREAT|O_RDWR, 0666); if (fd < 0) { rv = -1; goto done; } /* now try locking it */ lock_buf.l_type = F_WRLCK; lock_buf.l_start = 0; lock_buf.l_whence = SEEK_SET; lock_buf.l_len = 0; /* to EOF */ if (fcntl(fd, F_SETLK, &lock_buf) < 0) { if (errno == EACCES || errno == EAGAIN) rv = 1; else rv = -1; goto done; } /* and read the file in its entirety */ if (fstat(fd, &stat_buf) < 0) { rv = -1; goto done; } if (!(stat_buf.st_mode & S_IFREG)) { rv = -1; errno = EINVAL; goto done; } if (stat_buf.st_size) { lock->data = g_malloc(stat_buf.st_size+1); lock->len = stat_buf.st_size; if (read_fully(fd, lock->data, lock->len, NULL) < lock->len) { rv = -1; goto done; } lock->data[lock->len] = '\0'; } fd = -1; /* we'll keep the file now */ lock->locked = TRUE; /* the lock is acquired; record this in the hash table */ g_hash_table_insert(locally_locked_files, lock->filename, lock->filename); rv = 0; done: saved_errno = errno; g_static_mutex_unlock(&lock_lock); if (fd >= 0) /* close and unlock if an error occurred */ close(fd); errno = saved_errno; return rv; }
void *reader_thread(void *_arg) { orc_t *orc = (orc_t*) _arg; setup_thread(); orc->fd = -1; int reconnectcount = 0; reconnect: // reconnect, if necessary. while (orc->fd < 0) { LOG_INFO("Trying to connect to orcboard...(%i)", reconnectcount++); orc->fd = orc->impl->connect(orc->impl); if (orc->fd < 0) sleep(1); } // read for a while while (1) { // read a packet uint8_t buf[3]; int res = read_fully(orc->fd, buf, 1); if (res <= 0) goto disconnected; if (buf[0] != 0xED) { LOG_DEBUG("Recovering sync [%02X]", buf[0]); continue; } res = read_fully(orc->fd, &buf[1], 2); if (res <= 0) goto disconnected; int id = buf[1]; int datalen = buf[2]; transaction_t *t = &orc->transactions[id]; memcpy(t->response, buf, 3); res = read_fully(orc->fd, &t->response[PACKET_DATA], datalen + 1); if (res <= 0) goto disconnected; if (!packet_test_checksum(t->response)) { LOG_WARN("Bad checksum received from Orc"); continue; } if (t->response == garbage && t->response[1]>=orc->idLow && t->response[1]<=orc->idHigh) LOG_VERBOSE("Unsolicited ack, id = %02X", t->response[1]); // is this a message from orcd, assigning us a client id? if (t->response[1] == 0xf7) { orc->idLow = t->response[4]; orc->idHigh = t->response[5]; orc->idLast = orc->idLow; LOG_INFO("Got client transaction range: %02x-%02x", orc->idLow, orc->idHigh); } if (t->response[1] == 0xfe) handle_pad_packet(orc, t->response); if (t->response[1] == PACKET_ID_ORCBOARD_BROADCAST && packet_16u(t->response, 1) == MSG_ASYNC_HEARTBEAT) handle_heartbeat_packet(orc, t->response); pthread_mutex_lock(&t->mutex); pthread_cond_signal(&t->cond); pthread_mutex_unlock(&t->mutex); } disconnected: orc->impl->disconnect(orc->impl, orc->fd); orc->fd = -1; goto reconnect; // silence compiler return NULL; }