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

📄 ssh_ftp.c

📁 UNIX环境下命令行FTP/SFTP工具源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		if(id != expected_id) {			ftp_err("ID mismatch (%d != %d)\n", id, expected_id);			return -1;		}		if(type == SSH2_FXP_STATUS) {			int status = buffer_get_int(&msg);			if(status == SSH2_FX_EOF) {				break;			} else {				ftp_err("Couldn't read directory: %s\n", fx2txt(status));				ssh_close(handle, handle_len);				return status;			}		} else if(type != SSH2_FXP_NAME) {			ftp_err("Expected SSH2_FXP_NAME (%d) packet, got %s (%d)\n",					SSH2_FXP_NAME, ssh_reply2txt(type), type);		}		count = buffer_get_int(&msg);		if(count == 0)			break;		for(i = 0; i < count; i++) {			char *filename, *longname;			Attrib *a;			filename = buffer_get_string(&msg, NULL);			longname = buffer_get_string(&msg, NULL);			a = decode_attrib(&msg);			if(dir) {				*dir = xrealloc(*dir, sizeof(**dir) *				    (ents + 2));				(*dir)[ents] = xmalloc(sizeof(***dir));				(*dir)[ents]->filename = xstrdup(filename);				(*dir)[ents]->longname = xstrdup(longname);				memcpy(&(*dir)[ents]->a, a, sizeof(*a));				(*dir)[++ents] = NULL;			}			free(filename);			free(longname);		}	}	buffer_free(&msg);	ssh_close(handle, handle_len);	free(handle);	return 0;}void ssh_free_dirents(SFTP_DIRENT **s){	int i;	for(i = 0; s[i]; i++) {		free(s[i]->filename);		free(s[i]->longname);		free(s[i]);	}	free(s);}int ssh_close(char *handle, u_int handle_len){	u_int id, status;	Buffer msg;	buffer_init(&msg);	id = ftp->ssh_id++;	buffer_put_char(&msg, SSH2_FXP_CLOSE);	buffer_put_int(&msg, id);	buffer_put_string(&msg, handle, handle_len);	if(ssh_cmd(&msg) == -1)		return -1;	status = ssh_get_status(id);	if(status != SSH2_FX_OK)		ftp_err("Couldn't close file: %s\n", fx2txt(status));	buffer_free(&msg);	return status;}Attrib *ssh_get_decode_stat(u_int expected_id){	Buffer msg;	u_int type, id;	Attrib *a;	buffer_init(&msg);	if(ssh_reply(&msg) == -1)		return 0;	type = buffer_get_char(&msg);	id = buffer_get_int(&msg);	if(id != expected_id) {		ftp_err("ID mismatch (%d != %d)\n", id, expected_id);		return 0;	}	if(type == SSH2_FXP_STATUS) {		int status = buffer_get_int(&msg);		ftp_err("Couldn't stat remote file: %s\n", fx2txt(status));		return 0;	} else if (type != SSH2_FXP_ATTRS) {		ftp_err("Expected SSH2_FXP_ATTRS (%d) packet, got %s (%d)\n",				SSH2_FXP_ATTRS, ssh_reply2txt(type), type);		return 0;	}	a = decode_attrib(&msg);	buffer_free(&msg);	return(a);}void ssh_send_string_request(u_int id, u_int code, const char *s, u_int len){	Buffer msg;	buffer_init(&msg);	buffer_put_char(&msg, code);	buffer_put_int(&msg, id);	buffer_put_string(&msg, s, len);	ssh_cmd(&msg);	buffer_free(&msg);}void ssh_send_string_attrs_request(u_int id, u_int code, const char *s,								   u_int len, Attrib *a){	Buffer msg;	buffer_init(&msg);	buffer_put_char(&msg, code);	buffer_put_int(&msg, id);	buffer_put_string(&msg, s, len);	encode_attrib(&msg, a);	ssh_cmd(&msg);	buffer_free(&msg);}u_int ssh_get_status(int expected_id){	Buffer msg;	u_int type, id, status;	buffer_init(&msg);	if(ssh_reply(&msg) == -1)		return -1;	type = buffer_get_char(&msg);	id = buffer_get_int(&msg);	if (id != expected_id) {		ftp_err("ID mismatch (%d != %d)\n", id, expected_id);		return -1;	}	if (type != SSH2_FXP_STATUS) {		ftp_err("Expected SSH2_FXP_STATUS(%d) packet, got %s (%d)\n",				SSH2_FXP_STATUS, ssh_reply2txt(type), type);		return -1;	}	status = buffer_get_int(&msg);	buffer_free(&msg);	ftp->ssh_last_status = status;	return status;}int ssh_recv_binary(const char *remote_path, FILE *local_fp,					ftp_transfer_func hookf, u_int64_t offset){	u_int expected_id, handle_len, mode, type, id;/*	u_int64_t offset;*/	char *handle;	Buffer msg;	Attrib junk, *a;	int status;	time_t then = time(0) - 1;	ftp_set_close_handler();	if(hookf)		hookf(&ftp->ti);	ftp->ti.begin = false;	a = ssh_stat(remote_path);	if(a == 0)		return -1;	/* XXX: should we preserve set[ug]id? */	if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)		mode = S_IWRITE | (a->perm & 0777);	else		mode = 0666;	if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&	    (a->perm & S_IFDIR)) {		ftp_err("Cannot download a directory: %s\n", remote_path);		return -1;	}	buffer_init(&msg);	/* Send open request */	id = ftp->ssh_id++;	buffer_put_char(&msg, SSH2_FXP_OPEN);	buffer_put_int(&msg, id);	buffer_put_cstring(&msg, remote_path);	buffer_put_int(&msg, SSH2_FXF_READ);	attrib_clear(&junk); /* Send empty attributes */	encode_attrib(&msg, &junk);	ssh_cmd(&msg);	handle = ssh_get_handle(id, &handle_len);	if(handle == 0) {		buffer_free(&msg);		return -1;	}	/* Read from remote and write to local *//*	offset = 0;*/	while(true) {		u_int len;		char *data;		id = expected_id = ftp->ssh_id++;		buffer_clear(&msg);		buffer_put_char(&msg, SSH2_FXP_READ);		buffer_put_int(&msg, id);		buffer_put_string(&msg, handle, handle_len);		buffer_put_int64(&msg, offset);		buffer_put_int(&msg, COPY_SIZE);		ssh_cmd(&msg);		buffer_clear(&msg);		ssh_reply(&msg);		type = buffer_get_char(&msg);		id = buffer_get_int(&msg);		if(id != expected_id) {			ftp_err("ID mismatch (%d != %d)\n", id, expected_id);			return -1;		}		if(type == SSH2_FXP_STATUS) {			status = buffer_get_int(&msg);			if (status == SSH2_FX_EOF)				break;			else {				ftp_err("Couldn't read from remote "						"file \"%s\" : %s\n", remote_path,						fx2txt(status));				ssh_close(handle, handle_len);				goto done;			}		} else if (type != SSH2_FXP_DATA) {			ftp_err("Expected SSH2_FXP_DATA(%d) packet, got %s (%d)\n",			    SSH2_FXP_DATA, ssh_reply2txt(type), type);			return -1;		}		data = buffer_get_string(&msg, &len);		if (len > COPY_SIZE) {			ftp_err("Received more data than asked for %d > %d\n",					len, COPY_SIZE);			return -1;		}		if(ftp_sigints() > 0) {			ftp_trace("break due to sigint\n");			break;		}		if(atomicio(write, fileno(local_fp), data, len) != len) {			ftp_err("Couldn't write: %s\n", strerror(errno));			ssh_close(handle, handle_len);			ftp->ti.ioerror = true;			status = -1;			free(data);			goto done;		}		offset += len;		free(data);		ftp->ti.size += len;		if(hookf) {			time_t now = time(0);			if(now > then) {				hookf(&ftp->ti);				then = now;			}		}	}	status = ssh_close(handle, handle_len);	ftp_set_close_handler();done:	buffer_free(&msg);	free(handle);	return status;}int ssh_send_binary(const char *remote_path, FILE *local_fp,					ftp_transfer_func hookf, u_int64_t offset){	u_int handle_len, id;/*	u_int64_t offset;*/	char *handle;	Buffer msg;	Attrib a;	int status;	time_t then = time(0) - 1;	struct stat sb;	ftp_set_close_handler();	if(hookf)		hookf(&ftp->ti);	ftp->ti.begin = false;	if(fstat(fileno(local_fp), &sb) == -1) {		ftp_err("Couldn't fstat local file: %s\n", strerror(errno));		return -1;	}	stat_to_attrib(&sb, &a);	a.flags &= ~SSH2_FILEXFER_ATTR_SIZE;	a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;	a.perm &= 0777;	a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;	buffer_init(&msg);	/* Send open request */	id = ftp->ssh_id++;	buffer_put_char(&msg, SSH2_FXP_OPEN);	buffer_put_int(&msg, id);	buffer_put_cstring(&msg, remote_path);	/* if offset > 0, we are either appending or resuming a previous	 * download, so we should not truncate the file	 */	buffer_put_int(&msg, SSH2_FXF_WRITE | SSH2_FXF_CREAT |						(offset == 0 ? SSH2_FXF_TRUNC : 0));	encode_attrib(&msg, &a);	ssh_cmd(&msg);	buffer_clear(&msg);	handle = ssh_get_handle(id, &handle_len);	if(handle == 0) {		buffer_free(&msg);		return -1;	}	/* Read from local and write to remote */	while(true) {		int len;		char data[COPY_SIZE];		/*		 * Can't use atomicio here because it returns 0 on EOF, thus losing		 * the last block of the file		 */		do			len = read(fileno(local_fp), data, COPY_SIZE);		while((len == -1) && (errno == EINTR || errno == EAGAIN));		if(len == -1) {			ftp_err("Couldn't read from file: %s\n", strerror(errno));			return -1;		}		if(len == 0)			break;		buffer_clear(&msg);		buffer_put_char(&msg, SSH2_FXP_WRITE);		buffer_put_int(&msg, ++id);		buffer_put_string(&msg, handle, handle_len);		buffer_put_int64(&msg, offset);		buffer_put_string(&msg, data, len);		ssh_cmd(&msg);		status = ssh_get_status(id);		if(status != SSH2_FX_OK) {			ftp_err("Couldn't write to remote file \"%s\": %s\n",					remote_path, fx2txt(status));			ssh_close(handle, handle_len);			goto done;		}		offset += len;		ftp->ti.size += len;		if(hookf) {			time_t now = time(0);			if(now > then) {				hookf(&ftp->ti);				then = now;			}		}	}	status = ssh_close(handle, handle_len);done:	free(handle);	buffer_free(&msg);	return status;}char *ssh_readlink(char *path){	Buffer msg;	u_int type, expected_id, count, id;	char *filename, *longname;	Attrib *a;	expected_id = id = ftp->ssh_id++;	ssh_send_string_request(id, SSH2_FXP_READLINK, path, strlen(path));	buffer_init(&msg);	if(ssh_reply(&msg) == -1)		return 0;	type = buffer_get_char(&msg);	id = buffer_get_int(&msg);	if(id != expected_id) {		ftp_err("ID mismatch (%d != %d)", id, expected_id);		return 0;	}	if(type == SSH2_FXP_STATUS) {		u_int status = buffer_get_int(&msg);		ftp_err("Couldn't readlink: %s", fx2txt(status));		return 0;	} else if(type != SSH2_FXP_NAME) {		ftp_err("Expected SSH2_FXP_NAME (%d) packet, got %s (%d)",				SSH2_FXP_NAME, ssh_reply2txt(type), type);		return 0;	}	count = buffer_get_int(&msg);	if(count != 1) {		ftp_err("Got multiple names (%d) from SSH2_FXP_READLINK", count);		return 0;	}	filename = buffer_get_string(&msg, 0);	longname = buffer_get_string(&msg, 0);	a = decode_attrib(&msg);	free(longname);	buffer_free(&msg);	return filename;}

⌨️ 快捷键说明

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