#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include <netdb.h> //gethostbyname
#include <stdlib.h> //malloc
#include <stdarg.h> //va_list
//数据段的结构
struct bindex{
unsigned long start;
unsigned long end;
};
pthread_t g_tid[10]; //工作线程的tid,最多10个
struct bindex g_tsk[10]; //工作线程的任务起点和终点
//工作线程传入结构
struct antsdata{
char* serverip;
char* user;
char* pass;
char* enfile;
int port;
unsigned long *spos;
unsigned long *epos;
};
//统一的消息输出
void logmsg(char* fmt,...)
{
va_list args;
va_start(args,fmt);
vprintf(fmt, args);
va_end(args);
}
//ftp://user:pass@111.111.111.111:21/file/files.c
//返回1正确,返回0错误
int islegalurl(char *url)
{
char h[7];
memcpy(h,url,6);
h[6]=0;
return strcmp("ftp://",h)==0?1:0;
}
//域名解析函数,把例如www.xxx.com翻译成ip地址
//如果输入的是IP地址,返回同样的地址。
//返回1成功,返回0失败
//server 服务器名
//sip 存放ip地址的空间
//buflen sip空间长度
//本函数用到头文件为netdb.h
int getserverip(char *server,char *sip,int buflen)
{
struct hostent *host;
if((host=gethostbyname(server))==NULL) {
logmsg("==>获取ip地址失败,可能是查询DNS的问题。\n");
return 0;
} else {
if(NULL != inet_ntop(AF_INET,(void*)(host->h_addr),sip,buflen)) {
logmsg("==>获取ip地址成功。\n");
return 1;
}else{
logmsg("==>获取ip地址失败,可能是地址缓冲不够的问题。\n");
return 0;
}
}
}
//通过url提取用户名和口令信息
//返回1成功,0失败
int getuserandpassbyurl(char *url,char *user,int ulen,char *pass,int plen)
{
//寻找@,如果有则服务器从@后开始,到/结束
//如果没有,则从ftp://开始
char *p=url;
while(*p!='@' && *p!=0) p++;
if(*p=='@'){
char *e=p-1;
char *p=e;
while(*p!='/' && p>url) p--;
if(p==url) {
logmsg("找到@,但没找到前面的/,错误。\n");
return 0; //没找到前面的斜杠
}else {
char *s=p+1;
assert(e>s);
int len=e-s+1;
//search ':'
while(*p!=':' && p<e) p++;
if(p==e) {
logmsg("没找到分割用户和密码的冒号,错误。\n");
return 0; //无冒号分割
}
if(ulen < p-s+1) {
logmsg("用户名的空间不够,错误。\n");
return 0;
}
memcpy(user,s,p-s);
user[p-s]=0;
if(plen < e-p+1) {
logmsg("口令空间不够,错误。\n");
return 0;
}
memcpy(pass,p+1,e-p);
pass[e-p]=0;
return 1;
}
}else{
if(ulen < 11 || plen < 8 ) {
logmsg("用户名或口令空间不够,错误。\n");
return 0;
}
strcpy(user,"anonymous");
strcpy(pass,"miniftp");
return 1;
}
}
int getserverandportbyurl(char *url,char *server,int *port,int buflen /*server长度*/)
{
//寻找@,如果有则服务器从@后开始,到/结束
//如果没有,则从ftp://开始
char *p=url;
while(*p!='@' && *p!=0) p++;
if(*p=='@')
{
char *s=p+1;
while(*p!='/' && *p!=0) p++;
if(*p=='/')
{
int len=p-s; //包含端口在内的长度
//检查是否包含了端口在内
char *ck=p-1;
while(*ck!=':' && ck >s ) ck--;
if(ck==s) {//无端口
if(buflen < len+1) return 0;
memcpy(server,s,len);
server[len]=0;
*port=21;
return 1;
}else {
//有端口
int slen=ck-s;
int plen=len-slen-1;
if(buflen < slen) return 0;
memcpy(server,s,slen);
server[slen]=0;
char prt[8];
memcpy(prt,ck+1,plen);
prt[plen]=0;
*port=atoi(prt);
return 1;
}
}
else
{
return 0;
}
}
else //到了结尾没有@
{
p=url;
while(*p!='/' && *p!=0) p++;
p++;
while(*p!='/' && *p!=0) p++;
p++;
char *s=p;
while(*p!='/' && *p!=0) p++;
printf("3\n");
if(*p=='/') {
int len=p-s; //包含端口在内的长度
//检查是否包含了端口在内
char *ck=p-1;
while(*ck!=':' && ck >s ) ck--;
if(ck==s) {//无端口
if(buflen < len+1) return 0;
memcpy(server,s,len);
server[len]=0;
*port=21;
return 1;
}else {
//有端口
int slen=ck-s;
int plen=len-slen-1;
if(buflen < slen) return 0;
memcpy(server,s,slen);
server[slen]=0;
char prt[8];
memcpy(prt,ck+1,plen);
prt[plen]=0;
*port=atoi(prt);
return 1;
}
}else{
return 0;
}
}
}
//从url中获得文件段的数据
//不检查是否为目录,也不进行编码
int getfilebyurl(char* url,char *fn,int buflen)
{
//ftp://dfasdfas.com/dfad/dfs
//找第三个'/'
char *p=url;
while(*p!='/' && *p!=0) p++;
if(*p==0) {
logmsg("url格式不对\n");
return 0;
}
p++;
while(*p!='/' && *p!=0) p++;
if(*p==0) {
logmsg("url格式不对\n");
return 0;
}
p++;
while(*p!='/' && *p!=0) p++;
if(*p==0) {
logmsg("url格式不对\n");
return 0;
}
if(buflen< strlen(url)-(p-url)) {
logmsg("文件名空间不够。\n");
return 0;
}
memcpy(fn,p,strlen