Esempio n. 1
0
/**
 * mate_vfs_resolve:
 * @hostname: hostname you want to resolve.
 * @handle: pointer to a pointer to a #MateVFSResolveHandle.
 *
 * Tries to resolve @hostname. If the operation was successful you can
 * get the resolved addresses in form of #MateVFSAddress by calling
 * mate_vfs_resolve_next_address().
 * 
 * Return value: A #MateVFSResult indicating the success of the operation.
 *
 * Since: 2.8
 */
MateVFSResult
mate_vfs_resolve (const char              *hostname,
			    MateVFSResolveHandle  **handle)
{
#ifdef HAVE_GETADDRINFO
	   struct addrinfo hints, *result;
	   int res;
	   gboolean retry = TRUE;

restart:	   
	   memset (&hints, 0, sizeof (hints));
	   hints.ai_socktype = SOCK_STREAM;

#ifdef ENABLE_IPV6
# ifdef HAVE_AI_ADDRCONFIG /* RFC3493 */
	   hints.ai_flags = AI_ADDRCONFIG;
	   hints.ai_family = AF_UNSPEC;
# else	
	   hints.ai_family = AF_UNSPEC;
# endif	
#else
	   hints.ai_family = AF_INET;
#endif /* ENABLE_IPV6 */
	   res = getaddrinfo (hostname, NULL, &hints, &result);
	   
	   if (res != 0) {
			 if (retry && restart_resolve ()) {
				    retry = FALSE;
				    goto restart;
			 } else {
				    return _mate_vfs_result_from_gai_error (res);
			 }
	   }

	   *handle = g_new0 (MateVFSResolveHandle, 1);
	   
	   (*handle)->result  = result;
	   (*handle)->current = result;
	   
	   return MATE_VFS_OK;
#else /* HAVE_GETADDRINFO */
	   struct hostent resbuf, *result = &resbuf;
	   MateVFSResult ret;
	   int res;
	   gboolean retry = TRUE;
#ifdef HAVE_GETHOSTBYNAME_R_GLIBC
	   size_t buflen;
	   char *buf;
	   int h_errnop;

restart:	   
	   buf = NULL;
	   buflen = INIT_BUFSIZE;
	   h_errnop = 0;
	   
	   do {
			 buf = g_renew (char, buf, buflen);
			 
			 res = gethostbyname_r (hostname,
							    &resbuf,
							    buf,
							    buflen,
							    &result,
							    &h_errnop);
			 buflen *= 2;

	   } while (res == ERANGE);

	   if (res != 0 || result == NULL || result->h_addr_list[0] == NULL) {
			 g_free (buf);
			 if (retry && restart_resolve ()) {
				    retry = FALSE;
				    goto restart;
			 } else {
				    return mate_vfs_result_from_h_errno_val (h_errnop);
			 }
	   }

	   ret = resolvehandle_from_hostent (result, handle);
	   g_free (buf);
#elif HAVE_GETHOSTBYNAME_R_SOLARIS
	   size_t buflen;
	   char *buf;
	   int h_errnop;	   
restart:
	   
	   buf = NULL;
	   buflen = INIT_BUFSIZE;
	   h_errnop = 0;
	   
	   do {
			 buf = g_renew (char, buf, buflen);
			 
			 result = gethostbyname_r (hostname,
								  &resbuf,
								  buf,
								  buflen,
								  &h_errnop);
			 buflen *= 2;

	   } while (h_errnop == ERANGE);

	   if (result == NULL) {
			 g_free (buf);
		   
			 if (retry && restart_resolve ()) {
				    retry = FALSE;
				    goto restart;
			 } else {
				    return mate_vfs_result_from_h_errno_val (h_errnop);
			 }
	   }

	   ret = resolvehandle_from_hostent (result, handle);	
	   g_free (buf);
#elif HAVE_GETHOSTBYNAME_R_HPUX
	   struct hostent_data buf;

restart:
	   res = gethostbyname_r (hostname, result, &buf);

	   if (res != 0) {
			 if (retry && restart_resolve ()) {
				    retry = FALSE;
				    goto restart;
			 } else {
				    return mate_vfs_result_from_h_errno_val (h_errnop);
			 }
	   }

	   ret = resolvehandle_from_hostent (result, handle);
#else /* !HAVE_GETHOSTBYNAME_R_GLIBC && !HAVE_GETHOSTBYNAME_R_SOLARIS && !HAVE_GETHOSTBYNAME_R_HPUX */
	   res = 0;/* only set to avoid unused variable error */
	   
	   G_LOCK (dns_lock);
restart:
	   result = gethostbyname (hostname);

	   if (result == NULL) {
			 if (retry && restart_resolve ()) {
				    retry = FALSE;
				    goto restart;
			 } else {
#ifndef G_OS_WIN32
				    ret = mate_vfs_result_from_h_errno ();
#else
				    switch (WSAGetLastError ()) {
				    case WSAHOST_NOT_FOUND:
					    ret = MATE_VFS_ERROR_HOST_NOT_FOUND;
					    break;
				    case WSANO_DATA:
					    ret = MATE_VFS_ERROR_HOST_HAS_NO_ADDRESS;
					    break;
				    case WSATRY_AGAIN:
				    case WSANO_RECOVERY:
					    ret = MATE_VFS_ERROR_NAMESERVER;
				    default:
					    ret = MATE_VFS_ERROR_GENERIC;
				    }
#endif
			 }
	   } else {
			 ret = resolvehandle_from_hostent (result, handle);
	   }

	   G_UNLOCK (dns_lock);
#endif /* !HAVE_GETHOSTBYNAME_R_GLIBC && !HAVE_GETHOSTBYNAME_R_SOLARIS && !HAVE_GETHOSTBYNAME_R_HPUX */
	   return ret;
#endif /* HAVE_GETADDRINFO */
}
/**
 * mate_vfs_result_from_h_errno:
 * 
 * Converts the system "h_errno" to a #MateVFSResult (h_errno represents errors
 * accessing and finding internet hosts)
 *
 * Return value: a #MateVFSResult equivalent to the current system "h_errno".
 */
MateVFSResult
mate_vfs_result_from_h_errno (void)
{
	return mate_vfs_result_from_h_errno_val (h_errno);
}