Пример #1
0
static gpointer
pull_buffer_impl(
    XferElement *elt,
    size_t *size)
{
    XferFilterCrc *self = (XferFilterCrc *)elt;
    char *buf;
    XMsg *msg;

    if (elt->cancelled) {
	/* drain our upstream only if we're expecting an EOF */
	if (elt->expect_eof) {
	    xfer_element_drain_buffers(XFER_ELEMENT(self)->upstream);
	}

	/* return an EOF */
	*size = 0;
	return NULL;
    }

    /* get a buffer from upstream, crc it, and hand it back */
    buf = xfer_element_pull_buffer(XFER_ELEMENT(self)->upstream, size);
    if (buf) {
	crc32_add((uint8_t *)buf, *size, &elt->crc);
    } else {
	g_debug("sending XMSG_CRC message");
	g_debug("crc pull_buffer CRC: %08x",
		crc32_finish(&elt->crc));
	msg = xmsg_new(elt, XMSG_CRC, 0);
	msg->crc = crc32_finish(&elt->crc);
	msg->size = elt->crc.size;
	xfer_queue_message(elt->xfer, msg);
    }
    return buf;
}
Пример #2
0
static void
push_buffer_impl(
    XferElement *elt,
    gpointer buf,
    size_t len)
{
    XferFilterCrc *self = (XferFilterCrc *)elt;
    XMsg *msg;

    /* drop the buffer if we've been cancelled */
    if (elt->cancelled) {
	amfree(buf);
	return;
    }

    /* crc the given buffer and pass it downstream */
    if (buf) {
	crc32_add((uint8_t *)buf, len, &elt->crc);
    } else {
	g_debug("sending XMSG_CRC message to %p", elt);
	g_debug("crc push_buffer CRC: %08x",
		crc32_finish(&elt->crc));
	msg = xmsg_new(elt, XMSG_CRC, 0);
	msg->crc = crc32_finish(&elt->crc);
	msg->size = elt->crc.size;
	xfer_queue_message(elt->xfer, msg);
    }
    xfer_element_push_buffer(XFER_ELEMENT(self)->downstream, buf, len);
}
Пример #3
0
static void
pull_and_write(XferElementGlue *self)
{
    XferElement *elt = XFER_ELEMENT(self);
    int fd = get_write_fd(self);
    XMsg *msg;
    size_t written;

    self->write_fdp = NULL;

    while (!elt->cancelled) {
	size_t len;
	char *buf;

	/* get a buffer from upstream */
	buf = xfer_element_pull_buffer(elt->upstream, &len);
	if (!buf)
	    break;

	/* write it */
	if (!elt->downstream->drain_mode) {
	    written = full_write(fd, buf, len);
	    if (written < len) {
		if (elt->downstream->must_drain) {
		    g_debug("Error writing to fd %d: %s", fd, strerror(errno));
		} else if (elt->downstream->ignore_broken_pipe && errno == EPIPE) {
		} else {
		    if (!elt->cancelled) {
			xfer_cancel_with_error(elt,
			    _("Error writing to fd %d: %s"), fd, strerror(errno));
			xfer_cancel(elt->xfer);
			wait_until_xfer_cancelled(elt->xfer);
		    }
		    amfree(buf);
		    break;
		}
		elt->downstream->drain_mode = TRUE;
	    }
        }
	crc32_add((uint8_t *)buf, len, &elt->crc);

	amfree(buf);
    }

    if (elt->cancelled && elt->expect_eof)
	xfer_element_drain_buffers(elt->upstream);

    g_debug("sending XMSG_CRC message %p", elt->downstream);
    g_debug("pull_and_write CRC: %08x      size %lld",
	    crc32_finish(&elt->crc), (long long)elt->crc.size);
    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);

    /* close the fd we've been writing, as an EOF signal to downstream, and
     * set it to -1 to avoid accidental re-use */
    close_write_fd(self);
}
Пример #4
0
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);
}
Пример #5
0
static int
test_size(
    size_t size)
{
    crc_t crc1;
    crc_t crc16;
#if defined __GNUC__ && GCC_VERSION > 40300 && (defined __x86_64__ || defined __i386__ || defined __i486__ || defined __i586__ || defined __i686__)
    crc_t crchw;
#endif

    crc32_init(&crc1);
    crc32_init(&crc16);
#if defined __GNUC__ && GCC_VERSION > 40300 && (defined __x86_64__ || defined __i386__ || defined __i486__ || defined __i586__ || defined __i686__)
    crc32_init(&crchw);
#endif

    crc32_add_1byte(test_buf, size, &crc1);
    crc32_add_16bytes(test_buf, size, &crc16);
#if defined __GNUC__ && GCC_VERSION > 40300 && (defined __x86_64__ || defined __i386__ || defined __i486__ || defined __i586__ || defined __i686__)
    if (have_sse42) {
	crc32c_add_hw(test_buf, size, &crchw);
    }
#endif

#if defined __GNUC__ && GCC_VERSION > 40300 && (defined __x86_64__ || defined __i386__ || defined __i486__ || defined __i586__ || defined __i686__)
    g_fprintf(stderr, " %08x:%lld  %08x:%lld  %08x:%lld\n", crc32_finish(&crc1), (long long)crc1.size, crc32_finish(&crc16), (long long)crc16.size, crc32_finish(&crchw), (long long)crchw.size);
#else
    g_fprintf(stderr, " %08x:%lld  %08x:%lld\n", crc32_finish(&crc1), (long long)crc1.size, crc32_finish(&crc16), (long long)crc16.size);
#endif

    if (crc1.crc != crc16.crc ||
	crc1.size != crc16.size) {
	g_fprintf(stderr, " CRC16 %zu %08x:%lld != %08x:%lld\n", size, crc32_finish(&crc1), (long long)crc1.size, crc32_finish(&crc16), (long long)crc16.size);
	return FALSE;
    }
#if defined __GNUC__ && GCC_VERSION > 40300 && (defined __x86_64__ || defined __i386__ || defined __i486__ || defined __i586__ || defined __i686__)
    if (have_sse42) {
	if (crc1.crc != crchw.crc ||
	    crc1.size != crchw.size) {
	    g_fprintf(stderr, " CRChw %zu %08x:%lld != %08x:%lld\n", size, crc32_finish(&crc1), (long long)crc1.size, crc32_finish(&crchw), (long long)crchw.size);
	    return FALSE;
	}
    }
#endif
    return TRUE;
}
Пример #6
0
static int send_error_msg(port_addr fd, int error_code)
{
    // Send a fail response - <magic><resp_length = 8><error_code><crc>

    uint32_t resp_length = 8;
    uint32_t crc = crc32_start();
    crc = crc32_append(crc, &magic, 4);
    crc = crc32_append(crc, &resp_length, 4);
    crc = crc32_append(crc, &error_code, 4);
    crc = crc32_finish(crc);

    serial_write(fd, &magic, 4);
    serial_write(fd, &resp_length, 4);
    serial_write(fd, &error_code, 4);
    serial_write(fd, &crc, 4);

    fprintf(stderr, "Sent ERROR %i response\n", error_code);

    return 0;
}
Пример #7
0
static void
push_buffer_impl(
    XferElement *elt,
    gpointer buf,
    size_t len)
{
    XferDestNull *self = (XferDestNull *)elt;

    if (buf) {
	crc32_add(buf, len, &elt->crc);
    } else {
	XMsg *msg = xmsg_new((XferElement *)self, XMSG_CRC, 0);
	msg->crc = crc32_finish(&elt->crc);
	msg->size = elt->crc.size;
	xfer_queue_message(XFER_ELEMENT(self)->xfer, msg);
	return;
    }

    if (self->do_verify && !elt->cancelled) {
	if (!simpleprng_verify_buffer(&self->prng, buf, len)) {
	    xfer_cancel_with_error(elt,
		"verification of incoming bytestream failed; see stderr for details"),
	    wait_until_xfer_cancelled(elt->xfer);
	    amfree(buf);
	    return;
	}
    }

    self->byte_position += len;
    if (!self->sent_info) {
	/* send a superfluous message (this is a testing XferElement,
	 * after all) */
	XMsg *msg = xmsg_new((XferElement *)self, XMSG_INFO, 0);
	msg->message = g_strdup("Is this thing on?");
	xfer_queue_message(XFER_ELEMENT(self)->xfer, msg);
	self->sent_info = TRUE;
    }

    amfree(buf);
}
Пример #8
0
int crc32_test(void)
{
#ifndef LTC_TEST
   return CRYPT_NOP;
#else
   const void* in = "libtomcrypt";
   const unsigned char crc32[] = { 0xef, 0x76, 0x73, 0xb3 };
   unsigned char out[4];
   crc32_state ctx;
   crc32_init(&ctx);
   crc32_update(&ctx, in, strlen(in));
   crc32_finish(&ctx, out, 4);
   if (XMEMCMP(crc32, out, 4)) {
#ifdef LTC_TEST_DBG
      ulong32 _out, _crc32;
      LOAD32H(_out, out);
      LOAD32H(_crc32, crc32);
      printf("crc32 fail! Is: 0x%x Should: 0x%x\n", _out, _crc32);
#endif
      return CRYPT_FAIL_TESTVECTOR;
   }
   return CRYPT_OK;
#endif
}
Пример #9
0
static int do_cmd(int cmd, port_addr fd)
{
    switch(cmd)
    {
        case 0:
        {
            // Identify command

            // Read the command crc
            uint32_t ccrc;
            serial_read(fd, &ccrc, 4);
            uint32_t eccrc = crc32((void *)0, 0);
            if(ccrc != eccrc)
                return send_error_msg(fd, CRC_ERROR);

            // Set the response length and error code
            uint32_t resp_length = 12;
            uint32_t error_code = SUCCESS;

            // Build the response crc
            uint32_t crc = crc32_start();
            crc = crc32_append(crc, &magic, 4);
            crc = crc32_append(crc, &resp_length, 4);
            crc = crc32_append(crc, &error_code, 4);
            crc = crc32_append(crc, &server_caps, 4);
            crc = crc32_finish(crc);

            // Send the response
            serial_write(fd, &magic, 4);
            serial_write(fd, &resp_length, 4);
            serial_write(fd, &error_code, 4);
            serial_write(fd, &server_caps, 4);
            serial_write(fd, &crc, 4);

            fprintf(stderr, "Sent CMD0 response\n");

            return 0;
        }

        case 1:
        {
            // Read directory
            uint32_t eccrc = crc32_start();

            // Read the directory name
            uint16_t dir_name_len;
            serial_read(fd, &dir_name_len, 2);
            eccrc = crc32_append(eccrc, &dir_name_len, 2);
            char *dir_name = (char *)malloc((int)dir_name_len + 1);
            memset(dir_name, 0, dir_name_len + 1);
            serial_read(fd, dir_name, (size_t)dir_name_len);
            eccrc = crc32_append(eccrc, dir_name, (size_t)dir_name_len);
            eccrc = crc32_finish(eccrc);

            // Read the command crc
            uint32_t ccrc;
            serial_read(fd, &ccrc, 4);
            if(ccrc != eccrc)
                return send_error_msg(fd, CRC_ERROR);

            // Append the requested dir to the base dir
            int full_dir_len = strlen(base_dir) + 1 + dir_name_len + 1;
            char *full_dir = (char *)malloc(full_dir_len);
            memset(full_dir, 0, full_dir_len);
            strcat(full_dir, base_dir);
            strcat(full_dir, "/");
            strcat(full_dir, dir_name);

            // Try and read the requested directory
            DIR *dirp = opendir(full_dir);
            if(dirp == NULL)
            {
                free(dir_name);
                free(full_dir);
                if((errno == ENOENT) || (errno == ENOTDIR))
                    return send_error_msg(fd, PATH_NOT_FOUND);
                else
                    return send_error_msg(fd, UNKNOWN_ERROR);
            }

            // Count the directory entries
            int byte_count = 0;
            uint32_t entry_count = 0;
            struct dirent *de;
            while((de = readdir(dirp)) != NULL)
            {
                // Add space for byte_size, user_id, group_id
                //  and props fields
                byte_count += 16;

                // Add space for name string
                byte_count += 2;
                byte_count += strlen(de->d_name);

                entry_count++;
            }
            rewinddir(dirp);

            // Allocate the buffer to send
            uint8_t *buf = (uint8_t *)malloc(byte_count);
            int bptr = 0;

            // Fill in the buffer
            uint32_t entries_filled = 0;
            while((de = readdir(dirp)) != NULL)
            {
                // Build a string of the whole filename
                int fname_len = strlen(de->d_name);
                int path_len = full_dir_len + 1 + fname_len + 1;
                char *path = (char *)malloc(path_len);
                memset(path, 0, path_len);
                strcat(path, full_dir);
                strcat(path, "/");
                strcat(path, de->d_name);

                // Get the file stats
                struct stat stat_buf;
                if(stat(path, &stat_buf) != 0)
                {
                    fprintf(stderr, "Error running fstat on %s, errno = %i\n",
                            path, errno);
                    free(path);
                    free(buf);
                    free(full_dir);
                    free(dir_name);
                    return send_error_msg(fd, UNKNOWN_ERROR);
                }

                // Fill in the buffer
                write_word((uint32_t)stat_buf.st_size, buf, bptr);
                write_word((uint32_t)stat_buf.st_uid, buf, bptr + 4);
                write_word((uint32_t)stat_buf.st_gid, buf, bptr + 8);
                write_word((uint32_t)stat_buf.st_mode, buf, bptr + 12);
                bptr += 16;

                // Fill in the name
                write_halfword((uint16_t)dir_name_len, buf, bptr);
                bptr += 2;
                memcpy(&buf[bptr], de->d_name, dir_name_len);
                bptr += dir_name_len;

                free(path);

                entries_filled++;
            }
            if(entries_filled != entry_count)
            {
                // An error has occurred re-parsing the directory
                fprintf(stderr, "entries_filled (%i) != entry_count (%i)\n",
                        entries_filled, entry_count);
                free(buf);
                free(dir_name);
                free(full_dir);
                send_error_msg(fd, UNKNOWN_ERROR);
            }

            fprintf(stderr, "SERVER: %i directory entries, byte_count %i\n", entry_count, byte_count);

            // Set the response length and error code
            uint32_t resp_length = 16 + byte_count;
            uint32_t error_code = SUCCESS;
            uint32_t dir_entry_version = 0;

            // Build the response crc
            uint32_t crc = crc32_start();
            crc = crc32_append(crc, &magic, 4);
            crc = crc32_append(crc, &resp_length, 4);
            crc = crc32_append(crc, &error_code, 4);
            crc = crc32_append(crc, &entry_count, 4);
            crc = crc32_append(crc, &dir_entry_version, 4);
            crc = crc32_append(crc, buf, byte_count);
            crc = crc32_finish(crc);

            // Send the response
            serial_write(fd, &magic, 4);
            serial_write(fd, &resp_length, 4);
            serial_write(fd, &error_code, 4);
            serial_write(fd, &entry_count, 4);
            serial_write(fd, &dir_entry_version, 4);
            serial_write(fd, buf, byte_count);
            serial_write(fd, &crc, 4);

            fprintf(stderr, "Sent CMD1 response\n");

            free(buf);
            free(dir_name);
            free(full_dir);

            return 0;
        }
    }
    (void)fd;
    return 0;
}
Пример #10
0
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);
}
Пример #11
0
static void
push_buffer_impl(
    XferElement *elt,
    gpointer buf,
    size_t len)
{
    XferElementGlue *self = (XferElementGlue *)elt;
    XMsg *msg;

    /* accept first, if required */
    if (self->on_push & PUSH_ACCEPT_FIRST) {
	/* don't accept the next time around */
	self->on_push &= ~PUSH_ACCEPT_FIRST;

	if (elt->cancelled) {
	    return;
	}

	if ((self->output_data_socket = do_directtcp_accept(self,
					    &self->output_listen_socket)) == -1) {
	    /* do_directtcp_accept already signalled an error; xfer
	     * is cancelled */
	    return;
	}

	/* write to this new socket */
	self->write_fdp = &self->output_data_socket;
    }

    /* or connect first, if required */
    if (self->on_push & PUSH_CONNECT_FIRST) {
	/* don't accept the next time around */
	self->on_push &= ~PUSH_CONNECT_FIRST;

	if (elt->cancelled) {
	    return;
	}

	if ((self->output_data_socket = do_directtcp_connect(self,
				    elt->downstream->input_listen_addrs)) == -1) {
	    /* do_directtcp_connect already signalled an error; xfer
	     * is cancelled */
	    return;
	}

	/* read from this new socket */
	self->write_fdp = &self->output_data_socket;
    }

    switch (self->on_push) {
	case PUSH_TO_RING_BUFFER:
	    /* just drop packets if the transfer has been cancelled */
	    if (elt->cancelled) {
		amfree(buf);
		return;
	    }

	    /* make sure there's at least one element free */
	    amsemaphore_down(self->ring_free_sem);

	    /* set it */
	    self->ring[self->ring_head].buf = buf;
	    self->ring[self->ring_head].size = len;
	    self->ring_head = (self->ring_head + 1) % GLUE_RING_BUFFER_SIZE;

	    /* and mark this element as available for reading */
	    amsemaphore_up(self->ring_used_sem);

	    return;

	case PUSH_TO_FD: {
	    int fd = get_write_fd(self);

	    /* 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.  In this
	     * case we can assume the xfer has been cancelled and just discard
	     * the data. */
	    if (fd == -1)
		return;

	    if (elt->cancelled) {
		if (!elt->expect_eof || !buf) {
		    close_write_fd(self);

		    /* hack to ensure we won't close the fd again, if we get another push */
		    elt->expect_eof = TRUE;
		}

		amfree(buf);

		return;
	    }

	    /* write the full buffer to the fd, or close on EOF */
	    if (buf) {
		if (!elt->downstream->drain_mode &&
		    full_write(fd, buf, len) < len) {
		    if (elt->downstream->must_drain) {
			g_debug("Error writing to fd %d: %s",
				fd, strerror(errno));
		    } else if (elt->downstream->ignore_broken_pipe &&
			       errno == EPIPE) {
		    } else {
			if (!elt->cancelled) {
			    xfer_cancel_with_error(elt,
				_("Error writing to fd %d: %s"),
				fd, strerror(errno));
			    wait_until_xfer_cancelled(elt->xfer);
			}
			/* nothing special to do to handle a cancellation */
		    }
		    elt->downstream->drain_mode = TRUE;
		}
		crc32_add((uint8_t *)buf, len, &elt->crc);
		amfree(buf);
	    } else {
		g_debug("sending XMSG_CRC message");
		g_debug("push_to_fd CRC: %08x", crc32_finish(&elt->crc));
		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);

		close_write_fd(self);
	    }

	    return;
	}

	default:
	case PUSH_INVALID:
	    g_assert_not_reached();
	    break;
    }
}
Пример #12
0
/* loads the next level from open file fd. returns 0 on success, 1 on success with end of file reached, or -1 on error. */
static int loadlevelfromfile(struct sokgame *game, unsigned char **memptr, char *comment, int maxcommentlen) {
  int leveldatastarted = 0, endoffile = 0;
  int x, y, bytebuff;
  int commentfound = 0;
  char *origcomment = comment;
  game->positionx = -1;
  game->positiony = -1;
  game->field_width = 0;
  game->field_height = 0;
  game->solution = NULL;
  if ((comment != NULL) && (maxcommentlen > 0)) *comment = 0;

  /* Fill the area with floor */
  for (y = 0; y < 64; y++) {
    for (x = 0; x < 64; x++) {
      game->field[x][y] = field_floor;
    }
  }

  x = 0;
  y = 0;

  for (;;) {
    int rleprefix;
    rleprefix = readRLEbyte(memptr, &bytebuff);
    if (rleprefix < 0) endoffile = 1;
    if (endoffile != 0) break;
    for (; rleprefix > 0; rleprefix--) {
      switch (bytebuff) {
        case ' ': /* empty space */
        case '-': /* dash (-) and underscore (_) are sometimes used to denote empty spaces */
        case '_':
          game->field[x + 1][y + 1] |= field_floor;
          x += 1;
          break;
        case '#': /* wall */
          game->field[x + 1][y + 1] |= field_wall;
          x += 1;
          break;
        case '@': /* player */
          game->field[x + 1][y + 1] |= field_floor;
          game->positionx = x;
          game->positiony = y;
          x += 1;
          break;
        case '*': /* atom on goal */
          game->field[x + 1][y + 1] |= field_goal;
        case '$': /* atom */
          game->field[x + 1][y + 1] |= field_atom;
          x += 1;
          break;
        case '+': /* player on goal */
          game->positionx = x;
          game->positiony = y;
        case '.': /* goal */
          game->field[x + 1][y + 1] |= field_goal;
          x += 1;
          break;
        case '\n': /* next row */
        case '|':  /* some variants of the xsb format use | as the 'new row' separator (mostly when used with RLE) */
          if (leveldatastarted != 0) y += 1;
          x = 0;
          break;
        case '\r': /* CR - ignore those */
          break;
        default: /* anything else is a comment -> skip until end of line or end of file */
          if (leveldatastarted != 0) leveldatastarted = -1;
          if ((commentfound == 0) && (comment != NULL)) commentfound = -1;
          for (;;) {
            bytebuff = readbytefrommem(memptr);
            if (bytebuff == '\r') continue;
            if (bytebuff == '\n') break;
            if (bytebuff < 0) {
              endoffile = 1;
              break;
            }
            if (commentfound == -1) {
              if (maxcommentlen > 1) {
                  maxcommentlen--;
                  *comment = bytebuff;
                  comment += 1;
                } else {
                  commentfound = -2;
              }
            }
          }
          if (commentfound < 0) {
            commentfound = 1;
            *comment = 0;
            trim(origcomment);
          }
          break;
      }
      if ((leveldatastarted < 0) || (endoffile != 0)) break;
      if (x > 0) leveldatastarted = 1;
      if (x >= 62) return(ERR_LEVEL_TOO_LARGE);
      if (y >= 62) return(ERR_LEVEL_TOO_HIGH);
      if (x > game->field_width) game->field_width = x;
      if ((y >= game->field_height) && (x > 0)) game->field_height = y + 1;
    }
    if ((leveldatastarted < 0) || (endoffile != 0)) break;
  }

  /* check if the loaded game looks sane */
  if (game->positionx < 0) return(ERR_PLAYER_POS_UNDEFINED);
  if (game->field_height < 1) return(ERR_LEVEL_TOO_SMALL);
  if (game->field_width < 1) return(ERR_LEVEL_TOO_SMALL);
  if (leveldatastarted == 0) return(ERR_NO_LEVEL_DATA_FOUND);

  /* remove floors around the level */
  floodFillField(game, 63, 63);

  /* move the field by -1 vertically and horizontally to remove the additional row and column added for the fill function to be able to get around the field. */
  for (y = 0; y < 63; y++) {
    for (x = 0; x < 63; x++) {
      game->field[x][y] = game->field[x + 1][y + 1];
    }
  }
  /* compute the CRC32 of the field */
  game->crc32 = crc32_init();
  for (y = 0; y < game->field_width; y++) {
    for (x = 0; x < game->field_height; x++) {
      crc32_feed(&(game->crc32), &(game->field[x][y]), 1);
    }
  }
  crc32_finish(&(game->crc32));

  if (endoffile != 0) return(1);
  return(0);
}
Пример #13
0
static int send_message_int(int cmd_id, void *send_buf, size_t send_buf_len,
                            void *recv_buf, size_t recv_buf_len)
{
    // Send a message (v2 messages only)
#ifdef RASPBOOTIN_DEBUG
    printf("RASPBOOTIN: sending cmd %i\n");
    int fail_loc = 0;
#endif

    // Check capabilities
    if((cmd_id < 0) || (cmd_id > 31))
    {
        printf("RASPBOOTIN: invalid cmd number %i\n");
        return INVALID_CMD;
    }
    if(cmd_id == 3)
    {
        printf("RASPBOOTIN: cannot use send_message_int to send cmd 3\n");
        return INVALID_CMD;
    }
    uint32_t msg_capabilities = (1 << cmd_id);
    if(!(client_capabilities & msg_capabilities))
    {
        printf("RASPBOOTIN: client does not support cmd %i\n");
        return UNSUPPORTED_CMD;
    }
    if(!(server_capabilities & msg_capabilities))
    {
        printf("RASPBOOTIN: server does not support cmd %i\n");
        return UNSUPPORTED_CMD;
    }

    // The crc of the request is calculated from 'options'
    uint32_t crc = crc32(send_buf, send_buf_len);

    // Disable debug output on the uart
    rpi_boot_output_state ostate = output_get_state();
    output_disable_uart();

    // Clear the receive buffer
    while(uart_getc_timeout(1000) != -1);

    // Send the message
    uart_putc('\003');
    uart_putc('\003');
    uart_putc(cmd_id);

    uint8_t *send_p = (uint8_t *)send_buf;
    while(send_buf_len--)
        uart_putc(*send_p++);

    uart_putc(BYTE(crc, 0));
    uart_putc(BYTE(crc, 1));
    uart_putc(BYTE(crc, 2));
    uart_putc(BYTE(crc, 3));

    // Wait for the response
    usleep(2000);

    // Begin reading response
    int r_buf = 0;
    int ret = 0;

    // Read magic number
    uint32_t magic = 0;
    CHECK(read_lsb32(&magic, UART_TIMEOUT), 0);

    if(magic != MAGIC)
    {
#ifdef RASPBOOTIN_DEBUG
        printf("RASPBOOTIN: invalid magic received: %08x (expecting %08x)\n", magic, MAGIC);
#endif
        ret = INVALID_MAGIC;
        goto cleanup;
    }

    // Read response length
    uint32_t resp_length = 0;
    CHECK(read_lsb32(&resp_length, UART_TIMEOUT), 1);

    // Read error_code
    uint32_t error_code = 0;
    CHECK(read_lsb32(&error_code, UART_TIMEOUT), 2);

    if(error_code != SUCCESS)
    {
        ret = error_code;
#ifdef RASPBOOTIN_DEBUG
        fail_loc = 3;
#endif
        goto cleanup;
    }

    // Read the data (maximum is whatever is greater - recv_buf_len
    // or resp_length)
    // Resp_length is length of the message minus magic and crc
    //  therefore it includes the length of resp_length and error_code
    //  which have already been read, therefore subtract 8
    size_t data_to_read_to_buffer = (size_t)(resp_length - 8);
    size_t data_to_discard = 0;
    size_t data_to_pad = 0;
    if(data_to_read_to_buffer > recv_buf_len)
    {
        data_to_read_to_buffer = recv_buf_len;
        data_to_discard = data_to_read_to_buffer - recv_buf_len;
    }
    else if(recv_buf_len > data_to_read_to_buffer)
        data_to_pad = recv_buf_len - data_to_read_to_buffer;

    crc = crc32_start();
    crc = crc32_append(crc, &magic, 4);
    crc = crc32_append(crc, &resp_length, 4);
    crc = crc32_append(crc, &error_code, 4);
    int data_read = 0;
    uint8_t *rptr = (uint8_t *)recv_buf;
    while(data_to_read_to_buffer--)
    {
        r_buf = uart_getc_timeout(UART_TIMEOUT);
        CHECK(r_buf, 4);
        crc = crc32_append(crc, &r_buf, 1);
        *rptr++ = r_buf;
        data_read++;
    }
    while(data_to_discard--)
    {
        r_buf = uart_getc_timeout(UART_TIMEOUT);
        CHECK(r_buf, 5);
        crc = crc32_append(crc, &r_buf, 1);
    }
    while(data_to_pad--)
        *rptr++ = 0;
    crc = crc32_finish(crc);

    // Read the response CRC
    uint32_t resp_crc = 0;
    CHECK(read_lsb32(&resp_crc, UART_TIMEOUT), 6);
    if(resp_crc != crc)
    {
        ret = CRC_ERROR;
#ifdef RASPBOOTIN_DEBUG
        fail_loc = 7;
#endif
        goto cleanup;
    }

cleanup:
    if(ret == 0)
        ret = data_read;

    // Clear the uart buffer
    while(uart_getc_timeout(1000) != -1);

    // Re-enable uart debug output
    output_restore_state(ostate);

#ifdef RASPBOOTIN_DEBUG
    printf("RASPBOOTIN: send_message_int, returning %i (fail_loc %i)\n",
           ret, fail_loc);
    if(ret == CRC_ERROR)
    {
        printf("RASPBOOTIN: CRC error: read CRC %08x, expected %08x, magic %08x, resp_length %08x, error_code %08x\n",
               resp_crc, crc, magic, resp_length, error_code);
    }
#endif
    return ret;
}
Пример #14
0
static gpointer
holding_thread(
    gpointer data)
{
    XferDestHolding *self = XFER_DEST_HOLDING(data);
    XferElement *elt = XFER_ELEMENT(self);
    XMsg *msg;
    gchar *mesg = NULL;
    GTimer *timer = g_timer_new();

    DBG(1, "(this is the holding thread)");

    /* This is the outer loop, that loops once for each holding file or
     * CONTINUE command */
    g_mutex_lock(self->state_mutex);
    while (1) {
	gboolean done;
	/* wait until the main thread un-pauses us, and check that we have
	 * the relevant holding info available */
	while (self->paused && !elt->cancelled) {
	    DBG(9, "waiting to be unpaused");
	    g_cond_wait(self->state_cond, self->state_mutex);
	}
	DBG(9, "holding_thread done waiting");

        if (elt->cancelled)
	    break;

	self->data_bytes_written = 0;
	self->header_bytes_written = 0;

	/* new holding file */
	if (self->filename == NULL ||
	    strcmp(self->filename, self->new_filename) != 0) {
	    char    *tmp_filename;
	    char    *pc;
	    int      fd;
	    ssize_t  write_header_size;

	    if (self->use_bytes < HEADER_BLOCK_BYTES) {
		self->chunk_status = CHUNK_NO_ROOM;
		goto no_room;
	    }

	    tmp_filename = g_strjoin(NULL, self->new_filename, ".tmp", NULL);
	    pc = strrchr(tmp_filename, '/');
	    g_assert(pc != NULL);
	    *pc = '\0';
	    mkholdingdir(tmp_filename);
	    *pc = '/';

	    fd = open(tmp_filename, O_RDWR|O_CREAT|O_TRUNC, 0600);
	    if (fd < 0) {
		self->chunk_status = CHUNK_NO_ROOM;
		g_free(mesg);
		mesg = g_strdup_printf("Failed to open '%s': %s",
				       tmp_filename, strerror(errno));
		g_free(tmp_filename);
		goto no_room;
	    }
	    if (self->filename == NULL) {
		self->chunk_header->type = F_DUMPFILE;
	    } else {
		self->chunk_header->type = F_CONT_DUMPFILE;
	    }
	    self->chunk_header->cont_filename[0] = '\0';

	    write_header_size = write_header(self, fd);
	    if (write_header_size != HEADER_BLOCK_BYTES) {
		self->chunk_status = CHUNK_NO_ROOM;
		mesg = g_strdup_printf("Failed to write header to '%s': %s",
				       tmp_filename, strerror(errno));
		close(fd);
		unlink(tmp_filename);
		g_free(tmp_filename);
		goto no_room;
	    }
	    g_free(tmp_filename);
	    self->use_bytes -= HEADER_BLOCK_BYTES;

	    /* rewrite old_header */
	    if (self->filename &&
		strcmp(self->filename, self->new_filename) != 0) {
		close_chunk(self, self->new_filename);
	    }
	    self->filename = self->new_filename;
	    self->new_filename = NULL;
	    self->fd = fd;
	    self->header_bytes_written = HEADER_BLOCK_BYTES;
	    self->chunk_offset = HEADER_BLOCK_BYTES;
	}

	DBG(2, "beginning to write chunk");
	done = holding_thread_write_chunk(self);
	DBG(2, "done writing chunk");

	if (!done) /* cancelled */
	    break;

no_room:
	msg = xmsg_new(XFER_ELEMENT(self), XMSG_CHUNK_DONE, 0);
	msg->header_size = self->header_bytes_written;
	msg->data_size = self->data_bytes_written;
	msg->no_room = (self->chunk_status == CHUNK_NO_ROOM);
	if (mesg) {
	    msg->message = mesg;
	    mesg = NULL;
	}

	xfer_queue_message(elt->xfer, msg);

	/* pause ourselves and await instructions from the main thread */
	self->paused = TRUE;

	/* if this is the last part, we're done with the chunk loop */
	if (self->chunk_status == CHUNK_EOF) {
	    break;
	}
    }
    g_mutex_unlock(self->state_mutex);

    g_debug("sending XMSG_CRC message");
    g_debug("xfer-dest-holding CRC: %08x     size: %lld",
	    crc32_finish(&elt->crc), (long long)elt->crc.size);
    msg = xmsg_new(XFER_ELEMENT(self), XMSG_CRC, 0);
    msg->crc = crc32_finish(&elt->crc);
    msg->size = elt->crc.size;
    xfer_queue_message(elt->xfer, msg);

    msg = xmsg_new(XFER_ELEMENT(self), XMSG_DONE, 0);
    msg->duration = g_timer_elapsed(timer, NULL);
    g_timer_destroy(timer);
    /* tell the main thread we're done */
    xfer_queue_message(elt->xfer, msg);

    return NULL;
}
Пример #15
0
static gpointer
pull_buffer_impl(
    XferElement *elt,
    size_t *size)
{
    XferSourceRecovery *self = XFER_SOURCE_RECOVERY(elt);
    gpointer buf = NULL;
    int result;
    int devsize;
    XMsg *msg;

    g_assert(elt->output_mech == XFER_MECH_PULL_BUFFER);

    g_mutex_lock(self->start_part_mutex);

    if (elt->size == 0) {
	if (elt->offset == 0 && elt->orig_size == 0) {
	    self->paused = TRUE;
	} else {
	    DBG(2, "xfer-source-recovery sending XMSG_CRC message");
	    DBG(2, "xfer-source-recovery CRC: %08x     size %lld",
		crc32_finish(&elt->crc), (long long)elt->crc.size);
	    msg = xmsg_new(XFER_ELEMENT(self), XMSG_CRC, 0);
	    msg->crc = crc32_finish(&elt->crc);
	    msg->size = elt->crc.size;
	    xfer_queue_message(elt->xfer, msg);

	    /* the device has signalled EOF (really end-of-part), so clean up instance
	     * variables and report the EOP to the caller in the form of an xmsg */
	    DBG(2, "pull_buffer hit EOF; sending XMSG_SEGMENT_DONE");
	    msg = xmsg_new(XFER_ELEMENT(self), XMSG_SEGMENT_DONE, 0);
	    msg->size = self->part_size;
	    if (self->part_timer) {
		msg->duration = g_timer_elapsed(self->part_timer, NULL);
		g_timer_destroy(self->part_timer);
		self->part_timer = NULL;
	    }
	    msg->partnum = 0;
	    msg->fileno = self->device->file;
	    msg->successful = TRUE;
	    msg->eof = FALSE;

	    self->paused = TRUE;
	    device_clear_bytes_read(self->device);
	    self->bytes_read += self->part_size;
	    self->part_size = 0;
	    self->block_size = 0;

	    /* don't queue the XMSG_PART_DONE until we've adjusted all of our
	     * instance variables appropriately */
	    xfer_queue_message(elt->xfer, msg);

	    if (self->device->is_eof) {
		DBG(2, "pull_buffer hit EOF; sending XMSG_PART_DONE");
		msg = xmsg_new(XFER_ELEMENT(self), XMSG_PART_DONE, 0);
		msg->size = self->part_size;
		if (self->part_timer) {
		    msg->duration = g_timer_elapsed(self->part_timer, NULL);
		    g_timer_destroy(self->part_timer);
		    self->part_timer = NULL;
		}
		msg->partnum = 0;
		msg->fileno = self->device->file;
		msg->successful = TRUE;
		msg->eof = FALSE;

		xfer_queue_message(elt->xfer, msg);
	    }
	}
    }

    while (1) {
	/* make sure we have a device */
	while (self->paused && !elt->cancelled)
	    g_cond_wait(self->start_part_cond, self->start_part_mutex);

	/* indicate EOF on an cancel or when there are no more parts */
	if (elt->cancelled) {
            goto error;
	}
	if (self->done)
	    goto error;

	/* start the timer if this is the first pull_buffer of this part */
	if (!self->part_timer) {
	    DBG(2, "first pull_buffer of new part");
	    self->part_timer = g_timer_new();
	}
	if (elt->size == 0) {
	    result = -1;
	} else {
	    /* loop until we read a full block, in case the blocks are larger
	     * than  expected */
	    if (self->block_size == 0)
		self->block_size = (size_t)self->device->block_size;

	    do {
		int max_block;
		buf = g_malloc(self->block_size);
		if (buf == NULL) {
		    xfer_cancel_with_error(elt,
				_("%s: cannot allocate memory"),
				self->device->device_name);
		    g_mutex_unlock(self->start_part_mutex);
		    wait_until_xfer_cancelled(elt->xfer);
		    goto error_unlocked;
		}
		devsize = (int)self->block_size;
		if (elt->size < 0)
		    max_block = -1;
		else
		    max_block = (elt->size+self->block_size-1)/self->block_size;
		result = device_read_block(self->device, buf, &devsize, max_block);
		*size = devsize;

		if (result == 0) {
		    g_assert(*size > self->block_size);
		    self->block_size = devsize;
		    amfree(buf);
		}
	    } while (result == 0);

	    if (result > 0 &&
		(elt->offset ||
		 (elt->size > 0 && (long long unsigned)elt->size < *size))) {
		gpointer buf1 = g_malloc(self->block_size);
		if ((long long unsigned)elt->offset > *size) {
		    g_debug("offset > *size");
		} else if ((long long unsigned)elt->offset == *size) {
		    g_debug("offset == *size");
		}
		*size -= elt->offset;
		if (elt->size > 0 && (size_t)elt->size < *size)
		    *size = elt->size;
		memmove(buf1, buf + elt->offset, *size);
		elt->offset = 0;
		g_free(buf);
		buf = buf1;
	    }
	    if (result > 0)
		elt->size -= *size;

	}

	/* if this block was successful, return it */
	if (result > 0) {
	    self->part_size += *size;
	    break;
	}

	if (result < 0) {
	    amfree(buf);

	    /* if we're not at EOF, it's an error */
	    if (!self->device->is_eof && elt->size != 0) {
		xfer_cancel_with_error(elt,
		    _("error reading from %s: %s"),
		    self->device->device_name,
		    device_error_or_status(self->device));
		g_mutex_unlock(self->start_part_mutex);
		wait_until_xfer_cancelled(elt->xfer);
                goto error_unlocked;
	    }

	    DBG(2, "xfer-source-recovery sending XMSG_CRC message");
	    DBG(2, "xfer-source-recovery CRC: %08x     size %lld",
		crc32_finish(&elt->crc), (long long)elt->crc.size);
	    msg = xmsg_new(XFER_ELEMENT(self), XMSG_CRC, 0);
	    msg->crc = crc32_finish(&elt->crc);
	    msg->size = elt->crc.size;
	    xfer_queue_message(elt->xfer, msg);

	    /* the device has signalled EOF (really end-of-part), so clean up instance
	     * variables and report the EOP to the caller in the form of an xmsg */
	    DBG(2, "pull_buffer hit EOF; sending XMSG_PART_DONE");
	    msg = xmsg_new(XFER_ELEMENT(self), XMSG_PART_DONE, 0);
	    msg->size = self->part_size;
	    msg->duration = g_timer_elapsed(self->part_timer, NULL);
	    msg->partnum = 0;
	    msg->fileno = self->device->file;
	    msg->successful = TRUE;
	    msg->eof = FALSE;

	    self->paused = TRUE;
	    self->bytes_read += self->part_size;
	    device_clear_bytes_read(self->device);
	    self->part_size = 0;
	    self->block_size = 0;
	    if (self->part_timer) {
		g_timer_destroy(self->part_timer);
		self->part_timer = NULL;
	    }

	    /* don't queue the XMSG_PART_DONE until we've adjusted all of our
	     * instance variables appropriately */
	    xfer_queue_message(elt->xfer, msg);
	    if (elt->size == 0) {
		g_mutex_unlock(self->start_part_mutex);
		return NULL;
	    }
	}
    }

    g_mutex_unlock(self->start_part_mutex);

    if (buf) {
	crc32_add(buf, *size, &elt->crc);
    }

    return buf;
error:
    g_mutex_unlock(self->start_part_mutex);
error_unlocked:
    *size = 0;
    return NULL;
}