/* * %CopyrightBegin% * * Copyright Ericsson AB 1997-2016. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions 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 print_error(const char *msg); 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) { print_error("Error writing to pipe"); exit(1); } left = bytes; while (left > 0) { res = write(1, value+bytes-left, left); if (res <= 0) { print_error("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; /* Startup ACK. */ return_answer(OK); while (1) { /* * Wait for command from Erlang */ if ((res = read(0, &cmdLen, 1)) < 0) { print_error("Error reading from Erlang"); return; } if (res != 1){ /* Exactly one byte read ? */ print_error("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) { print_error("Erlang has closed"); return; } else { print_error("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; } static void print_error(const char *msg) { /* try to use one write only */ fprintf(stderr, "[os_mon] win32 supervisor port (win32sysinfo): %s\r\n", msg); fflush(stderr); }