示例#1
0
static int
put_file_func (CameraFilesystem *fs, const char *folder, const char *filename, CameraFile *file,
	       void *data, GPContext *context)
{
	Camera *camera = data;

	/*
	 * Upload the file to the camera. Use gp_file_get_data_and_size etc.
	 */
	int result = -EPROTO;
	time_t startTime = time(NULL);
	enum {
		START,
		DATA,
		END,
		FINISHED
	} state;
	int src = -1;
	int r;
	int update = 0;
	struct stat srcStat;
	__u64 fileSize;
	__u64 byteCount = 0;
	const char *filename;
	char *path;
	struct tf_packet reply;

	if(0 != fstat(src, &srcStat))
	{
		gp_log (GP_LOG_ERROR, "topfield", "ERROR: Can not examine source file: %s\n",
			strerror(errno));
		result = errno;
		goto out;
	}

	fileSize = srcStat.st_size;
	if(fileSize == 0)
	{
		gp_log (GP_LOG_ERROR, "topfield", "ERROR: Source file is empty - not transfering.\n");
		result = -ENODATA;
		goto out;
	}

	path = get_path (camera, folder, filename);
	r = send_cmd_hdd_file_send(camera, PUT, path, context);
	if(r < 0)
		goto out;

	state = START;
	while(0 < get_tf_packet(camera, &reply, context)) {
		update = (update + 1) % 16;
		switch (get_u32(&reply.cmd)) {
		case SUCCESS:
			switch (state) {
			case START: {
				/* Send start */
				struct typefile *tf = (struct typefile *) packet.data;

				put_u16(&packet.length, PACKET_HEAD_SIZE + 114);
				put_u32(&packet.cmd, DATA_HDD_FILE_START);
				time_to_tfdt(srcStat.st_mtime, &tf->stamp);
				tf->filetype = 2;
				put_u64(&tf->size, srcStat.st_size);
				strncpy((char *) tf->name, path, 94);
				tf->name[94] = '\0';
				tf->unused = 0;
				tf->attrib = 0;
				gp_log (GP_LOG_DEBUG, "topfield", "%s: DATA_HDD_FILE_START\n", __func__);
				r = send_tf_packet(camera, &packet, context);
				if(r < 0)
				{
					gp_log (GP_LOG_ERROR, "topfield", "ERROR: Incomplete send.\n");
					goto out;
				}
				state = DATA;
				break;
			}

			case DATA: {
				int payloadSize = sizeof(packet.data) - 9;
				ssize_t w = read(src, &packet.data[8], payloadSize);

				/* Detect a Topfield protcol bug and prevent the sending of packets
				   that are a multiple of 512 bytes. */
				if((w > 4) && (((((PACKET_HEAD_SIZE + 8 + w) + 1) & ~1) % 0x200) == 0)) {
					lseek(src, -4, SEEK_CUR);
					w -= 4;
					payloadSize -= 4;
				}

				put_u16(&packet.length, PACKET_HEAD_SIZE + 8 + w);
				put_u32(&packet.cmd, DATA_HDD_FILE_DATA);
				put_u64(packet.data, byteCount);
				byteCount += w;

				/* Detect EOF and transition to END */
				if((w < 0) || (byteCount >= fileSize)) {
					state = END;
				}

				if(w > 0) {
					gp_log (GP_LOG_DEBUG, "topfield", "%s: DATA_HDD_FILE_DATA\n", __func__);
					r = send_tf_packet(camera, &packet, context);
					if(r < w) {
						gp_log (GP_LOG_ERROR, "topfield", "ERROR: Incomplete send.\n");
						goto out;
					}
				}

				if(!update && !quiet) {
					progressStats(fileSize, byteCount, startTime);
				}
				break;
			}

			case END:
				/* Send end */
				put_u16(&packet.length, PACKET_HEAD_SIZE);
				put_u32(&packet.cmd, DATA_HDD_FILE_END);
				gp_log (GP_LOG_DEBUG, "topfield", "%s: DATA_HDD_FILE_END\n", __func__);
				r = send_tf_packet(camera, &packet, context);
				if(r < 0) {
					gp_log (GP_LOG_ERROR, "topfield", "ERROR: Incomplete send.\n");
					goto out;
				}
				state = FINISHED;
				break;

			case FINISHED:
				result = 0;
				goto out;
				break;
			}
			break;

		case FAIL:
			gp_log (GP_LOG_ERROR, "topfield", "ERROR: Device reports %s\n", decode_error(&reply));
			goto out;
			break;

		default:
			gp_log (GP_LOG_ERROR, "topfield", "ERROR: Unhandled packet (%d)\n", get_u32(&reply.cmd));
			break;
		}
	}
	finalStats(byteCount, startTime);
out:
	close(src);
	return result;
}
示例#2
0
文件: puppy.c 项目: silid/libpuppy
int do_hdd_file_get(int fd, char *srcPath, char *dstPath)
{
    int result = -EPROTO;
    time_t startTime = time(NULL);
    enum
    {
        START,
        DATA,
        ABORT
    } state;
    int dst = -1;
    int r;
    int update = 0;
    __u64 byteCount = 0;
    struct utimbuf mod_utime_buf = { 0, 0 };

    dst = open64(dstPath, O_WRONLY | O_CREAT | O_TRUNC,
                 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
    if(dst < 0)
    {
        fprintf(stderr, "ERROR: Can not open destination file: %s\n",
                strerror(errno));
        return errno;
    }

    r = send_cmd_hdd_file_send(fd, GET, srcPath);
    if(r < 0)
    {
        goto out;
    }

    state = START;
    while(0 < (r = get_tf_packet(fd, &reply)))
    {
        update = (update + 1) % 16;
        switch (get_u32(&reply.cmd))
        {
            case DATA_HDD_FILE_START:
                if(state == START)
                {
                    struct typefile *tf = (struct typefile *) reply.data;

                    byteCount = get_u64(&tf->size);
                    mod_utime_buf.actime = mod_utime_buf.modtime =
                        tfdt_to_time(&tf->stamp);

                    send_success(fd);
                    state = DATA;
                }
                else
                {
                    fprintf(stderr,
                            "ERROR: Unexpected DATA_HDD_FILE_START packet in state %d\n",
                            state);
                    send_cancel(fd);
                    state = ABORT;
                }
                break;

            case DATA_HDD_FILE_DATA:
                if(state == DATA)
                {
                    __u64 offset = get_u64(reply.data);
                    __u16 dataLen =
                        get_u16(&reply.length) - (PACKET_HEAD_SIZE + 8);
                    ssize_t w;

                    if(!update && !quiet)
                    {
                        progressStats(byteCount, offset + dataLen, startTime);
                    }

                    if(r < get_u16(&reply.length))
                    {
                        fprintf(stderr,
                                "ERROR: Short packet %d instead of %d\n", r,
                                get_u16(&reply.length));
                        /* TODO: Fetch the rest of the packet */
                    }

                    w = write(dst, &reply.data[8], dataLen);
                    if(w < dataLen)
                    {
                        /* Can't write data - abort transfer */
                        fprintf(stderr, "ERROR: Can not write data: %s\n",
                                strerror(errno));
                        send_cancel(fd);
                        state = ABORT;
                    }
                }
                else
                {
                    fprintf(stderr,
                            "ERROR: Unexpected DATA_HDD_FILE_DATA packet in state %d\n",
                            state);
                    send_cancel(fd);
                    state = ABORT;
                }
                break;

            case DATA_HDD_FILE_END:
                send_success(fd);
                result = 0;
                goto out;
                break;

            case FAIL:
                fprintf(stderr, "ERROR: Device reports %s\n",
                        decode_error(&reply));
                send_cancel(fd);
                state = ABORT;
                break;

            case SUCCESS:
                goto out;
                break;

            default:
                fprintf(stderr, "ERROR: Unhandled packet (cmd 0x%x)\n",
                        get_u32(&reply.cmd));
        }
    }
    utime(dstPath, &mod_utime_buf);
    finalStats(byteCount, startTime);

  out:
    close(dst);
    return result;
}
示例#3
0
static int
get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
	       CameraFileType type, CameraFile *file, void *data,
	       GPContext *context)
{
	Camera *camera = data;
	int result = GP_ERROR_IO;
	enum {
		START,
		DATA,
		ABORT
	} state;
	int r, pid = 0, update = 0;
	uint64_t byteCount = 0;
	struct utimbuf mod_utime_buf = { 0, 0 };
	char *path;
	struct tf_packet reply;

	if (type != GP_FILE_TYPE_NORMAL)
		return GP_ERROR_NOT_SUPPORTED;

	do_cmd_turbo (camera, "ON", context);

	path = get_path(camera, folder, filename);
	r = send_cmd_hdd_file_send(camera, GET, path, context);
	free (path);
	if(r < 0)
		goto out;

	state = START;
	while(0 < (r = get_tf_packet(camera, &reply, context)))
	{
		update = (update + 1) % 4;
		switch (get_u32(&reply.cmd)) {
		case DATA_HDD_FILE_START:
			if(state == START) {
				struct typefile *tf = (struct typefile *) reply.data;

				byteCount = get_u64(&tf->size);
				pid = gp_context_progress_start (context, byteCount, _("Downloading %s..."), filename);
				mod_utime_buf.actime = mod_utime_buf.modtime =
				tfdt_to_time(&tf->stamp);

				send_success(camera,context);
				state = DATA;
			} else {
				gp_log (GP_LOG_ERROR, "topfield", "ERROR: Unexpected DATA_HDD_FILE_START packet in state %d\n", state);
				send_cancel(camera,context);
				state = ABORT;
			}
			break;

		case DATA_HDD_FILE_DATA:
			if(state == DATA) {
				uint64_t offset = get_u64(reply.data);
				uint16_t dataLen = get_u16(&reply.length) - (PACKET_HEAD_SIZE + 8);
				int w;

				if (!update) { /* avoid doing it too often */
					gp_context_progress_update (context, pid, offset + dataLen);
					if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL) {
						send_cancel(camera,context);
						state = ABORT;
					}
				}

				if(r < get_u16(&reply.length)) {
					gp_log (GP_LOG_ERROR, "topfield", "ERROR: Short packet %d instead of %d\n", r, get_u16(&reply.length));
					/* TODO: Fetch the rest of the packet */
				}

				w = gp_file_append (file, (char*)&reply.data[8], dataLen);

				if(w < GP_OK) {
					/* Can't write data - abort transfer */
					gp_log (GP_LOG_ERROR, "topfield", "ERROR: Can not write data: %d\n", w);
					send_cancel(camera,context);
					state = ABORT;
				}
			} else {
				gp_log (GP_LOG_ERROR, "topfield", "ERROR: Unexpected DATA_HDD_FILE_DATA packet in state %d\n", state);
				send_cancel(camera,context);
				state = ABORT;
			}
			break;

		case DATA_HDD_FILE_END:
			send_success(camera,context);
			result = GP_OK;
			goto out;
			break;

		case FAIL:
			gp_log (GP_LOG_ERROR, "topfield", "ERROR: Device reports %s\n", decode_error(&reply));
			send_cancel(camera,context);
			state = ABORT;
			break;

		case SUCCESS:
			goto out;
			break;

		default:
			gp_log (GP_LOG_ERROR, "topfield", "ERROR: Unhandled packet (cmd 0x%x)\n", get_u32(&reply.cmd));
			break;
		}
	}
	if (pid) gp_context_progress_stop (context, pid);
out:
	do_cmd_turbo (camera, "OFF", context);
	return result;
}
示例#4
0
文件: puppy.c 项目: silid/libpuppy
int do_hdd_file_put(int fd, char *srcPath, char *dstPath)
{
    int result = -EPROTO;
    time_t startTime = time(NULL);
    enum
    {
        START,
        DATA,
        END,
        FINISHED
    } state;
    int src = -1;
    int r;
    int update = 0;
    struct stat64 srcStat;
    __u64 fileSize;
    __u64 byteCount = 0;

    trace(4, fprintf(stderr, "%s\n", __func__));

    src = open64(srcPath, O_RDONLY);
    if(src < 0)
    {
        fprintf(stderr, "ERROR: Can not open source file: %s\n",
                strerror(errno));
        return errno;
    }

    if(0 != fstat64(src, &srcStat))
    {
        fprintf(stderr, "ERROR: Can not examine source file: %s\n",
                strerror(errno));
        result = errno;
        goto out;
    }

    fileSize = srcStat.st_size;
    if(fileSize == 0)
    {
        fprintf(stderr, "ERROR: Source file is empty - not transfering.\n");
        result = -ENODATA;
        goto out;
    }

    r = send_cmd_hdd_file_send(fd, PUT, dstPath);
    if(r < 0)
    {
        goto out;
    }

    state = START;
    while(0 < get_tf_packet(fd, &reply))
    {
        update = (update + 1) % 16;
        switch (get_u32(&reply.cmd))
        {
            case SUCCESS:
                switch (state)
                {
                    case START:
                    {
                        /* Send start */
                        struct typefile *tf = (struct typefile *) packet.data;

                        put_u16(&packet.length, PACKET_HEAD_SIZE + 114);
                        put_u32(&packet.cmd, DATA_HDD_FILE_START);
                        time_to_tfdt(srcStat.st_mtime, &tf->stamp);
                        tf->filetype = 2;
                        put_u64(&tf->size, srcStat.st_size);
                        strncpy((char *) tf->name, dstPath, 94);
                        tf->name[94] = '\0';
                        tf->unused = 0;
                        tf->attrib = 0;
                        trace(3,
                              fprintf(stderr, "%s: DATA_HDD_FILE_START\n",
                                      __func__));
                        r = send_tf_packet(fd, &packet);
                        if(r < 0)
                        {
                            fprintf(stderr, "ERROR: Incomplete send.\n");
                            goto out;
                        }
                        state = DATA;
                        break;
                    }

                    case DATA:
                    {
                        int payloadSize = sizeof(packet.data) - 9;
                        ssize_t w = read(src, &packet.data[8], payloadSize);

                        /* Detect a Topfield protcol bug and prevent the sending of packets
                           that are a multiple of 512 bytes. */
                        if((w > 4)
                           &&
                           (((((PACKET_HEAD_SIZE + 8 + w) +
                               1) & ~1) % 0x200) == 0))
                        {
                            lseek64(src, -4, SEEK_CUR);
                            w -= 4;
                            payloadSize -= 4;
                        }

                        put_u16(&packet.length, PACKET_HEAD_SIZE + 8 + w);
                        put_u32(&packet.cmd, DATA_HDD_FILE_DATA);
                        put_u64(packet.data, byteCount);
                        byteCount += w;

                        /* Detect EOF and transition to END */
                        if((w < 0) || (byteCount >= fileSize))
                        {
                            state = END;
                        }

                        if(w > 0)
                        {
                            trace(3,
                                  fprintf(stderr, "%s: DATA_HDD_FILE_DATA\n",
                                          __func__));
                            r = send_tf_packet(fd, &packet);
                            if(r < w)
                            {
                                fprintf(stderr, "ERROR: Incomplete send.\n");
                                goto out;
                            }
                        }

                        if(!update && !quiet)
                        {
                            progressStats(fileSize, byteCount, startTime);
                        }
                        break;
                    }

                    case END:
                        /* Send end */
                        put_u16(&packet.length, PACKET_HEAD_SIZE);
                        put_u32(&packet.cmd, DATA_HDD_FILE_END);
                        trace(3,
                              fprintf(stderr, "%s: DATA_HDD_FILE_END\n",
                                      __func__));
                        r = send_tf_packet(fd, &packet);
                        if(r < 0)
                        {
                            fprintf(stderr, "ERROR: Incomplete send.\n");
                            goto out;
                        }
                        state = FINISHED;
                        break;

                    case FINISHED:
                        result = 0;
                        goto out;
                        break;
                }
                break;

            case FAIL:
                fprintf(stderr, "ERROR: Device reports %s\n",
                        decode_error(&reply));
                goto out;
                break;

            default:
                fprintf(stderr, "ERROR: Unhandled packet\n");
                break;
        }
    }
    finalStats(byteCount, startTime);

  out:
    close(src);
    return result;
}