/* vi: set sw=4 ts=4: */
/*
* ftpget
*
* Mini implementation of FTP to retrieve a remote file.
*
* Copyright (C) 2002 Jeff Angielski, The PTR Group <jeff@theptrgroup.com>
* Copyright (C) 2002 Glenn McGrath <bug1@iinet.net.au>
*
* Based on wget.c by Chip Rosenthal Covad Communications
* <chip@laserlink.net>
*
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
//#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <mntent.h>
#include <netdb.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stddef.h>
#include <string.h>
#include <strings.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/statfs.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <termios.h>
#include <time.h>
#include <unistd.h>
#include <utime.h>
#include <getopt.h>
#include <limits.h>
#define FTP_HEAD_SIZE 512
/* We hijack this constant to mean something else */
/* It doesn't hurt because we will remove this bit anyway */
#define DIE_ON_ERROR AI_CANONNAME
#define isdigit(a) ((unsigned)((a) - '0') <= 9)
//#define xatou(rest) xatoull##rest
#define LONE_DASH(s) ((s)[0] == '-' && !(s)[1])
#define NOT_LONE_DASH(s) ((s)[0] != '-' || (s)[1])
#define ENABLE_FEATURE_IPV6 0
#define type long
#define xstrtou(rest) xstrtoul##rest
#define xstrto(rest) xstrtol##rest
#define xatou(rest) xatoul##rest
#define xato(rest) xatol##rest
#define XSTR_UTYPE_MAX ULONG_MAX
#define XSTR_TYPE_MAX LONG_MAX
#define XSTR_TYPE_MIN LONG_MIN
#define XSTR_STRTOU strtoul
#include "ftp_template.c"
#define bb_error_msg_and_die(fmt,args...) { \
printf ("%s( %d): "fmt"\n" , __FILE__,__LINE__, ##args); \
exit(-1); \
}
#define bb_error_msg(fmt,args...) printf ("%s( %d): "fmt , __FILE__,__LINE__, ##args)
typedef signed char smallint;
typedef struct len_and_sockaddr {
socklen_t len;
union {
struct sockaddr sa;
struct sockaddr_in sin;
};
} len_and_sockaddr;
typedef struct ftp_host_info_s {
const char *user;
const char *password;
struct len_and_sockaddr *lsa;
} ftp_host_info_t;
static smallint verbose_flag=1;
static smallint do_continue;
char * safe_strncpy(char *dst, const char *src, size_t size)
{
if (!size) return dst;
dst[--size] = '\0';
return strncpy(dst, src, size);
}
uint16_t xatou16(const char *numstr)
{
return xatoul_range(numstr, 0, 0xffff);
}
void set_nport(len_and_sockaddr *lsa, unsigned port)
{
if (lsa->sa.sa_family == AF_INET)
{
lsa->sin.sin_port = port;
return;
}
/* What? UNIX socket? IPX?? :) */
}
void *xmalloc(int size)
{
void *ptr;
ptr = malloc(size);
if (ptr == NULL && size != 0)
bb_error_msg_and_die("memory exhausted");
return ptr;
}
static len_and_sockaddr* str2sockaddr(
const char *host, int port,
int ai_flags)
{
int rc;
len_and_sockaddr *r = NULL;
struct addrinfo *result = NULL;
const char *org_host = host; /* only for error msg */
const char *cp;
struct addrinfo hint;
/* Ugly parsing of host:addr */
if (ENABLE_FEATURE_IPV6 && host[0] == '[') {
host++;
cp = strchr(host, ']');
if (!cp || cp[1] != ':') /* Malformed: must have [xx]:nn */
bb_error_msg_and_die("bad address '%s'", org_host);
//return r; /* return NULL */
} else {
cp = strrchr(host, ':');
if (ENABLE_FEATURE_IPV6 && cp && strchr(host, ':') != cp) {
/* There is more than one ':' (e.g. "::1") */
cp = NULL; /* it's not a port spec */
}
}
if (cp) {
int sz = cp - host + 1;
host = safe_strncpy(alloca(sz), host, sz);
if (ENABLE_FEATURE_IPV6 && *cp != ':')
cp++; /* skip ']' */
cp++; /* skip ':' */
port = xatou16(cp);
}
memset(&hint, 0 , sizeof(hint));
#if !ENABLE_FEATURE_IPV6
hint.ai_family = AF_INET; /* do not try to find IPv6 */
#else
hint.ai_family = af;
#endif
/* Needed. Or else we will get each address thrice (or more)
* for each possible socket type (tcp,udp,raw...): */
hint.ai_socktype = SOCK_STREAM;
hint.ai_flags = ai_flags & ~DIE_ON_ERROR;
rc = getaddrinfo(host, NULL, &hint, &result);
if (rc || !result) {
bb_error_msg("bad address '%s'", org_host);
if (ai_flags & DIE_ON_ERROR)
exit(-1);
goto ret;
}
r = xmalloc(offsetof(len_and_sockaddr, sa) + result->ai_addrlen);
r->len = result->ai_addrlen;
memcpy(&r->sa, result->ai_addr, result->ai_addrlen);
set_nport(r, htons(port));
ret:
freeaddrinfo(result);
return r;
}
int xsocket(int nDomain, int nType, int nProtocol)
{
int r;
r = socket(nDomain, nType, nProtocol);
if (r < 0) {
/* Hijack vaguely related config option */
bb_error_msg_and_die("socket");
}
return r;
}
void xconnect(int s, const struct sockaddr *s_addr, socklen_t addrlen)
{
if (connect(s, s_addr, addrlen) < 0)
{
close(s);
if (s_addr->sa_family == AF_INET)
bb_error_msg_and_die("%s (%s)",
"cannot connect to remote host",
inet_ntoa(((struct sockaddr_in *)s_addr)->sin_addr));
//bb_error_msg_and_die("cannot connect to remote host");
}
}
int xconnect_stream(const len_and_sockaddr *lsa)
{
int fd = xsocket(lsa->sa.sa_family, SOCK_STREAM, 0);
xconnect(fd, &lsa->sa, lsa->len);
return fd;
}
int xopen(const char *pathname, int flags, int mode)
{
int ret;
ret = open(pathname, flags, mode);
if (ret < 0) {
bb_error_msg_and_die("can't open '%s'", pathname);
}
return ret;
}
ssize_t safe_read(int fd, void *buf, size_t count)
{
ssize_t n;
do {
n = read(fd, buf, count);
} while (n < 0 && errno == EINTR);
return n;
}
ssize_t safe_write(int fd, const void *buf, size_t count)
{
ssize_t n;
do {
n = write(fd, buf, count);
} while (n < 0 && errno == EINTR);
return n;
}
/*
* Write all of the supplied buffer out to a file.
* This does multiple writes as necessary.
* Returns the amount written, or -1 on an error.
*/
ssize_t full_write(int fd, const void *buf, size_t len)
{
ssize_t cc;
ssize_t total;
total = 0;
while (len) {
cc = safe_write(fd, buf, len);
if (cc < 0)
return cc; /* write() returns -1 on failure. */
total += cc;
buf = ((const char *)buf) + cc;
len -= cc;
}
return total;
}
static off_t bb_full_fd_action(int src_fd, int dst_fd, off_t size)
{
int status = -1;
off_t total = 0;
char buffer[BUFSIZ];
if (src_fd < 0)
goto out;
if (!size) {
size = BUFSIZ;
status = 1; /* copy until eof */
}
while (1) {
ssize_t rd;
rd = safe_read(src_fd, buffer, size > BUFSIZ ? BUFSIZ : size);
//printf("-----rd =%d----\n", rd);
if (!rd) { /* eof - all done */
status = 0;
break;
}
if (rd < 0) {
//bb_error_msg(bb_msg_read_error);
break;
}
/* dst_fd == -1 is a fake, else... */
if (dst_fd >= 0) {
ssize_t wr = full_write(dst_fd, buffer, rd);
if (wr < rd) {
//bb_error_msg(bb_msg_write_error);
break;
}
}
total += rd;
if (status < 0) { /* if we aren't copying till EOF... */
size -= rd;
if (!size) {
/* 'size' bytes copied - all done */
status = 0;
break;
}
}
}
out:
return status ? -1 : total;
}
off_t bb_copyfd_size(int fd1, int fd2, off_t size)
{
if (size) {
return bb_full_fd_action(fd1, fd2, size);
}
return 0;
}
off_t bb_copyfd_eof(int fd1, int fd2)
{
return bb_full_fd_action(fd1, fd2, 0);
}
static void ftp_die(const char *msg, const char *remote)
{
/* Guard against garbage from remote server */
const char *cp = remote;
while (*cp >= ' ' && *cp < '\x7f') cp++;
bb_error_msg_and_die("unexpected server response%s%s: %.*s",
msg ? " to " : "", msg ? msg : "",
(int)(cp - remote), remote);
exit(-1);
}
static int ftpcmd(const char *s1, const char *s2, FILE *stream, char *buf)
{
unsigned n;
if (verbose_flag) {
bb_error_msg("cmd %s %s", s1, s2);
}
if (s1) {
if (s2) {
fprintf(stream, "%s %s\r\n", s1, s2);
} else {
fprintf(stream, "%s\r\n", s1);
}
}
do {
char *buf_ptr;
if (fgets(buf, 510, stream) == NULL) {
bb_error_msg_and_die("fgets");
}
buf_pt
compass_dh
- 粉丝: 0
- 资源: 1
最新资源
- 利用JNI来实现android与SO文件的交互中文最新版本
- 用VirtualBox安装Android-x864.0图文教程中文4.8MB最新版本
- 基于Android系统的手机地图应用软件开发中文3.78MB最新版本
- AndroidStudio环境下的jni调用(NDK)的方法中文最新版本
- Vue + UEditor + v-model 实体绑定.zip
- 最新版本ArcGISForAndroidEclipse环境配置中文最新版本
- VS Code 的 Vue 工具 .zip
- AndroidStudio快捷键中文最新版本
- TypeScript 和 Vue 的入门模板,带有详细的 README,描述了如何将两者结合使用 .zip
- The Net Ninja YouTube 频道上的 Vue.js 2 播放列表的课程文件.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈