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

📄 ftp-retr.c

📁 linux下的网络下载工具prozilla的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	    connection->status = REMOTEFATAL;	    return err;	}    } else    {	/*	 * Ok..since PASV is not to be used... 	 */	passive_mode = FALSE;    }    if (passive_mode == FALSE)	/*				 * try to use PORT instead 				 */    {	err = ftp_get_listen_socket(connection->control_sock,				    &(connection->listen_sock));	if (err != FTPOK)	{	    message("listen failed");	    close(connection->control_sock);	    connection->status = REMOTEFATAL;	    return err;	}    }    /*     * do we need to start from a different position? If so      * * does the server support REST      */    if (connection->remote_startpos > 0	&& connection->u.resume_support == TRUE)    {	err =	    ftp_rest(connection->control_sock,		     connection->remote_startpos);	if (err != FTPOK)	{	    message("REST failed");	    close(connection->control_sock);	    connection->status = REMOTEFATAL;	    return err;	}	message("REST ok");    }    err = ftp_retr(connection->control_sock, connection->u.file);    if (err != FTPOK)    {	message("RETR failed");	close(connection->control_sock);	connection->status = REMOTEFATAL;	return err;    }    if (passive_mode == FALSE)	/*				 * Then we have to accept the connection 				 */    {	err = accept_connection(connection->listen_sock,				&(connection->data_sock));	if (err != ACCEPTOK)	{	    close(connection->control_sock);	    connection->status = REMOTEFATAL;	    return err;	}    }    /*     * Lets get the file and store it      */    /*     * open the file with current mode      */    if (!	(connection->fp =	 fopen(connection->localfile, connection->file_mode)))    {	close(connection->control_sock);	close(connection->data_sock);	connection->status = LOCALFATAL;	return FOPENERR;    }    /*     * prioritize packets      */    setsockopt(connection->data_sock, IPPROTO_IP, IP_TOS,	       (char *) &tos, sizeof(tos));    /*Make sure all writes go directly to the file */    setvbuf(connection->fp, NULL, _IONBF, 0);    connection->status = DOWNLOADING;    /*     * lets store the start time in the connections structure     * if this is the first time we have started      */    if ((connection->time_begin.tv_sec == 0)	&& (connection->time_begin.tv_usec == 0))	gettimeofday(&connection->time_begin, NULL);    if (connection->main_file_size != -1)    {	err = ftp_retr_fsize_known(connection, connection->fp);	return err;    } else    {	err = ftp_retr_fsize_notknown(connection, connection->fp);    }    close(connection->control_sock);    close(connection->data_sock);    return err;}/* This function attemps to retrieve the requested file, if a error occurs it retries     * until either the file is retrieved properly or the max number of retry attemps are * exceeded */void ftp_loop(connection_data * connection){    uerr_t err = FTPERR;    int first_attempt = TRUE;    assert(rt.try_attempts >= 0);    assert(connection->try_attempts >= 0);    pthread_cleanup_push(clean_ftpsocks, (void *) connection);        connection->ftp_login_reject_start=0;    do    {	if (first_attempt != TRUE)	{	    sleep(rt.retry_delay);	/*					 * Sleep 					 */	    if (rt.try_attempts == 0)	/*					 * Try infinitely 					 */	    {		message("Trying infinitely...attempt %d",			connection->try_attempts);	    } else		message("Trying....attempt %d of %d",			connection->try_attempts, rt.try_attempts);	    delay_ms(400);	    connection->status = IDLE;	}	/*	 * Well if this connection is resumable, and this is not the first attempt,lets try to 	 * see whether on the previous attempt any bytes were 	 * downloaded, if so call the resume function which 	 * will do the changes	 */	if ((connection->try_attempts > 0)	    && (connection->u.resume_support == TRUE))	{	    /*	     * So the conenctions first attempt failed somehow 	     * however the connection may have downloaded some data	     * before terminating, so lets see whether the download	     */	    if (resume_modify_ftp_single_connection(connection) != 0)	    {		connection->status = LOCALFATAL;		pthread_exit(0);		return;	    }	    /*	     * Then change the connections file acess method to append,	     * since we want it to append to the end when restarting	     */	    assert(connection->file_mode);	    free(connection->file_mode);	    connection->file_mode = kstrdup("ab");	}	if (first_attempt == TRUE)	    first_attempt = FALSE;	if (rt.num_connections == 1)	    err = ftp_get_file_to_end(connection);	else	    err = ftp_get_file_chunk(connection);	connection->try_attempts++;	if (err == FTPOK)	    pthread_exit(0);	/*	 * So some error has occured 	 * Lets figure out whether it was a error which has to be handled	 * at this level or passed to the thread which launched this	 */	switch (err)	{	    /*	     * Is it a local error ie: not enough free space etc 	     * if so display a helpful message and return	     */	case FWRITEERR:	    message("Error writing to  file %s : %s",		    connection->u.file, strerror(errno));	    pthread_exit(0);	    return;	    break;	case FOPENERR:	    message("Error opening file %s for writing: %s",		    connection->localfile, strerror(errno));	    pthread_exit(0);	    return;	    break;	case CONERROR:	    if (errno == ETIMEDOUT)		message		    ("Connection Attempt Timed out,Retrying in %d seconds",		     rt.retry_delay);	    else		message("Error while connecting..retrying in %d seconds",			rt.retry_delay);	    break;	case FTPLOGREFUSED:	    /*	     * This will be handled by the handle_threads func in main.c	     */	    pthread_exit(0);	    return;	    break;	case FTPCONREFUSED:	    /*	     * This will be handled by the handle_threads func in main.c	     */	    pthread_exit(0);	    return;	    break;	case SERVERCLOSECONERR:	    message		("Server closed the conenction prematurely!...Retrying in %d seconds",		 rt.retry_delay);	    break;	default:	    message		("Error occured in connection.......Retrying in %d seconds",		 rt.retry_delay);	    break;	}    }    while ((connection->try_attempts < rt.try_attempts)	   || (rt.try_attempts == 0));    assert(err != FTPOK);    connection->status = MAXTRYS;    pthread_cleanup_pop(0);    pthread_exit(0);}/*  * This will download till it receives the required bytes, if the server  * closes the connection prematurely, this routine will return a error if the  * required number of bytes have not been got.    */uerr_t ftp_retr_fsize_known(connection_data * connection, FILE * fp){    int bytes_read = 0;    off_t total = 0;    off_t temp = connection->remote_endpos - connection->remote_startpos;    while (temp > 0)    {	if (temp < FTP_BUFFER_SIZE && temp > 0)	{	    while (temp > 0)	    {		bytes_read = ftp_read_msg(connection->data_sock,					  connection->ftp_buffer, temp);		if ((bytes_read == 0 && temp > 0))		{		    /* The conenction as closed by the server prematurely :( */		    message("Server closed the connection prematurely!");		    fclose(fp);		    connection->status = REMOTEFATAL;		    return SERVERCLOSECONERR;		}		if (bytes_read == -1)		{		    message("Error receving data");		    fclose(fp);		    if (errno == ETIMEDOUT)		    {			message("connection timed out");			connection->status = TIMEDOUT;			return READERR;		    }		    connection->status = REMOTEFATAL;		    return READERR;		}		if (bytes_read != fwrite(connection->ftp_buffer,					 sizeof(char), bytes_read, fp))		{		    message("write failed");		    fclose(fp);		    connection->status = LOCALFATAL;		    return FWRITEERR;		}		temp -= bytes_read;		total += bytes_read;		connection->remote_bytes_received += bytes_read;		calc_con_ratebps(connection);		throttle_con_rate(connection);	    }	    break;	}	bytes_read =	    ftp_read_msg(connection->data_sock, connection->ftp_buffer,			 FTP_BUFFER_SIZE);	if ((bytes_read == 0 && temp > 0))	{	    /* The conenction as closed by the server prematurely :( */	    message("Server closed the conenction prematurely!");	    fclose(fp);	    connection->status = REMOTEFATAL;	    return SERVERCLOSECONERR;	}	if (bytes_read == -1)	{	    message("Error receving data");	    fclose(fp);	    if (errno == ETIMEDOUT)	    {		message("connection timed out");		connection->status = TIMEDOUT;		return READERR;	    }	    connection->status = REMOTEFATAL;	    return READERR;	}	if (bytes_read !=	    fwrite(connection->ftp_buffer, sizeof(char), bytes_read, fp))	{	    message("write failed");	    fclose(fp);	    connection->status = LOCALFATAL;	    return FWRITEERR;	}	temp -= bytes_read;	total += bytes_read;	connection->remote_bytes_received += bytes_read;	calc_con_ratebps(connection);	throttle_con_rate(connection);    }    fclose(fp);    connection->status = COMPLETED;    message("download for this connection completed");    message("%s : %Ld received", connection->localfile, (long long) total);    return FTPOK;}/* This will download till it receives a EOF */uerr_t ftp_retr_fsize_notknown(connection_data * connection, FILE * fp){    off_t bytes_read;    do    {	bytes_read =	    krecv(connection->data_sock, connection->ftp_buffer,		  FTP_BUFFER_SIZE, 0, rt.timeout);	if (bytes_read > 0)	{	    if (fwrite		(connection->ftp_buffer, sizeof(char), bytes_read,		 fp) < bytes_read)	    {		fclose(fp);		message("write failed");		connection->status = LOCALFATAL;		return FWRITEERR;	    }	    connection->remote_bytes_received += bytes_read;	    calc_con_ratebps(connection);	    throttle_con_rate(connection);	}    }    while (bytes_read > 0);    fclose(fp);    if (bytes_read == -1)    {	if (errno == ETIMEDOUT)	{	    message("connection timed out");	    connection->status = TIMEDOUT;	    return READERR;	}	connection->status = REMOTEFATAL;	return READERR;    }    connection->status = COMPLETED;    message("download for this connection completed");    message("%s : %Ld received", connection->localfile,	    (long long) connection->remote_bytes_received);    return FTPOK;}uerr_t fetch_ftp_portions(urlinfo * url_data, ftp_stat_t * fs,			  int same_url, ftp_mirror * mirrors,			  int num_servers){    uerr_t err;    interface_ret i_ret;    do    {	if (same_url == FALSE)	{	    err = ftp_get_info(url_data, fs);	    if (err == FTPOK)	    {		if (fs->fp.flagtryretr == 0 && fs->fp.flagtrycwd == 1)		    die("Error:  %s is a directory, not a file",			url_data->file);	    } else	    {		switch (err)		{		case HOSTERR:		    die("Unable to resolve %s", url_data->host);		    break;		case CONREFUSED:		    die("%s Rejected the Connection Attempt",			url_data->host);		    break;		case CONERROR:		    if (errno == ETIMEDOUT)		    {			die("The connection Attempt to %s timed out",			    url_data->host);		    } else			die("Error while attempting to connect to %s",			    url_data->host);		    break;		case FTPCONREFUSED:		    die("%s Rejected the Connection Attempt",			url_data->host);		    break;		case FTPLOGREFUSED:		    die("The FTP server has rejected the login attempt.");		    break;		case FTPNSFOD:		    die("Error: A file called %s was not found on the server", url_data->file);		    break;		default:		    die("A error occured while trying to get info from the server\n");		    break;		}	    }	}	/*	 * If resume is not supported default to one connection	 */	if (url_data->resume_support == FALSE)	{	    rt.num_connections = 1;	    if (rt.run_mode == RESUME)	    {		message("Warning: This server does not support RESUME\n");		delay_ms(2000);		/*Change the run mode to normal, if a previous download is detected 		   the other routines will give the user the option of aborting or overwriting		 */		rt.run_mode = NORMAL;	    }	}	/*	 *  If force mode is false, check and prompt the user if the file	 *  or it's downloaded fragments are already existing	 */	if (rt.force_mode == FALSE)	{	    if (query_overwrite_target(url_data->file) != 0)	    {		die("Error while querying for %s", url_data->file);	    }	}	/*	 * Process the logfile if it exists 	 */	do_logfile(url_data);	switch (rt.run_mode)	{	case NORMAL:	    ftp_allocate_connections(url_data, url_data->file_size, "wb");	    break;	case RESUME:	    ftp_allocate_connections(url_data, url_data->file_size, "ab");	    break;	default:	    die("Error: unsupported mode\n");	}	i_ret = do_downloads(mirrors, num_servers);	if (i_ret == USER_NEXT_SERV)	{	    int cur_server =		get_mirror_list_pos(url_data->url, mirrors, num_servers);	    freeurl(url_data, 0);	    debug_prz("restarting %s", mirrors[cur_server + 1].full_name);	    err = parseurl(mirrors[cur_server + 1].full_name, url_data, 0);	    if (err != URLOK)	    {		die("The  URL is syntatically wrong!\n");	    }	    same_url = FALSE;	    rt.run_mode = RESUME;	    message("Continuing from %s", url_data->host);	    delay_ms(1000);	    erase();	} else if (i_ret == USER_PREV_SERV)	{	    int cur_server =		get_mirror_list_pos(url_data->url, mirrors, num_servers);	    freeurl(url_data, 0);	    err = parseurl(mirrors[cur_server - 1].full_name, url_data, 0);	    if (err != URLOK)	    {		die("The  URL is syntatically wrong!\n");	    }	    same_url = FALSE;	    rt.run_mode = RESUME;	    message("Continuing from %s", url_data->host);	    delay_ms(1000);	    erase();	}    }    while (i_ret == USER_NEXT_SERV || i_ret == USER_PREV_SERV);    return 1;}

⌨️ 快捷键说明

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