From 84adefa331c4159d432d22840663c38f155cd4c1 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Fri, 20 Nov 2009 14:54:40 +0000 Subject: The R13B03 release. --- lib/os_mon/c_src/win32sysinfo.c | 318 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 318 insertions(+) create mode 100644 lib/os_mon/c_src/win32sysinfo.c (limited to 'lib/os_mon/c_src/win32sysinfo.c') diff --git a/lib/os_mon/c_src/win32sysinfo.c b/lib/os_mon/c_src/win32sysinfo.c new file mode 100644 index 0000000000..2a155aae87 --- /dev/null +++ b/lib/os_mon/c_src/win32sysinfo.c @@ -0,0 +1,318 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1997-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +/** + * win32sysinfo.c + * + * File: win32sysinfo.c + * Purpose: Portprogram for supervision of disk and memory usage. + * + * Synopsis: win32sysinfo + * + * PURPOSE OF THIS PROGRAM + * + * This program supervises the reports the memory status or disk status + * on request from the Erlang system + * + * + * SPAWNING FROM ERLANG + * + * This program is started from Erlang as follows, + * + * Port = open_port({spawn, 'memsup'}, [{packet,1}]) for UNIX + * + * COMMUNICATION + * + * WIN32 + * + * get_disk_info 'd' (request info about all drives) + * The result is returned as one packet per logical drive with the + * following format: + * Drive Type AvailableBytes TotalBytes TotalBytesFree + * END + * + * Example: + * A:\ DRIVE_REMOVABLE 0 0 0 + * C:\ DRIVE_FIXED 10000000 20000000 10000000 + * END + + * get_disk_info 'd'Driveroot (where Driveroot is a string like this "A:\\" + * (request info of specific drive) + * The result is returned with the same format as above exept that + * Type will be DRIVE_NOT_EXIST if the drive does not exist. + * + * get_mem_info 'm' (request info about memory) + * + * The result is returned as one packet with the following format + * + * + * + * + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "winbase.h" + +#define MEM_INFO 'm' +#define DISK_INFO 'd' +#define OK "o" + +#define ERLIN_FD 0 +#define ERLOUT_FD 1 + + +typedef BOOL (WINAPI *tfpGetDiskFreeSpaceEx)(LPCTSTR, PULARGE_INTEGER,PULARGE_INTEGER,PULARGE_INTEGER); + +static tfpGetDiskFreeSpaceEx fpGetDiskFreeSpaceEx; + +static void +return_answer(char* value) +{ + int left, bytes, res; + + bytes = strlen(value); /* Skip trailing zero */ + + res = write(1,(char*) &bytes,1); + if (res != 1) { + fprintf(stderr,"win32sysinfo:Error writing to pipe"); + exit(1); + } + + left = bytes; + + while (left > 0) + { + res = write(1, value+bytes-left, left); + if (res <= 0) + { + fprintf(stderr,"win32sysinfo:Error writing to pipe"); + exit(1); + } + left -= res; + } +} + +void output_drive_info(char* drive){ + ULARGE_INTEGER availbytes,totbytesfree,totbytes; + OSVERSIONINFO osinfo; + char answer[512]; + osinfo.dwOSVersionInfoSize=sizeof(OSVERSIONINFO); + GetVersionEx(&osinfo); + switch (GetDriveType(drive)) { + case DRIVE_UNKNOWN: + sprintf(answer,"%s DRIVE_UNKNOWN 0 0 0\n",drive); + return_answer(answer); + break; + case DRIVE_NO_ROOT_DIR: + sprintf(answer,"%s DRIVE_NO_ROOT_DIR 0 0 0\n",drive); + return_answer(answer); + break; + case DRIVE_REMOVABLE: + sprintf(answer,"%s DRIVE_REMOVABLE 0 0 0\n",drive); + return_answer(answer); + break; + case DRIVE_FIXED: + /* if ((osinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) && + (LOWORD(osinfo.dwBuildNumber) <= 1000)) { + sprintf(answer,"%s API_NOT_SUPPORTED 0 0 0\n",drive); + return_answer(answer); + } + else + */ + if (fpGetDiskFreeSpaceEx == NULL){ + sprintf(answer,"%s API_NOT_SUPPORTED 0 0 0\n",drive); + return_answer(answer); + } + else + if (fpGetDiskFreeSpaceEx(drive,&availbytes,&totbytes,&totbytesfree)){ + sprintf(answer,"%s DRIVE_FIXED %I64u %I64u %I64u\n",drive,availbytes,totbytes,totbytesfree); + return_answer(answer); + } + else { + sprintf(answer,"%s API_ERROR 0 0 0\n",drive); + return_answer(answer); + } + break; + case DRIVE_REMOTE: + sprintf(answer,"%s DRIVE_REMOTE 0 0 0\n",drive); + return_answer(answer); + break; + case DRIVE_CDROM: + sprintf(answer,"%s DRIVE_CDROM 0 0 0\n",drive); + return_answer(answer); + break; + case DRIVE_RAMDISK: + sprintf(answer,"%s DRIVE_RAMDISK 0 0 0\n",drive); + return_answer(answer); + break; + default: + sprintf(answer,"%s DRIVE_NOT_EXIST 0 0 0\n",drive); + return_answer(answer); + } /* switch */ +} + +int load_if_possible() { + HINSTANCE lh; + if((lh = LoadLibrary("KERNEL32")) ==NULL) + return 0; /* error */ + if ((fpGetDiskFreeSpaceEx = + (tfpGetDiskFreeSpaceEx) GetProcAddress(lh,"GetDiskFreeSpaceExA")) ==NULL) + return GetLastError(); /* error */ + return 1; +} + +void get_disk_info_all(){ + DWORD dwNumBytesForDriveStrings; + char DriveStrings[255]; + char* dp = DriveStrings; + + dwNumBytesForDriveStrings = GetLogicalDriveStrings(254,dp); + if (dwNumBytesForDriveStrings != 0) { + /* GetLogicalDriveStringsIs supported on this platform */ + while (*dp != 0) { + output_drive_info(dp); + dp = strchr(dp,0) +1; + } + } + else { + /* GetLogicalDriveStrings is not supported (some old W95) */ + DWORD dwDriveMask = GetLogicalDrives(); + int nDriveNum; + char drivename[]="A:\\"; + /*printf("DriveName95 DriveType BytesAvail BytesTotal BytesTotalFree\n");*/ + for (nDriveNum = 0; dwDriveMask != 0;nDriveNum++) { + if (dwDriveMask & 1) { + drivename[0]='A'+ nDriveNum; + output_drive_info(drivename); + } + dwDriveMask = dwDriveMask >> 1; + } + } +} + +void get_avail_mem_ext() { + char answer[512]; + MEMORYSTATUSEX ms; + ms.dwLength=sizeof(MEMORYSTATUSEX); + GlobalMemoryStatusEx(&ms); + sprintf(answer,"%d %I64d %I64d %I64d %I64d %I64d %I64d\n", + ms.dwMemoryLoad, + ms.ullTotalPhys, + ms.ullAvailPhys, + ms.ullTotalPageFile, + ms.ullAvailPageFile, + ms.ullTotalVirtual, + ms.ullAvailVirtual + ); + return_answer(answer); + /* + DWORD dwLength; + DWORD dwMemoryLoad; + DWORDLONG ullTotalPhys; + DWORDLONG ullAvailPhys; + DWORDLONG ullTotalPageFile; + DWORDLONG ullAvailPageFile; + DWORDLONG ullTotalVirtual; + DWORDLONG ullAvailVirtual; + */ +} + +static void +message_loop() +{ + char cmdLen; + char cmd[512]; + int res; + + fprintf(stderr,"in message_loop\n"); + /* Startup ACK. */ + return_answer(OK); + while (1) + { + /* + * Wait for command from Erlang + */ + if ((res = read(0, &cmdLen, 1)) < 0) { + fprintf(stderr,"win32sysinfo:Error reading from Erlang."); + return; + } + + if (res != 1){ /* Exactly one byte read ? */ + fprintf(stderr,"win32sysinfo:Erlang has closed."); + return; + } + if ((res = read(0, &cmd, cmdLen)) == cmdLen){ + if (cmdLen == 1) { + switch (cmd[0]) { + case MEM_INFO: + get_avail_mem_ext(); + return_answer(OK); + break; + case DISK_INFO: + get_disk_info_all(); + return_answer(OK); + break; + default: /* ignore all other messages */ + break; + } /* switch */ + } + else + if ((res > 0) && (cmd[0]==DISK_INFO)) { + cmd[cmdLen] = 0; + output_drive_info(&cmd[1]); + return_answer("OK"); + return; + } + else + return_answer("xEND"); + } + else if (res == 0) { + fprintf(stderr,"win32sysinfo:Erlang has closed."); + return; + } + else { + fprintf(stderr,"win32sysinfo:Error reading from Erlang."); + return; + } + } +} + +int main(int argc, char ** argv){ + + _setmode(0, _O_BINARY); + _setmode(1, _O_BINARY); + load_if_possible(); + message_loop(); + return 0; +} + + + + + + + -- cgit v1.2.3