Пример #1
0
static sg_error
sg_vector_clone_into_int(sg_vector **dest, const sg_vector *src){

	/* we can assume that everything is correct from caller perspective */
	size_t i;
	sg_vector *tmp   = ((*dest)->used_count == src->used_count)
			 ? *dest
			 : sg_vector_resize(*dest, src->used_count);
	char const *src_data   = VECTOR_DATA_CONST(src);
	char *dest_data = VECTOR_DATA(tmp);
	size_t item_size = src->info.item_size;

	assert(src->info.copy_fn);

	if( !tmp ) {
		RETURN_FROM_PREVIOUS_ERROR( "vector", sg_get_error() );
	}

	for( i = 0; i < src->used_count; ++i ) {
		sg_error rc = src->info.copy_fn( src_data + i * item_size, dest_data + i * item_size );
		if( SG_ERROR_NONE != rc ) {
			sg_vector_free( tmp );
			*dest = NULL;
			return rc;
		}
	}

	*dest = tmp;

	return SG_ERROR_NONE;
}
Пример #2
0
static sg_error sg_user_stats_item_copy(sg_user_stats *d, const sg_user_stats *s) {

	if( SG_ERROR_NONE != sg_update_string(&d->login_name, s->login_name) ||
	    SG_ERROR_NONE != sg_update_mem(&d->record_id, s->record_id, s->record_id_size) ||
	    SG_ERROR_NONE != sg_update_string(&d->device, s->device) ||
	    SG_ERROR_NONE != sg_update_string(&d->hostname, s->hostname) ) {
		RETURN_FROM_PREVIOUS_ERROR( "user", sg_get_error() );
	}

	d->record_id_size = s->record_id_size;
	d->pid = s->pid;
	d->tv = s->tv;

	return SG_ERROR_NONE;
}
Пример #3
0
static sg_error
sg_network_io_stats_item_copy(const sg_network_io_stats *s, sg_network_io_stats *d) {

	if( SG_ERROR_NONE != sg_update_string(&d->interface_name, s->interface_name) ) {
		RETURN_FROM_PREVIOUS_ERROR( "network", sg_get_error() );
	}

	d->tx = s->tx;
	d->rx = s->rx;
	d->ipackets = s->ipackets;
	d->opackets = s->opackets;
	d->ierrors = s->ierrors;
	d->oerrors = s->oerrors;
	d->collisions = s->collisions;
	d->systime = s->systime;

	return SG_ERROR_NONE;
}
Пример #4
0
static sg_error
sg_get_user_stats_int(sg_vector **user_stats_vector_ptr) {
	size_t num_users = 0;
	sg_user_stats *user_ptr;
	time_t now = time(NULL);

#if defined (WIN32)
	LPWKSTA_USER_INFO_0 buf = NULL;
	LPWKSTA_USER_INFO_0 tmp_buf;
	unsigned long entries_read = 0;
	unsigned long entries_tot = 0;
	unsigned long resumehandle = 0;
	NET_API_STATUS nStatus;
	int i;
	char name[256];

#undef VECTOR_UPDATE_ERROR_CLEANUP
#define VECTOR_UPDATE_ERROR_CLEANUP if (buf != NULL) NetApiBufferFree(buf);

	do {
		nStatus = NetWkstaUserEnum(NULL, 0, (LPBYTE*)&buf,
				MAX_PREFERRED_LENGTH, &entries_read,
				&entries_tot, &resumehandle);
		if((nStatus == NERR_Success) || (nStatus == ERROR_MORE_DATA)) {
			if((tmp_buf = buf) == NULL)
				continue;

			for( i = 0; i < entries_read; ++i ) {
				/* assert(tmp_buf != NULL); */
				if( tmp_buf == NULL ) {
					sg_set_error(SG_ERROR_PERMISSION, "User list");
					ERROR_LOG("user", "Permission denied fetching user details");
					break; /* XXX break and not return? */
				}
				/* It's in unicode. We are not. Convert */
				WideCharToMultiByte(CP_ACP, 0, tmp_buf->wkui0_username, -1, name, sizeof(name), NULL, NULL);

				VECTOR_UPDATE(user_stats_vector_ptr, num_users + 1, user_ptr, sg_user_stats);
				if( SG_ERROR_NONE != sg_update_string( &user_ptr[num_users].login_name, name ) ) {
					VECTOR_UPDATE_ERROR_CLEANUP
					RETURN_FROM_PREVIOUS_ERROR( "user", sg_get_error() );
				}

				user_ptr[num_users].systime = now;

				++tmp_buf;
				++num_users;
			}
		}
		else {
			RETURN_WITH_SET_ERROR("user", SG_ERROR_PERMISSION, "User enum");
		}

		if (buf != NULL) {
			NetApiBufferFree(buf);
			buf=NULL;
		}
	} while (nStatus == ERROR_MORE_DATA);

	if (buf != NULL)
		NetApiBufferFree(buf);
#elif defined(CAN_USE_UTMPX) || defined(CAN_USE_UTMP)

#define SG_LUPDATE_IF(tgt,obj,memb) \
	(((void *)(&(obj->memb))) == ((void *)(&(obj->memb[0])))) \
	? sg_lupdate_string(tgt, obj->memb, sizeof(obj->memb))\
	: sg_update_string(tgt, obj->memb)

#define UTMP_MUTEX_NAME "utmp"

#undef VECTOR_UPDATE_ERROR_CLEANUP
# if defined(CAN_USE_UTMPX)
	struct utmpx *utx;
# endif
# if defined(CAN_USE_UTMP)
	struct utmp *ut;
# endif

	/* following block contains code for utmpx */
# if defined(CAN_USE_UTMPX)
#  ifdef ENABLE_THREADS
#   define VECTOR_UPDATE_ERROR_CLEANUP endutxent(); sg_unlock_mutex(UTMP_MUTEX_NAME);
	sg_lock_mutex(UTMP_MUTEX_NAME);
#  else
#   define VECTOR_UPDATE_ERROR_CLEANUP endutxent();
#  endif
	setutxent();
	while( NULL != (utx = getutxent()) ) {
		if( USER_PROCESS != utx->ut_type )
			continue;

		VECTOR_UPDATE(user_stats_vector_ptr, num_users + 1, user_ptr, sg_user_stats);

		if( ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].login_name, utx, ut_user ) ) ||
#  if defined(HAVE_UTMPX_HOST)
#   if defined(HAVE_UTMPX_SYSLEN)
		    ( SG_ERROR_NONE != sg_lupdate_string( &user_ptr[num_users].hostname, utx->ut_host, utx->ut_syslen + 1 ) ) ||
#   else
		    ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].hostname, utx, ut_host ) ) ||
#   endif
#  endif
		    ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].device, utx, ut_line ) ) ||
		    ( SG_ERROR_NONE != sg_update_mem( (void *)(&user_ptr[num_users].record_id), utx->ut_id, sizeof(utx->ut_id) ) ) ) {
			    VECTOR_UPDATE_ERROR_CLEANUP
			    RETURN_FROM_PREVIOUS_ERROR( "user", sg_get_error() );
		}

		user_ptr[num_users].record_id_size = sizeof(utx->ut_id);
		user_ptr[num_users].pid = utx->ut_pid;
		user_ptr[num_users].login_time = utx->ut_tv.tv_sec;
		user_ptr[num_users].systime = now;

		++num_users;
	}

	endutxent();

	if(!num_users) {
# endif

	/* following block contains code for utmp */
# if defined(CAN_USE_UTMP)

#  undef VECTOR_UPDATE_ERROR_CLEANUP
#  ifdef ENABLE_THREADS
#   define VECTOR_UPDATE_ERROR_CLEANUP endutent(); sg_unlock_mutex(UTMP_MUTEX_NAME);
#  else
#   define VECTOR_UPDATE_ERROR_CLEANUP endutent();
#  endif
	setutent();
	while( NULL != (ut = getutent()) ) {
#  ifdef HAVE_UTMP_TYPE
		if( USER_PROCESS != ut->ut_type )
			continue;
#  elif defined(HAVE_UTMP_NAME)
	    if (ut->ut_name[0] == '\0')
		    continue;
#  elif defined(HAVE_UTMP_USER)
	    if (ut->ut_user[0] == '\0')
		    continue;
#  endif

	    VECTOR_UPDATE(user_stats_vector_ptr, num_users + 1, user_ptr, sg_user_stats);

	    if( ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].device, ut, ut_line ) )
#  if defined(HAVE_UTMP_USER)
	     || ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].login_name, ut, ut_user ) )
#  elif defined(HAVE_UTMP_NAME)
	     || ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].login_name, ut, ut_name ) )
#  endif
#  if defined(HAVE_UTMP_HOST)
	     || ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].hostname, ut, ut_host ) )
#  endif
#  if defined(HAVE_UTMP_ID)
	     || ( SG_ERROR_NONE != sg_update_mem( (void **)(&user_ptr[num_users].record_id), ut->ut_id, sizeof(ut->ut_id) ) )
#  endif
	    ) {
			VECTOR_UPDATE_ERROR_CLEANUP
			RETURN_FROM_PREVIOUS_ERROR( "user", sg_get_error() );
	    }

#  if defined(HAVE_UTMP_ID)
	    user_ptr[num_users].record_id_size = sizeof(ut->ut_id);
#  endif
#  if defined(HAVE_UTMP_PID)
	    user_ptr[num_users].pid = ut->ut_pid;
#  endif
#if defined(HAVE_UTMP_TIME)
	    user_ptr[num_users].login_time = ut->ut_time;
#endif
	    user_ptr[num_users].systime = now;

	    ++num_users;
    }

    endutent();
# endif

# if defined(CAN_USE_UTMPX)
    }
#endif

# ifdef ENABLE_THREADS
    sg_unlock_mutex(UTMP_MUTEX_NAME);
# endif
#elif defined(HAVE_STRUCT_UTMP) && defined(_PATH_UTMP)
    struct utmp entry;
    FILE *f;

    if ((f=fopen(_PATH_UTMP, "r")) == NULL) {
	    RETURN_WITH_SET_ERROR_WITH_ERRNO("user", SG_ERROR_OPEN, _PATH_UTMP);
    }

#ifdef SG_LUPDATE_IF
#undef SG_LUPDATE_IF
#endif

#define SG_LUPDATE_IF(tgt,obj,memb) \
	(((void *)(&(obj.memb))) == ((void *)(&(obj.memb[0])))) \
	? sg_lupdate_string(tgt, obj.memb, sizeof(obj.memb))\
	: sg_update_string(tgt, obj.memb)

#undef VECTOR_UPDATE_ERROR_CLEANUP
#define VECTOR_UPDATE_ERROR_CLEANUP fclose(f);

    while((fread(&entry, sizeof(entry),1,f)) != 0){
#ifdef HAVE_UTMP_TYPE
	    if( USER_PROCESS != ut->ut_type )
		    continue;
#elif defined(HAVE_UTMP_NAME)
	    if (entry.ut_name[0] == '\0')
		    continue;
#elif defined(HAVE_UTMP_USER)
	    if (entry.ut_user[0] == '\0')
		    continue;
#endif

	    VECTOR_UPDATE(user_stats_vector_ptr, num_users + 1, user_ptr, sg_user_stats);

	    if( ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].device, entry, ut_line ) )
#if defined(HAVE_UTMP_USER)
	     || ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].login_name, entry, ut_user ) )
#elif defined(HAVE_UTMP_NAME)
	     || ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].login_name, entry, ut_name ) )
#endif
#if defined(HAVE_UTMP_HOST)
	     || ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].hostname, entry, ut_host ) )
#endif
#if defined(HAVE_UTMP_ID)
	     || ( SG_ERROR_NONE != sg_update_mem( &user_ptr[num_users].record_id, entry.ut_id, sizeof(entry.ut_id) ) )
#endif
	    ) {
			VECTOR_UPDATE_ERROR_CLEANUP
			RETURN_FROM_PREVIOUS_ERROR( "user", sg_get_error() );
	    }

#if defined(HAVE_UTMP_ID)
	    user_ptr[num_users].record_id_size = sizeof(entry.ut_id);
#endif
#if defined(HAVE_UTMP_PID)
	    user_ptr[num_users].pid = entry.ut_pid;
#endif
#if defined(HAVE_UTMP_TIME)
	    user_ptr[num_users].login_time = entry.ut_time;
#endif
		user_ptr[num_users].systime = now;

		++num_users;
	}

	fclose(f);
#else
	RETURN_WITH_SET_ERROR("user", SG_ERROR_UNSUPPORTED, OS_TYPE);
#endif

	return SG_ERROR_NONE;
}
Пример #5
0
sg_error
sg_vector_compute_diff(sg_vector **dest_vector_ptr, const sg_vector *cur_vector, const sg_vector *last_vector) {

	if( NULL == dest_vector_ptr ) {
		RETURN_WITH_SET_ERROR("vector", SG_ERROR_INVALID_ARGUMENT, "sg_vector_compute_diff(dest_vector_ptr)");
	}

	if( cur_vector ) {
		sg_error rc = sg_vector_clone_into( dest_vector_ptr, cur_vector ); /* proves *dest, cur */
		if( SG_ERROR_NONE != rc ) {
			RETURN_FROM_PREVIOUS_ERROR( "vector", rc );
		}

		if( NULL == *dest_vector_ptr )
			return SG_ERROR_NONE;
		assert( cur_vector->info.compute_diff_fn );
		assert( cur_vector->info.compare_fn );

		TRACE_LOG_FMT("vector",
			      "computing vector diff between vector containing %lu items (cur) and vector containing %lu items (last)",
			      cur_vector->used_count, last_vector ? last_vector->used_count : 0 );

		if( last_vector &&
		    ( SG_ERROR_NONE == sg_prove_vector(last_vector) ) &&
		    ( SG_ERROR_NONE == sg_prove_vector_compat(cur_vector, last_vector ) ) ) {
			size_t i, item_size = last_vector->info.item_size;
			unsigned matched[(cur_vector->used_count / (8 * sizeof(unsigned))) + 1];

			char *diff = VECTOR_DATA(*dest_vector_ptr);
			char const *last = VECTOR_DATA_CONST(last_vector);

			memset( matched, 0, sizeof(matched) );

			for( i = 0; i < (*dest_vector_ptr)->used_count; ++i ) {
				size_t j;
				for( j = 0; j < last_vector->used_count; ++j ) {
					if( BIT_ISSET(matched, j) ) /* already matched? */
						continue;

					if (last_vector->info.compare_fn(last + j * item_size, diff + i * item_size) == 0) {
						BIT_SET(matched, j);
						last_vector->info.compute_diff_fn(last + j * item_size, diff + i * item_size);
					}
				}

				if( j == last_vector->used_count ) {
					/* We have lost an item since last time - skip */
				}
			}

			/* XXX append the items lost since last run? */
		}
	}
	else {
		sg_vector_free(*dest_vector_ptr);
		*dest_vector_ptr = NULL;

		RETURN_WITH_SET_ERROR("vector", SG_ERROR_INVALID_ARGUMENT, "sg_vector_compute_diff(cur_vector)");
	}

	return SG_ERROR_NONE;
}
Пример #6
0
static sg_error
sg_get_host_info_int(sg_host_info *host_info_buf) {

#ifdef WIN32
	unsigned long nameln;
	char *name;
	long long result;
	OSVERSIONINFOEX osinfo;
	SYSTEM_INFO sysinfo;
	char *tmp_name;
	char tmp[10];
#else
	struct utsname os;
# if defined(HPUX)
	struct pst_static pstat_static;
	struct pst_dynamic pstat_dynamic;
	time_t currtime;
	long boottime;
# elif defined(SOLARIS)
	time_t boottime, curtime;
	kstat_ctl_t *kc;
	kstat_t *ksp;
	kstat_named_t *kn;
	char *isainfo = NULL;
	long isabufsz, rc;
# elif defined(LINUX) || defined(CYGWIN)
	FILE *f;
# elif defined(ALLBSD)
	int mib[2];
	struct timeval boottime;
	time_t curtime;
	size_t size;
	int ncpus;
#  if defined(HW_MACHINE_ARCH) || defined(HW_MACHINE)
	char arch_name[16];
#  endif
# elif defined(AIX)
	static perfstat_cpu_total_t cpu_total;
	sg_error rc;
#  if defined(HAVE_GETUTXENT)
	struct utmpx *ut;
#  else
	struct utmp *ut;
#  endif
# endif
#endif

	host_info_buf->ncpus = 0;
	host_info_buf->maxcpus = 0;
	host_info_buf->bitwidth = 0;
	host_info_buf->host_state = sg_unknown_configuration;
	host_info_buf->uptime = 0;
	host_info_buf->systime = 0;

#ifdef WIN32
	/* these settings are static after boot, so why get them
	 * constantly?
	 *
	 * Because we want to know some changes anyway - at least
	 * when the hostname (DNS?) changes
	 */

	/* get system name */
	nameln = MAX_COMPUTERNAME_LENGTH + 1;
	name = sg_malloc(nameln);
	if(name == NULL) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	/*
	 * XXX probably GetComputerNameEx() is a better entry point ...
	 */
	if( GetComputerName(name, &nameln) == 0 ) {
		free(name);
		RETURN_WITH_SET_ERROR("os", SG_ERROR_HOST, "GetComputerName");
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->hostname, name)) {
		free(name);
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}
	free(name);

	/* get OS name, version and build */
	ZeroMemory(&osinfo, sizeof(OSVERSIONINFOEX));
	osinfo.dwOSVersionInfoSize = sizeof(osinfo);
	if(!GetVersionEx(&osinfo)) {
		RETURN_WITH_SET_ERROR("os", SG_ERROR_HOST, "GetVersionEx");
	}
	GetSystemInfo(&sysinfo);

	/* Release - single number */
	if(snprintf(tmp, sizeof(tmp), "%ld", osinfo.dwBuildNumber) == -1) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SPRINTF, NULL);
	}
	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_release, tmp)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	/* Version */
	/* usually a single digit . single digit, eg 5.0 */
	if(snprintf(tmp, sizeof(tmp), "%ld.%ld", osinfo.dwMajorVersion,
				osinfo.dwMinorVersion) == -1) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}
	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_version, tmp)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	/* OS name */
	tmp_name = get_os_name(osinfo, sysinfo);
	if(tmp_name == NULL) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_name, tmp_name)) {
		free(tmp_name);
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}
	free(tmp_name);

	/* Platform */
	switch(sysinfo.wProcessorArchitecture) {
		case PROCESSOR_ARCHITECTURE_INTEL:
			if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform,
						"Intel")) {
				RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
			}
			break;
		case PROCESSOR_ARCHITECTURE_IA64:
			if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform,
						"IA64")) {
				RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
			}
			break;
		case PROCESSOR_ARCHITECTURE_AMD64:
			if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform,
						"AMD64")) {
				RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
			}
			break;
		default:
			if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform,
						"Unknown")){
				RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
			}
			break;
	}

	if(read_counter_large(SG_WIN32_UPTIME, &result)) {
		RETURN_WITH_SET_ERROR("os", SG_ERROR_PDHREAD, PDH_UPTIME);
	}

	host_info_buf->uptime = (time_t) result;
#else
	if((uname(&os)) < 0) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_UNAME, NULL);
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_name, os.sysname)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_release, os.release)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_version, os.version)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform, os.machine)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->hostname, os.nodename)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	/* get uptime */
#ifdef HPUX
	if (pstat_getstatic(&pstat_static, sizeof(pstat_static), 1, 0) == -1) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_PSTAT, "pstat_static");
	}

	if (pstat_getdynamic(&pstat_dynamic, sizeof(pstat_dynamic), 1, 0) == -1) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_PSTAT, "pstat_dynamic");
	}

	currtime = time(NULL);

	boottime = pstat_static.boot_time;

	host_info_buf->uptime = currtime - boottime;
	host_info_buf->ncpus = pstat_dynamic.psd_proc_cnt;
	host_info_buf->maxcpus = pstat_dynamic.psd_max_proc_cnt;
	host_info_buf->bitwidth = sysconf(_SC_KERNEL_BITS);

	/*
	 * TODO: getting virtualization state
	 *       1) on boostrapping this component, try loading /opt/hpvm/lib/libhpvm.so (or so)
	 *       2) get function addresses for
	 *          a) HPVM_boolean hpvm_api_server_check()
	 *          b) HPVM_boolean hpvm_api_virtmach_check()
	 *
	 * Seems to be hardware virtualization ...
	 * See: http://docstore.mik.ua/manuals/hp-ux/en/T2767-90141/index.html (hpvmpubapi(3))
	 *      http://jreypo.wordpress.com/tag/hpvm/
	 *      http://jreypo.wordpress.com/category/hp-ux/page/3/
	 *      http://h20338.www2.hp.com/enterprise/us/en/os/hpux11i-partitioning-integrity-vm.html
	 */

#elif defined(SOLARIS)
	if ((kc = kstat_open()) == NULL) {
		RETURN_WITH_SET_ERROR("os", SG_ERROR_KSTAT_OPEN, NULL);
	}

	if((ksp=kstat_lookup(kc, "unix", -1, "system_misc"))==NULL){
		kstat_close(kc);
		RETURN_WITH_SET_ERROR("os", SG_ERROR_KSTAT_LOOKUP, "unix,-1,system_misc");
	}
	if (kstat_read(kc, ksp, 0) == -1) {
		kstat_close(kc);
		RETURN_WITH_SET_ERROR("os", SG_ERROR_KSTAT_READ, NULL);
	}
	if((kn=kstat_data_lookup(ksp, "boot_time")) == NULL){
		kstat_close(kc);
		RETURN_WITH_SET_ERROR("os", SG_ERROR_KSTAT_DATA_LOOKUP, "boot_time");
	}
	/* XXX verify on Solaris 10 if it's still ui32 */
	boottime = (kn->value.ui32);

	kstat_close(kc);

	time(&curtime);
	host_info_buf->uptime = curtime - boottime;

	host_info_buf->ncpus = sysconf(_SC_NPROCESSORS_ONLN);
	host_info_buf->maxcpus = sysconf(_SC_NPROCESSORS_CONF);
	isainfo = sg_malloc( isabufsz = (32 * sizeof(*isainfo)) );
	if( NULL == isainfo ) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}
# define MKSTR(x) #x
# if defined(SI_ARCHITECTURE_K)
#  define SYSINFO_CMD SI_ARCHITECTURE_K
# elif defined(SI_ISALIST)
#  define SYSINFO_CMD SI_ISALIST
# else
#  define SYSINFO_CMD SI_ARCHITECTURE
# endif
sysinfo_again:
	if( -1 == ( rc = sysinfo( SYSINFO_CMD, isainfo, isabufsz ) ) ) {
		free(isainfo);
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSINFO, MKSTR(SYSINFO_CMD) );
	}
	else if( rc > isabufsz ) {
		char *tmp = sg_realloc(isainfo, rc);
		if( NULL == tmp ) {
			free(isainfo);
			RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
		}
		isabufsz = rc;
		isainfo = tmp;
		goto sysinfo_again;
	}

	host_info_buf->bitwidth = get_bitwidth_by_arch_name(isainfo);
	free(isainfo);
	host_info_buf->host_state = sg_unknown_configuration;

#elif defined(LINUX) || defined(CYGWIN)
	if ((f=fopen("/proc/uptime", "r")) == NULL) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_OPEN, "/proc/uptime");
	}

#define TIME_T_SCANF_FMT (sizeof(int[(((time_t)-1)/2)%4+1]) == sizeof(int[1]) ? "%ld %*d" : "%lu %*d" )
	if((fscanf(f,TIME_T_SCANF_FMT,&host_info_buf->uptime)) != 1){
		fclose(f);
		RETURN_WITH_SET_ERROR("os", SG_ERROR_PARSE, NULL);
	}
	fclose(f);

# if defined(LINUX)
	host_info_buf->ncpus = sysconf(_SC_NPROCESSORS_ONLN);
	host_info_buf->maxcpus = sysconf(_SC_NPROCESSORS_CONF);
	if( access( "/proc/sys/kernel/vsyscall64", F_OK ) == 0 ||
	    access( "/proc/sys/abi/vsyscall32", F_OK ) == 0 ) {
		host_info_buf->bitwidth = 64;
	}
	else {
		host_info_buf->bitwidth = sysconf(_SC_LONG_BIT); // well, maybe 64-bit disabled 128-bit system o.O
	}
	host_info_buf->host_state = sg_unknown_configuration;
# endif

#elif defined(ALLBSD)
	mib[0] = CTL_KERN;
	mib[1] = KERN_BOOTTIME;
	size = sizeof(boottime);
	if (sysctl(mib, 2, &boottime, &size, NULL, 0) < 0) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_KERN.KERN_BOOTTIME");
	}
	time(&curtime);
	host_info_buf->uptime= curtime - boottime.tv_sec;

# if defined(HW_NCPU)
	mib[0] = CTL_HW;
	mib[1] = HW_NCPU;
	size = sizeof(int);
	if( sysctl( mib, 2, &ncpus, &size, NULL, 0 ) < 0 ) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_HW.HW_NCPU" );
	}
# endif
# if defined(HW_MACHINE_ARCH)
	mib[0] = CTL_HW;
	mib[1] = HW_MACHINE_ARCH;
	size = sizeof(arch_name);
	if( sysctl( mib, 2, arch_name, &size, NULL, 0 ) == 0 ) {
		host_info_buf->bitwidth = get_bitwidth_by_arch_name(arch_name);
	}
	else {
# endif
# if defined(HW_MACHINE)
	mib[0] = CTL_HW;
	mib[1] = HW_MACHINE;
	size = sizeof(arch_name);
	if( sysctl( mib, 2, arch_name, &size, NULL, 0 ) == 0 ) {
		host_info_buf->bitwidth = get_bitwidth_by_arch_name(arch_name);
	}
	else {
		SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_HW.HW_MACHINE" );
	}
# elif defined(HW_MACHINE_ARCH)
		SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_HW.HW_MACHINE_ARCH" );
# endif
# if defined(HW_MACHINE_ARCH)
	}
# endif
	host_info_buf->host_state = sg_unknown_configuration; /* details must be analysed "manually", no syscall */
	host_info_buf->maxcpus = (unsigned)ncpus;
# if defined(HW_NCPUONLINE)
	/* use knowledge about number of cpu's online, when available instead of assuming all of them */
	mib[0] = CTL_HW;
	mib[1] = HW_NCPUONLINE;
	size = sizeof(int);
	if( sysctl( mib, 2, &ncpus, &size, NULL, 0 ) < 0 ) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_HW.HW_NCPUONLINE" );
	}
# endif
	host_info_buf->ncpus = (unsigned)ncpus;

#elif defined(AIX)
	if(perfstat_cpu_total(NULL, &cpu_total, sizeof(cpu_total), 1) != 1) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "perfstat_cpu_total");
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform, cpu_total.description)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	host_info_buf->ncpus = cpu_total.ncpus;
	host_info_buf->maxcpus = cpu_total.ncpus_cfg;
	host_info_buf->bitwidth = sysconf(_SC_AIX_KERNEL_BITMODE);
	if( sysconf(_SC_LPAR_ENABLED) > 0 ) {
		host_info_buf->host_state = sg_hardware_virtualized;
	}
	else {
		host_info_buf->host_state = sg_physical_host;
	}

#ifdef ENABLE_THREADS
	if( SG_ERROR_NONE != ( rc = sg_lock_mutex("utmp") ) ) {
		RETURN_FROM_PREVIOUS_ERROR( "os", rc );
	}
#endif
# if defined(HAVE_GETUTXENT)
#  define UTENTFN getutxent
#  define UTENTTM ut->ut_tv.tv_sec
	setutxent();
# else
#  define UTENTFN getutent
#  define UTENTTM ut->ut_time
	setutent();
# endif
	while( NULL != ( ut = UTENTFN() ) ) {
		if( ut->ut_type == BOOT_TIME ) {
			host_info_buf->uptime = time(NULL) - UTENTTM;
			break;
		}
	}
# if defined(HAVE_GETUTXENT)
	endutxent();
# else
	endutent();
# endif
#ifdef ENABLE_THREADS
	if( SG_ERROR_NONE != ( rc = sg_unlock_mutex("utmp") ) ) {
		RETURN_FROM_PREVIOUS_ERROR( "os", rc );
	}
#endif
#else
	RETURN_WITH_SET_ERROR("os", SG_ERROR_UNSUPPORTED, OS_TYPE);
#endif
#endif /* WIN32 */

	host_info_buf->systime = time(NULL);

	return SG_ERROR_NONE;
}
Пример #7
0
static sg_error
sg_get_page_stats_int(sg_page_stats *page_stats_buf){
#ifdef SOLARIS
	kstat_ctl_t *kc;
	kstat_t *ksp;
	cpu_stat_t cs;
#elif defined(LINUX) || defined(CYGWIN)
	FILE *f;
#define LINE_BUF_SIZE 256
	char line_buf[LINE_BUF_SIZE];
#elif defined(HAVE_HOST_STATISTICS) || defined(HAVE_HOST_STATISTICS64)
# if defined(HAVE_HOST_STATISTICS64)
	struct vm_statistics64 vm_stats;
# else
	struct vm_statistics vm_stats;
# endif
	mach_msg_type_number_t count;
	kern_return_t rc;
#elif defined(HAVE_STRUCT_UVMEXP_SYSCTL) && defined(VM_UVMEXP2)
	int mib[2];
	struct uvmexp_sysctl uvm;
	size_t size = sizeof(uvm);
#elif defined(HAVE_STRUCT_UVMEXP) && defined(VM_UVMEXP)
	int mib[2];
	struct uvmexp uvm;
	size_t size = sizeof(uvm);
#elif defined(FREEBSD) || defined(DFBSD)
	size_t size;
#elif defined(NETBSD) || defined(OPENBSD)
	int mib[2];
	struct uvmexp uvm;
	size_t size = sizeof(uvm);
#elif defined(AIX)
	perfstat_memory_total_t mem;
#elif defined(HPUX)
	struct pst_vminfo vminfo;
#endif

	page_stats_buf->systime = time(NULL);
	page_stats_buf->pages_pagein=0;
	page_stats_buf->pages_pageout=0;

#ifdef SOLARIS
	if ((kc = kstat_open()) == NULL) {
		RETURN_WITH_SET_ERROR("page", SG_ERROR_KSTAT_OPEN, NULL);
	}

	for (ksp = kc->kc_chain; ksp!=NULL; ksp = ksp->ks_next) {
		if ((strcmp(ksp->ks_module, "cpu_stat")) != 0)
			continue;
		if (kstat_read(kc, ksp, &cs) == -1)
			continue;

		page_stats_buf->pages_pagein  += (long long)cs.cpu_vminfo.pgpgin;
		page_stats_buf->pages_pageout += (long long)cs.cpu_vminfo.pgpgout;
	}

	kstat_close(kc);
#elif defined(LINUX) || defined(CYGWIN)
	if ((f = fopen("/proc/vmstat", "r")) != NULL) {
		unsigned matches = 0;

		while( (matches < 2) && (fgets(line_buf, sizeof(line_buf), f) != NULL) ) {
			unsigned long long value;

			if (sscanf(line_buf, "%*s %llu", &value) != 1)
				continue;

			if (strncmp(line_buf, "pgpgin ", 7) == 0) {
				page_stats_buf->pages_pagein = value;
				++matches;
			}
			else if (strncmp(line_buf, "pgpgout ", 8) == 0) {
				page_stats_buf->pages_pageout = value;
				++matches;
			}
		}

		fclose(f);

		if( matches < 2 ) {
			RETURN_WITH_SET_ERROR( "page", SG_ERROR_PARSE, "/proc/vmstat" );
		}
	}
	else if ((f = fopen("/proc/stat", "r")) != NULL) {
		if (sg_f_read_line(f, line_buf, sizeof(line_buf), "page") == NULL) {
			fclose(f);
			RETURN_FROM_PREVIOUS_ERROR( "page", sg_get_error() );
		}

		fclose(f);

		if( sscanf( line_buf, "page %llu %llu", &page_stats_buf->pages_pagein, &page_stats_buf->pages_pageout ) != 2 ) {
			RETURN_WITH_SET_ERROR("page", SG_ERROR_PARSE, "page");
		}
	}
	else {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("page", SG_ERROR_OPEN, "/proc/stat");
	}
#elif defined(HAVE_HOST_STATISTICS) || defined(HAVE_HOST_STATISTICS64)
	self_host_port = mach_host_self();
# if defined(HAVE_HOST_STATISTICS64)
	count = HOST_VM_INFO64_COUNT;
	rc = host_statistics64(self_host_port, HOST_VM_INFO64, (host_info64_t)(&vm_stats), &count);
# else
	count = HOST_VM_INFO_COUNT;
	rc = host_statistics(self_host_port, HOST_VM_INFO, (host_info_t)(&vm_stats), &count);
# endif
	if( rc != KERN_SUCCESS ) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO_CODE( "mem", SG_ERROR_MACHCALL, rc, "host_statistics" );
	}

	page_stats_buf->pages_pagein = vm_stats.pageins;
	page_stats_buf->pages_pageout = vm_stats.pageouts;
#elif defined(HAVE_STRUCT_UVMEXP_SYSCTL) && defined(VM_UVMEXP2)
	mib[0] = CTL_VM;
	mib[1] = VM_UVMEXP2;

	if (sysctl(mib, 2, &uvm, &size, NULL, 0) < 0) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTL, "CTL_VM.VM_UVMEXP2");
	}

	page_stats_buf->pages_pagein = uvm.pgswapin;
	page_stats_buf->pages_pageout = uvm.pgswapout;
#elif defined(HAVE_STRUCT_UVMEXP) && defined(VM_UVMEXP)
	mib[0] = CTL_VM;
	mib[1] = VM_UVMEXP;

	if (sysctl(mib, 2, &uvm, &size, NULL, 0) < 0) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTL, "CTL_VM.VM_UVMEXP");
	}

	page_stats_buf->pages_pagein = uvm.pgswapin;
	page_stats_buf->pages_pageout = uvm.pgswapout;
#elif defined(FREEBSD) || defined(DFBSD)
	size = sizeof(page_stats_buf->pages_pagein);
	if (sysctlbyname("vm.stats.vm.v_swappgsin", &page_stats_buf->pages_pagein, &size, NULL, 0) < 0) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("page", SG_ERROR_SYSCTLBYNAME, "vm.stats.vm.v_swappgsin");
	}

	size = sizeof(page_stats_buf->pages_pageout);
	if (sysctlbyname("vm.stats.vm.v_swappgsout", &page_stats_buf->pages_pageout, &size, NULL, 0) < 0) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("page", SG_ERROR_SYSCTLBYNAME, "vm.stats.vm.v_swappgsout");
	}
#elif defined(AIX)
	/* return code is number of structures returned */
	if(perfstat_memory_total(NULL, &mem, sizeof(perfstat_memory_total_t), 1) != 1) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("page", SG_ERROR_SYSCTLBYNAME, "perfstat_memory_total");
	}

	page_stats_buf->pages_pagein  = mem.pgins;
	page_stats_buf->pages_pageout = mem.pgouts;
#elif defined(HPUX)
	if( pstat_getvminfo( &vminfo, sizeof(vminfo), 1, 0 ) == -1 ) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("page", SG_ERROR_SYSCTLBYNAME, "pstat_getswap");
	}

	page_stats_buf->pages_pagein  = vminfo.psv_spgin;
	page_stats_buf->pages_pageout = vminfo.psv_spgout;
#else
	RETURN_WITH_SET_ERROR("page", SG_ERROR_UNSUPPORTED, OS_TYPE);
#endif

	return SG_ERROR_NONE;
}
Пример #8
0
static sg_error
sg_get_swap_stats_int(sg_swap_stats *swap_stats_buf) {

#ifdef HPUX
#define SWAP_BATCH 5
	struct pst_swapinfo pstat_swapinfo[SWAP_BATCH];
	int swapidx = 0;
	int num, i;
#elif defined(SOLARIS)
# if defined(HAVE_STRUCT_SWAPTABLE)
	struct swaptable *swtbl;
	int nswap, i;
# elif defined(HAVE_STRUCT_ANONINFO)
	struct anoninfo ai;
# endif
#elif defined(LINUX) || defined(CYGWIN)
	FILE *f;
#define LINE_BUF_SIZE 256
	char line_buf[LINE_BUF_SIZE];
	unsigned long long value;
	unsigned matches = 0;
#elif defined(HAVE_STRUCT_XSWDEV)
	struct xswdev xsw;
	struct xswdev *xswbuf = NULL, *xswptr = NULL;
	int n;
	int mib[16];
	size_t mibsize, size;
#elif defined(HAVE_STRUCT_XSW_USAGE)
	int mib[2] = {CTL_VM, VM_SWAPUSAGE};
	struct xsw_usage xsw;
	size_t mibsize = 2, size = sizeof(xsw);
#elif defined(HAVE_STRUCT_UVMEXP_SYSCTL) && defined(VM_UVMEXP2)
	int mib[2] = { CTL_VM, VM_UVMEXP2 };
	struct uvmexp_sysctl uvm;
	size_t size = sizeof(uvm);
#elif defined(HAVE_STRUCT_UVMEXP) && defined(VM_UVMEXP)
	int mib[2] = { CTL_VM, VM_UVMEXP };
	struct uvmexp uvm;
	size_t size = sizeof(uvm);
#elif defined(ALLBSD)
	/* fallback if no reasonable API is supported */
	struct kvm_swap swapinfo;
	kvm_t *kvmd;
#elif defined(AIX)
	perfstat_memory_total_t mem;
#elif defined(WIN32)
	MEMORYSTATUSEX memstats;
#endif

	swap_stats_buf->total = 0;
	swap_stats_buf->used = 0;
	swap_stats_buf->free = 0;

#ifdef HPUX
	for(;;) {
		num = pstat_getswap(pstat_swapinfo, sizeof pstat_swapinfo[0],
				    SWAP_BATCH, swapidx);
		if (num == -1) {
			RETURN_WITH_SET_ERROR_WITH_ERRNO("swap", SG_ERROR_PSTAT, "pstat_getswap");
		}
		else if (num == 0) {
			break;
		}

		for (i = 0; i < num; ++i) {
			struct pst_swapinfo *si = &pstat_swapinfo[i];

			if ((si->pss_flags & SW_ENABLED) != SW_ENABLED)
				continue;

			if ((si->pss_flags & SW_BLOCK) == SW_BLOCK) {
				swap_stats_buf->total += ((long long) si->pss_nblksavail) * 1024LL;
				swap_stats_buf->used += ((long long) si->pss_nfpgs) * 1024LL;
				swap_stats_buf->free = swap_stats_buf->total - swap_stats_buf->used;
			}

			if ((si->pss_flags & SW_FS) == SW_FS) {
				swap_stats_buf->total += ((long long) si->pss_limit) * 1024LL;
				swap_stats_buf->used += ((long long) si->pss_allocated) * 1024LL;
				swap_stats_buf->free = swap_stats_buf->total - swap_stats_buf->used;
			}
		}
		swapidx = pstat_swapinfo[num - 1].pss_idx + 1;
	}
#elif defined(AIX)
	/* return code is number of structures returned */
	if(perfstat_memory_total(NULL, &mem, sizeof(perfstat_memory_total_t), 1) != 1) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("swap", SG_ERROR_SYSCTLBYNAME, "perfstat_memory_total");
	}

	swap_stats_buf->total = ((long long)mem.pgsp_total) * sys_page_size;
	swap_stats_buf->free  = ((long long)mem.pgsp_free)  * sys_page_size;
	swap_stats_buf->used  = swap_stats_buf->total - swap_stats_buf->free;
#elif defined(SOLARIS)
# if defined(HAVE_STRUCT_SWAPTABLE)
again:
	if( ( nswap = swapctl(SC_GETNSWP, 0) ) == -1 ) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("swap", SG_ERROR_SWAPCTL, NULL);
	}
	if( nswap != 0 ) {
		char *buf = sg_malloc( nswap * sizeof(char) * (PATH_MAX+1) + 1 );
		if( NULL == buf ) {
			RETURN_FROM_PREVIOUS_ERROR( "swap", sg_get_error() );
		}

		swtbl = sg_malloc( sizeof(*swtbl) + ( nswap * sizeof(swtbl->swt_ent[0]) ) );
		if( NULL == swtbl ) {
			free(buf);
			RETURN_FROM_PREVIOUS_ERROR( "swap", sg_get_error() );
		}

		memset( buf, 0, nswap * sizeof(char) * (PATH_MAX+1) + 1 );
		memset( swtbl, 0, sizeof(*swtbl) + ( nswap * sizeof(swtbl->swt_ent[0]) ) );

		for( i = 0; i < nswap; ++i )
			swtbl->swt_ent[i].ste_path = buf + (i * (PATH_MAX+1));

		swtbl->swt_n = nswap;
		if ((i = swapctl(SC_LIST, swtbl)) < 0) {
			free( buf );
			free( swtbl );
			RETURN_WITH_SET_ERROR_WITH_ERRNO("swap", SG_ERROR_SWAPCTL, NULL);
		}
		if( i > nswap ) {
			free( swtbl );
			free( buf );
			goto again;
		}
		for( i = 0; i < nswap; ++i ) {
			swap_stats_buf->total = swtbl->swt_ent[i].ste_pages;
			swap_stats_buf->free = swtbl->swt_ent[i].ste_free;
		}
		free( swtbl );
		free( buf );
		swap_stats_buf->total *= sys_page_size;
		swap_stats_buf->free *= sys_page_size;
		swap_stats_buf->used = swap_stats_buf->total - swap_stats_buf->free;
	}
# elif defined(HAVE_STRUCT_ANONINFO)
	if (swapctl(SC_AINFO, &ai) == -1) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("swap", SG_ERROR_SWAPCTL, NULL);
	}

	swap_stats_buf->total = ai.ani_max;
	swap_stats_buf->total *= sys_page_size;
	swap_stats_buf->used = ai.ani_resv;
	swap_stats_buf->used *= sys_page_size;
	swap_stats_buf->free = swap_stats_buf->total - swap_stats_buf->used;
# else
	RETURN_WITH_SET_ERROR("swap", SG_ERROR_UNSUPPORTED, OS_TYPE);
# endif
#elif defined(LINUX) || defined(CYGWIN)
	if ((f = fopen("/proc/meminfo", "r")) == NULL) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("swap", SG_ERROR_OPEN, "/proc/meminfo");
	}

	while( (matches < 2) && (fgets(line_buf, sizeof(line_buf), f) != NULL) ) {
		if (sscanf(line_buf, "%*s %llu kB", &value) != 1)
			continue;
		value *= 1024;

		if (strncmp(line_buf, "SwapTotal:", 10) == 0) {
			swap_stats_buf->total = value;
			++matches;
		}
		else if (strncmp(line_buf, "SwapFree:", 9) == 0) {
			swap_stats_buf->free = value;
			++matches;
		}
	}

	fclose(f);

	if( matches < 2 ) {
		RETURN_WITH_SET_ERROR( "swap", SG_ERROR_PARSE, "/proc/meminfo" );
	}

	swap_stats_buf->used = swap_stats_buf->total - swap_stats_buf->free;
#elif defined(HAVE_STRUCT_XSWDEV)
	mibsize = 2;
	if( swapinfo_array ) {
		size = 0;
		if( sysctl( swapinfo_mib, 2, NULL, &size, NULL, 0 ) < 0 ) {
			RETURN_WITH_SET_ERROR_WITH_ERRNO("swap", SG_ERROR_SYSCTL, swapinfo_sysctl_name);
		}
		if( NULL == ( xswbuf = sg_malloc( size ) ) ) {
			RETURN_FROM_PREVIOUS_ERROR( "swap", sg_get_error() );
		}
		if( sysctl( swapinfo_mib, 2, xswbuf, &size, NULL, 0 ) < 0 ) {
			RETURN_WITH_SET_ERROR_WITH_ERRNO("swap", SG_ERROR_SYSCTL, swapinfo_sysctl_name);
		}
	}
	else {
		mib[0] = swapinfo_mib[0];
		mib[1] = swapinfo_mib[1];
	}

	for (n = 0; ; ++n) {
		if( !swapinfo_array ) {
			mib[mibsize] = n;
			size = sizeof(xsw);

			if (sysctl(mib, (unsigned)(mibsize + 1), &xsw, &size, NULL, 0) < 0) {
				if (errno == ENOENT)
					break;
				free( xswbuf );
				RETURN_WITH_SET_ERROR_WITH_ERRNO("swap", SG_ERROR_SYSCTL, swapinfo_sysctl_name);
			}

			xswptr = &xsw;
		}
# if defined(HAVE_STRUCT_XSWDEV_SIZE)
		else {
			if( ((size_t)n) >= (size / xswbuf->xsw_size) )
				break;
			xswptr = xswbuf + n;
		}

		if( xswptr == NULL ) {
			RETURN_WITH_SET_ERROR("swap", SG_ERROR_MEMSTATUS, "no swap status");
		}

#  ifdef XSWDEV_VERSION
		if( xswptr->xsw_version != XSWDEV_VERSION ) {
			free( xswbuf );
			RETURN_WITH_SET_ERROR("swap", SG_ERROR_XSW_VER_MISMATCH, NULL);
		}
#  endif
# endif

		swap_stats_buf->total += (unsigned long long) xswptr->xsw_nblks;
		swap_stats_buf->used += (unsigned long long) xswptr->xsw_used;
	}

	free( xswbuf );

	swap_stats_buf->total *= (size_t)sys_page_size;
	swap_stats_buf->used *= (size_t)sys_page_size;
	if( 0 == swap_stats_buf->free )
		swap_stats_buf->free = swap_stats_buf->total - swap_stats_buf->used;
	else
		swap_stats_buf->free *= (size_t)sys_page_size;

#elif defined(HAVE_STRUCT_XSW_USAGE)

	if (sysctl(mib, (unsigned)mibsize, &xsw, &size, NULL, 0) < 0) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("swap", SG_ERROR_SYSCTL, "CTL_VM.VM_SWAPUSAGE" );
	}

	swap_stats_buf->total = (unsigned long long) xsw.xsu_total;
	swap_stats_buf->used = (unsigned long long) xsw.xsu_used;
	swap_stats_buf->free = (unsigned long long) xsw.xsu_avail;
#elif defined(HAVE_STRUCT_UVMEXP_SYSCTL) && defined(VM_UVMEXP2)
	if (sysctl(mib, 2, &uvm, &size, NULL, 0) < 0) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("swap", SG_ERROR_SYSCTL, "CTL_VM.VM_UVMEXP2");
	}

	swap_stats_buf->total = uvm.pagesize * uvm.swpages;
	swap_stats_buf->used = uvm.pagesize * uvm.swpginuse; /* XXX swpgonly ? */
	swap_stats_buf->free = swap_stats_buf->total - swap_stats_buf->used;
#elif defined(HAVE_STRUCT_UVMEXP) && defined(VM_UVMEXP)
	if (sysctl(mib, 2, &uvm, &size, NULL, 0) < 0) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("swap", SG_ERROR_SYSCTL, "CTL_VM.VM_UVMEXP");
	}

	swap_stats_buf->total = (unsigned long long)uvm.pagesize * (unsigned long long)uvm.swpages;
	swap_stats_buf->used = (unsigned long long)uvm.pagesize * (unsigned long long)uvm.swpginuse; /* XXX swpgonly ? */
	swap_stats_buf->free = swap_stats_buf->total - swap_stats_buf->used;
#elif defined(ALLBSD)
	/* XXX probably not mt-safe! */
	kvmd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, NULL);
	if(kvmd == NULL) {
		RETURN_WITH_SET_ERROR("swap", SG_ERROR_KVM_OPENFILES, NULL);
	}

	if ((kvm_getswapinfo(kvmd, &swapinfo, 1,0)) == -1) {
		kvm_close( kvmd );
		RETURN_WITH_SET_ERROR("swap", SG_ERROR_KVM_GETSWAPINFO, NULL);
	}

	swap_stats_buf->total = (long long)swapinfo.ksw_total;
	swap_stats_buf->used = (long long)swapinfo.ksw_used;
	kvm_close( kvmd );

	swap_stats_buf->total *= sys_page_size;
	swap_stats_buf->used *= sys_page_size;
	swap_stats_buf->free = swap_stats_buf->total - swap_stats_buf->used;
#elif defined(WIN32)
	memstats.dwLength = sizeof(memstats);
	if (!GlobalMemoryStatusEx(&memstats)) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("swap", SG_ERROR_MEMSTATUS, "GloblaMemoryStatusEx");
	}

	/* the PageFile stats include Phys memory "minus an overhead".
	 * Due to this unknown "overhead" there's no way to extract just page
	 * file use from these numbers */
	swap_stats_buf->total = memstats.ullTotalPageFile;
	swap_stats_buf->free = memstats.ullAvailPageFile;
	swap_stats_buf->used = swap_stats_buf->total - swap_stats_buf->free;
#else
	RETURN_WITH_SET_ERROR("swap", SG_ERROR_UNSUPPORTED, OS_TYPE);
#endif

	swap_stats_buf->systime = time(NULL);

	return SG_ERROR_NONE;
}