|
@@ -0,0 +1,994 @@
|
|
|
+#include <stdio.h>
|
|
|
+#include <stdio.h>
|
|
|
+#include <unistd.h>
|
|
|
+#include <string.h>
|
|
|
+#include <string>
|
|
|
+#include <vector>
|
|
|
+#include <map>
|
|
|
+#include <ext/stdio_filebuf.h>
|
|
|
+#include <iostream>
|
|
|
+#include <fstream>
|
|
|
+#include <signal.h>
|
|
|
+#include <sys/statvfs.h>
|
|
|
+#include <sys/statfs.h>
|
|
|
+#include <sys/types.h>
|
|
|
+#include <fcntl.h>
|
|
|
+#include <unistd.h>
|
|
|
+#include <limits.h>
|
|
|
+#include <libudev.h>
|
|
|
+#include <poll.h>
|
|
|
+//#include <usb.h>
|
|
|
+#include <gfa/gfasitarautils.h>
|
|
|
+//#include <gfa/gfaipc.h>
|
|
|
+#include "../../src/gfaipc.h"
|
|
|
+#include "../../src/ipcpriv.h"
|
|
|
+
|
|
|
+/////////////////////////////////////////////////////////////////////////////
|
|
|
+
|
|
|
+#ifdef _DEBUG
|
|
|
+#define TRACE(...) fprintf(stdout, __VA_ARGS__), fflush(stdout)
|
|
|
+#else // _DEBUG
|
|
|
+#define TRACE(...)
|
|
|
+#endif // _DEBUG
|
|
|
+
|
|
|
+#define UNUSED(v) (void)v
|
|
|
+#define _countof(a) (sizeof(a) / sizeof(*a))
|
|
|
+
|
|
|
+#define _APPID GFA_APPCTRL_APPID_SYSINFO
|
|
|
+#define _APPNAME "SysInfo"
|
|
|
+#define _CYCLE_INTV 500
|
|
|
+
|
|
|
+#define _STR_EQUALS(s, t) (!!s && !strcmp(s, t))
|
|
|
+#define _NUM_TO_BIT(i) (0x01 << (i))
|
|
|
+#define _MOUNTS_FILE "/proc/mounts"
|
|
|
+
|
|
|
+#define _INTERNAL_EMMC_DISK "mmcblk1"
|
|
|
+#define _INTERNAL_EMMC_PART1 "mmcblk1p1"
|
|
|
+#define _INTERNAL_EMMC_PART2 "mmcblk1p2"
|
|
|
+
|
|
|
+/////////////////////////////////////////////////////////////////////////////
|
|
|
+
|
|
|
+typedef std::map<std::string, std::string> MountMap;
|
|
|
+
|
|
|
+/////////////////////////////////////////////////////////////////////////////
|
|
|
+
|
|
|
+static long long _NumberFromString(const char *pszString, int base = 10, bool *pbErr = NULL);
|
|
|
+static const char* _ReadDevPropertyValue(struct udev_device* dev, const char *pszKey, char *pszValue, size_t nCChValue, bool bTruncate = false);
|
|
|
+static long long _ReadDevPropertyValue(struct udev_device* dev, const char *pszKey, int base = 10, bool *pbErr = NULL);
|
|
|
+
|
|
|
+/////////////////////////////////////////////////////////////////////////////
|
|
|
+
|
|
|
+// console=ttyO0,115200 root=/dev/mmcblk0p2 rw rootwait vram=50M cma=50M
|
|
|
+
|
|
|
+/////////////////////////////////////////////////////////////////////////////
|
|
|
+/////////////////////////////////////////////////////////////////////////////
|
|
|
+/////////////////////////////////////////////////////////////////////////////
|
|
|
+
|
|
|
+ssize_t _LookupPartition(const GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, const char *pszDevNode)
|
|
|
+{
|
|
|
+ ssize_t nIndex = -1;
|
|
|
+
|
|
|
+ if(pszDevNode && *pszDevNode)
|
|
|
+ {
|
|
|
+ for(size_t i = 0; i < _countof(sdm.parts); ++i)
|
|
|
+ {
|
|
|
+ if(sdm.parts[i].valid && !strcmp(sdm.parts[i].szDevNode, pszDevNode))
|
|
|
+ {
|
|
|
+ nIndex = i; // found partition
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return nIndex;
|
|
|
+}
|
|
|
+
|
|
|
+ssize_t _AddPartition(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, const GFA_SYSINFO_PARTITION &part, bool &bChange)
|
|
|
+{
|
|
|
+ ssize_t nIndex = -1;
|
|
|
+ bChange = false;
|
|
|
+
|
|
|
+ if((nIndex = _LookupPartition(sdm, part.szDevNode)) >= 0)
|
|
|
+ return nIndex; // partition already exists
|
|
|
+
|
|
|
+ for(size_t i = 0; i < _countof(sdm.parts); ++i)
|
|
|
+ {
|
|
|
+ if(!sdm.parts[i].valid)
|
|
|
+ {
|
|
|
+ memcpy(&sdm.parts[i], &part, sizeof(GFA_SYSINFO_PARTITION));
|
|
|
+ sdm.parts[i].valid = true;
|
|
|
+ bChange = true;
|
|
|
+ nIndex = i;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return nIndex;
|
|
|
+}
|
|
|
+
|
|
|
+ssize_t _RemovePartition(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, ssize_t nIndex, bool &bChange)
|
|
|
+{
|
|
|
+ bChange = false;
|
|
|
+ if(nIndex >= 0 && nIndex < (ssize_t)_countof(sdm.parts))
|
|
|
+ {
|
|
|
+ bChange = sdm.parts[nIndex].valid;
|
|
|
+ sdm.parts[nIndex].valid = false;
|
|
|
+ }
|
|
|
+ return nIndex;
|
|
|
+}
|
|
|
+
|
|
|
+ssize_t _RemovePartition(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, const char *pszDevNode, bool &bChange)
|
|
|
+{
|
|
|
+ ssize_t nIndex = _LookupPartition(sdm, pszDevNode);
|
|
|
+ return _RemovePartition(sdm, nIndex, bChange);
|
|
|
+}
|
|
|
+
|
|
|
+bool _PartitionSetDisk(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, ssize_t nPartIdx, ssize_t nDiskIdx, bool &bChange)
|
|
|
+{
|
|
|
+ bChange = false;
|
|
|
+ if( (nPartIdx >= 0) && (nPartIdx < (ssize_t)_countof(sdm.parts)) &&
|
|
|
+ (nDiskIdx >= 0) && (nDiskIdx < (ssize_t)_countof(sdm.disks)))
|
|
|
+ {
|
|
|
+ if(sdm.parts[nPartIdx].nDiskIdx != nDiskIdx)
|
|
|
+ {
|
|
|
+ sdm.parts[nPartIdx].nDiskIdx = nDiskIdx;
|
|
|
+ bChange = true;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+ssize_t _PartitionGetDisk(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, ssize_t nPartIdx)
|
|
|
+{
|
|
|
+ if((nPartIdx >= 0) && (nPartIdx < (ssize_t)_countof(sdm.parts)))
|
|
|
+ return sdm.parts[nPartIdx].nDiskIdx;
|
|
|
+ return -1;
|
|
|
+}
|
|
|
+
|
|
|
+void _ClearMapChanges(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm)
|
|
|
+{
|
|
|
+ sdm.nPartChangeMask = 0;
|
|
|
+}
|
|
|
+
|
|
|
+bool _MapChanged(const GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm)
|
|
|
+{
|
|
|
+ return !!sdm.nPartChangeMask;
|
|
|
+}
|
|
|
+
|
|
|
+unsigned int _SetPartitionChange(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, ssize_t nPartIdx)
|
|
|
+{
|
|
|
+ if((nPartIdx >= 0) && (nPartIdx < (ssize_t)_countof(sdm.parts)))
|
|
|
+ {
|
|
|
+ unsigned int nChanged = _NUM_TO_BIT(nPartIdx);
|
|
|
+ sdm.nPartChangeMask |= nChanged;
|
|
|
+ }
|
|
|
+ return sdm.nPartChangeMask;
|
|
|
+}
|
|
|
+
|
|
|
+/////////////////////////////////////////////////////////////////////////////
|
|
|
+
|
|
|
+ssize_t _LookupDisk(const GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, const char *pszDevNode)
|
|
|
+{
|
|
|
+ ssize_t nIndex = -1;
|
|
|
+
|
|
|
+ if(pszDevNode && *pszDevNode)
|
|
|
+ {
|
|
|
+ for(size_t i = 0; i < _countof(sdm.disks); ++i)
|
|
|
+ {
|
|
|
+ if(sdm.disks[i].valid && !strcmp(sdm.disks[i].szDevNode, pszDevNode))
|
|
|
+ {
|
|
|
+ nIndex = i; // found partition
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return nIndex;
|
|
|
+}
|
|
|
+
|
|
|
+ssize_t _AddDisk(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, const GFA_SYSINFO_DISK &disk, bool &bChange)
|
|
|
+{
|
|
|
+ ssize_t nIndex = -1;
|
|
|
+ bChange = false;
|
|
|
+
|
|
|
+ if((nIndex = _LookupDisk(sdm, disk.szDevNode)) >= 0)
|
|
|
+ return nIndex; // partition already exists
|
|
|
+
|
|
|
+ for(size_t i = 0; i < _countof(sdm.disks); ++i)
|
|
|
+ {
|
|
|
+ if(!sdm.disks[i].valid)
|
|
|
+ {
|
|
|
+ memcpy(&sdm.disks[i], &disk, sizeof(GFA_SYSINFO_DISK));
|
|
|
+ sdm.disks[i].valid = true;
|
|
|
+ bChange = true;
|
|
|
+ nIndex = i;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return nIndex;
|
|
|
+}
|
|
|
+
|
|
|
+ssize_t _RemoveDisk(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, ssize_t nIndex, bool &bChange)
|
|
|
+{
|
|
|
+ bChange = false;
|
|
|
+ if(nIndex >= 0 && nIndex < (ssize_t)_countof(sdm.disks))
|
|
|
+ {
|
|
|
+ bChange = sdm.disks[nIndex].valid;
|
|
|
+ sdm.disks[nIndex].valid = false;
|
|
|
+ }
|
|
|
+ return nIndex;
|
|
|
+}
|
|
|
+
|
|
|
+ssize_t _RemoveDisk(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, const char *pszDevNode, bool &bChange)
|
|
|
+{
|
|
|
+ ssize_t nIndex = _LookupDisk(sdm, pszDevNode);
|
|
|
+ return _RemoveDisk(sdm, nIndex, bChange);
|
|
|
+}
|
|
|
+
|
|
|
+unsigned int _DiskAddPartition(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, ssize_t nDiskIdx, ssize_t nPartIdx, bool &bChange)
|
|
|
+{
|
|
|
+ bChange = false;
|
|
|
+ if( (nPartIdx >= 0) && (nPartIdx < (ssize_t)_countof(sdm.parts)) &&
|
|
|
+ (nDiskIdx >= 0) && (nDiskIdx < (ssize_t)_countof(sdm.disks)))
|
|
|
+ {
|
|
|
+ GFA_SYSINFO_DISK &disk = sdm.disks[nDiskIdx];
|
|
|
+
|
|
|
+ for(unsigned int i = 0; i < disk.nPartCount; ++i)
|
|
|
+ {
|
|
|
+ if(disk.aPartIdx[i] == nPartIdx)
|
|
|
+ return disk.nPartCount;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(disk.nPartCount < _countof(disk.aPartIdx))
|
|
|
+ {
|
|
|
+ disk.aPartIdx[disk.nPartCount++] = nPartIdx;
|
|
|
+ bChange = true;
|
|
|
+ return disk.nPartCount;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+unsigned int _DiskRemovePartition(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, ssize_t nDiskIdx, ssize_t nPartIdx, bool &bChange)
|
|
|
+{
|
|
|
+ bChange = false;
|
|
|
+ if( (nPartIdx >= 0) && (nPartIdx < (ssize_t)_countof(sdm.parts)) &&
|
|
|
+ (nDiskIdx >= 0) && (nDiskIdx < (ssize_t)_countof(sdm.disks)))
|
|
|
+ {
|
|
|
+ unsigned int i, j;
|
|
|
+ GFA_SYSINFO_DISK &disk = sdm.disks[nDiskIdx];
|
|
|
+
|
|
|
+ for(i = 0; i < disk.nPartCount; ++i)
|
|
|
+ {
|
|
|
+ if(disk.aPartIdx[i] == nPartIdx)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(i < disk.nPartCount)
|
|
|
+ {
|
|
|
+ for(j = i + 1; j < disk.nPartCount; ++i, ++j)
|
|
|
+ {
|
|
|
+ disk.aPartIdx[i] = disk.aPartIdx[j];
|
|
|
+ }
|
|
|
+ bChange = true;
|
|
|
+ return --disk.nPartCount;
|
|
|
+ }
|
|
|
+ return disk.nPartCount;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/////////////////////////////////////////////////////////////////////////////
|
|
|
+/////////////////////////////////////////////////////////////////////////////
|
|
|
+
|
|
|
+static const char *g_pszStateNames[] =
|
|
|
+{
|
|
|
+ "Not running",
|
|
|
+ "Initializing",
|
|
|
+ "Running",
|
|
|
+ "Paused",
|
|
|
+ "Hanging",
|
|
|
+ "Terminating",
|
|
|
+ "Invalid"
|
|
|
+};
|
|
|
+
|
|
|
+/////////////////////////////////////////////////////////////////////////////
|
|
|
+
|
|
|
+static volatile bool g_fRun = false;
|
|
|
+static volatile bool g_fPause = false;
|
|
|
+
|
|
|
+/////////////////////////////////////////////////////////////////////////////
|
|
|
+
|
|
|
+static void _SigHandler(int sig)
|
|
|
+{
|
|
|
+ UNUSED(sig);
|
|
|
+ g_fPause = false;
|
|
|
+ g_fRun = false;
|
|
|
+}
|
|
|
+
|
|
|
+/////////////////////////////////////////////////////////////////////////////
|
|
|
+
|
|
|
+static bool _LookupMountPoint(MountMap &mm, const char *pszNode, char *pszMntPoint, size_t nCChMntPoint)
|
|
|
+{
|
|
|
+ MountMap::const_iterator it = mm.find(pszNode);
|
|
|
+ if(it == mm.end())
|
|
|
+ return false;
|
|
|
+ const std::string &s = it->second;
|
|
|
+
|
|
|
+ if(s.length() < nCChMntPoint)
|
|
|
+ {
|
|
|
+ strcpy(pszMntPoint, s.c_str());
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+static bool _UpdatePartitionSizeInfo(MountMap &mm, GFA_SYSINFO_PARTITION &part)
|
|
|
+{
|
|
|
+ if(_LookupMountPoint(mm, part.szDevNode, part.szMntPoint, sizeof(part.szMntPoint)))
|
|
|
+ {
|
|
|
+ struct statvfs stvs;
|
|
|
+
|
|
|
+ if(!statvfs(part.szMntPoint, &stvs))
|
|
|
+ {
|
|
|
+ part.nKiBSize = stvs.f_bsize * stvs.f_blocks / 1024;
|
|
|
+ part.nKiBFree = stvs.f_bsize * stvs.f_bfree / 1024;
|
|
|
+ part.nKiBUsed = part.nKiBSize - part.nKiBFree;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ part.nKiBSize = 0;
|
|
|
+ part.nKiBFree = 0;
|
|
|
+ part.nKiBUsed = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ memset(part.szMntPoint, 0, sizeof(part.szMntPoint));
|
|
|
+ part.nKiBSize = 0;
|
|
|
+ part.nKiBFree = 0;
|
|
|
+ part.nKiBUsed = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+/////////////////////////////////////////////////////////////////////////////
|
|
|
+
|
|
|
+static void _UpdateMountMap(MountMap &mm)
|
|
|
+{
|
|
|
+ char szLine[512], szNode[512], szMount[512];
|
|
|
+ std::ifstream mounts(_MOUNTS_FILE);
|
|
|
+ mm.clear();
|
|
|
+
|
|
|
+ while(mounts.getline(szLine, sizeof(szLine)).good())
|
|
|
+ {
|
|
|
+ if((sscanf(szLine, "%s %s", szNode, szMount) == 2))
|
|
|
+ {
|
|
|
+ std::string key(szNode);
|
|
|
+ std::string val(szMount);
|
|
|
+ mm.emplace(key, val);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/////////////////////////////////////////////////////////////////////////////
|
|
|
+
|
|
|
+static bool _ProcessMounts(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, MountMap &mm)
|
|
|
+{
|
|
|
+ bool bChange = false;
|
|
|
+ char szMntPoint[_countof(GFA_SYSINFO_PARTITION::szMntPoint)];
|
|
|
+
|
|
|
+ for(size_t i = 0; i < _countof(sdm.parts); ++i)
|
|
|
+ {
|
|
|
+ GFA_SYSINFO_PARTITION &part = sdm.parts[i];
|
|
|
+
|
|
|
+ if(part.valid)
|
|
|
+ {
|
|
|
+ bool bMountedOld = !!*part.szMntPoint;
|
|
|
+ bool bMountedNew = _LookupMountPoint(mm, part.szDevNode, szMntPoint, sizeof(szMntPoint));
|
|
|
+
|
|
|
+ if(!bMountedOld && bMountedNew)
|
|
|
+ {
|
|
|
+// TRACE("Partition %s: mounted at %s\n", part.szDevNode, szMntPoint);
|
|
|
+ memcpy(part.szMntPoint, szMntPoint, sizeof(part.szMntPoint));
|
|
|
+ _UpdatePartitionSizeInfo(mm, part);
|
|
|
+ _SetPartitionChange(sdm, i);
|
|
|
+ bChange = true;
|
|
|
+ }
|
|
|
+ else if(bMountedOld && !bMountedNew)
|
|
|
+ {
|
|
|
+// TRACE("Partition %s: unmounted from %s\n", part.szDevNode, part.szMntPoint);
|
|
|
+ memset(part.szMntPoint, 0, sizeof(part.szMntPoint));
|
|
|
+ _UpdatePartitionSizeInfo(mm, part);
|
|
|
+ _SetPartitionChange(sdm, i);
|
|
|
+ bChange = true;
|
|
|
+ }
|
|
|
+ else if(bMountedOld && bMountedNew)
|
|
|
+ {
|
|
|
+ if(strcmp(part.szMntPoint, szMntPoint))
|
|
|
+ {
|
|
|
+// TRACE("Partition %s: mount point changed: %s -> %s\n", part.szDevNode, part.szMntPoint, szMntPoint);
|
|
|
+ memcpy(part.szMntPoint, szMntPoint, sizeof(part.szMntPoint));
|
|
|
+ _UpdatePartitionSizeInfo(mm, part);
|
|
|
+ _SetPartitionChange(sdm, i);
|
|
|
+ bChange = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return bChange;
|
|
|
+}
|
|
|
+
|
|
|
+/////////////////////////////////////////////////////////////////////////////
|
|
|
+
|
|
|
+static void _ProcessCtrlMessages(HAPPCTRL hAC, HAPPINFO hAI)
|
|
|
+{
|
|
|
+ ctrlmsg_t nCtrlMsg;
|
|
|
+
|
|
|
+ while(g_fRun && (nCtrlMsg = ::GfaIpcAppCtrlGetNextCtrlMsg(hAI)))
|
|
|
+ {
|
|
|
+ switch(nCtrlMsg)
|
|
|
+ {
|
|
|
+ case GFA_APPCTRL_CTRLMSG_STOP:
|
|
|
+ g_fRun = false;
|
|
|
+ TRACE("Received Message: STOP!\n");
|
|
|
+ break;
|
|
|
+ case GFA_APPCTRL_CTRLMSG_PAUSE:
|
|
|
+ if(!g_fPause)
|
|
|
+ {
|
|
|
+ g_fPause = true;
|
|
|
+ ::GfaIpcAppCtrlSetState(hAC, GIAS_Paused);
|
|
|
+ TRACE("%-8s: State: %s\n", "Me", g_pszStateNames[GIAS_Paused]);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case GFA_APPCTRL_CTRLMSG_RESUME:
|
|
|
+ if(g_fPause)
|
|
|
+ {
|
|
|
+ g_fPause = false;
|
|
|
+ ::GfaIpcAppCtrlSetState(hAC, GIAS_Running);
|
|
|
+ TRACE("%-8s: State: %s\n", "Me", g_pszStateNames[GIAS_Running]);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static const char* _GetFileSpec(const char *pszName)
|
|
|
+{
|
|
|
+ if(pszName && *pszName)
|
|
|
+ {
|
|
|
+ const char *pSlash = strrchr(pszName, '/');
|
|
|
+ if(pSlash)
|
|
|
+ return ++pSlash;
|
|
|
+ else
|
|
|
+ return pszName;
|
|
|
+ }
|
|
|
+
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+static bool _IsInternalEmmc(const char *pszDevNode)
|
|
|
+{
|
|
|
+ if(pszDevNode)
|
|
|
+ {
|
|
|
+ const char *pszDevName = _GetFileSpec(pszDevNode);
|
|
|
+ return _STR_EQUALS(pszDevName, _INTERNAL_EMMC_PART1) || _STR_EQUALS(pszDevName, _INTERNAL_EMMC_PART2);
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+#if 0
|
|
|
+static void _EnumDevProperties(struct udev_device *dev, int nIndent)
|
|
|
+{
|
|
|
+ if(dev)
|
|
|
+ {
|
|
|
+ struct udev_list_entry *prop;
|
|
|
+ struct udev_list_entry *props = udev_device_get_properties_list_entry(dev);
|
|
|
+
|
|
|
+ if(props)
|
|
|
+ {
|
|
|
+ udev_list_entry_foreach(prop, props)
|
|
|
+ {
|
|
|
+ const char *pszName = udev_list_entry_get_name(prop);
|
|
|
+ const char *pszValue = udev_list_entry_get_value(prop);
|
|
|
+
|
|
|
+ if(pszName && pszValue)
|
|
|
+ {
|
|
|
+ TRACE("%-*s+ %s = \"%s\"\n", nIndent + 2, " ", pszName, pszValue);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void _EnumDevSysAttributes(struct udev_device *dev, int nIndent)
|
|
|
+{
|
|
|
+ if(dev)
|
|
|
+ {
|
|
|
+ struct udev_list_entry *att;
|
|
|
+ struct udev_list_entry *atts = udev_device_get_sysattr_list_entry(dev);
|
|
|
+ if(atts)
|
|
|
+ {
|
|
|
+ udev_list_entry_foreach(att, atts)
|
|
|
+ {
|
|
|
+ const char *pszName = udev_list_entry_get_name(att);
|
|
|
+ const char *pszValue = udev_device_get_sysattr_value(dev, pszName);
|
|
|
+
|
|
|
+ if(pszName && pszValue && strcmp(pszName, "uevent"))
|
|
|
+ {
|
|
|
+ TRACE("%-*s- %s = \"%s\"\n", nIndent + 2, " ", pszName, pszValue);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+#define _BYTE_SIZE_KIB (1ULL << 10) // Kibibyte
|
|
|
+#define _BYTE_SIZE_MIB (1ULL << 20) // Mebibyte
|
|
|
+#define _BYTE_SIZE_GIB (1ULL << 30) // Gibibyte
|
|
|
+#define _BYTE_SIZE_TIB (1ULL << 40) // Tebibyte
|
|
|
+#define _BYTE_SIZE_PIB (1ULL << 50) // Pebibyte
|
|
|
+#define _BYTE_SIZE_EIB (1ULL << 60) // Exbibyte
|
|
|
+
|
|
|
+static const char *_FormatByteSize(unsigned long long nCb, char *pszBuf, size_t nCChBuf)
|
|
|
+{
|
|
|
+ if(pszBuf && nCChBuf)
|
|
|
+ {
|
|
|
+ int nPrec = 2;
|
|
|
+ double val = nCb;
|
|
|
+
|
|
|
+ if(nCb < _BYTE_SIZE_KIB)
|
|
|
+ {
|
|
|
+ snprintf(pszBuf, nCChBuf, "%llu Byte", nCb); // Byte
|
|
|
+ }
|
|
|
+ else if(nCb < _BYTE_SIZE_MIB)
|
|
|
+ {
|
|
|
+ val /= _BYTE_SIZE_KIB;
|
|
|
+ snprintf(pszBuf, nCChBuf, "%.*f KiB", nPrec, val); // KiB
|
|
|
+ }
|
|
|
+ else if(nCb < _BYTE_SIZE_GIB)
|
|
|
+ {
|
|
|
+ val /= _BYTE_SIZE_MIB;
|
|
|
+ snprintf(pszBuf, nCChBuf, "%.*f MiB", nPrec, val); // MiB
|
|
|
+ }
|
|
|
+ else if(nCb < _BYTE_SIZE_TIB)
|
|
|
+ {
|
|
|
+ val /= _BYTE_SIZE_GIB;
|
|
|
+ snprintf(pszBuf, nCChBuf, "%.*f GiB", nPrec, val); // GiB
|
|
|
+ }
|
|
|
+ else if(nCb < _BYTE_SIZE_PIB)
|
|
|
+ {
|
|
|
+ val /= _BYTE_SIZE_TIB;
|
|
|
+ snprintf(pszBuf, nCChBuf, "%.*f TiB", nPrec, val); // TiB
|
|
|
+ }
|
|
|
+ else if(nCb < _BYTE_SIZE_EIB)
|
|
|
+ {
|
|
|
+ val /= _BYTE_SIZE_PIB;
|
|
|
+ snprintf(pszBuf, nCChBuf, "%.*f PiB", nPrec, val); // PiB
|
|
|
+ }
|
|
|
+
|
|
|
+ return pszBuf;
|
|
|
+ }
|
|
|
+
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+static void _DumpStorageDeviceMap(const GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm)
|
|
|
+{
|
|
|
+ TRACE("\n");
|
|
|
+ for(size_t i = 0; i < _countof(sdm.disks); ++i)
|
|
|
+ {
|
|
|
+ char szByteBuf[16];
|
|
|
+ const GFA_SYSINFO_DISK &disk = sdm.disks[i];
|
|
|
+
|
|
|
+ if(disk.valid)
|
|
|
+ {
|
|
|
+ TRACE("Disk:\n");
|
|
|
+ TRACE(" |-Label: %s\n", disk.szName);
|
|
|
+ TRACE(" |-Vendor: %s\n", *disk.szVendor ? disk.szVendor : "");
|
|
|
+ TRACE(" |-Node: %s\n", disk.szDevNode);
|
|
|
+ TRACE(" |-Type: %s\n", *disk.szBus ? disk.szBus : "mmc");
|
|
|
+
|
|
|
+ for(unsigned int j = 0; j < disk.nPartCount; ++j)
|
|
|
+ {
|
|
|
+ ssize_t nIndex = disk.aPartIdx[j];
|
|
|
+ const GFA_SYSINFO_PARTITION &part = sdm.parts[nIndex];
|
|
|
+ bool bMounted = !!*part.szMntPoint;
|
|
|
+
|
|
|
+ TRACE(" |-Partition:\n");
|
|
|
+ TRACE(" |-Label: %s\n", part.szFsLabel);
|
|
|
+ TRACE(" |-Node: %s\n", part.szDevNode);
|
|
|
+ TRACE(" |-PA-Size: %s\n", _FormatByteSize(part.nKiBPartSize * _BYTE_SIZE_KIB, szByteBuf, sizeof(szByteBuf)));
|
|
|
+ TRACE(" |-Mount: %s\n", bMounted ? part.szMntPoint : "Not mounted");
|
|
|
+ if(bMounted)
|
|
|
+ {
|
|
|
+ TRACE(" |-FS-Type: %s\n", part.szFsType);
|
|
|
+ TRACE(" |-FS-Ver.: %s\n", part.szFsVersion);
|
|
|
+ TRACE(" |-FS-Size: %s\n", _FormatByteSize(part.nKiBSize * _BYTE_SIZE_KIB, szByteBuf, sizeof(szByteBuf)));
|
|
|
+ TRACE(" |-FS-Used: %s\n", _FormatByteSize(part.nKiBUsed * _BYTE_SIZE_KIB, szByteBuf, sizeof(szByteBuf)));
|
|
|
+ TRACE(" |-FS-Free: %s\n", _FormatByteSize(part.nKiBFree * _BYTE_SIZE_KIB, szByteBuf, sizeof(szByteBuf)));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ TRACE("\n");
|
|
|
+}
|
|
|
+
|
|
|
+static long long _NumberFromString(const char *pszString, int base, bool *pbErr)
|
|
|
+{
|
|
|
+ if(!pszString || !*pszString)
|
|
|
+ {
|
|
|
+ if(pbErr)
|
|
|
+ *pbErr = true;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ char *endptr;
|
|
|
+ long long nRet = strtoll(pszString, &endptr, base);
|
|
|
+
|
|
|
+ if( (((nRet == LLONG_MAX) || (nRet == LLONG_MIN)) && (errno == ERANGE)) ||
|
|
|
+ ((nRet == 0) && (errno == EINVAL)) ||
|
|
|
+ (!!*endptr))
|
|
|
+ {
|
|
|
+ if(pbErr)
|
|
|
+ *pbErr = true;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(pbErr)
|
|
|
+ *pbErr = false;
|
|
|
+ return nRet;
|
|
|
+}
|
|
|
+
|
|
|
+static long long _ReadDevPropertyValue(struct udev_device* dev, const char *pszKey, int base, bool *pbErr)
|
|
|
+{
|
|
|
+ char szNum[64];
|
|
|
+ return _NumberFromString(_ReadDevPropertyValue(dev, pszKey, szNum, sizeof(szNum), false), base, pbErr);
|
|
|
+}
|
|
|
+
|
|
|
+static const char* _ReadDevPropertyValue(struct udev_device* dev, const char *pszKey, char *pszValue, size_t nCChValue, bool bTruncate)
|
|
|
+{
|
|
|
+ if(!pszValue || !nCChValue)
|
|
|
+ return NULL;
|
|
|
+ memset(pszValue, 0, nCChValue);
|
|
|
+
|
|
|
+ const char *pszVal = udev_device_get_property_value(dev, pszKey);
|
|
|
+
|
|
|
+ if(pszVal)
|
|
|
+ {
|
|
|
+ size_t nLen = strlen(pszVal);
|
|
|
+
|
|
|
+ if(nLen < nCChValue)
|
|
|
+ {
|
|
|
+ strcpy(pszValue, pszVal);
|
|
|
+ return pszValue;
|
|
|
+ }
|
|
|
+ else if(bTruncate)
|
|
|
+ {
|
|
|
+ memcpy(pszValue, pszVal, nCChValue);
|
|
|
+ pszValue[nCChValue - 1] = '\0';
|
|
|
+ return pszValue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+static void _ProcessPartition(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, MountMap &mm, struct udev_device* dev)
|
|
|
+{
|
|
|
+ if(dev)
|
|
|
+ {
|
|
|
+ bool bChange;
|
|
|
+ GFA_SYSINFO_PARTITION part;
|
|
|
+ memset(&part, 0, sizeof(part));
|
|
|
+ part.nDiskIdx = -1;
|
|
|
+ ssize_t nPartIdx = -1;
|
|
|
+ ssize_t nDiskIdx = -1;
|
|
|
+
|
|
|
+ const char *pszDevNode = udev_device_get_devnode(dev);
|
|
|
+
|
|
|
+ if(!pszDevNode)
|
|
|
+ return;
|
|
|
+ if(_IsInternalEmmc(pszDevNode))
|
|
|
+ return; // skip internal emmc
|
|
|
+ strncpy(part.szDevNode, pszDevNode, sizeof(part.szDevNode) - 1);
|
|
|
+
|
|
|
+ const char *pszAction = udev_device_get_action(dev);
|
|
|
+ bool bAdd = _STR_EQUALS(pszAction, "add");
|
|
|
+ bool bRem = _STR_EQUALS(pszAction, "remove");
|
|
|
+ bool bEnum = !pszAction;
|
|
|
+
|
|
|
+ if(bAdd || bEnum)
|
|
|
+ {
|
|
|
+ if(_LookupPartition(sdm, part.szDevNode) >= 0)
|
|
|
+ return;
|
|
|
+
|
|
|
+ _ReadDevPropertyValue(dev, "ID_FS_LABEL", part.szFsLabel, sizeof(part.szFsLabel), true);
|
|
|
+ _ReadDevPropertyValue(dev, "ID_FS_TYPE", part.szFsType, sizeof(part.szFsType), true);
|
|
|
+ _ReadDevPropertyValue(dev, "ID_FS_VERSION", part.szFsVersion, sizeof(part.szFsVersion), true);
|
|
|
+ part.nKiBPartSize = _ReadDevPropertyValue(dev, "ID_PART_ENTRY_SIZE") / 2;
|
|
|
+
|
|
|
+ _UpdatePartitionSizeInfo(mm, part);
|
|
|
+
|
|
|
+ struct udev_device* cur = dev;
|
|
|
+
|
|
|
+ while((cur = udev_device_get_parent(cur)))
|
|
|
+ {
|
|
|
+ const char *pszSs = udev_device_get_subsystem(cur);
|
|
|
+ const char *pszDt = udev_device_get_devtype(cur);
|
|
|
+ const char *pszDn = udev_device_get_devnode(cur);
|
|
|
+
|
|
|
+ if(!pszDn)
|
|
|
+ break;
|
|
|
+
|
|
|
+ if(_STR_EQUALS(pszSs, "usb") || _STR_EQUALS(pszSs, "block"))
|
|
|
+ {
|
|
|
+ if(_STR_EQUALS(pszDt, "disk"))
|
|
|
+ {
|
|
|
+ GFA_SYSINFO_DISK disk;
|
|
|
+ memset(&disk, 0, sizeof(disk));
|
|
|
+ strncpy(disk.szDevNode, pszDn, sizeof(disk.szDevNode) - 1);
|
|
|
+
|
|
|
+ if(!_ReadDevPropertyValue(cur, "ID_NAME", disk.szName, sizeof(disk.szName), true))
|
|
|
+ _ReadDevPropertyValue(cur, "ID_MODEL", disk.szName, sizeof(disk.szName), true);
|
|
|
+ _ReadDevPropertyValue(cur, "ID_VENDOR", disk.szVendor, sizeof(disk.szVendor), true);
|
|
|
+ _ReadDevPropertyValue(cur, "ID_BUS", disk.szBus, sizeof(disk.szBus), true);
|
|
|
+
|
|
|
+ if((nDiskIdx = _AddDisk(sdm, disk, bChange)) >= 0)
|
|
|
+ {
|
|
|
+ if((nPartIdx = _AddPartition(sdm, part, bChange)) < 0)
|
|
|
+ {
|
|
|
+ if(sdm.disks[nDiskIdx].nPartCount == 0)
|
|
|
+ _RemoveDisk(sdm, nDiskIdx, bChange);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ _DiskAddPartition(sdm, nDiskIdx, nPartIdx, bChange);
|
|
|
+ _PartitionSetDisk(sdm, nPartIdx, nDiskIdx, bChange);
|
|
|
+ _SetPartitionChange(sdm, nPartIdx);
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if(bRem)
|
|
|
+ {
|
|
|
+ if((nPartIdx = _LookupPartition(sdm, pszDevNode)) >= 0)
|
|
|
+ {
|
|
|
+ _RemovePartition(sdm, nPartIdx, bChange);
|
|
|
+ _SetPartitionChange(sdm, nPartIdx);
|
|
|
+
|
|
|
+ if((nDiskIdx = _PartitionGetDisk(sdm, nPartIdx)) >= 0)
|
|
|
+ {
|
|
|
+ if(!_DiskRemovePartition(sdm, nDiskIdx, nPartIdx, bChange))
|
|
|
+ {
|
|
|
+ _RemoveDisk(sdm, nDiskIdx, bChange);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void _EnumStorageDevices(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, MountMap &mm, struct udev* udev)
|
|
|
+{
|
|
|
+ struct udev_enumerate* enumerate = udev_enumerate_new(udev);
|
|
|
+ udev_enumerate_add_match_subsystem(enumerate, "block");
|
|
|
+ udev_enumerate_add_match_property(enumerate, "DEVTYPE", "partition");
|
|
|
+ udev_enumerate_scan_devices(enumerate);
|
|
|
+
|
|
|
+ struct udev_list_entry *devices = udev_enumerate_get_list_entry(enumerate);
|
|
|
+ struct udev_list_entry *entry;
|
|
|
+
|
|
|
+ udev_list_entry_foreach(entry, devices)
|
|
|
+ {
|
|
|
+ const char *pszPath = udev_list_entry_get_name(entry);
|
|
|
+ struct udev_device* dev = udev_device_new_from_syspath(udev, pszPath);
|
|
|
+
|
|
|
+ _ProcessPartition(sdm, mm, dev);
|
|
|
+ udev_device_unref(dev);
|
|
|
+ }
|
|
|
+
|
|
|
+ udev_enumerate_unref(enumerate);
|
|
|
+}
|
|
|
+
|
|
|
+/////////////////////////////////////////////////////////////////////////////
|
|
|
+/////////////////////////////////////////////////////////////////////////////
|
|
|
+/////////////////////////////////////////////////////////////////////////////
|
|
|
+
|
|
|
+int main(int argc, char *argv[])
|
|
|
+{
|
|
|
+ UNUSED(argc);
|
|
|
+ UNUSED(argv);
|
|
|
+
|
|
|
+ HAPPCTRL hAC = NULL;
|
|
|
+ HAPPINFO hAI;
|
|
|
+ CCycleTimer ct(_CYCLE_INTV);
|
|
|
+ cy_time_t wStart, wEnd, wCur = 0;
|
|
|
+ struct udev* udev = NULL;
|
|
|
+ struct timeval tv;
|
|
|
+ memset(&tv, 0, sizeof(tv));
|
|
|
+ struct udev_monitor *pUdevMon = NULL;
|
|
|
+ GFA_SYSINFO_STORAGE_DEVICE_MAP sdm;
|
|
|
+ memset(&sdm, 0, sizeof(sdm));
|
|
|
+ MountMap mm;
|
|
|
+
|
|
|
+ pollfd pfd[2];
|
|
|
+ memset(&pfd, 0, sizeof(pfd));
|
|
|
+
|
|
|
+ /////////////////////////////////////////////////////////////////////////
|
|
|
+ /////////////////////////////////////////////////////////////////////////
|
|
|
+ /////////////////////////////////////////////////////////////////////////
|
|
|
+ // signal handling
|
|
|
+
|
|
|
+ struct sigaction sa;
|
|
|
+ memset(&sa, 0, sizeof(sa));
|
|
|
+
|
|
|
+ // handle signals
|
|
|
+ sa.sa_handler = _SigHandler;
|
|
|
+ sigaction(SIGHUP, &sa, NULL); // handles user's terminal disconnect
|
|
|
+ sigaction(SIGQUIT, &sa, NULL); // handles Ctrl + '\'
|
|
|
+ sigaction(SIGTERM, &sa, NULL); // handles normal termination
|
|
|
+ sigaction(SIGABRT, &sa, NULL); // handles abnormal termination (i.e. abort())
|
|
|
+ sigaction(SIGINT, &sa, NULL); // handles Ctrl + 'C'
|
|
|
+
|
|
|
+ // ignore signals
|
|
|
+ sa.sa_handler = SIG_IGN;
|
|
|
+ sigaction(SIGTSTP, &sa, NULL); // ignores Ctrl + 'Z'
|
|
|
+ sigaction(SIGCHLD, &sa, NULL); // ignores child process termination
|
|
|
+ sigaction(0, &sa, NULL); // ignores shell termination
|
|
|
+
|
|
|
+ /////////////////////////////////////////////////////////////////////////
|
|
|
+ /////////////////////////////////////////////////////////////////////////
|
|
|
+ /////////////////////////////////////////////////////////////////////////
|
|
|
+ // initialize
|
|
|
+
|
|
|
+ do
|
|
|
+ {
|
|
|
+ if(!(hAC = ::GfaIpcAppCtrlAcquire(_APPID, _APPNAME, _CYCLE_INTV * 1000, _CYCLE_INTV * 3000)))
|
|
|
+ break;
|
|
|
+
|
|
|
+ if(!::GfaIpcAppCtrlCreateSysInfo(hAC))
|
|
|
+ break;
|
|
|
+
|
|
|
+ if(!(udev = udev_new()))
|
|
|
+ {
|
|
|
+ fprintf(stderr, "udev_new() failed\n");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ _UpdateMountMap(mm);
|
|
|
+ _EnumStorageDevices(sdm, mm, udev);
|
|
|
+ _DumpStorageDeviceMap(sdm);
|
|
|
+
|
|
|
+ if((pUdevMon = udev_monitor_new_from_netlink(udev, "udev")))
|
|
|
+ {
|
|
|
+ udev_monitor_filter_add_match_subsystem_devtype(pUdevMon, "block", "partition");
|
|
|
+ udev_monitor_enable_receiving(pUdevMon);
|
|
|
+
|
|
|
+ pfd[0].fd = udev_monitor_get_fd(pUdevMon);
|
|
|
+ pfd[0].events = POLLIN;
|
|
|
+ pfd[0].revents = 0;
|
|
|
+ pfd[1].fd = open(_MOUNTS_FILE, O_RDONLY, 0);
|
|
|
+ pfd[1].events = POLLPRI;
|
|
|
+ pfd[1].revents = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+// ;;GfaIpcDumpSHMROT();
|
|
|
+ ::GfaIpcAppCtrlSetState(hAC, GIAS_Initializing);
|
|
|
+
|
|
|
+// if(!::GfaIpcAppCtrlSubscribeStateEvents(hAC, GFA_APPCTRL_APPID_USER_01))
|
|
|
+// break;
|
|
|
+
|
|
|
+ TRACE("My Name: %s\n", _APPNAME);
|
|
|
+ TRACE("My AppID: %llu\n", _APPID);
|
|
|
+ TRACE("My PID: %d\n", getpid());
|
|
|
+ TRACE("My Cycle: %d\n", _CYCLE_INTV);
|
|
|
+
|
|
|
+ g_fRun = true;
|
|
|
+ ::GfaIpcAppCtrlSetState(hAC, GIAS_Running);
|
|
|
+ ::GfaIpcAppCtrlUpdateStorageDeviceMap(hAC, sdm);
|
|
|
+ }
|
|
|
+ while(false);
|
|
|
+
|
|
|
+ /////////////////////////////////////////////////////////////////////////
|
|
|
+ /////////////////////////////////////////////////////////////////////////
|
|
|
+ /////////////////////////////////////////////////////////////////////////
|
|
|
+ // run
|
|
|
+
|
|
|
+ while(g_fRun)
|
|
|
+ {
|
|
|
+ /////////////////////////////////////////////////////////////////////
|
|
|
+ // trigger cycle timer
|
|
|
+
|
|
|
+ ct.Trigger();
|
|
|
+
|
|
|
+ /////////////////////////////////////////////////////////////////////
|
|
|
+ // update app control info
|
|
|
+
|
|
|
+ if((hAI = ::GfaIpcAppCtrlInfoUpdate(hAC, wCur)))
|
|
|
+ {
|
|
|
+ _ProcessCtrlMessages(hAC, hAI);
|
|
|
+// _ProcessStateEvents(hAC, hAI);
|
|
|
+ }
|
|
|
+
|
|
|
+ /////////////////////////////////////////////////////////////////////
|
|
|
+ // if not paused, do work
|
|
|
+
|
|
|
+ if(!g_fPause && g_fRun)
|
|
|
+ {
|
|
|
+ wStart = ct.GetMicroTick();
|
|
|
+ ::GfaIpcAppCtrlUpdateSysInfo(hAC);
|
|
|
+ wEnd = ct.GetMicroTick();
|
|
|
+ wCur = wEnd - wStart;
|
|
|
+
|
|
|
+ _ClearMapChanges(sdm);
|
|
|
+
|
|
|
+ while(poll(pfd, 2, _CYCLE_INTV / 5) > 0)
|
|
|
+ {
|
|
|
+ _UpdateMountMap(mm);
|
|
|
+
|
|
|
+ if(pfd[0].revents & POLLIN)
|
|
|
+ {
|
|
|
+ struct udev_device* dev;
|
|
|
+
|
|
|
+ while((dev = udev_monitor_receive_device(pUdevMon)))
|
|
|
+ {
|
|
|
+ _ProcessPartition(sdm, mm, dev);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if(pfd[1].revents & POLLPRI)
|
|
|
+ {
|
|
|
+ _ProcessMounts(sdm, mm);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if(_MapChanged(sdm))
|
|
|
+ {
|
|
|
+ ::GfaIpcAppCtrlUpdateStorageDeviceMap(hAC, sdm);
|
|
|
+ _DumpStorageDeviceMap(sdm);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /////////////////////////////////////////////////////////////////////
|
|
|
+ // if running, sleep
|
|
|
+
|
|
|
+ if(g_fRun)
|
|
|
+ ct.Sleep1();
|
|
|
+ }
|
|
|
+
|
|
|
+ /////////////////////////////////////////////////////////////////////////
|
|
|
+ /////////////////////////////////////////////////////////////////////////
|
|
|
+ /////////////////////////////////////////////////////////////////////////
|
|
|
+ // terminate
|
|
|
+
|
|
|
+ if(pfd[0].fd >= 0)
|
|
|
+ close(pfd[0].fd);
|
|
|
+ if(pfd[1].fd >= 0)
|
|
|
+ close(pfd[1].fd);
|
|
|
+ if(pUdevMon)
|
|
|
+ udev_monitor_unref(pUdevMon);
|
|
|
+ if(udev)
|
|
|
+ udev_unref(udev);
|
|
|
+
|
|
|
+ if(hAC)
|
|
|
+ {
|
|
|
+ ::GfaIpcAppCtrlSetState(hAC, GIAS_Terminating);
|
|
|
+ ::GfaIpcAppCtrlReleaseSysInfo(hAC);
|
|
|
+ ::GfaIpcAppCtrlRelease(hAC);
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|