/* Get an ftp connection to use for an operation. */ error_t ftpfs_get_ftp_conn (struct ftpfs *fs, struct ftp_conn **conn) { struct ftpfs_conn *fsc; pthread_spin_lock (&fs->conn_lock); fsc = fs->free_conns; if (fsc) fs->free_conns = fsc->next; pthread_spin_unlock (&fs->conn_lock); if (! fsc) { error_t err; fsc = malloc (sizeof (struct ftpfs_conn)); if (! fsc) return ENOMEM; err = ftp_conn_create (fs->ftp_params, fs->ftp_hooks, &fsc->conn); if (! err) { /* Set connection type to binary. */ err = ftp_conn_set_type (fsc->conn, "I"); if (err) ftp_conn_free (fsc->conn); } if (err) { free (fsc); return err; } /* For debugging purposes, give each connection a unique integer id. */ fsc->conn->hook = (void *)(uintptr_t)conn_id++; } pthread_spin_lock (&fs->conn_lock); fsc->next = fs->conns; fs->conns = fsc; pthread_spin_unlock (&fs->conn_lock); *conn = fsc->conn; return 0; }
/* Return an ftp connection for the host NAME using PARAMS, and add an entry for it to *HOSTS. If a connection already exists in HOSTS, it is returned instead of making a new one. If an error occurrs, a message is printed and 0 is returned. */ static struct ftpdir_host * get_host_conn (char *name, struct ftp_conn_params *params, struct ftpdir_host **hosts) { error_t err; struct ftpdir_host *h; struct hostent *he; for (h = *hosts; h; h = h->next) if (strcmp (h->name, name) == 0) return h; he = gethostbyname (name); if (! he) { error (0, 0, "%s: %s", name, hstrerror (h_errno)); return 0; } for (h = *hosts; h; h = h->next) if (he->h_addrtype == h->params.addr_type && he->h_length == h->params.addr_len && bcmp (he->h_addr_list[0], h->params.addr, he->h_length) == 0) return h; h = malloc (sizeof (struct ftpdir_host)); if (! h) { error (0, ENOMEM, "%s", name); return 0; } h->params = *params; h->params.addr = malloc (he->h_length); h->name = strdup (he->h_name); if (!h->name || !h->params.addr) err = ENOMEM; else { bcopy (he->h_addr_list[0], h->params.addr, he->h_length); h->params.addr_len = he->h_length; h->params.addr_type = he->h_addrtype; err = ftp_conn_create (&h->params, &conn_hooks, &h->conn); } if (err) { error (0, err, "%s", he->h_name); if (h->name) free (h->name); if (h->params.addr) free (h->params.addr); free (h); return 0; } h->next = *hosts; *hosts = h; return h; }