diff -ur /tmp/gt4.0.5-all-source-installer/source-trees/gass/copy/source/globus_url_copy.c gt4.0.5-all-source-installer/source-trees/gass/copy/source/globus_url_copy.c --- source-trees/gt2-cvs/gass/copy/source/globus_url_copy.c 2005-12-02 00:03:28.000000000 +0100 +++ source-trees/gt2-cvs/gass/copy/source/globus_url_copy.c 2007-08-22 16:16:31.815007875 +0200 @@ -91,6 +91,7 @@ globus_bool_t list_uses_data_mode; globus_bool_t ipv6; globus_bool_t allo; + globus_bool_t gridftp2; /* the need for 2 is due to the fact that gass copy is * not copying attributes @@ -327,6 +328,8 @@ " If set to >0, Blocked mode will be used, with this as the blocksize.\n" " -ipv6\n" " use ipv6 when available (EXPERIMENTAL)\n" +" -nogridftp2\n" +" do not use GridFTP2 even when available\n" "\n"; /*********** @@ -410,7 +413,8 @@ arg_noallo, arg_stripe_bs, arg_striped, - arg_num = arg_striped + arg_nogridftp2, + arg_num = arg_nogridftp2 }; #define listname(x) x##_aliases @@ -451,6 +455,7 @@ flagdef(arg_ipv6, "-ipv6","-IPv6"); flagdef(arg_allo, "-allo","-allocate"); flagdef(arg_noallo, "-no-allo","-no-allocate"); +flagdef(arg_nogridftp2, "-nogridftp2","-nogridftp2"); oneargdef(arg_f, "-f", "-filename", GLOBUS_NULL, GLOBUS_NULL); oneargdef(arg_stripe_bs, "-sbs", "-striped-block-size", test_integer, GLOBUS_NULL); @@ -504,7 +509,8 @@ setupopt(arg_allo); \ setupopt(arg_noallo); \ setupopt(arg_stripe_bs); \ - setupopt(arg_striped); + setupopt(arg_striped); \ + setupopt(arg_nogridftp2); static globus_bool_t globus_l_globus_url_copy_ctrlc = GLOBUS_FALSE; static globus_bool_t globus_l_globus_url_copy_ctrlc_handled = GLOBUS_FALSE; @@ -1372,6 +1378,7 @@ guc_info->ipv6 = GLOBUS_FALSE; guc_info->allo = GLOBUS_TRUE; guc_info->create_dest = GLOBUS_FALSE; + guc_info->gridftp2 = GLOBUS_TRUE; /* determine the program name */ @@ -1559,6 +1566,10 @@ break; + case arg_nogridftp2: + guc_info->gridftp2 = GLOBUS_FALSE; + break; + default: globus_url_copy_l_args_error_fmt("parse panic, arg id = %d", instance->id_number); @@ -2132,6 +2143,16 @@ return -1; } } + + result = globus_ftp_client_handleattr_set_gridftp2( + &ftp_handleattr, guc_info->gridftp2); + if(result != GLOBUS_SUCCESS) + { + fprintf(stderr, _GASCSL("Error: Unable to set gridftp2 support %s\n"), + globus_error_print_friendly(globus_error_peek(result))); + + return -1; + } globus_gass_copy_handleattr_set_ftp_attr( &gass_copy_handleattr, &ftp_handleattr); diff -ur /tmp/gt4.0.5-all-source-installer/source-trees/gridftp/client/source/globus_ftp_client_attr.c gt4.0.5-all-source-installer/source-trees/gridftp/client/source/globus_ftp_client_attr.c --- source-trees/gt2-cvs/gridftp/client/source/globus_ftp_client_attr.c 2006-10-14 09:24:10.000000000 +0200 +++ source-trees/gt2-cvs/gridftp/client/source/globus_ftp_client_attr.c 2007-08-22 16:31:44.775034502 +0200 @@ -45,6 +45,7 @@ globus_ftp_client_handleattr_init( globus_ftp_client_handleattr_t * attr) { + char * tmpstr; globus_i_ftp_client_handleattr_t * i_attr; GlobusFuncName(globus_ftp_client_handleattr_init); @@ -64,6 +65,25 @@ i_attr->nl_ftp = GLOBUS_FALSE; i_attr->nl_io = GLOBUS_FALSE; i_attr->rfc1738_url = GLOBUS_FALSE; + + /* Use of gridftp2 defaults to false, unless + * GLOBUS_FTP_CLIENT_GRIDFTP2 has been set to 'true', 'enabled', + * or 'yes'. + */ + tmpstr = globus_libc_getenv("GLOBUS_FTP_CLIENT_GRIDFTP2"); + if(tmpstr != GLOBUS_NULL + && (strncasecmp(tmpstr, "true", 5) == 0 + || strncasecmp(tmpstr, "enabled", 8) == 0 + || strncasecmp(tmpstr, "yes", 4) == 0)) + { + i_attr->gridftp2 = GLOBUS_TRUE; + } + else + { + i_attr->gridftp2 = GLOBUS_FALSE; + } + + *attr = i_attr; return GLOBUS_SUCCESS; @@ -337,6 +357,79 @@ /* globus_ftp_client_handleattr_get_rfc1738_url() */ /*@}*/ + +/** + * @name GridFTP2 support + */ +/*@{*/ +/** + * Enable/Disable GridFTP2 [GFD.41] support for servers supporting + * it. @ingroup globus_ftp_client_handleattr + * + * + * @param attr + * Attribute to modify + * @param gridftp + * Set to GLOBUS_TRUE to enable GridFTP2 support. + * Default of GLOBUS_FALSE specifies that GridFTP is disabled. + */ +globus_result_t +globus_ftp_client_handleattr_set_gridftp2( + globus_ftp_client_handleattr_t * attr, + globus_bool_t gridftp2) +{ + globus_object_t * err = GLOBUS_SUCCESS; + globus_i_ftp_client_handleattr_t * i_attr; + GlobusFuncName(globus_ftp_client_handleattr_set_gridftp2); + + if(attr == GLOBUS_NULL) + { + err = GLOBUS_I_FTP_CLIENT_ERROR_NULL_PARAMETER("attr"); + + goto error_exit; + } + i_attr = *(globus_i_ftp_client_handleattr_t **) attr; + + i_attr->gridftp2 = gridftp2; + + return GLOBUS_SUCCESS; + + error_exit: + return globus_error_put(err); +} +/* globus_ftp_client_handleattr_set_gridftp2() */ + +globus_result_t +globus_ftp_client_handleattr_get_gridftp2( + const globus_ftp_client_handleattr_t * attr, + globus_bool_t * gridftp2) +{ + const globus_i_ftp_client_handleattr_t * i_attr; + globus_object_t * err = GLOBUS_SUCCESS; + GlobusFuncName(globus_ftp_client_handleattr_get_gridftp2); + + if(attr == GLOBUS_NULL) + { + err = GLOBUS_I_FTP_CLIENT_ERROR_NULL_PARAMETER("attr"); + + goto error_exit; + } + if(gridftp2 == GLOBUS_NULL) + { + err = GLOBUS_I_FTP_CLIENT_ERROR_NULL_PARAMETER("gridftp2"); + + goto error_exit; + } + i_attr = *(const globus_i_ftp_client_handleattr_t **) attr; + (*gridftp2) = i_attr->gridftp2; + + return GLOBUS_SUCCESS; + error_exit: + return globus_error_put(err); +} +/* globus_ftp_client_handleattr_get_griftp2() */ +/*@}*/ + /** * @name URL Caching */ @@ -2669,6 +2762,7 @@ dest->nl_io = src->nl_io; dest->url_cache = GLOBUS_NULL; dest->plugins = GLOBUS_NULL; + dest->gridftp2 = src->gridftp2; tmp = src->url_cache; diff -ur /tmp/gt4.0.5-all-source-installer/source-trees/gridftp/client/source/globus_ftp_client.c gt4.0.5-all-source-installer/source-trees/gridftp/client/source/globus_ftp_client.c --- source-trees/gt2-cvs/gridftp/client/source/globus_ftp_client.c 2006-10-14 09:24:10.000000000 +0200 +++ source-trees/gt2-cvs/gridftp/client/source/globus_ftp_client.c 2007-08-22 15:54:02.810132468 +0200 @@ -457,10 +457,15 @@ static const char * setup_mlst = "SETUP_MLST"; static const char * mlst = "MLST"; static const char * setup_stat = "SETUP_STAT"; + static const char * setup_getput_get = "SETUP_GETPUT_GET"; + static const char * setup_getput_put = "SETUP_GETPUT_PUT"; static const char * stat = "STAT"; static const char * retr = "RETR"; static const char * stor = "STOR"; static const char * mdtm = "MDTM"; + static const char * getput_pasv_get = "GETPUT_PASV_GET"; + static const char * getput_pasv_put = "GETPUT_PASV_PUT"; + static const char * getput_pasv_transfer = "GETPUT_PASV_TRANSFER"; static const char * ready_for_data = "READY_FOR_DATA"; static const char * need_last_block = "NEED_LAST_BLOCK"; static const char * need_empty_queue = "NEED_EMPTY_QUEUE"; @@ -594,6 +599,12 @@ case GLOBUS_FTP_CLIENT_TARGET_SETUP_STAT: return setup_stat; break; + case GLOBUS_FTP_CLIENT_TARGET_SETUP_GETPUT_GET: + return setup_getput_get; + break; + case GLOBUS_FTP_CLIENT_TARGET_SETUP_GETPUT_PUT: + return setup_getput_put; + break; case GLOBUS_FTP_CLIENT_TARGET_STAT: return stat; break; @@ -645,6 +656,15 @@ case GLOBUS_FTP_CLIENT_TARGET_MDTM: return mdtm; break; + case GLOBUS_FTP_CLIENT_TARGET_GETPUT_PASV_GET: + return getput_pasv_get; + break; + case GLOBUS_FTP_CLIENT_TARGET_GETPUT_PASV_PUT: + return getput_pasv_put; + break; + case GLOBUS_FTP_CLIENT_TARGET_GETPUT_PASV_TRANSFER: + return getput_pasv_transfer; + break; case GLOBUS_FTP_CLIENT_TARGET_READY_FOR_DATA: return ready_for_data; break; diff -ur /tmp/gt4.0.5-all-source-installer/source-trees/gridftp/client/source/globus_ftp_client_data.c gt4.0.5-all-source-installer/source-trees/gridftp/client/source/globus_ftp_client_data.c --- source-trees/gt2-cvs/gridftp/client/source/globus_ftp_client_data.c 2005-04-19 01:01:36.000000000 +0200 +++ source-trees/gt2-cvs/gridftp/client/source/globus_ftp_client_data.c 2007-08-22 15:54:02.862135432 +0200 @@ -178,7 +178,8 @@ !(i_handle->source->state == GLOBUS_FTP_CLIENT_TARGET_READY_FOR_DATA || i_handle->source->state == GLOBUS_FTP_CLIENT_TARGET_NEED_LAST_BLOCK) && !(i_handle->source->state == GLOBUS_FTP_CLIENT_TARGET_RETR || - i_handle->source->state == GLOBUS_FTP_CLIENT_TARGET_LIST)) || + i_handle->source->state == GLOBUS_FTP_CLIENT_TARGET_LIST || + i_handle->source->state == GLOBUS_FTP_CLIENT_TARGET_GETPUT_PASV_GET)) || i_handle->state == GLOBUS_FTP_CLIENT_HANDLE_FINALIZE) { /* We've already hit EOF on the data channel. We'll just @@ -387,7 +388,8 @@ if((i_handle->state == GLOBUS_FTP_CLIENT_HANDLE_DEST_STOR_OR_ESTO && !(i_handle->dest->state == GLOBUS_FTP_CLIENT_TARGET_READY_FOR_DATA || i_handle->dest->state == GLOBUS_FTP_CLIENT_TARGET_NEED_LAST_BLOCK) && - i_handle->dest->state != GLOBUS_FTP_CLIENT_TARGET_STOR) || + i_handle->dest->state != GLOBUS_FTP_CLIENT_TARGET_STOR && + i_handle->dest->state != GLOBUS_FTP_CLIENT_TARGET_GETPUT_PASV_PUT) || i_handle->state == GLOBUS_FTP_CLIENT_HANDLE_FINALIZE) { /* We've already sent EOF. We'll just return that information diff -ur /tmp/gt4.0.5-all-source-installer/source-trees/gridftp/client/source/globus_ftp_client.h gt4.0.5-all-source-installer/source-trees/gridftp/client/source/globus_ftp_client.h --- source-trees/gt2-cvs/gridftp/client/source/globus_ftp_client.h 2006-10-14 09:24:10.000000000 +0200 +++ source-trees/gt2-cvs/gridftp/client/source/globus_ftp_client.h 2007-08-22 15:54:02.902137711 +0200 @@ -510,6 +510,16 @@ globus_bool_t * rfc1738_url); globus_result_t +globus_ftp_client_handleattr_set_gridftp2( + globus_ftp_client_handleattr_t * attr, + globus_bool_t gridftp2); + +globus_result_t +globus_ftp_client_handleattr_get_gridftp2( + const globus_ftp_client_handleattr_t * attr, + globus_bool_t * gridftp2); + +globus_result_t globus_ftp_client_handleattr_set_netlogger( globus_ftp_client_handleattr_t * attr, globus_netlogger_handle_t * nl_handle); @@ -1052,6 +1062,7 @@ GLOBUS_FTP_CLIENT_FEATURE_ERET, GLOBUS_FTP_CLIENT_FEATURE_SIZE, GLOBUS_FTP_CLIENT_FEATURE_CKSM, + GLOBUS_FTP_CLIENT_FEATURE_GETPUT, GLOBUS_FTP_CLIENT_FEATURE_MLST, GLOBUS_FTP_CLIENT_FEATURE_CHMOD, GLOBUS_FTP_CLIENT_FEATURE_MAX, diff -ur /tmp/gt4.0.5-all-source-installer/source-trees/gridftp/client/source/globus_ftp_client_plugin.h gt4.0.5-all-source-installer/source-trees/gridftp/client/source/globus_ftp_client_plugin.h --- source-trees/gt2-cvs/gridftp/client/source/globus_ftp_client_plugin.h 2006-10-14 09:24:10.000000000 +0200 +++ source-trees/gt2-cvs/gridftp/client/source/globus_ftp_client_plugin.h 2007-08-22 15:54:02.946140219 +0200 @@ -74,7 +74,7 @@ /** ALLO, REST */ GLOBUS_FTP_CLIENT_CMD_MASK_TRANSFER_MODIFIERS = 1<<3, - /** STOR, RETR, ESTO, ERET, APPE, LIST, NLST, MLSD */ + /** STOR, RETR, ESTO, ERET, APPE, LIST, NLST, MLSD, GET, PUT */ GLOBUS_FTP_CLIENT_CMD_MASK_FILE_ACTIONS = 1<<4, /** HELP, SITE HELP, FEAT, STAT, SYST, SIZE */ diff -ur /tmp/gt4.0.5-all-source-installer/source-trees/gridftp/client/source/globus_ftp_client_state.c gt4.0.5-all-source-installer/source-trees/gridftp/client/source/globus_ftp_client_state.c --- source-trees/gt2-cvs/gridftp/client/source/globus_ftp_client_state.c 2007-02-06 03:38:22.000000000 +0100 +++ source-trees/gt2-cvs/gridftp/client/source/globus_ftp_client_state.c 2007-08-22 15:56:13.625587216 +0200 @@ -124,6 +124,26 @@ globus_i_ftp_client_handle_t * client_handle, globus_ftp_control_response_t * response); +static +globus_result_t +globus_l_ftp_client_use_gridftp2_getput( + globus_i_ftp_client_target_t * target, + globus_bool_t * getput); + +static +globus_result_t +globus_l_ftp_client_send_get( + globus_i_ftp_client_target_t * target, + char * pathname, + globus_bool_t pasv); + +static +globus_result_t +globus_l_ftp_client_send_put( + globus_i_ftp_client_target_t * target, + char * pathname, + globus_bool_t pasv); + /** * Buffer size command applicability information. * @internal @@ -218,6 +238,7 @@ unsigned long pbsz = 0; int rc, oldrc, i; char * pathname; + globus_bool_t gridftp2_getput; GlobusFuncName(globus_i_ftp_client_response_callback); target = (globus_i_ftp_client_target_t *) user_arg; @@ -254,7 +275,17 @@ client_handle->state == GLOBUS_FTP_CLIENT_HANDLE_RESTART) { goto finish; + } + + /* The behaviour of several states depends on whether to use the + * GFD.47 (a.k.a GridFTP 2) GETPUT extension. + */ + result = globus_l_ftp_client_use_gridftp2_getput(target, &gridftp2_getput); + if (result != GLOBUS_SUCCESS) + { + goto result_fault; } + /* This redo is used to make a second run through the state * machine, which a few states will require. */ @@ -1622,6 +1653,11 @@ goto redo; case GLOBUS_FTP_CLIENT_TARGET_SETUP_PASV: + if(gridftp2_getput == GLOBUS_TRUE) + { + goto skip_pasv; + } + if(globus_i_ftp_client_can_reuse_data_conn(client_handle)) { goto skip_pasv; @@ -1742,6 +1778,11 @@ } } + if(gridftp2_getput == GLOBUS_TRUE) + { + goto skip_port; + } + tmpstr = globus_libc_malloc(56 * client_handle->num_pasv_addresses + 7 /*SPOR|PORT|EPRT\r\n\0*/); /* ' |2|<45>|<5>|' == 56 */ @@ -2286,16 +2327,30 @@ } goto redo; case GLOBUS_FTP_CLIENT_GET: - target->state = GLOBUS_FTP_CLIENT_TARGET_SETUP_GET; - goto redo; + if (gridftp2_getput == GLOBUS_TRUE) + { + target->state = GLOBUS_FTP_CLIENT_TARGET_SETUP_GETPUT_GET; + } + else + { + target->state = GLOBUS_FTP_CLIENT_TARGET_SETUP_GET; + } + goto redo; case GLOBUS_FTP_CLIENT_PUT: - target->state = GLOBUS_FTP_CLIENT_TARGET_SETUP_PUT; + if (gridftp2_getput == GLOBUS_TRUE) + { + target->state = GLOBUS_FTP_CLIENT_TARGET_SETUP_GETPUT_PUT; + } + else + { + target->state = GLOBUS_FTP_CLIENT_TARGET_SETUP_PUT; + } goto redo; case GLOBUS_FTP_CLIENT_TRANSFER: if(client_handle->state == GLOBUS_FTP_CLIENT_HANDLE_DEST_SETUP_CONNECTION) { - target->state = GLOBUS_FTP_CLIENT_TARGET_SETUP_TRANSFER_DEST; + target->state = GLOBUS_FTP_CLIENT_TARGET_SETUP_TRANSFER_DEST; } else { @@ -2971,76 +3026,110 @@ { goto result_fault; } - break; + break; case GLOBUS_FTP_CLIENT_TARGET_SETUP_TRANSFER_DEST: globus_assert( client_handle->state == GLOBUS_FTP_CLIENT_HANDLE_DEST_SETUP_CONNECTION); - /* The destination is prepared first. We send all - * of the commands we need to, including the STOR - * or ESTO, and then turn our attention to the - * source. - */ - target->mask = GLOBUS_FTP_CLIENT_CMD_MASK_FILE_ACTIONS; + /* The destination is prepared first. We send all of the + * commands we need to, including the PUT, STOR or ESTO, and + * then turn our attention to the source. + */ + target->mask = GLOBUS_FTP_CLIENT_CMD_MASK_FILE_ACTIONS; - if(client_handle->esto_alg_str != GLOBUS_NULL) - { - globus_i_ftp_client_plugin_notify_command( - client_handle, - target->url_string, - target->mask, - "ESTO %s %s" CRLF, - client_handle->esto_alg_str, - pathname); - } - else - { - globus_i_ftp_client_plugin_notify_command( - client_handle, - target->url_string, - target->mask, - "STOR %s" CRLF, - pathname); - } + if (gridftp2_getput == GLOBUS_TRUE) + { + result = + globus_l_ftp_client_send_put(target, pathname, GLOBUS_TRUE); + if(result != GLOBUS_SUCCESS) + { + goto result_fault; + } - if(client_handle->state == GLOBUS_FTP_CLIENT_HANDLE_ABORT || - client_handle->state == GLOBUS_FTP_CLIENT_HANDLE_RESTART || - client_handle->state == GLOBUS_FTP_CLIENT_HANDLE_FAILURE) - { - break; - } + if(client_handle->state == GLOBUS_FTP_CLIENT_HANDLE_ABORT || + client_handle->state == GLOBUS_FTP_CLIENT_HANDLE_RESTART || + client_handle->state == GLOBUS_FTP_CLIENT_HANDLE_FAILURE) + { + break; + } - globus_assert(client_handle->state == - GLOBUS_FTP_CLIENT_HANDLE_DEST_SETUP_CONNECTION); + if(globus_i_ftp_client_can_reuse_data_conn(client_handle)) + { + /* In this case we do not expect a 127 reply. + */ + target->state = GLOBUS_FTP_CLIENT_TARGET_STOR; + } + else + { + target->state = GLOBUS_FTP_CLIENT_TARGET_GETPUT_PASV_TRANSFER; - target->state = GLOBUS_FTP_CLIENT_TARGET_STOR; + /* In this case we have to wait for the 127 reply + * before we can setup the transfer at the source. + */ + break; + } + } + else + { + if(client_handle->esto_alg_str != GLOBUS_NULL) + { + globus_i_ftp_client_plugin_notify_command( + client_handle, + target->url_string, + target->mask, + "ESTO %s %s" CRLF, + client_handle->esto_alg_str, + pathname); + } + else + { + globus_i_ftp_client_plugin_notify_command( + client_handle, + target->url_string, + target->mask, + "STOR %s" CRLF, + pathname); + } + + if(client_handle->state == GLOBUS_FTP_CLIENT_HANDLE_ABORT || + client_handle->state == GLOBUS_FTP_CLIENT_HANDLE_RESTART || + client_handle->state == GLOBUS_FTP_CLIENT_HANDLE_FAILURE) + { + break; + } - if(client_handle->esto_alg_str != GLOBUS_NULL) - { - result = globus_ftp_control_send_command( - handle, - "ESTO %s %s" CRLF, - globus_i_ftp_client_response_callback, - user_arg, - client_handle->esto_alg_str, - pathname); - } - else - { - result = globus_ftp_control_send_command( - handle, - "STOR %s" CRLF, - globus_i_ftp_client_response_callback, - user_arg, + globus_assert(client_handle->state == + GLOBUS_FTP_CLIENT_HANDLE_DEST_SETUP_CONNECTION); + + target->state = GLOBUS_FTP_CLIENT_TARGET_STOR; + + if(client_handle->esto_alg_str != GLOBUS_NULL) + { + result = globus_ftp_control_send_command( + handle, + "ESTO %s %s" CRLF, + globus_i_ftp_client_response_callback, + user_arg, + client_handle->esto_alg_str, + pathname); + } + else + { + result = globus_ftp_control_send_command( + handle, + "STOR %s" CRLF, + globus_i_ftp_client_response_callback, + user_arg, pathname); - } + } - if(result != GLOBUS_SUCCESS) - { - goto result_fault; - } + if(result != GLOBUS_SUCCESS) + { + goto result_fault; + } + } target = client_handle->source; @@ -3072,61 +3161,328 @@ target->mask = GLOBUS_FTP_CLIENT_CMD_MASK_FILE_ACTIONS; - if(client_handle->eret_alg_str) - { - globus_i_ftp_client_plugin_notify_command( - client_handle, - target->url_string, - target->mask, - "ERET %s %s" CRLF, - client_handle->eret_alg_str, - pathname); - } - else - { - globus_i_ftp_client_plugin_notify_command( - client_handle, - target->url_string, - target->mask, - "RETR %s" CRLF, - pathname); - } + if (gridftp2_getput == GLOBUS_TRUE) + { + result = + globus_l_ftp_client_send_get(target, pathname, GLOBUS_FALSE); + if(result != GLOBUS_SUCCESS) + { + goto result_fault; + } - if(client_handle->state == GLOBUS_FTP_CLIENT_HANDLE_ABORT || - client_handle->state == GLOBUS_FTP_CLIENT_HANDLE_RESTART || - client_handle->state == GLOBUS_FTP_CLIENT_HANDLE_FAILURE) - { - break; - } - globus_assert(client_handle->state == - GLOBUS_FTP_CLIENT_HANDLE_THIRD_PARTY_TRANSFER); + if(client_handle->state == GLOBUS_FTP_CLIENT_HANDLE_ABORT || + client_handle->state == GLOBUS_FTP_CLIENT_HANDLE_RESTART || + client_handle->state == GLOBUS_FTP_CLIENT_HANDLE_FAILURE) + { + break; + } + + target->state = GLOBUS_FTP_CLIENT_TARGET_RETR; + } + else + { + if(client_handle->eret_alg_str) + { + globus_i_ftp_client_plugin_notify_command( + client_handle, + target->url_string, + target->mask, + "ERET %s %s" CRLF, + client_handle->eret_alg_str, + pathname); + } + else + { + globus_i_ftp_client_plugin_notify_command( + client_handle, + target->url_string, + target->mask, + "RETR %s" CRLF, + pathname); + } + + if(client_handle->state == GLOBUS_FTP_CLIENT_HANDLE_ABORT || + client_handle->state == GLOBUS_FTP_CLIENT_HANDLE_RESTART || + client_handle->state == GLOBUS_FTP_CLIENT_HANDLE_FAILURE) + { + break; + } + globus_assert(client_handle->state == + GLOBUS_FTP_CLIENT_HANDLE_THIRD_PARTY_TRANSFER); + + target->state = GLOBUS_FTP_CLIENT_TARGET_RETR; + + if(client_handle->eret_alg_str) + { + result = globus_ftp_control_send_command( + handle, + "ERET %s %s\r\n", + globus_i_ftp_client_response_callback, + user_arg, + client_handle->eret_alg_str, + pathname); + } + else + { + result = globus_ftp_control_send_command( + handle, + "RETR %s" CRLF, + globus_i_ftp_client_response_callback, + user_arg, + pathname); + } + if(result != GLOBUS_SUCCESS) + { + goto result_fault; + } + } + break; - target->state = GLOBUS_FTP_CLIENT_TARGET_RETR; + case GLOBUS_FTP_CLIENT_TARGET_SETUP_GETPUT_GET: + globus_assert( + client_handle->state == + GLOBUS_FTP_CLIENT_HANDLE_SOURCE_SETUP_CONNECTION); - if(client_handle->eret_alg_str) - { - result = globus_ftp_control_send_command( - handle, - "ERET %s %s\r\n", - globus_i_ftp_client_response_callback, - user_arg, - client_handle->eret_alg_str, - pathname); - } - else - { - result = globus_ftp_control_send_command( - handle, - "RETR %s" CRLF, - globus_i_ftp_client_response_callback, - user_arg, - pathname); - } - if(result != GLOBUS_SUCCESS) - { - goto result_fault; - } - break; + client_handle->state = + GLOBUS_FTP_CLIENT_HANDLE_SOURCE_RETR_OR_ERET; + + if(target->mode == GLOBUS_FTP_CONTROL_MODE_EXTENDED_BLOCK || + globus_i_ftp_client_can_reuse_data_conn(client_handle)) + { + /* In extended block mode, we will be the passive party + * and do not expect a 127 reply. + * + * If a connection was cached, we do not expect a 127 reply + * either. + */ + target->state = GLOBUS_FTP_CLIENT_TARGET_RETR; + + /* Setup data connection. Since we do not expect a 127 + * reply, we need to do this before sending GET. + */ + result = + globus_ftp_control_data_connect_read(target->control_handle, + GLOBUS_NULL, + GLOBUS_NULL); + if(result != GLOBUS_SUCCESS) + { + goto result_fault; + } + } + else + { + /* We require a 127 reply and will setup the connection once + * it has been received. + */ + target->state = GLOBUS_FTP_CLIENT_TARGET_GETPUT_PASV_GET; + } + + target->mask = GLOBUS_FTP_CLIENT_CMD_MASK_FILE_ACTIONS; + if(target->mode == GLOBUS_FTP_CONTROL_MODE_EXTENDED_BLOCK) + { + /* In extended block mode, we will be the passive + * party. GLOBUS_FTP_CLIENT_TARGET_SETUP_PORT has already + * filled in client_handle->pasv_address. + */ + result = + globus_l_ftp_client_send_get(target, pathname, GLOBUS_FALSE); + } + else + { + /* In all other cases we prefer to be active. + */ + result = + globus_l_ftp_client_send_get(target, pathname, GLOBUS_TRUE); + } + if(result != GLOBUS_SUCCESS) + { + goto result_fault; + } + break; + + case GLOBUS_FTP_CLIENT_TARGET_SETUP_GETPUT_PUT: + globus_assert( + client_handle->state == + GLOBUS_FTP_CLIENT_HANDLE_DEST_SETUP_CONNECTION); + + client_handle->state = GLOBUS_FTP_CLIENT_HANDLE_DEST_STOR_OR_ESTO; + + if(globus_i_ftp_client_can_reuse_data_conn(client_handle)) + { + /* In this case we do not expect a 127 reply. + */ + target->state = GLOBUS_FTP_CLIENT_TARGET_STOR; + + /* Create the data connection. + */ + result = + globus_ftp_control_data_connect_write(target->control_handle, + GLOBUS_NULL, + GLOBUS_NULL); + if(result != GLOBUS_SUCCESS) + { + goto result_fault; + } + } + else + { + target->state = GLOBUS_FTP_CLIENT_TARGET_GETPUT_PASV_PUT; + } + + target->mask = GLOBUS_FTP_CLIENT_CMD_MASK_FILE_ACTIONS; + result = globus_l_ftp_client_send_put(target, pathname, GLOBUS_TRUE); + if(result != GLOBUS_SUCCESS) + { + goto result_fault; + } + break; + + case GLOBUS_FTP_CLIENT_TARGET_GETPUT_PASV_GET: + if((!error) && + response->code == 127) + { + /* Setup our side of PASV. + */ + globus_l_ftp_client_parse_pasv( + handle, + response, + &client_handle->pasv_address, + &client_handle->num_pasv_addresses); + + if(client_handle->num_pasv_addresses == 1) + { + result = + globus_ftp_control_local_port( + handle, + client_handle->pasv_address); + } + else + { + result = + globus_ftp_control_local_spor( + handle, + client_handle->pasv_address, + client_handle->num_pasv_addresses); + } + if(result != GLOBUS_SUCCESS) + { + goto result_fault; + } + + /* Create the data connection. + */ + result = + globus_ftp_control_data_connect_read(target->control_handle, + GLOBUS_NULL, + GLOBUS_NULL); + if(result != GLOBUS_SUCCESS) + { + goto result_fault; + } + + target->state = GLOBUS_FTP_CLIENT_TARGET_RETR; + } + else + { + target->state = GLOBUS_FTP_CLIENT_TARGET_SETUP_CONNECTION; + goto notify_fault; + } + break; + + case GLOBUS_FTP_CLIENT_TARGET_GETPUT_PASV_PUT: + if((!error) && + response->code == 127) + { + /* Setup our side of PASV. + */ + globus_l_ftp_client_parse_pasv( + handle, + response, + &client_handle->pasv_address, + &client_handle->num_pasv_addresses); + + if(client_handle->num_pasv_addresses == 1) + { + result = + globus_ftp_control_local_port( + handle, + client_handle->pasv_address); + } + else + { + result = + globus_ftp_control_local_spor( + handle, + client_handle->pasv_address, + client_handle->num_pasv_addresses); + } + if(result != GLOBUS_SUCCESS) + { + goto result_fault; + } + + /* Create the data connection. + */ + result = + globus_ftp_control_data_connect_write(target->control_handle, + GLOBUS_NULL, + GLOBUS_NULL); + if(result != GLOBUS_SUCCESS) + { + goto result_fault; + } + + target->state = GLOBUS_FTP_CLIENT_TARGET_STOR; + } + else + { + target->state = GLOBUS_FTP_CLIENT_TARGET_SETUP_CONNECTION; + goto notify_fault; + } + break; + + case GLOBUS_FTP_CLIENT_TARGET_GETPUT_PASV_TRANSFER: + if((!error) && + response->code == 127) + { + globus_l_ftp_client_parse_pasv( + handle, + response, + &client_handle->pasv_address, + &client_handle->num_pasv_addresses); + + /* The passive end of a 3rd party transfer is always the + * destination. + */ + target->state = GLOBUS_FTP_CLIENT_TARGET_STOR; + + /* Now continue setting up the source of the transfer. + */ + target = client_handle->source; + + error = + globus_i_ftp_client_target_activate(client_handle, + target, + ®istered); + if(registered == GLOBUS_FALSE) + { + if(client_handle->state==GLOBUS_FTP_CLIENT_HANDLE_ABORT || + client_handle->state==GLOBUS_FTP_CLIENT_HANDLE_RESTART) + { + break; + } + else + { + goto connection_error; + } + } + } + else + { + target->state = GLOBUS_FTP_CLIENT_TARGET_SETUP_CONNECTION; + goto notify_fault; + } + break; case GLOBUS_FTP_CLIENT_TARGET_LIST: case GLOBUS_FTP_CLIENT_TARGET_RETR: @@ -3858,6 +4214,13 @@ GLOBUS_FTP_CLIENT_FEATURE_SIZE, GLOBUS_FTP_CLIENT_TRUE); } + else if(strncmp(feature_label, "GETPUT", 6) == 0) + { + globus_i_ftp_client_feature_set( + target->features, + GLOBUS_FTP_CLIENT_FEATURE_GETPUT, + GLOBUS_FTP_CLIENT_TRUE); + } else if(strncmp(feature_label, "MLST", 4) == 0) { globus_i_ftp_client_feature_set( @@ -5003,5 +5366,247 @@ { } +static +globus_result_t +globus_l_ftp_client_use_gridftp2_getput( + globus_i_ftp_client_target_t * target, + globus_bool_t * getput) +{ + globus_i_ftp_client_handle_t * client_handle; + globus_ftp_client_handleattr_t handle_attr; + globus_result_t result; + + client_handle = target->owner; + handle_attr = &client_handle->attr; + + /* Are GFD.47 extensions enabled? + */ + result = + globus_ftp_client_handleattr_get_gridftp2(&handle_attr, getput); + if(result != GLOBUS_SUCCESS || *getput == GLOBUS_FALSE) + { + return result; + } + + /* Does requested operation allow the use of GETPUT? + */ + if (client_handle->op != GLOBUS_FTP_CLIENT_TRANSFER + && client_handle->op != GLOBUS_FTP_CLIENT_GET + && client_handle->op != GLOBUS_FTP_CLIENT_PUT) + { + *getput = GLOBUS_FALSE; + return GLOBUS_SUCCESS; + } + + /* Does target support GFD.47? + */ + if (globus_i_ftp_client_feature_get( + target->features, + GLOBUS_FTP_CLIENT_FEATURE_GETPUT) == GLOBUS_FTP_CLIENT_FALSE) + { + *getput = GLOBUS_FALSE; + return GLOBUS_SUCCESS; + } + + /* GFD.47 style GETPUT does not support extended server side + * processing. + */ + if (client_handle->eret_alg_str != GLOBUS_NULL) + { + *getput = GLOBUS_FALSE; + return GLOBUS_SUCCESS; + } + + /* In principal, GFD.47 supports striping, however the exact + * details for configuring striping using GETPUT are currently + * unknown. + */ + if (target->attr->layout.mode != GLOBUS_FTP_CONTROL_STRIPING_NONE) + { + *getput = GLOBUS_FALSE; + return GLOBUS_SUCCESS; + } + + /* GFD.47 doesn't tell us how to do IPv6. + */ + if(target->attr->allow_ipv6) + { + *getput = GLOBUS_FALSE; + return GLOBUS_SUCCESS; + } + + return GLOBUS_SUCCESS; +} + +/** + * Sends a GFD.47 compliant GET command. + */ +static +globus_result_t +globus_l_ftp_client_send_get( + globus_i_ftp_client_target_t * target, + char * pathname, + globus_bool_t pasv) +{ + char * tmpstr = GLOBUS_NULL; + globus_i_ftp_client_handle_t * client_handle; + int rc, oldrc; + globus_result_t result; + + client_handle = target->owner; + + tmpstr = globus_libc_malloc(56 * client_handle->num_pasv_addresses + 6); + + if(tmpstr == GLOBUS_NULL) + { + return globus_error_put(GLOBUS_ERROR_NO_INFO); + } + + if(globus_i_ftp_client_can_reuse_data_conn(client_handle)) + { + tmpstr[0] = 0; + } + else if(pasv == GLOBUS_TRUE) + { + sprintf(tmpstr, "pasv;"); + } + else + { + rc = oldrc = 0; + globus_assert(!target->attr->allow_ipv6); + globus_assert(client_handle->num_pasv_addresses == 1); + globus_assert(client_handle->pasv_address[0].hostlen != 16); + + rc += sprintf(&tmpstr[oldrc], + "port=%d,%d,%d,%d,%d,%d;", + client_handle->pasv_address[0].host[0], + client_handle->pasv_address[0].host[1], + client_handle->pasv_address[0].host[2], + client_handle->pasv_address[0].host[3], + (client_handle->pasv_address[0].port >> 8) + & 0xff, + client_handle->pasv_address[0].port & 0xff); + if(rc == oldrc) + { + globus_libc_free(tmpstr); + return globus_error_put(GLOBUS_ERROR_NO_INFO); + } + } + + globus_i_ftp_client_plugin_notify_command( + client_handle, + target->url_string, + target->mask, + "GET path=%s;%s" CRLF, + pathname, + tmpstr); + + if(client_handle->state == GLOBUS_FTP_CLIENT_HANDLE_ABORT || + client_handle->state == GLOBUS_FTP_CLIENT_HANDLE_RESTART || + client_handle->state == GLOBUS_FTP_CLIENT_HANDLE_FAILURE) + { + globus_libc_free(tmpstr); + return GLOBUS_SUCCESS; + } + + result = + globus_ftp_control_send_command( + target->control_handle, + "GET path=%s;%s" CRLF, + globus_i_ftp_client_response_callback, + target, + pathname, + tmpstr); + + globus_libc_free(tmpstr); + + return result; +} + +/** + * Sends a GFD.47 compliant PUT command. + */ +static +globus_result_t +globus_l_ftp_client_send_put( + globus_i_ftp_client_target_t * target, + char * pathname, + globus_bool_t pasv) +{ + char * tmpstr = GLOBUS_NULL; + globus_i_ftp_client_handle_t * client_handle; + int rc, oldrc; + globus_result_t result; + + client_handle = target->owner; + + tmpstr = globus_libc_malloc(56 * client_handle->num_pasv_addresses + 6); + + if(tmpstr == GLOBUS_NULL) + { + return globus_error_put(GLOBUS_ERROR_NO_INFO); + } + + if(globus_i_ftp_client_can_reuse_data_conn(client_handle)) + { + tmpstr[0] = 0; + } + else if(pasv == GLOBUS_TRUE) + { + sprintf(tmpstr, "pasv;"); + } + else + { + rc = oldrc = 0; + globus_assert(!target->attr->allow_ipv6); + globus_assert(client_handle->num_pasv_addresses == 1); + globus_assert(client_handle->pasv_address[0].hostlen != 16); + + rc += sprintf(&tmpstr[oldrc], + "port=%d,%d,%d,%d,%d,%d;", + client_handle->pasv_address[0].host[0], + client_handle->pasv_address[0].host[1], + client_handle->pasv_address[0].host[2], + client_handle->pasv_address[0].host[3], + (client_handle->pasv_address[0].port >> 8) + & 0xff, + client_handle->pasv_address[0].port & 0xff); + if(rc == oldrc) + { + globus_libc_free(tmpstr); + return globus_error_put(GLOBUS_ERROR_NO_INFO); + } + } + + globus_i_ftp_client_plugin_notify_command( + client_handle, + target->url_string, + target->mask, + "PUT path=%s;%s" CRLF, + pathname, + tmpstr); + + if(client_handle->state == GLOBUS_FTP_CLIENT_HANDLE_ABORT || + client_handle->state == GLOBUS_FTP_CLIENT_HANDLE_RESTART || + client_handle->state == GLOBUS_FTP_CLIENT_HANDLE_FAILURE) + { + globus_libc_free(tmpstr); + return GLOBUS_SUCCESS; + } + + result = + globus_ftp_control_send_command( + target->control_handle, + "PUT path=%s;%s" CRLF, + globus_i_ftp_client_response_callback, + target, + pathname, + tmpstr); + + globus_libc_free(tmpstr); + + return result; +} + #endif diff -ur /tmp/gt4.0.5-all-source-installer/source-trees/gridftp/client/source/globus_i_ftp_client.h gt4.0.5-all-source-installer/source-trees/gridftp/client/source/globus_i_ftp_client.h --- source-trees/gt2-cvs/gridftp/client/source/globus_i_ftp_client.h 2006-10-14 09:24:10.000000000 +0200 +++ source-trees/gt2-cvs/gridftp/client/source/globus_i_ftp_client.h 2007-08-22 15:54:02.994142954 +0200 @@ -189,6 +189,12 @@ globus_bool_t rfc1738_url; + /** + * Use GRIDFTP2 if supported by the server + */ + + globus_bool_t gridftp2; + /** * List of cached URLs. * @@ -324,12 +330,17 @@ GLOBUS_FTP_CLIENT_TARGET_SETUP_MDTM, GLOBUS_FTP_CLIENT_TARGET_SETUP_MLST, GLOBUS_FTP_CLIENT_TARGET_SETUP_STAT, + GLOBUS_FTP_CLIENT_TARGET_SETUP_GETPUT_GET, + GLOBUS_FTP_CLIENT_TARGET_SETUP_GETPUT_PUT, GLOBUS_FTP_CLIENT_TARGET_MLST, GLOBUS_FTP_CLIENT_TARGET_STAT, GLOBUS_FTP_CLIENT_TARGET_LIST, GLOBUS_FTP_CLIENT_TARGET_RETR, GLOBUS_FTP_CLIENT_TARGET_STOR, GLOBUS_FTP_CLIENT_TARGET_MDTM, + GLOBUS_FTP_CLIENT_TARGET_GETPUT_PASV_GET, + GLOBUS_FTP_CLIENT_TARGET_GETPUT_PASV_PUT, + GLOBUS_FTP_CLIENT_TARGET_GETPUT_PASV_TRANSFER, GLOBUS_FTP_CLIENT_TARGET_READY_FOR_DATA, GLOBUS_FTP_CLIENT_TARGET_NEED_LAST_BLOCK, GLOBUS_FTP_CLIENT_TARGET_NEED_EMPTY_QUEUE,