⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 psftp.c

📁 一个支持FTP,SFTP的客户端程序
💻 C
📖 第 1 页 / 共 3 页
字号:
    }

    fp = CreateFileA(localfile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
    if (fp == INVALID_HANDLE_VALUE)
    {
	FzSFtpIpc_Error1("Unable to open %s", localfile);
	sfree(outfname);
	return 0;
    }
    if (restart) {
	sftp_register(req = fxp_open_send(outfname, SSH_FXF_WRITE));
    } else {
	sftp_register(req = fxp_open_send(outfname, SSH_FXF_WRITE |
					  SSH_FXF_CREAT | SSH_FXF_TRUNC));
    }
    rreq = sftp_find_request(pktin = sftp_recv());
    assert(rreq == req);
    fh = fxp_open_recv(pktin, rreq);

    if (!fh) {
	FzSFtpIpc_Error2("%s: %s", outfname, fxp_error());
	sfree(outfname);
	return 0;
    }

    if (restart) {
	LONG high, low;
	char decbuf[30];
	struct fxp_attrs attrs;
	int ret;

	sftp_register(req = fxp_fstat_send(fh));
	rreq = sftp_find_request(pktin = sftp_recv());
	assert(rreq == req);
	ret = fxp_fstat_recv(pktin, rreq, &attrs);

	if (!ret) {
	    CloseHandle(fp);
	    FzSFtpIpc_Error2("Read size of %s: %s", outfname, fxp_error());
	    sfree(outfname);
	    return 0;
	}
	if (!(attrs.flags & SSH_FILEXFER_ATTR_SIZE)) {
	    CloseHandle(fp);
	    FzSFtpIpc_Error1("Read size of %s: Size was not given", outfname);
	    sfree(outfname);
	    return 0;
	}
	offset = attrs.size;
	uint64_decimal(offset, decbuf);
	printf("reput: restarting at file position %s\n", decbuf);
	if (uint64_compare(offset, uint64_make(0, LONG_MAX)) > 0) {
	    CloseHandle(fp);
	    FzSFtpIpc_Error("reput: remote file is larger than we can deal with");
	    sfree(outfname);
	    return 0;
	}
	high = offset.hi;
	low = offset.lo;
	low = SetFilePointer(fp, low, &high, FILE_BEGIN);
	if (low == 0xFFFFFFFF && GetLastError())
	{
	    low = 0;
	    high = 0;
	    low = SetFilePointer(fp, low, &high, FILE_END);
	}
	FzSFtpIpc_Status3("Uploading %s to %s, restarting at file position %s", localfile, file, decbuf);
    } else {
	offset = uint64_make(0, 0);
	FzSFtpIpc_Status2("Uploading %s to %s", localfile, file);
    }

    /*
     * FIXME: we can use FXP_FSTAT here to get the file size, and
     * thus put up a progress bar.
     */
    ret = 1;
    xfer = xfer_upload_init(fh, offset);
    err = eof = 0;
    while ((!err && !eof) || !xfer_done(xfer)) {
	char buffer[4096 * 2];
	int len;
	while (xfer_upload_ready(xfer) && !err && !eof) {
	    BOOL res = ReadFile(fp, buffer, sizeof(buffer), &len, 0);
	    if (!res)
	    {
		FzSFtpIpc_Error("Error while reading local file");
		err = 1;
	    }
	    else if (len == 0)
	    {
		eof = 1;
	    }
	    else
	    {
		xfer_upload_data(xfer, buffer, len);
		FzSFtpIpc_SendRequest(SFTP_DATAID_CTS_TRANSFERSTATUS, 4, &len);
	    }
	}

	if (!xfer_done(xfer))
	{
	    pktin = sftp_recv();
	    ret = xfer_upload_gotpkt(xfer, pktin);

	    if (!ret) {
	        FzSFtpIpc_Error1("Error while writing: %s", fxp_error());
	        err = 1;
	    }
	}
    }

    xfer_cleanup(xfer);

    sftp_register(req = fxp_close_send(fh));
    rreq = sftp_find_request(pktin = sftp_recv());
    assert(rreq == req);
    fxp_close_recv(pktin, rreq);

    CloseHandle(fp);
    sfree(outfname);

    if (ret>0)
	FzSFtpIpc_SendRequest(SFTP_DATAID_CTS_PUT, 0, 0);

    return ret;
}

int sftp_cmd_mkdir(char *cmd)
{
    char *dir;
    struct sftp_packet *pktin;
    struct sftp_request *req, *rreq;
    int result;

    if (back == NULL) {
	FzSFtpIpc_Error("Not connected to a host");
	return 0;
    }

    dir = canonify(cmd);
    if (!dir) {
	FzSFtpIpc_Error2("%s: %s", dir, fxp_error());
	return 0;
    }

    sftp_register(req = fxp_mkdir_send(dir));
    rreq = sftp_find_request(pktin = sftp_recv());
    assert(rreq == req);
    result = fxp_mkdir_recv(pktin, rreq);

    if (!result) {
	FzSFtpIpc_Error2("mkdir %s: %s", dir, fxp_error());
	sfree(dir);
	return 0;
    }

    {
	char msg[]="Directory created successfully";
	FzSFtpIpc_SendRequest(SFTP_DATAID_CTS_MKD, strlen(msg)+1, msg);
    }

    sfree(dir);
    return 1;
}

int sftp_cmd_rmdir(char *cmd)
{
    char *dir;
    struct sftp_packet *pktin;
    struct sftp_request *req, *rreq;
    int result;

    if (back == NULL) {
	FzSFtpIpc_Error("Not connected to a host");
	return 0;
    }

    dir = canonify(cmd);
    if (!dir) {
	FzSFtpIpc_Error2("%s: %s", cmd, fxp_error());
	return 0;
    }

    sftp_register(req = fxp_rmdir_send(dir));
    rreq = sftp_find_request(pktin = sftp_recv());
    assert(rreq == req);
    result = fxp_rmdir_recv(pktin, rreq);

    if (!result) {
	FzSFtpIpc_Error2("rmdir %s: %s", dir, fxp_error());
	sfree(dir);
	return 0;
    }

    {
	char msg[]="Directory removed successfully";
	FzSFtpIpc_SendRequest(SFTP_DATAID_CTS_RMD, strlen(msg)+1, msg);
    }

    sfree(dir);
    return 1;
}

int sftp_cmd_rm(char *cmd)
{
    char *fname;
    struct sftp_packet *pktin;
    struct sftp_request *req, *rreq;
    int result;

    if (back == NULL) {
	FzSFtpIpc_Error("Not connected to a host");
	return 0;
    }

    fname = canonify(cmd);
    if (!fname) {
	FzSFtpIpc_Error2("%s: %s", cmd, fxp_error());
	return 0;
    }

    sftp_register(req = fxp_remove_send(fname));
    rreq = sftp_find_request(pktin = sftp_recv());
    assert(rreq == req);
    result = fxp_remove_recv(pktin, rreq);

    if (!result) {
	FzSFtpIpc_Error2("rm %s: %s", fname, fxp_error());
	sfree(fname);
	return 0;
    }

    sfree(fname);

    {
	char msg[]="File deleted successfully";
	FzSFtpIpc_SendRequest(SFTP_DATAID_CTS_DELE, strlen(msg)+1, msg);
    }

    return 1;
}

int sftp_cmd_mv(char *src, char *dst)
{
    char *srcfname, *dstfname;
    struct sftp_packet *pktin;
    struct sftp_request *req, *rreq;
    int result;

    if (back == NULL) {
	FzSFtpIpc_Error("Not connected to a host");
	return 0;
    }

    srcfname = canonify(src);
    if (!srcfname) {
	FzSFtpIpc_Error2("%s: %s", src, fxp_error());
	return 0;
    }

    dstfname = canonify(dst);
    if (!dstfname) {
	FzSFtpIpc_Error2("%s: %s", dst, fxp_error());
	return 0;
    }

    sftp_register(req = fxp_rename_send(srcfname, dstfname));
    rreq = sftp_find_request(pktin = sftp_recv());
    assert(rreq == req);
    result = fxp_rename_recv(pktin, rreq);

    if (!result) {
	char const *error = fxp_error();
	struct fxp_attrs attrs;

	/*
	 * The move might have failed because dstfname pointed at a
	 * directory. We check this possibility now: if dstfname
	 * _is_ a directory, we re-attempt the move by appending
	 * the basename of srcfname to dstfname.
	 */
	sftp_register(req = fxp_stat_send(dstfname));
	rreq = sftp_find_request(pktin = sftp_recv());
	assert(rreq == req);
	result = fxp_stat_recv(pktin, rreq, &attrs);

	if (result &&
	    (attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS) &&
	    (attrs.permissions & 0040000)) {
	    char *p;
	    char *newname, *newcanon;
	    printf("(destination %s is a directory)\n", dstfname);
	    p = srcfname + strlen(srcfname);
	    while (p > srcfname && p[-1] != '/') p--;
	    newname = dupcat(dstfname, "/", p, NULL);
	    newcanon = canonify(newname);
	    sfree(newname);
	    if (newcanon) {
		sfree(dstfname);
		dstfname = newcanon;

		sftp_register(req = fxp_rename_send(srcfname, dstfname));
		rreq = sftp_find_request(pktin = sftp_recv());
		assert(rreq == req);
		result = fxp_rename_recv(pktin, rreq);

		error = result ? NULL : fxp_error();
	    }
	}
	if (error) {
	    FzSFtpIpc_Error3("Move/Rename %s %s: %s", srcfname, dstfname, error);
	    sfree(srcfname);
	    sfree(dstfname);
	    return 0;
	}
    }
    {
        char str[]="File moved / renamed successfully";
        FzSFtpIpc_SendRequest(SFTP_DATAID_CTS_RENAME, strlen(str)+1, str);
    }

    sfree(srcfname);
    sfree(dstfname);
    return 1;
}

int sftp_cmd_chmod(char *value, char *filename)
{
    char *fname, *mode;
    int result;
    struct fxp_attrs attrs;
    unsigned attrs_clr, attrs_xor, oldperms, newperms;
    struct sftp_packet *pktin;
    struct sftp_request *req, *rreq;

    if (back == NULL) {
	FzSFtpIpc_Error("Not connected to a host");
	return 0;
    }

    /*
     * Attempt to parse the mode specifier in cmd->words[1]. We
     * don't support the full horror of Unix chmod; instead we
     * support a much simpler syntax in which the user can either
     * specify an octal number, or a comma-separated sequence of
     * [ugoa]*[-+=][rwxst]+. (The initial [ugoa] sequence may
     * _only_ be omitted if the only attribute mentioned is t,
     * since all others require a user/group/other specification.
     * Additionally, the s attribute may not be specified for any
     * [ugoa] specifications other than exactly u or exactly g.
     */
    attrs_clr = attrs_xor = 0;
    mode = value;
    if (mode[0] >= '0' && mode[0] <= '9') {
	if (mode[strspn(mode, "01234567")]) {
	    FzSFtpIpc_Error("chmod: numeric file modes should contain digits 0-7 only");
	    return 0;
	}
	attrs_clr = 07777;
	sscanf(mode, "%o", &attrs_xor);
	attrs_xor &= attrs_clr;
    } else {
	while (*mode) {
	    char *modebegin = mode;
	    unsigned subset, perms;
	    int action;

	    subset = 0;
	    while (*mode && *mode != ',' &&
		   *mode != '+' && *mode != '-' && *mode != '=') {
		switch (*mode) {
		  case 'u': subset |= 04700; break; /* setuid, user perms */
		  case 'g': subset |= 02070; break; /* setgid, group perms */
		  case 'o': subset |= 00007; break; /* just other perms */
		  case 'a': subset |= 06777; break; /* all of the above */
		  default:
		    FzSFtpIpc_Error3("chmod: file mode '%.*s' contains unrecognised user/group/other specifier '%c'",
				      strcspn(modebegin, ","), modebegin, *mode);
			return 0;
		}
		mode++;
	    }
	    if (!*mode || *mode == ',') {
		FzSFtpIpc_Error2("chmod: file mode '%.*s' is incomplete",
		       strcspn(modebegin, ","), modebegin);
		return 0;
	    }
	    action = *mode++;
	    if (!*mode || *mode == ',') {
		printf("chmod: file mode '%.*s' is incomplete\n",
		       strcspn(modebegin, ","), modebegin);
		return 0;
	    }
	    perms = 0;
	    while (*mode && *mode != ',') {
		switch (*mode) {
		  case 'r': perms |= 00444; break;
		  case 'w': perms |= 00222; break;
		  case 'x': perms |= 00111; break;
		  case 't': perms |= 01000; subset |= 01000; break;
		  case 's':
		    if ((subset & 06777) != 04700 &&
			(subset & 06777) != 02070) {
			FzSFtpIpc_Error2("chmod: file mode '%.*s': set[ug]id bit should"
					 " be used with exactly one of u or g only",
					 strcspn(modebegin, ","), modebegin);
			return 0;
		    }
		    perms |= 06000;
		    break;
		  default:
		    FzSFtpIpc_Error3("chmod: file mode '%.*s' contains unrecognised"
				     " permission specifier '%c'",
				     strcspn(modebegin, ","), modebegin, *mode);
		    return 0;
		}
		mode++;
	    }
	    if (!(subset & 06777) && (perms &~ subset)) {
		FzSFtpIpc_Error2("chmod: file mode '%.*s' contains no user/group/other"
				 " specifier and permissions other than 't'",
				 strcspn(modebegin, ","), modebegin);
		return 0;
	    }
	    perms &= subset;
	    switch (action) {
	      case '+':
		attrs_clr |= perms;
		attrs_xor |= perms;
		break;
	      case '-':
		attrs_clr |= perms;
		attrs_xor &= ~perms;
		break;
	      case '=':
		attrs_clr |= subset;
		attrs_xor |= perms;
		break;
	    }
	    if (*mode) mode++;	       /* eat comma */
	}
    }

    fname = canonify(filename);
    if (!fname) {
	FzSFtpIpc_Error2("%s: %s", filename, fxp_error());
	return 0;
    }

    sftp_register(req = fxp_stat_send(fname));
    rreq = sftp_find_request(pktin = sftp_recv());
    assert(rreq == req);
    result = fxp_stat_recv(pktin, rreq, &attrs);

    if (!result || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS)) {
	FzSFtpIpc_Error2("get attrs for %s: %s\n", fname,
			 result ? "file permissions not provided" : fxp_error());
	sfree(fname);
	return 0;
    }

    attrs.flags = SSH_FILEXFER_ATTR_PERMISSIONS;   /* perms _only_ */
    oldperms = attrs.permissions & 07777;
    attrs.permissions &= ~attrs_clr;
    attrs.permissions ^= attrs_xor;
    newperms = attrs.permissions & 07777;

    sftp_register(req = fxp_setstat_send(fname, attrs));
    rreq = sftp_find_request(pktin = sftp_recv());
    assert(rreq == req);
    result = fxp_setstat_recv(pktin, rreq);

    if (!result) {
	FzSFtpIpc_Error2("set attrs for %s: %s", fname, fxp_error());
	sfree(fname);
	return 0;
    }

    {
	char str[]="chmod successful";
	FzSFtpIpc_SendRequest(SFTP_DATAID_CTS_CHMOD, strlen(str)+1, str);
    }

    sfree(fname);
    return 1;
}

void do_sftp_cleanup()
{
	char ch;
	if (back) {
		back->special(backhandle, TS_EOF);
		sftp_recvdata(&ch,	1);
		back->free(backhandle);
		sftp_cleanup_request();
	}
	if (pwd) {
		sfree(pwd);
		pwd = NULL;
	}
	if (homedir) {
		sfree(homedir);
		homedir = NULL;
	}
}

static int do_sftp_init(void)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -