Back to index

nordugrid-arc-nox  1.1.0~rc6
Public Member Functions | Private Types | Private Member Functions | Static Private Member Functions | Private Attributes
Arc::Lister Class Reference

#include <Lister.h>

Collaboration diagram for Arc::Lister:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 Lister (GSSCredential &credential)
 ~Lister ()
int retrieve_dir_info (const URL &url, bool names_only=false)
int retrieve_file_info (const URL &url, bool names_only=false)
 operator bool ()
std::list< FileInfo >::iterator begin ()
std::list< FileInfo >::iterator end ()
int size () const
int close_connection ()

Private Types

enum  callback_status_t { CALLBACK_NOTREADY = 0, CALLBACK_DONE = 1, CALLBACK_ERROR = 2 }

Private Member Functions

callback_status_t wait_for_callback ()
callback_status_t wait_for_data_callback ()
void resp_destroy ()
globus_ftp_control_response_class_t send_command (const char *command, const char *arg, bool wait_for_response, char **sresp, char delim=0)
int setup_pasv (globus_ftp_control_host_port_t &pasv_addr)
int handle_connect (const URL &url)
int transfer_list (void)

Static Private Member Functions

static void resp_callback (void *arg, globus_ftp_control_handle_t *h, globus_object_t *error, globus_ftp_control_response_t *response)
static void list_read_callback (void *arg, globus_ftp_control_handle_t *hctrl, globus_object_t *error, globus_byte_t *buffer, globus_size_t length, globus_off_t offset, globus_bool_t eof)
static void list_conn_callback (void *arg, globus_ftp_control_handle_t *hctrl, unsigned int stripe_ndx, globus_bool_t reused, globus_object_t *error)

Private Attributes

bool inited
bool facts
char readbuf [4096]
globus_cond_t cond
globus_mutex_t mutex
globus_ftp_control_handle_t * handle
std::list< FileInfofnames
globus_ftp_control_response_t resp [LISTER_MAX_RESPONSES]
int resp_n
callback_status_t callback_status
callback_status_t data_callback_status
globus_off_t list_shift
bool connected
bool pasv_set
bool data_activated
bool free_format
unsigned short int port
std::string host
std::string username
std::string userpass
std::string path
std::string scheme
GSSCredentialcredential

Detailed Description

Definition at line 20 of file Lister.h.


Member Enumeration Documentation

Enumerator:
CALLBACK_NOTREADY 
CALLBACK_DONE 
CALLBACK_ERROR 

Definition at line 31 of file Lister.h.


Constructor & Destructor Documentation

Definition at line 431 of file Lister.cpp.

    : inited(false),
      handle(NULL),
      resp_n(0),
      callback_status(CALLBACK_NOTREADY),
      connected(false),
      pasv_set(false),
      data_activated(false),
      credential(credential),
      port((unsigned short int)(-1)) {
    if (globus_cond_init(&cond, GLOBUS_NULL) != GLOBUS_SUCCESS) {
      logger.msg(ERROR, "Failed initing condition");
      return;
    }
    if (globus_mutex_init(&mutex, GLOBUS_NULL) != GLOBUS_SUCCESS) {
      logger.msg(ERROR, "Failed initing mutex");
      globus_cond_destroy(&cond);
      return;
    }
    handle = (globus_ftp_control_handle_t*)
             malloc(sizeof(globus_ftp_control_handle_t));
    if (handle == NULL) {
      logger.msg(ERROR, "Failed allocating memory for handle");
      globus_mutex_destroy(&mutex);
      globus_cond_destroy(&cond);
    }
    if (globus_ftp_control_handle_init(handle) != GLOBUS_SUCCESS) {
      logger.msg(ERROR, "Failed initing handle");
      globus_mutex_destroy(&mutex);
      globus_cond_destroy(&cond);
      free(handle);
      handle = NULL;
      return;
    }
    inited = true;
  }

Here is the call graph for this function:

Definition at line 495 of file Lister.cpp.

                  {
    close_connection();
    if (inited) {
      if (globus_ftp_control_handle_destroy(handle) == GLOBUS_SUCCESS) {
        free(handle);
        handle = NULL;
      }
      else {
        logger.msg(VERBOSE, "Memory leak (globus_ftp_control_handle_t)");
        handle = NULL;
      }
      globus_mutex_destroy(&mutex);
      globus_cond_destroy(&cond);
    }
  }

Here is the call graph for this function:


Member Function Documentation

std::list<FileInfo>::iterator Arc::Lister::begin ( ) [inline]

Definition at line 82 of file Lister.h.

                                      {
      return fnames.begin();
    }

Here is the caller graph for this function:

Definition at line 468 of file Lister.cpp.

                               {
    if (!connected)
      return 0;
    logger.msg(VERBOSE, "Closing connection");
    if (globus_ftp_control_quit(handle, resp_callback, this) !=
        GLOBUS_SUCCESS)
      if (globus_ftp_control_force_close(handle, resp_callback, this) !=
          GLOBUS_SUCCESS) {
        logger.msg(INFO, "Failed to close connection 1");
        return -1;
      }
    if (wait_for_callback() != CALLBACK_DONE) {
      if (globus_ftp_control_force_close(handle, resp_callback, this) !=
          GLOBUS_SUCCESS) {
        logger.msg(INFO, "Failed to close connection 2");
        return -1;
      }
      if (wait_for_callback() != CALLBACK_DONE) {
        logger.msg(INFO, "Failed to close connection 3");
        return -1;
      }
    }
    connected = false;
    logger.msg(VERBOSE, "Closed successfully");
    return 0;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

std::list<FileInfo>::iterator Arc::Lister::end ( ) [inline]

Definition at line 85 of file Lister.h.

                                    {
      return fnames.end();
    }

Here is the caller graph for this function:

int Arc::Lister::handle_connect ( const URL url) [private]

Definition at line 562 of file Lister.cpp.

                                           {
    GlobusResult res;
    /* get listing */
    fnames.clear();
    globus_ftp_control_auth_info_t auth;

    if ((url.Protocol() != "ftp") &&
        (url.Protocol() != "gsiftp")) {
      logger.msg(ERROR, "Unsupported protocol in url %s", url.str());
      return -1;
    }

    bool reconnect = true;

    if (connected)
      if ((host == url.Host()) &&
          (port == url.Port()) &&
          (scheme == url.Protocol()) &&
          (username == url.Username()) &&
          (userpass == url.Passwd())) {
        /* same server - check if connection alive */
        logger.msg(VERBOSE, "Reusing connection");
        if (send_command("NOOP", NULL, true, NULL) ==
            GLOBUS_FTP_POSITIVE_COMPLETION_REPLY)
          reconnect = false;
      }

    path = url.Path();
    if ((path.length() != 0) && (path[path.length() - 1] == '/'))
      path.resize(path.length() - 1);
    if (reconnect) {
      connected = false;
      pasv_set = false;
      port = url.Port();
      scheme = url.Protocol();
      host = url.Host();
      username = url.Username();
      userpass = url.Passwd();
      /*
         !!!!!!!!!!!!!!!!!!!!!!!!!!!
         disconnect here ???????????
       */
      if (!(res = globus_ftp_control_connect(handle,
                                             const_cast<char*>(host.c_str()),
                                             port, &resp_callback, this))) {
        logger.msg(ERROR, "Failed connecting to server %s:%d",
                   host.c_str(), port);
        logger.msg(ERROR, "Failure: %s", res.str());
        return -1;
      }
      if (wait_for_callback() != CALLBACK_DONE) {
        logger.msg(ERROR, "Failed to connect to server %s:%d",
                   host.c_str(), port);
        resp_destroy();
        return -1;
      }
      resp_destroy();
      char *username_ = const_cast<char*>(username.c_str());
      char *userpass_ = const_cast<char*>(userpass.c_str());
      globus_bool_t use_auth;
      if (scheme == "gsiftp") {
        if (username.empty())
          username_ = default_gsiftp_user;
        if (userpass.empty())
          userpass_ = default_gsiftp_pass;
        if (globus_ftp_control_auth_info_init(&auth, credential,
                                              GLOBUS_TRUE, username_,
                                              userpass_, GLOBUS_NULL,
                                              GLOBUS_NULL) !=
            GLOBUS_SUCCESS) {
          logger.msg(ERROR, "Bad authentication information");
          return -1;
        }
        use_auth = GLOBUS_TRUE;
      }
      else {
        if (username.empty())
          username_ = default_ftp_user;
        if (userpass.empty())
          userpass_ = default_ftp_pass;
        if (globus_ftp_control_auth_info_init(&auth, GSS_C_NO_CREDENTIAL,
                                              GLOBUS_FALSE, username_,
                                              userpass_, GLOBUS_NULL,
                                              GLOBUS_NULL) !=
            GLOBUS_SUCCESS) {
          logger.msg(ERROR, "Bad authentication information");
          return -1;
        }
        use_auth = GLOBUS_FALSE;
      }
      if (globus_ftp_control_authenticate(handle, &auth, use_auth,
                                          resp_callback, this) !=
          GLOBUS_SUCCESS) {
        logger.msg(ERROR, "Failed authenticating");
        return -1;
      }
      if (wait_for_callback() != CALLBACK_DONE) {
        logger.msg(ERROR, "Failed authenticating");
        resp_destroy();
        return -1;
      }
      resp_destroy();
      connected = true;
    }
    return 0;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

void Arc::Lister::list_conn_callback ( void *  arg,
globus_ftp_control_handle_t *  hctrl,
unsigned int  stripe_ndx,
globus_bool_t  reused,
globus_object_t *  error 
) [static, private]

Definition at line 288 of file Lister.cpp.

                                                          {
    /* if(!callback_active) return; */
    Lister *it = (Lister*)arg;
    if (error != GLOBUS_SUCCESS) {
      std::string tmp = globus_object_to_string(error);
      logger.msg(INFO, "Failure: %s", tmp);
      globus_mutex_lock(&(it->mutex));
      it->data_callback_status = CALLBACK_ERROR;
      globus_cond_signal(&(it->cond));
      globus_mutex_unlock(&(it->mutex));
      return;
    }
    it->list_shift = 0;
    it->fnames.clear();
    it->data_activated = true;
    if (globus_ftp_control_data_read(hctrl, (globus_byte_t*)(it->readbuf),
                                     sizeof(it->readbuf) - 1,
                                     &list_read_callback, arg) !=
        GLOBUS_SUCCESS) {
      logger.msg(INFO, "Failed reading data");
      globus_mutex_lock(&(it->mutex));
      it->data_callback_status = CALLBACK_ERROR;
      globus_cond_signal(&(it->cond));
      globus_mutex_unlock(&(it->mutex));
      return;
    }
  }

Here is the call graph for this function:

Here is the caller graph for this function:

void Arc::Lister::list_read_callback ( void *  arg,
globus_ftp_control_handle_t *  hctrl,
globus_object_t *  error,
globus_byte_t *  buffer,
globus_size_t  length,
globus_off_t  offset,
globus_bool_t  eof 
) [static, private]

Definition at line 170 of file Lister.cpp.

                                                     {
    Lister *it = (Lister*)arg;
    if(!it->data_activated) return;
    length += it->list_shift;
    if (error != GLOBUS_SUCCESS) {
      /* no such file or connection error - assume no such file */
      logger.msg(INFO, "Error getting list of files (in list)");
      std::string tmp = globus_object_to_string(error);
      logger.msg(INFO, "Failure: %s", tmp);
      logger.msg(INFO, "Assuming - file not found");
      globus_mutex_lock(&(it->mutex));
      it->data_callback_status = CALLBACK_ERROR;
      globus_cond_signal(&(it->cond));
      globus_mutex_unlock(&(it->mutex));
      return;
    }
    /* parse names and add to list */
    /* suppose we are receiving ordered blocks of data (no multiple streams) */
    char *name;
    (it->readbuf)[length] = 0;
    name = it->readbuf;
    it->list_shift = 0;
    for (;;) {
      if ((*name) == 0)
        break;
      globus_size_t nlen;
      nlen = strcspn(name, "\n\r");
      name[nlen] = 0;
      logger.msg(VERBOSE, "list record: %s", name);
      if (nlen == length)
        if (!eof) {
          memmove(it->readbuf, name, nlen);
          it->list_shift = nlen;
          break;
        }
      if (nlen == 0) { // skip empty std::string
        if (length == 0)
          break;
        name++;
        length--;
        continue;
      }
      char *attrs = name;
      if (it->facts) {
        for (; *name;) {
          nlen--;
          length--;
          if (*name == ' ') {
            name++;
            break;
          }
          name++;
        }
      }
      if(it->free_format) {
        // assuming it is 'ls -l'-like
        // a lot of attributes followed by filename
        // NOTE: it is not possible to reliably distinguish files
        // with empty spaces. So assuming no such files.
        char* name_start = strrchr(name,' ');
        if(name_start) {
          nlen-=(name_start-name+1);
          length-=(name_start-name+1);
          name=name_start+1;
        };
      };
      std::list<FileInfo>::iterator i;
      if (name[0] == '/') {
        i = it->fnames.insert(it->fnames.end(), FileInfo(name));
      } else {
        std::string name_ = !it->path.empty() ? it->path : "/";
        // Workaround for bug in our gridftp server!
        if(name[0]) {
          name_ += "/";
          name_ += name;
        }
        i = it->fnames.insert(it->fnames.end(), FileInfo(name_));
      }
      if (it->facts)
        SetAttributes(*i, attrs);
      if (nlen == length)
        break;
      name += (nlen + 1);
      length -= (nlen + 1);
      if (((*name) == '\r') || ((*name) == '\n')) {
        name++;
        length--;
      }
    }
    if (!eof) {
      if (globus_ftp_control_data_read(it->handle, (globus_byte_t*)
                                       ((it->readbuf) + (it->list_shift)),
                                       sizeof(it->readbuf) -
                                       (it->list_shift) - 1,
                                       &list_read_callback, arg) !=
          GLOBUS_SUCCESS) {
        logger.msg(INFO, "Failed reading list of files");
        globus_mutex_lock(&(it->mutex));
        it->data_callback_status = CALLBACK_ERROR;
        globus_cond_signal(&(it->cond));
        globus_mutex_unlock(&(it->mutex));
      }
      return;
    }
    it->data_activated = false;
    globus_mutex_lock(&(it->mutex));
    it->data_callback_status = CALLBACK_DONE;
    globus_cond_signal(&(it->cond));
    globus_mutex_unlock(&(it->mutex));
    return;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

Arc::Lister::operator bool ( ) [inline]

Definition at line 79 of file Lister.h.

                    {
      return inited;
    }
void Arc::Lister::resp_callback ( void *  arg,
globus_ftp_control_handle_t *  h,
globus_object_t *  error,
globus_ftp_control_response_t *  response 
) [static, private]

Definition at line 133 of file Lister.cpp.

                                                                      {
    Lister *it = (Lister*)arg;
    globus_mutex_lock(&(it->mutex));
    if (error != GLOBUS_SUCCESS) {
      it->callback_status = CALLBACK_ERROR;
      std::string tmp = globus_object_to_string(error);
      logger.msg(INFO, "Failure: %s", tmp);
      if (response)
        logger.msg(INFO, "Response: %s", response->response_buffer);
    }
    else {
      if (it->resp_n < LISTER_MAX_RESPONSES) {
        memmove((it->resp) + 1, it->resp,
                sizeof(globus_ftp_control_response_t) * (it->resp_n));
        if (response->response_buffer) {
          globus_ftp_control_response_copy(response, it->resp);
        } else {    // invalid reply causes *_copy to segfault
          it->resp->response_buffer = (globus_byte_t*)strdup("000 ");
          it->resp->response_buffer_size = 5;
          it->resp->response_length = 4;
          it->resp->code = 0;
          it->resp->response_class = GLOBUS_FTP_UNKNOWN_REPLY;
        }
        (it->resp_n)++;
      }
      it->callback_status = CALLBACK_DONE;
      if(response->response_buffer) {
        dos_to_unix((char*)(response->response_buffer));
        logger.msg(VERBOSE, "Response(%i): %s", (int)(response->response_length), response->response_buffer);
      }
    }
    globus_cond_signal(&(it->cond));
    globus_mutex_unlock(&(it->mutex));
  }

Here is the call graph for this function:

Here is the caller graph for this function:

void Arc::Lister::resp_destroy ( ) [private]

Definition at line 124 of file Lister.cpp.

                            {
    globus_mutex_lock(&mutex);
    if (resp_n > 0) {
      globus_ftp_control_response_destroy(resp + (resp_n - 1));
      resp_n--;
    }
    globus_mutex_unlock(&mutex);
  }

Here is the caller graph for this function:

int Arc::Lister::retrieve_dir_info ( const URL url,
bool  names_only = false 
)

Definition at line 785 of file Lister.cpp.

                                                              {
    if(handle_connect(url) != 0) return -1;
    globus_ftp_control_response_class_t cmd_resp;
    char *sresp = NULL;
    if (url.Protocol() == "gsiftp") {
      cmd_resp = send_command("DCAU", "N", true, &sresp, '"');
      if ((cmd_resp != GLOBUS_FTP_POSITIVE_COMPLETION_REPLY) &&
          (cmd_resp != GLOBUS_FTP_PERMANENT_NEGATIVE_COMPLETION_REPLY)) {
        if (sresp) {
          logger.msg(INFO, "DCAU failed: %s", sresp);
          free(sresp);
        }
        else
          logger.msg(INFO, "DCAU failed");
        return -1;
      }
      free(sresp);
    }
    globus_ftp_control_dcau_t dcau;
    dcau.mode = GLOBUS_FTP_CONTROL_DCAU_NONE;
    globus_ftp_control_local_dcau(handle, &dcau, GSS_C_NO_CREDENTIAL);
    globus_ftp_control_host_port_t pasv_addr;
    facts = true;
    free_format = false;
    if (setup_pasv(pasv_addr) != 0)
      return -1;
    if(!names_only) {
      /* try MLSD */
      cmd_resp = send_command("MLSD", path.c_str(), true, &sresp);
      if (cmd_resp == GLOBUS_FTP_PERMANENT_NEGATIVE_COMPLETION_REPLY) {
        logger.msg(INFO, "MLSD is not supported - trying NLST");
        free(sresp);
        /* run NLST */
        facts = false;
        cmd_resp = send_command("NLST", path.c_str(), true, &sresp);
      }
    } else {
      facts = false;
      cmd_resp = send_command("NLST", path.c_str(), true, &sresp);
    }
    if (cmd_resp == GLOBUS_FTP_POSITIVE_COMPLETION_REPLY) {
      /* completion is not expected here */
      pasv_set = false;
      logger.msg(INFO, "Immediate completion: %s", sresp);
      if (sresp)
        free(sresp);
      return -1;
    }
    if ((cmd_resp != GLOBUS_FTP_POSITIVE_PRELIMINARY_REPLY) &&
        (cmd_resp != GLOBUS_FTP_POSITIVE_INTERMEDIATE_REPLY)) {
      if (sresp) {
        logger.msg(INFO, "NLST/MLSD failed: %s", sresp);
        free(sresp);
      }
      else
        logger.msg(INFO, "NLST/MLSD failed");
      return -1;
    }
    free(sresp);
    return transfer_list();
  }

Here is the call graph for this function:

Here is the caller graph for this function:

int Arc::Lister::retrieve_file_info ( const URL url,
bool  names_only = false 
)

Definition at line 669 of file Lister.cpp.

                                                               {
    if(handle_connect(url) != 0) return -1;
    globus_ftp_control_response_class_t cmd_resp;
    char *sresp;
    if (url.Protocol() == "gsiftp") {
      cmd_resp = send_command("DCAU", "N", true, &sresp, '"');
      if ((cmd_resp != GLOBUS_FTP_POSITIVE_COMPLETION_REPLY) &&
          (cmd_resp != GLOBUS_FTP_PERMANENT_NEGATIVE_COMPLETION_REPLY)) {
        if (sresp) {
          logger.msg(INFO, "DCAU failed: %s", sresp);
          free(sresp);
        }
        else
          logger.msg(INFO, "DCAU failed");
        return -1;
      }
      free(sresp);
    }
    globus_ftp_control_dcau_t dcau;
    dcau.mode = GLOBUS_FTP_CONTROL_DCAU_NONE;
    globus_ftp_control_local_dcau(handle, &dcau, GSS_C_NO_CREDENTIAL);
    globus_ftp_control_host_port_t pasv_addr;
    facts = true;
    free_format = false;
    if(!names_only) {
      /* try MLST */
      cmd_resp = send_command("MLST", path.c_str(), true, &sresp);
      if (cmd_resp == GLOBUS_FTP_PERMANENT_NEGATIVE_COMPLETION_REPLY) {
        logger.msg(INFO, "MLST is not supported - trying LIST");
        free(sresp);
        /* run NLST */
        if (setup_pasv(pasv_addr) != 0)
          return -1;
        facts = false;
        free_format = true;
        cmd_resp = send_command("LIST", path.c_str(), true, &sresp);
      } else {
        // MLST replies through control channel
        // 250 -
        //  information
        // 250 -
        if (cmd_resp != GLOBUS_FTP_POSITIVE_COMPLETION_REPLY) {
          logger.msg(INFO, "Immediate completion expected: %s", sresp);
          free(sresp);
          return -1;
        }
        // Try to collect full response
        char* nresp = strchr(sresp,'\n');
        if(nresp) {
          ++nresp;
        } else {
          free(sresp);
          cmd_resp = send_command(NULL, NULL, true, &sresp);
          if(cmd_resp != GLOBUS_FTP_UNKNOWN_REPLY) {
            logger.msg(INFO, "Missing information in reply: %s", sresp);
            free(sresp);
            return -1;
          }
          nresp=sresp;
        }
        char* fresp = NULL;
        if(nresp) {
          if(*nresp == ' ') ++nresp;
          fresp=strchr(nresp,'\n');
          // callback
          *fresp=0;
          list_shift = 0;
          fnames.clear();
          int nlength = strlen(nresp);
          if(nlength > sizeof(readbuf)) nlength=sizeof(readbuf);
          memcpy(readbuf,nresp,nlength);
          list_read_callback(this,handle,GLOBUS_SUCCESS,
                             (globus_byte_t*)readbuf,nlength,0,1);
        };
        if(fresp) {
          ++fresp;
        } else {
          free(sresp);
          cmd_resp = send_command(NULL, NULL, true, &sresp);
          if(cmd_resp != GLOBUS_FTP_POSITIVE_COMPLETION_REPLY) {
            logger.msg(INFO, "Missing final reply: %s", sresp);
            free(sresp);
            return -1;
          }
          fresp=sresp;
        }
        free(sresp);
        return 0; 
      }
    } else {
      if (setup_pasv(pasv_addr) != 0) return -1;
      facts = false;
      free_format = true;
      cmd_resp = send_command("LIST", path.c_str(), true, &sresp);
    }
    if (cmd_resp == GLOBUS_FTP_POSITIVE_COMPLETION_REPLY) {
      /* completion is not expected here */
      pasv_set = false;
      logger.msg(INFO, "Unexpected immediate completion: %s", sresp);
      if (sresp) free(sresp);
      return -1;
    }
    if ((cmd_resp != GLOBUS_FTP_POSITIVE_PRELIMINARY_REPLY) &&
        (cmd_resp != GLOBUS_FTP_POSITIVE_INTERMEDIATE_REPLY)) {
      if (sresp) {
        logger.msg(INFO, "LIST/MLST failed: %s", sresp);
        free(sresp);
      }
      else
        logger.msg(INFO, "LIST/MLST failed");
      return -1;
    }
    free(sresp);
    return transfer_list();
  }

Here is the call graph for this function:

Here is the caller graph for this function:

globus_ftp_control_response_class_t Arc::Lister::send_command ( const char *  command,
const char *  arg,
bool  wait_for_response,
char **  sresp,
char  delim = 0 
) [private]

Definition at line 320 of file Lister.cpp.

                                                                                                                                                 {
    char *cmd = NULL;
    if (sresp)
      (*sresp) = NULL;
    if (command) { /* if no command - waiting for second reply */
      globus_mutex_lock(&mutex);
      for (int i = 0; i < resp_n; i++)
        globus_ftp_control_response_destroy(resp + i);
      resp_n = 0;
      callback_status = CALLBACK_NOTREADY;
      globus_mutex_unlock(&mutex);
      {
        std::string cmds(command);
        if(arg) {
          cmds += " ";
          cmds += arg;
        }
        logger.msg(VERBOSE, "Command: %s", cmds);
        cmds += "\r\n";
        cmd = (char*)malloc(cmds.length()+1);
        if (cmd == NULL) {
          logger.msg(ERROR, "Memory allocation error");
          return GLOBUS_FTP_UNKNOWN_REPLY;
        }
        strncpy(cmd,cmds.c_str(),cmds.length()+1);
        cmd[cmds.length()] = 0;
      }
      if (globus_ftp_control_send_command(handle, cmd, resp_callback, this)
          != GLOBUS_SUCCESS) {
        logger.msg(VERBOSE, "%s failed", command);
        if (cmd)
          free(cmd);
        return GLOBUS_FTP_UNKNOWN_REPLY;
      }
      logger.msg(DEBUG, "Command is being sent");
    }
    if (wait_for_response) {
      globus_mutex_lock(&mutex);
      while ((callback_status == CALLBACK_NOTREADY) && (resp_n == 0)) {
        logger.msg(DEBUG, "Waiting for response");
        globus_cond_wait(&cond, &mutex);
      }
      free(cmd);
      if (callback_status != CALLBACK_DONE) {
        logger.msg(DEBUG, "Callback got failure");
        callback_status = CALLBACK_NOTREADY;
        if (resp_n > 0) {
          globus_ftp_control_response_destroy(resp + (resp_n - 1));
          resp_n--;
        }
        globus_mutex_unlock(&mutex);
        return GLOBUS_FTP_UNKNOWN_REPLY;
      }
      if ((sresp) && (resp_n > 0)) {
        if (delim == 0) {
          (*sresp) = (char*)malloc(resp[resp_n - 1].response_length);
          if ((*sresp) != NULL) {
            memcpy(*sresp, (char*)(resp[resp_n - 1].response_buffer + 4),
                   resp[resp_n - 1].response_length - 4);
            (*sresp)[resp[resp_n - 1].response_length - 4] = 0;
            logger.msg(VERBOSE, "Response: %s", *sresp);
          }
          else
            logger.msg(ERROR, "Memory allocation error");
        }
        else {
          /* look for pair of enclosing characters */
          logger.msg(VERBOSE, "Response: %s", resp[resp_n - 1].response_buffer);
          char *s_start = (char*)(resp[resp_n - 1].response_buffer + 4);
          char *s_end = NULL;
          int l = 0;
          s_start = strchr(s_start, delim);
          if (s_start) {
            s_start++;
            if (delim == '(')
              delim = ')';
            else if (delim == '{')
              delim = '}';
            else if (delim == '[')
              delim = ']';
            s_end = strchr(s_start, delim);
            if (s_end)
              l = s_end - s_start;
          }
          if (l > 0) {
            (*sresp) = (char*)malloc(l + 1);
            if ((*sresp) != NULL) {
              memcpy(*sresp, s_start, l);
              (*sresp)[l] = 0;
              logger.msg(VERBOSE, "Response: %s", *sresp);
            }
          }
        }
      }
      globus_ftp_control_response_class_t resp_class =
        GLOBUS_FTP_UNKNOWN_REPLY;
      if (resp_n > 0) {
        resp_class = resp[resp_n - 1].response_class;
        globus_ftp_control_response_destroy(resp + (resp_n - 1));
        resp_n--;
      }
      if (resp_n == 0)
        callback_status = CALLBACK_NOTREADY;
      globus_mutex_unlock(&mutex);
      return resp_class;
    }
    else
      return GLOBUS_FTP_POSITIVE_COMPLETION_REPLY;
    /* !!!!!!! Memory LOST - cmd !!!!!!!! */
  }

Here is the call graph for this function:

Here is the caller graph for this function:

int Arc::Lister::setup_pasv ( globus_ftp_control_host_port_t &  pasv_addr) [private]

Definition at line 511 of file Lister.cpp.

                                                                  {
    if(pasv_set) return 0;
    char *sresp;
    GlobusResult res;
    if (send_command("PASV", NULL, true, &sresp, '(') !=
        GLOBUS_FTP_POSITIVE_COMPLETION_REPLY) {
      if (sresp) {
        logger.msg(INFO, "PASV failed: %s", sresp);
        free(sresp);
      }
      else
        logger.msg(INFO, "PASV failed");
      return -1;
    }
    pasv_addr.port = 0;
    if (sresp) {
      int port_low, port_high;
      if (sscanf(sresp, "%i,%i,%i,%i,%i,%i",
                 &(pasv_addr.host[0]), &(pasv_addr.host[1]),
                 &(pasv_addr.host[2]), &(pasv_addr.host[3]),
                 &port_high, &port_low) == 6)
        pasv_addr.port = ((port_high & 0x000FF) << 8) | (port_low & 0x000FF);
    }
    if (pasv_addr.port == 0) {
      logger.msg(INFO, "Can't parse host and port in response to PASV");
      if (sresp)
        free(sresp);
      return -1;
    }
    free(sresp);
    logger.msg(VERBOSE, "Data channel: %d.%d.%d.%d %d", pasv_addr.host[0],
               pasv_addr.host[1], pasv_addr.host[2], pasv_addr.host[3],
               pasv_addr.port);
    if (!(res = globus_ftp_control_local_port(handle, &pasv_addr))) {
      logger.msg(INFO, "Obtained host and address are not acceptable");
      logger.msg(INFO, "Failure: %s", res.str());
      return -1;
    }
    /* it looks like _pasv is not enough for connection - start reading
       immediately */
    data_callback_status = (callback_status_t)CALLBACK_NOTREADY;
    if (globus_ftp_control_data_connect_read(handle, &list_conn_callback,
                                             this) != GLOBUS_SUCCESS) {
      logger.msg(INFO, "Failed to open data channel");
      pasv_set = false;
      return -1;
    }
    pasv_set = true;
    return 0;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

int Arc::Lister::size ( ) const [inline]

Definition at line 88 of file Lister.h.

                     {
      return fnames.size();
    }
int Arc::Lister::transfer_list ( void  ) [private]

Definition at line 847 of file Lister.cpp.

                                {
    globus_ftp_control_response_class_t cmd_resp;
    char* sresp = NULL;
    /* start transfer */
    for (;;) {
      /* waiting for response received */
      cmd_resp = send_command(NULL, NULL, true, &sresp);
      if (cmd_resp == GLOBUS_FTP_POSITIVE_COMPLETION_REPLY)
        break;
      if ((cmd_resp != GLOBUS_FTP_POSITIVE_PRELIMINARY_REPLY) &&
          (cmd_resp != GLOBUS_FTP_POSITIVE_INTERMEDIATE_REPLY)) {
        if (sresp) {
          logger.msg(INFO, "Data transfer aborted: %s", sresp);
          free(sresp);
        }
        else
          logger.msg(INFO, "Data transfer aborted");
        // Destroy data connections here ?????????
        pasv_set = false;
        return -1;
      }
      if (sresp)
        free(sresp);
    }
    if (sresp)
      free(sresp);
    /* waiting for data ended */
    if (wait_for_data_callback() != CALLBACK_DONE) {
      logger.msg(INFO, "Failed to transfer data");
      pasv_set = false;
      return -1;
    }
    pasv_set = false;
    /* success */
    return 0;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 102 of file Lister.cpp.

                                                    {
    callback_status_t res;
    globus_mutex_lock(&mutex);
    while (callback_status == CALLBACK_NOTREADY)
      globus_cond_wait(&cond, &mutex);
    res = callback_status;
    callback_status = CALLBACK_NOTREADY;
    globus_mutex_unlock(&mutex);
    return res;
  }

Here is the caller graph for this function:

Definition at line 113 of file Lister.cpp.

                                                         {
    callback_status_t res;
    globus_mutex_lock(&mutex);
    while (data_callback_status == CALLBACK_NOTREADY)
      globus_cond_wait(&cond, &mutex);
    res = data_callback_status;
    data_callback_status = CALLBACK_NOTREADY;
    globus_mutex_unlock(&mutex);
    return res;
  }

Here is the caller graph for this function:


Member Data Documentation

Definition at line 36 of file Lister.h.

globus_cond_t Arc::Lister::cond [private]

Definition at line 25 of file Lister.h.

bool Arc::Lister::connected [private]

Definition at line 39 of file Lister.h.

Definition at line 49 of file Lister.h.

Definition at line 41 of file Lister.h.

Definition at line 37 of file Lister.h.

bool Arc::Lister::facts [private]

Definition at line 23 of file Lister.h.

std::list<FileInfo> Arc::Lister::fnames [private]

Definition at line 28 of file Lister.h.

bool Arc::Lister::free_format [private]

Definition at line 42 of file Lister.h.

globus_ftp_control_handle_t* Arc::Lister::handle [private]

Definition at line 27 of file Lister.h.

std::string Arc::Lister::host [private]

Definition at line 44 of file Lister.h.

bool Arc::Lister::inited [private]

Definition at line 22 of file Lister.h.

globus_off_t Arc::Lister::list_shift [private]

Definition at line 38 of file Lister.h.

globus_mutex_t Arc::Lister::mutex [private]

Definition at line 26 of file Lister.h.

bool Arc::Lister::pasv_set [private]

Definition at line 40 of file Lister.h.

std::string Arc::Lister::path [private]

Definition at line 47 of file Lister.h.

unsigned short int Arc::Lister::port [private]

Definition at line 43 of file Lister.h.

char Arc::Lister::readbuf[4096] [private]

Definition at line 24 of file Lister.h.

globus_ftp_control_response_t Arc::Lister::resp[LISTER_MAX_RESPONSES] [private]

Definition at line 29 of file Lister.h.

int Arc::Lister::resp_n [private]

Definition at line 30 of file Lister.h.

std::string Arc::Lister::scheme [private]

Definition at line 48 of file Lister.h.

std::string Arc::Lister::username [private]

Definition at line 45 of file Lister.h.

std::string Arc::Lister::userpass [private]

Definition at line 46 of file Lister.h.


The documentation for this class was generated from the following files: