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

📄 ftpsend.c

📁 UNIX环境下命令行FTP/SFTP工具源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	if(!ftp->ti.remote_name)		ftp->ti.remote_name = xstrdup("remote");}int ftp_list(const char *cmd, const char *param, FILE *fp){	if(!cmd || !fp || !ftp_connected())		return -1;	if(ftp->ssh_pid)		return ssh_list(cmd, param, fp);	reset_transfer_info();	foo_hookf = 0;#if 0 /* don't care about transfer type, binary should work well... */	ftp_type(tmAscii);#endif	if(ftp_init_transfer() != 0)		return -1;	ftp_set_tmp_verbosity(vbNone);	if(param)		ftp_cmd("%s %s", cmd, param);	else		ftp_cmd("%s", cmd);	if(ftp->code != ctPrelim)		return -1;	if(sock_accept(ftp->data, "r", ftp_is_passive()) != 0) {		perror("accept()");		return -1;	}	if(FILE_recv_ascii(ftp->data->sin, fp) != 0)		return -1;	sock_destroy(ftp->data);	ftp_read_reply();	ftp->data = 0;	return ftp->code == ctComplete ? 0 : -1;}void transfer_finished(void){	ftp->ti.finished = true;	if(foo_hookf)		foo_hookf(&ftp->ti);}static int ftp_init_receive(const char *path, transfer_mode_t mode,							ftp_transfer_func hookf){	long rp = ftp->restart_offset;	char *e;	ftp->restart_offset = 0L;	foo_hookf = hookf;	reset_transfer_info();	if(ftp_init_transfer() != 0)		return -1;	ftp_type(mode);	if(rp > 0) {		/* fp is assumed to be fseek'd already */		ftp_cmd("REST %ld", rp);		if(ftp->code != ctContinue)			return -1;		ftp->ti.size = rp;		ftp->ti.restart_size = rp;	}	ftp_cmd("RETR %s", path);	if(ftp->code != ctPrelim)		return -1;	if(sock_accept(ftp->data, "r", ftp_is_passive()) != 0) {		ftp_err(_("data connection not accepted\n"));		return -1;	}	/* try to get the total file size */	{		/* see if we have cached this directory/file */		rfile *f = ftp_cache_get_file(path);		if(f)			ftp->ti.total_size = f->size;		else {			/* try to figure out file size from RETR reply			 * Opening BINARY mode data connection for foo.mp3 (14429793 bytes)			 *                                                  ^^^^^^^^ aha!			 *			 * note: this might not be the _total_ filesize if we are RESTarting			 */			e = strstr(ftp->reply, " bytes");			if(e != 0) {				while((e > ftp->reply) && isdigit((int)e[-1]))					e--;				ftp->ti.total_size = strtoul(e,NULL,10);			} /* else we don't bother */		}	}	return 0;}static int ftp_do_receive(FILE *fp,						  transfer_mode_t mode, ftp_transfer_func hookf){	int r;	if(mode == tmBinary)		r = FILE_recv_binary(ftp->data->sin, fp);	else		r = FILE_recv_ascii(ftp->data->sin, fp);	sock_destroy(ftp->data);	ftp->data = 0;	if(r == 0) {		transfer_finished();		ftp_read_reply();		ftp->ti.ioerror = (ftp->code != ctComplete);		if(ftp->code != ctComplete) {			ftp_trace("transfer failed\n");			return -1;		}	} else		transfer_finished();	return (r == 0 && !ftp->ti.ioerror && !ftp->ti.interrupted) ? 0 : -1;}int ftp_receive(const char *path, FILE *fp,				transfer_mode_t mode, ftp_transfer_func hookf){	if(ftp->ssh_pid)		return ssh_do_receive(path, fp, mode, hookf);	if(ftp_init_receive(path, mode, hookf) != 0)		return -1;	return ftp_do_receive(fp, mode, hookf);}static int ftp_send(const char *path, FILE *fp, putmode_t how,					transfer_mode_t mode, ftp_transfer_func hookf){	int r;	long rp = ftp->restart_offset;	ftp->restart_offset = 0L;	if(how == putUnique && !ftp->has_stou_command)		return -1;	reset_transfer_info();	ftp->ti.transfer_is_put = true;	if(ftp_init_transfer() != 0)		return -1;	ftp_type(mode);	if(rp > 0) {		/* fp is assumed to be fseek'd already */		ftp_cmd("REST %ld", rp);		if(ftp->code != ctContinue)			return -1;		ftp->ti.size = rp;		ftp->ti.restart_size = rp;	}	ftp_set_tmp_verbosity(vbError);	switch(how) {	  case putUnique:		ftp_cmd("STOU %s", path);		if(ftp->fullcode == 502)			ftp->has_stou_command = false;		break;	  case putAppend:		ftp_cmd("APPE %s", path);		break;	  case putNormal:	  default:		ftp_cmd("STOR %s", path);		break;	}	if(ftp->code != ctPrelim)		return -1;	if(how == putUnique) {		/* try to figure out remote filename */		char *e = strstr(ftp->reply, " for ");		if(e) {			int l;			e += 5;			l = strlen(e);			if(l) {				free(ftp->ti.local_name);				if(*e == '\'')					ftp->ti.local_name = xstrndup(e+1, l-3);				else					ftp->ti.local_name = xstrndup(e, l-1);				ftp_trace("parsed unique filename as '%s'\n",						  ftp->ti.local_name);			}		}	}	if(sock_accept(ftp->data, "w", ftp_is_passive()) != 0) {		ftp_err(_("data connection not accepted\n"));		return -1;	}	ftp_cache_flush_mark_for(path);	if(mode == tmBinary)		r = FILE_send_binary(fp, ftp->data->sin);	else		r = FILE_send_ascii(fp, ftp->data->sin);	sock_flush(ftp->data);	sock_destroy(ftp->data);	ftp->data = 0;	if(r == 0) {		transfer_finished();		ftp_read_reply();		ftp->ti.ioerror = (ftp->code != ctComplete);		if(ftp->code != ctComplete) {			ftp_trace("transfer failed\n");			return -1;		}	} else		transfer_finished();	return 0;}/* transfers SRCFILE on SRCFTP to DESTFILE on DESTFTP * using pasv mode on SRCFTP and port mode on DESTFTP * */int ftp_fxpfile(Ftp *srcftp, const char *srcfile,				Ftp *destftp, const char *destfile,				fxpmode_t how, transfer_mode_t mode){	int r;	unsigned int old_reply_timeout;	Ftp *thisftp;	unsigned char addr[6];/*	printf("FxP: %s -> %s\n", srcftp->url->hostname, destftp->url->hostname);*/	if(srcftp == destftp) {		ftp_err(_("FxP between same hosts\n"));		return -1;	}	if(ftp->ssh_pid) {		ftp_err("FxP with SSH not implemented\n");		return -1;	}	thisftp = ftp; /* save currently active connection */	/* setup source side */	ftp_use(srcftp);	ftp_type(mode);	if(ftp_pasv(addr) != 0) {		ftp_use(thisftp);		return -1;	}	ftp->ti.total_size = -1;	/* setup destination side */	ftp_use(destftp);	ftp_type(mode);	ftp_cmd("PORT %d,%d,%d,%d,%d,%d",			addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);	if(ftp->code != ctComplete) {		ftp_use(thisftp);		return -1;	}	ftp->ti.total_size = -1;	ftp_use(destftp);	if(how == fxpResume) {		rfile *f;		f = ftp_get_file(destfile);		if(f && f->size != (unsigned long long)-1)			ftp->restart_offset = f->size;		else {			ftp->restart_offset = ftp_filesize(destfile);			if(ftp->restart_offset == (unsigned long long)-1) {				ftp_err(_("unable to get remote filesize of '%s',"						  " unable to resume\n"),						destfile);				ftp->restart_offset = 0L;			}		}	} else		ftp->restart_offset = 0L;	if(ftp->restart_offset) {		/* RESTart on destftp */		ftp_cmd("REST %ld", ftp->restart_offset);		if(ftp->code != ctContinue)			return -1;		ftp_use(srcftp);		ftp_cmd("REST %ld", ftp->restart_offset);		if(ftp->code != ctContinue)			return -1;	}	/* issue a STOR command on DESTFTP */	ftp_use(destftp);	switch(how) {	case fxpUnique:		if(ftp->has_stou_command) {			ftp_cmd("STOU %s", destfile);			if(ftp->fullcode == 502)				ftp->has_stou_command = false;		} else {			ftp->code = ctError;			ftp->fullcode = 502;		}		break;	case fxpAppend:		ftp_cmd("APPE %s", destfile);		break;	case fxpNormal:	default:		ftp_cmd("STOR %s", destfile);		break;	}	ftp_cache_flush_mark_for(destfile);	if(ftp->code != ctPrelim) {		ftp_use(thisftp);		return -1;	}	/* issue a RETR command on SRCFTP */	ftp_use(srcftp);	ftp_cmd("RETR %s", srcfile);	if(ftp->code != ctPrelim) {		ftp_use(destftp);		ftp_abort(0);		ftp_use(thisftp);		return -1;	}	ftp_use(destftp);	old_reply_timeout = ftp->reply_timeout;	ftp_reply_timeout(0);	ftp_read_reply();	ftp_reply_timeout(old_reply_timeout);	r = (ftp->code == ctComplete ? 0 : -1);	ftp_use(srcftp);	old_reply_timeout = ftp->reply_timeout;	ftp_reply_timeout(0);	ftp_read_reply();	ftp_reply_timeout(old_reply_timeout);	ftp_use(thisftp);	return r;}int ftp_getfile(const char *infile, const char *outfile, getmode_t how,				transfer_mode_t mode, ftp_transfer_func hookf){	FILE *fp;	int r;	struct stat statbuf;	long rp = 0;	int (*close_func)(FILE *fp);	if(stat(outfile, &statbuf) == 0) {		if(S_ISDIR(statbuf.st_mode)) {			ftp_err(_("%s: is a directory\n"), outfile);			return -1;		}		if(!(statbuf.st_mode & S_IWRITE)) {			ftp_err(_("%s: permission denied\n"), outfile);			return -1;		}		if(how == getResume)			ftp->restart_offset = statbuf.st_size;	} else		ftp->restart_offset = 0L;	ftp->ti.total_size = -1;	/* we need to save this, because ftp_init_receive() sets it to zero */	rp = ftp->restart_offset;	reset_transfer_info();	if(ftp->ssh_pid) {		/* we need to stat the remote file, so we are sure we can read it		 * this needs to be done before we call ssh_do_receive, because by		 * then, the file is created, and would leave a zero-size file opon		 * failure		 */		Attrib *a = ssh_stat(infile);		if(a == 0) {			ftp_err(_("Unable to stat file '%s'\n"), infile);			return -1;		}		/* FIXME: how can we check if it will be possible to transfer		 * the specified file?		 */	} else if(ftp_init_receive(infile, mode, hookf) != 0)		return -1;	if(how == getPipe) {		fp = popen(outfile, "w");		close_func = pclose;	} else {		fp = fopen(outfile,				   (rp > 0L || (how == getAppend)) ? "a" : "w");		close_func = fclose;	}	if(!fp) {		ftp_err("%s: %s\n", outfile, strerror(errno));		ftp->restart_offset = 0L;		return -1;	}	if(rp > 0L) {		if(fseeko(fp, rp, SEEK_SET) != 0) {			ftp_err(_("%s: %s, transfer cancelled\n"),					outfile, strerror(errno));			close_func(fp);			ftp->restart_offset = 0L;			return -1;		}	}	free(ftp->ti.remote_name);	free(ftp->ti.local_name);	ftp->ti.remote_name = xstrdup(infile);	ftp->ti.local_name = xstrdup(outfile);	foo_hookf = hookf;	if(ftp->ssh_pid)		r = ssh_do_receive(infile, fp, mode, hookf);	else		r = ftp_do_receive(fp, mode, hookf);	close_func(fp);	return r;}int ftp_putfile(const char *infile, const char *outfile, putmode_t how,				transfer_mode_t mode, ftp_transfer_func hookf){	FILE *fp;	int r;	struct stat statbuf;	if(stat(infile, &statbuf) != 0) {		perror(infile);		return -1;	}	if(S_ISDIR(statbuf.st_mode)) {		ftp_err(_("%s: is a directory\n"), infile);		return -1;	}	fp = fopen(infile, "r");	if(fp == 0) {		perror(infile);		return -1;	}	ftp->ti.total_size = statbuf.st_size;	free(ftp->ti.remote_name);	free(ftp->ti.local_name);	ftp->ti.remote_name = xstrdup(infile); /* actually local file, or _target_ */	ftp->ti.local_name = xstrdup(outfile); /* actually remote file, or _source_ */	if(how == putResume) {		rfile *f;		f = ftp_get_file(outfile);		if(f && f->size != (unsigned long long)-1)			ftp->restart_offset = f->size;		else {			ftp->restart_offset = ftp_filesize(outfile);			if(ftp->restart_offset == (unsigned long long)-1) {				ftp_err(_("unable to get remote filesize of '%s',"						  " unable to resume\n"),						outfile);				ftp->restart_offset = 0L;			}		}	} else		ftp->restart_offset = 0L;	if(ftp->restart_offset > 0L) {		if(fseeko(fp, ftp->restart_offset, SEEK_SET) != 0) {			ftp_err(_("%s: %s, transfer cancelled\n"),					outfile, strerror(errno));			fclose(fp);			return -1;		}	}	foo_hookf = hookf;	if(ftp->ssh_pid)		r = ssh_send(outfile, fp, how, mode, hookf);	else		r = ftp_send(outfile, fp, how, mode, hookf);	fclose(fp);	return r;}

⌨️ 快捷键说明

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