Exemple #1
0
static int
fsp_connect (gftp_request * request)
{
  fsp_protocol_data * lpd;
  intptr_t network_timeout;

  g_return_val_if_fail (request != NULL, GFTP_EFATAL);
  g_return_val_if_fail (request->protonum == GFTP_FSP_NUM, GFTP_EFATAL);

  if(! request->port)
      request->port = gftp_protocol_default_port (request);

  lpd = request->protocol_data;
  lpd->fsp=fsp_open_session(request->hostname, request->port, request->password);

  if(lpd->fsp == NULL)
    return (GFTP_ERETRYABLE);
  /* set up network timeout */
  gftp_lookup_request_option (request, "network_timeout", &network_timeout);
  lpd->fsp->timeout=1000*network_timeout;

  if (!request->directory)
    request->directory = g_strdup ("/");

  request->datafd = lpd->fsp->fd;
  return (0);
}
Exemple #2
0
static void
do_fsp(struct connection *conn)
{
	FSP_SESSION *ses;
	struct stat sb;
	struct uri *uri = conn->uri;
	struct auth_entry *auth;
	unsigned char *host = get_uri_string(uri, URI_HOST);
	unsigned char *data = get_uri_string(uri, URI_DATA);
	unsigned short port = (unsigned short)get_uri_port(uri);
	unsigned char *password = NULL;

	decode_uri(data);
	if (uri->passwordlen) {
		password = get_uri_string(uri, URI_PASSWORD);
	} else {
		auth = find_auth(uri);
		if (auth) password = auth->password;
	}

	/* fsp_open_session may not set errno if getaddrinfo fails
	 * https://sourceforge.net/tracker/index.php?func=detail&aid=2036798&group_id=93841&atid=605738
	 * Try to detect this bug and use an ELinks-specific error
	 * code instead, so that we can display a message anyway.  */
	errno = 0;
	ses = fsp_open_session(host, port, password);
	if (!ses) {
		if (errno)
			fsp_error(connection_state_for_errno(errno));
		else
			fsp_error(connection_state(S_FSP_OPEN_SESSION_UNKN));
	}

	/* fsplib 0.8 ABI depends on _FILE_OFFSET_BITS
	 * https://sourceforge.net/tracker/index.php?func=detail&aid=1674729&group_id=93841&atid=605738
	 * If ELinks and fsplib are using different values of
	 * _FILE_OFFSET_BITS, then they get different definitions of
	 * struct stat, and the st_size stored by fsp_stat is
	 * typically not the same as the st_size read by ELinks.
	 * Fortunately, st_mode seems to have the same offset and size
	 * in both versions of struct stat.
	 *
	 * If all the bytes used by the 32-bit st_size are also used
	 * by the 64-bit st_size, then ELinks may be able to guess
	 * which ones they are, because the current version 2 of FSP
	 * supports only 32-bit file sizes in protocol packets.  Begin
	 * by filling struct stat with 0xAA so that it's easier to
	 * detect which bytes fsp_stat has left unchanged.  (Only
	 * sb.st_size really needs to be filled, but filling the rest
	 * too helps viewing the data with a debugger.)  */
	memset(&sb, 0xAA, sizeof(sb));
	if (fsp_stat(ses, data, &sb)) fsp_error(connection_state_for_errno(errno));

	if (S_ISDIR(sb.st_mode)) {
		fsp_directory(ses, uri);
	} else { /* regular file */
		char buf[READ_SIZE];
		FSP_FILE *file = fsp_fopen(ses, data, "r");
		int r;

		if (!file) {
			fsp_error(connection_state_for_errno(errno));
		}

#if SIZEOF_OFF_T >= 8
		if (sb.st_size < 0 || sb.st_size > 0xFFFFFFFF) {
			/* Probably a _FILE_OFFSET_BITS mismatch as
			 * described above.  Try to detect which half
			 * of st_size is the real size.  This may
			 * depend on the endianness of the processor
			 * and on the padding in struct stat.  */
			if ((sb.st_size & 0xFFFFFFFF00000000ULL) == 0xAAAAAAAA00000000ULL)
				sb.st_size = sb.st_size & 0xFFFFFFFF;
			else if ((sb.st_size & 0xFFFFFFFF) == 0xAAAAAAAA)
				sb.st_size = (sb.st_size >> 32) & 0xFFFFFFFF;
			else	/* Can't figure it out. */
				sb.st_size = 1;
		}
#endif

		/* Send filesize */
		fprintf(stderr, "%" OFF_PRINT_FORMAT "\n",
			(off_print_T) sb.st_size);
		fclose(stderr);

		while ((r = fsp_fread(buf, 1, READ_SIZE, file)) > 0) {
			int off = 0;

			while (r) {
				int w = safe_write(STDOUT_FILENO, buf + off, r);

				if (w == -1) goto out;
				off += w;
				r -= w;
			}
		}
out:
		fsp_fclose(file);
		fsp_close_session(ses);
		exit(0);
	}