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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }