Exemple #1
0
static int cftp_receive_handle(struct cftp_descriptor *desc, struct cftp_file_request *req)
{
	int ret;

	switch (req->st_mode & S_IFMT)
	{
	case S_IFBLK:
	case S_IFCHR:
		println("Create Device: %s", req->filename);
		remove(req->filename);
		ret = mknod(req->filename, req->st_mode, req->st_rdev);
		break;

	case S_IFLNK:
		println("Create Symlink: %s", req->filename);
		remove(req->filename);
		ret = symlink(req->filename + text_len(req->filename) + 1, req->filename);
		if (ret < 0 && errno == EEXIST)
		{
			ret = 0;
		}
		break;

	case S_IFDIR:
		println("Create Directory: %s", req->filename);
		ret = mkdir(req->filename, req->st_mode);
		if (ret < 0 && errno == EEXIST)
		{
			ret = 0;
		}
		break;

	case S_IFREG:
		println("Receive Regular File: %s", req->filename);
		if (desc->receive_handle)
		{
			return desc->receive_handle(desc->data, req);
		}

		return cftp_server_receive_file(desc, req->filename, req->st_mode, req->offset, req->size);

	default:
		error_msg("unknown file type");
		cftp_send_error_message(desc, (struct cftp_error_message *) req, "unknown file type");
		return -EINVAL;
	}

	if (ret < 0)
	{
		cftp_send_error_message(desc, (struct cftp_error_message *) req, __FUNCTION__);
	}
	else
	{
		cftp_send_ack_message(desc, (struct cftp_ack_message *) req, 0, 0);
	}

	return ret;
}
Exemple #2
0
static int cftp_command_handle(struct cftp_descriptor *desc, struct cftp_command_request *req)
{
	int ret;

	ret = system(req->command);
	if (ret < 0) {
		cftp_send_error_message(desc, (struct cftp_error_message *) req, "system");
	} else {
		cftp_send_ack_message(desc, (struct cftp_ack_message *) req, 0, 0);
	}

	return ret;
}
Exemple #3
0
int cftp_server_receive_file(struct cftp_descriptor *desc, const char *filename, mode_t mode, u32 offset, size_t size)
{
	int fd;
	int ret;
	union cftp_message *msg;
	ssize_t recvlen, sendlen;
	u16 blk_num;
	struct progress_bar bar;
	size_t max_xfer_length;

	max_xfer_length = desc->max_xfer_length;

	msg = malloc(max_xfer_length);
	if (msg == NULL) {
		pr_err_info("malloc");
		return -ENOMEM;
	}

	fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, mode);
	if (fd < 0) {
		pr_err_info("open file %s faild", filename);
		cftp_send_error_message(desc, (struct cftp_error_message *) msg, "open file %s faild", filename);
		ret = fd;
		goto out_free_msg;
	}

	if (offset) {
		ret = lseek(fd, offset, SEEK_SET);
		if (ret < 0) {
			pr_err_info("lseek");
			cftp_send_error_message(desc, (struct cftp_error_message *) msg, "seek file %s faild", filename);
			goto out_free_msg;
		}
	}

	println("offset = %s", size2text(offset));
	println("size = %s", size2text(size));

	blk_num = 0;
	progress_bar_init(&bar, size, 0, PROGRESS_BAR_TYPE_DATA);

	while (1) {
		sendlen = cftp_send_ack_message(desc, (struct cftp_ack_message *) msg, blk_num, desc->retry_count);
		if (sendlen < 0) {
			pr_err_info("cftp_send_ack_message");
			ret = sendlen;
			goto out_close_file;
		}

		recvlen = cftp_receive_data(desc, msg, max_xfer_length);
		if (recvlen < 0) {
			pr_err_info("cftp_receive_data");
			cftp_send_error_message(desc, (struct cftp_error_message *) msg, "receive file failed");
			ret = recvlen;
			goto out_close_file;
		}

		switch (msg->type) {
		case CFTP_PACKAGE_ERROR:
			show_error_message((struct cftp_error_message *) msg);
			ret = -EFAULT;
			goto out_close_file;

		case CFTP_PACKAGE_DATA:
			if (msg->data_pkg.blk_num != blk_num) {
				pr_warn_info("blk_num %d != %d", msg->data_pkg.blk_num, blk_num);
				continue;
			}

			sendlen = write(fd, msg->data_pkg.data, recvlen - sizeof(msg->data_pkg));
			if (sendlen < 0) {
				pr_err_info("write");
				cftp_send_error_message(desc, (struct cftp_error_message *) msg, "write file failed");
				ret = sendlen;
				goto out_close_file;
			}

			blk_num++;

			if ((size_t) recvlen < max_xfer_length) {
				cftp_send_ack_message(desc, (struct cftp_ack_message *) msg, blk_num, 0);
				progress_bar_finish(&bar);
				println("Receive data complete");
				ret = 0;
				goto out_close_file;
			} else {
				progress_bar_add(&bar, sendlen);
			}
			break;

		default:
			pr_err_info("invalid package type");
			cftp_send_error_message(desc, (struct cftp_error_message *) msg, "invalid package type");
			ret = -EINVAL;
			goto out_close_file;
		}
	}

out_close_file:
	close(fd);
out_free_msg:
	free(msg);

	return ret;
}
Exemple #4
0
int cftp_client_receive_file(struct cftp_descriptor *desc, const char *file_in, u32 offset_in, const char *file_out, u32 offset_out, size_t size)
{
	int fd;
	int ret;
	ssize_t recvlen, sendlen;
	u16 blk_num;
	union cftp_message *msg;
	size_t max_xfer_length;

	fd = open(file_out, O_WRONLY | O_CREAT | O_TRUNC, 0777);
	if (fd < 0) {
		pr_err_info("open file %s failed", file_out);
		return fd;
	}

	if (offset_out) {
		ret = lseek(fd, offset_out, SEEK_SET);
		if (ret < 0) {
			pr_err_info("lseek");
			goto out_close_file;
		}
	}

	max_xfer_length = desc->max_xfer_length;

	msg = malloc(max_xfer_length);
	if (msg == NULL) {
		pr_err_info("malloc");
		ret = -ENOMEM;
		goto out_close_file;
	}

	sendlen = cftp_send_file_reuest(desc, (void *) msg, file_in, NULL, offset_in, size, 1);
	if (sendlen < 0) {
		pr_err_info("cftp_send_data_retry");
		ret = sendlen;
		goto out_free_msg;
	}

	println("Remote@%s => Local@%s", file_in, file_out);
	println("seek = %s", size2text(offset_out));
	println("skip = %s", size2text(offset_in));
	println("size = %s", size2text(size));

	blk_num = 0;

	while (1) {
		recvlen = cftp_receive_data(desc, msg, max_xfer_length);
		if (recvlen < 0) {
			pr_err_info("cftp_receive_data");
			ret = recvlen;
			goto out_free_msg;
		}

		switch (msg->type) {
		case CFTP_PACKAGE_ERROR:
			show_error_message((struct cftp_error_message *) msg);
			ret = -EFAULT;
			goto out_free_msg;

		case CFTP_PACKAGE_DATA:
			if (msg->data_pkg.blk_num == blk_num) {
				sendlen = write(fd, msg->data_pkg.data, recvlen - sizeof(msg->data_pkg));
				if (sendlen < 0) {
					pr_err_info("write");
					cftp_send_error_message(desc, (struct cftp_error_message *) msg, "write file failed");
					ret = sendlen;
					goto out_free_msg;
				}

				blk_num++;

				if ((blk_num & 0xFF) == 0) {
					print_char('.');
				}

				if ((size_t) recvlen < max_xfer_length) {
					println(" Receive data complete");
					cftp_send_ack_message(desc, (struct cftp_ack_message *) msg, blk_num, 0);
					ret = 0;
					goto out_free_msg;
				}
			} else {
				pr_warn_info("%d != %d", msg->data_pkg.blk_num, blk_num);
			}

			sendlen = cftp_send_ack_message(desc, (struct cftp_ack_message *) msg, blk_num, desc->retry_count);
			if (sendlen < 0) {
				pr_err_info("cftp_send_ack_message");
				ret = sendlen;
				goto out_free_msg;
			}
			break;

		default:
			pr_err_info("invalid package type");
			cftp_send_error_message(desc, (struct cftp_error_message *) msg, "invalid package type");
			ret = -EINVAL;
			goto out_free_msg;
		}
	}

out_free_msg:
	free(msg);
out_close_file:
	close(fd);

	return ret;
}