main.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <string.h>
  4. #include <string>
  5. #include <vector>
  6. #include <map>
  7. #include <ext/stdio_filebuf.h>
  8. #include <iostream>
  9. #include <fstream>
  10. #include <signal.h>
  11. #include <sys/statvfs.h>
  12. #include <sys/statfs.h>
  13. #include <sys/types.h>
  14. #include <fcntl.h>
  15. #include <unistd.h>
  16. #include <limits.h>
  17. #include <libudev.h>
  18. #include <poll.h>
  19. #include <errno.h>
  20. #include <gfa/gfasitarautils.h>
  21. #include "../../src/gfaipc.h"
  22. #include "../../src/ipcpriv.h"
  23. /////////////////////////////////////////////////////////////////////////////
  24. #ifdef _DEBUG
  25. #define TRACE(...) fprintf(stdout, __VA_ARGS__), fflush(stdout)
  26. #else // _DEBUG
  27. #define TRACE(...)
  28. #endif // _DEBUG
  29. #define UNUSED(v) (void)v
  30. #define _countof(a) (sizeof(a) / sizeof(*a))
  31. /////////////////////////////////////////////////////////////////////////////
  32. #define _BYTE_SIZE_KIB (1ULL << 10) // Kibibyte
  33. #define _BYTE_SIZE_MIB (1ULL << 20) // Mebibyte
  34. #define _BYTE_SIZE_GIB (1ULL << 30) // Gibibyte
  35. #define _BYTE_SIZE_TIB (1ULL << 40) // Tebibyte
  36. #define _BYTE_SIZE_PIB (1ULL << 50) // Pebibyte
  37. #define _BYTE_SIZE_EIB (1ULL << 60) // Exbibyte
  38. #define _APPID GFA_APPCTRL_APPID_SYSINFO
  39. #define _APPNAME "SysInfo"
  40. #define _CYCLE_INTV 500
  41. #define _STR_EQUALS(s, t) (!!s && !strcmp(s, t))
  42. #define _MOUNTS_FILE "/proc/mounts"
  43. #define _INTERNAL_EMMC_DISK "mmcblk1"
  44. #define _INTERNAL_EMMC_PART1 "mmcblk1p1"
  45. #define _INTERNAL_EMMC_PART2 "mmcblk1p2"
  46. /////////////////////////////////////////////////////////////////////////////
  47. typedef std::map<std::string, std::string> MountMap;
  48. /////////////////////////////////////////////////////////////////////////////
  49. static volatile bool g_fRun = false;
  50. static volatile bool g_fPause = false;
  51. static volatile bool g_fZombie = false;
  52. /////////////////////////////////////////////////////////////////////////////
  53. static const char *g_pszStateNames[] =
  54. {
  55. "Not running",
  56. "Initializing",
  57. "Running",
  58. "Paused",
  59. "Hanging",
  60. "Terminating",
  61. "Invalid"
  62. };
  63. /////////////////////////////////////////////////////////////////////////////
  64. static long long _NumberFromString(const char *pszString, int base = 10, bool *pbErr = NULL);
  65. static const char* _ReadDevPropertyValue(struct udev_device* dev, const char *pszKey, char *pszValue, size_t nCChValue, bool bTruncate = false);
  66. static long long _ReadDevPropertyValue(struct udev_device* dev, const char *pszKey, int base = 10, bool *pbErr = NULL);
  67. /////////////////////////////////////////////////////////////////////////////
  68. /////////////////////////////////////////////////////////////////////////////
  69. /////////////////////////////////////////////////////////////////////////////
  70. static int _LookupPartition(const GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, const char *pszDevNode)
  71. {
  72. int nIndex = -1;
  73. if(pszDevNode && *pszDevNode)
  74. {
  75. for(size_t i = 0; i < _countof(sdm.parts); ++i)
  76. {
  77. if(sdm.parts[i].valid && !strcmp(sdm.parts[i].szDevNode, pszDevNode))
  78. {
  79. nIndex = i; // found partition
  80. break;
  81. }
  82. }
  83. }
  84. return nIndex;
  85. }
  86. static int _AddPartition(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, const GFA_SYSINFO_PARTITION &part, bool &bChange)
  87. {
  88. int nIndex = -1;
  89. bChange = false;
  90. if((nIndex = _LookupPartition(sdm, part.szDevNode)) >= 0)
  91. return nIndex; // partition already exists
  92. for(size_t i = 0; i < _countof(sdm.parts); ++i)
  93. {
  94. if(!sdm.parts[i].valid)
  95. {
  96. memcpy(&sdm.parts[i], &part, sizeof(GFA_SYSINFO_PARTITION));
  97. sdm.parts[i].valid = true;
  98. bChange = true;
  99. nIndex = i;
  100. break;
  101. }
  102. }
  103. return nIndex;
  104. }
  105. static int _RemovePartition(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, int nIndex, bool &bChange)
  106. {
  107. bChange = false;
  108. if(nIndex >= 0 && nIndex < (int)_countof(sdm.parts))
  109. {
  110. bChange = sdm.parts[nIndex].valid;
  111. sdm.parts[nIndex].valid = false;
  112. }
  113. return nIndex;
  114. }
  115. #if 0
  116. static int _RemovePartition(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, const char *pszDevNode, bool &bChange)
  117. {
  118. int nIndex = _LookupPartition(sdm, pszDevNode);
  119. return _RemovePartition(sdm, nIndex, bChange);
  120. }
  121. #endif
  122. static bool _PartitionSetDisk(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, int nPartIdx, int nDiskIdx, bool &bChange)
  123. {
  124. bChange = false;
  125. if( (nPartIdx >= 0) && (nPartIdx < (int)_countof(sdm.parts)) &&
  126. (nDiskIdx >= 0) && (nDiskIdx < (int)_countof(sdm.disks)))
  127. {
  128. if(sdm.parts[nPartIdx].nDiskIdx != nDiskIdx)
  129. {
  130. sdm.parts[nPartIdx].nDiskIdx = nDiskIdx;
  131. bChange = true;
  132. }
  133. return true;
  134. }
  135. return false;
  136. }
  137. static int _PartitionGetDisk(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, int nPartIdx)
  138. {
  139. if((nPartIdx >= 0) && (nPartIdx < (int)_countof(sdm.parts)))
  140. return sdm.parts[nPartIdx].nDiskIdx;
  141. return -1;
  142. }
  143. static void _ClearMapChanges(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm)
  144. {
  145. sdm.nPartChangeMask = 0;
  146. }
  147. static bool _DeviceMapChanged(const GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm)
  148. {
  149. return !!sdm.nPartChangeMask;
  150. }
  151. static unsigned int _SetPartitionChange(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, int nPartIdx)
  152. {
  153. if((nPartIdx >= 0) && (nPartIdx < (int)_countof(sdm.parts)))
  154. {
  155. unsigned int nChanged = (0x01 << nPartIdx);
  156. sdm.nPartChangeMask |= nChanged;
  157. }
  158. return sdm.nPartChangeMask;
  159. }
  160. /////////////////////////////////////////////////////////////////////////////
  161. static int _LookupDisk(const GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, const char *pszDevNode)
  162. {
  163. int nIndex = -1;
  164. if(pszDevNode && *pszDevNode)
  165. {
  166. for(size_t i = 0; i < _countof(sdm.disks); ++i)
  167. {
  168. if(sdm.disks[i].valid && !strcmp(sdm.disks[i].szDevNode, pszDevNode))
  169. {
  170. nIndex = i; // found partition
  171. break;
  172. }
  173. }
  174. }
  175. return nIndex;
  176. }
  177. static int _AddDisk(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, const GFA_SYSINFO_DISK &disk, bool &bChange)
  178. {
  179. int nIndex = -1;
  180. bChange = false;
  181. if((nIndex = _LookupDisk(sdm, disk.szDevNode)) >= 0)
  182. return nIndex; // partition already exists
  183. for(size_t i = 0; i < _countof(sdm.disks); ++i)
  184. {
  185. if(!sdm.disks[i].valid)
  186. {
  187. memcpy(&sdm.disks[i], &disk, sizeof(GFA_SYSINFO_DISK));
  188. sdm.disks[i].valid = true;
  189. bChange = true;
  190. nIndex = i;
  191. break;
  192. }
  193. }
  194. return nIndex;
  195. }
  196. static int _RemoveDisk(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, int nIndex, bool &bChange)
  197. {
  198. bChange = false;
  199. if(nIndex >= 0 && nIndex < (int)_countof(sdm.disks))
  200. {
  201. bChange = sdm.disks[nIndex].valid;
  202. sdm.disks[nIndex].valid = false;
  203. }
  204. return nIndex;
  205. }
  206. #if 0
  207. static int _RemoveDisk(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, const char *pszDevNode, bool &bChange)
  208. {
  209. int nIndex = _LookupDisk(sdm, pszDevNode);
  210. return _RemoveDisk(sdm, nIndex, bChange);
  211. }
  212. #endif
  213. static unsigned int _DiskAddPartition(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, int nDiskIdx, int nPartIdx, bool &bChange)
  214. {
  215. bChange = false;
  216. if( (nPartIdx >= 0) && (nPartIdx < (int)_countof(sdm.parts)) &&
  217. (nDiskIdx >= 0) && (nDiskIdx < (int)_countof(sdm.disks)))
  218. {
  219. GFA_SYSINFO_DISK &disk = sdm.disks[nDiskIdx];
  220. for(unsigned int i = 0; i < disk.nPartCount; ++i)
  221. {
  222. if(disk.aPartIdx[i] == nPartIdx)
  223. return disk.nPartCount;
  224. }
  225. if(disk.nPartCount < _countof(disk.aPartIdx))
  226. {
  227. disk.aPartIdx[disk.nPartCount++] = nPartIdx;
  228. bChange = true;
  229. return disk.nPartCount;
  230. }
  231. }
  232. return 0;
  233. }
  234. static unsigned int _DiskRemovePartition(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, int nDiskIdx, int nPartIdx, bool &bChange)
  235. {
  236. bChange = false;
  237. if( (nPartIdx >= 0) && (nPartIdx < (int)_countof(sdm.parts)) &&
  238. (nDiskIdx >= 0) && (nDiskIdx < (int)_countof(sdm.disks)))
  239. {
  240. unsigned int i, j;
  241. GFA_SYSINFO_DISK &disk = sdm.disks[nDiskIdx];
  242. for(i = 0; i < disk.nPartCount; ++i)
  243. {
  244. if(disk.aPartIdx[i] == nPartIdx)
  245. break;
  246. }
  247. if(i < disk.nPartCount)
  248. {
  249. for(j = i + 1; j < disk.nPartCount; ++i, ++j)
  250. {
  251. disk.aPartIdx[i] = disk.aPartIdx[j];
  252. }
  253. bChange = true;
  254. return --disk.nPartCount;
  255. }
  256. return disk.nPartCount;
  257. }
  258. return 0;
  259. }
  260. /////////////////////////////////////////////////////////////////////////////
  261. /////////////////////////////////////////////////////////////////////////////
  262. /////////////////////////////////////////////////////////////////////////////
  263. static bool _LookupMountPoint(MountMap &mm, const char *pszNode, char *pszMntPoint, size_t nCChMntPoint)
  264. {
  265. MountMap::const_iterator it = mm.find(pszNode);
  266. if(it == mm.end())
  267. return false;
  268. const std::string &s = it->second;
  269. if(s.length() < nCChMntPoint)
  270. {
  271. strcpy(pszMntPoint, s.c_str());
  272. return true;
  273. }
  274. return false;
  275. }
  276. static bool _UpdatePartitionFsInfo(MountMap &mm, GFA_SYSINFO_PARTITION &part)
  277. {
  278. if(_LookupMountPoint(mm, part.szDevNode, part.szMntPoint, sizeof(part.szMntPoint)))
  279. {
  280. struct statvfs stvs;
  281. if(!statvfs(part.szMntPoint, &stvs))
  282. {
  283. part.nKiBSize = stvs.f_bsize * stvs.f_blocks / 1024;
  284. part.nKiBFree = stvs.f_bsize * stvs.f_bfree / 1024;
  285. part.nKiBUsed = part.nKiBSize - part.nKiBFree;
  286. }
  287. else
  288. {
  289. TRACE("statvfs failed on \"%s\": %s\n", part.szMntPoint, strerror(errno));
  290. memset(part.szMntPoint, 0, sizeof(part.szMntPoint));
  291. part.nKiBSize = 0;
  292. part.nKiBFree = 0;
  293. part.nKiBUsed = 0;
  294. }
  295. return true;
  296. }
  297. else
  298. {
  299. memset(part.szMntPoint, 0, sizeof(part.szMntPoint));
  300. part.nKiBSize = 0;
  301. part.nKiBFree = 0;
  302. part.nKiBUsed = 0;
  303. }
  304. return false;
  305. }
  306. /////////////////////////////////////////////////////////////////////////////
  307. static std::string _StrReplace(std::string &s, const char *pszFind, const char *pszRepl)
  308. {
  309. std::string r = s;
  310. if(pszFind && *pszFind && pszRepl)
  311. {
  312. size_t nFind, nLen = strlen(pszFind);
  313. while((nFind = r.find(pszFind)) != std::string::npos)
  314. {
  315. r = r.replace(nFind, nLen, pszRepl);
  316. }
  317. }
  318. return r;
  319. }
  320. static std::string _UnescapeMountpointString(std::string &s)
  321. {
  322. std::string r = s;
  323. r = _StrReplace(r, "\\040", " ");
  324. r = _StrReplace(r, "\\011", "\t");
  325. r = _StrReplace(r, "\\012", "\n");
  326. r = _StrReplace(r, "\\134", "\\");
  327. return r;
  328. }
  329. static void _UpdateMountMap(MountMap &mm)
  330. {
  331. char szLine[512], szNode[512], szMount[512];
  332. std::ifstream mounts(_MOUNTS_FILE);
  333. mm.clear();
  334. while(mounts.getline(szLine, sizeof(szLine)).good())
  335. {
  336. if((sscanf(szLine, "%s %s", szNode, szMount) == 2))
  337. {
  338. std::string key(szNode);
  339. key = _UnescapeMountpointString(key);
  340. std::string val(szMount);
  341. val = _UnescapeMountpointString(val);
  342. mm.emplace(key, val);
  343. }
  344. }
  345. }
  346. /////////////////////////////////////////////////////////////////////////////
  347. static bool _ProcessMounts(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, MountMap &mm)
  348. {
  349. bool bChange = false;
  350. char szMntPoint[_countof(GFA_SYSINFO_PARTITION::szMntPoint)];
  351. for(size_t i = 0; i < _countof(sdm.parts); ++i)
  352. {
  353. GFA_SYSINFO_PARTITION &part = sdm.parts[i];
  354. if(part.valid)
  355. {
  356. bool bMountedOld = !!*part.szMntPoint;
  357. bool bMountedNew = _LookupMountPoint(mm, part.szDevNode, szMntPoint, sizeof(szMntPoint));
  358. if(!bMountedOld && bMountedNew)
  359. {
  360. memcpy(part.szMntPoint, szMntPoint, sizeof(part.szMntPoint));
  361. _UpdatePartitionFsInfo(mm, part);
  362. _SetPartitionChange(sdm, i);
  363. bChange = true;
  364. }
  365. else if(bMountedOld && !bMountedNew)
  366. {
  367. memset(part.szMntPoint, 0, sizeof(part.szMntPoint));
  368. _UpdatePartitionFsInfo(mm, part);
  369. _SetPartitionChange(sdm, i);
  370. bChange = true;
  371. }
  372. else if(bMountedOld && bMountedNew)
  373. {
  374. if(strcmp(part.szMntPoint, szMntPoint))
  375. {
  376. memcpy(part.szMntPoint, szMntPoint, sizeof(part.szMntPoint));
  377. _UpdatePartitionFsInfo(mm, part);
  378. _SetPartitionChange(sdm, i);
  379. bChange = true;
  380. }
  381. }
  382. }
  383. }
  384. return bChange;
  385. }
  386. /////////////////////////////////////////////////////////////////////////////
  387. static void _ProcessCtrlMessages(HAPPCTRL hAC, HAPPINFO hAI)
  388. {
  389. ctrlmsg_t nCtrlMsg;
  390. while(g_fRun && (nCtrlMsg = ::GfaIpcAppCtrlGetNextCtrlMsg(hAI)))
  391. {
  392. switch(nCtrlMsg)
  393. {
  394. case GFA_APPCTRL_CTRLMSG_STOP:
  395. g_fRun = false;
  396. TRACE("Received Message: STOP!\n");
  397. break;
  398. case GFA_APPCTRL_CTRLMSG_PAUSE:
  399. if(!g_fPause)
  400. {
  401. g_fPause = true;
  402. ::GfaIpcAppCtrlSetState(hAC, GIAS_Paused);
  403. TRACE("%-8s: State: %s\n", "Me", g_pszStateNames[GIAS_Paused]);
  404. }
  405. break;
  406. case GFA_APPCTRL_CTRLMSG_RESUME:
  407. if(g_fPause)
  408. {
  409. g_fPause = false;
  410. ::GfaIpcAppCtrlSetState(hAC, GIAS_Running);
  411. TRACE("%-8s: State: %s\n", "Me", g_pszStateNames[GIAS_Running]);
  412. }
  413. break;
  414. default:
  415. break;
  416. }
  417. }
  418. }
  419. static const char* _GetFileSpec(const char *pszPathname)
  420. {
  421. if(pszPathname && *pszPathname)
  422. {
  423. const char *pSlash = strrchr(pszPathname, '/');
  424. if(pSlash)
  425. return ++pSlash;
  426. else
  427. return pszPathname;
  428. }
  429. return NULL;
  430. }
  431. static bool _IsInternalEmmc(const char *pszDevNode)
  432. {
  433. if(pszDevNode)
  434. {
  435. const char *pszDevName = _GetFileSpec(pszDevNode);
  436. return _STR_EQUALS(pszDevName, _INTERNAL_EMMC_PART2) || _STR_EQUALS(pszDevName, _INTERNAL_EMMC_PART1);
  437. }
  438. return false;
  439. }
  440. #if 0
  441. static void _EnumDevProperties(struct udev_device *dev, int nIndent)
  442. {
  443. if(dev)
  444. {
  445. struct udev_list_entry *prop;
  446. struct udev_list_entry *props = ::udev_device_get_properties_list_entry(dev);
  447. if(props)
  448. {
  449. udev_list_entry_foreach(prop, props)
  450. {
  451. const char *pszName = ::udev_list_entry_get_name(prop);
  452. const char *pszValue = ::udev_list_entry_get_value(prop);
  453. if(pszName && pszValue)
  454. {
  455. TRACE("%-*s+ %s = \"%s\"\n", nIndent + 2, " ", pszName, pszValue);
  456. }
  457. }
  458. }
  459. }
  460. }
  461. static void _EnumDevSysAttributes(struct udev_device *dev, int nIndent)
  462. {
  463. if(dev)
  464. {
  465. struct udev_list_entry *att;
  466. struct udev_list_entry *atts = ::udev_device_get_sysattr_list_entry(dev);
  467. if(atts)
  468. {
  469. udev_list_entry_foreach(att, atts)
  470. {
  471. const char *pszName = ::udev_list_entry_get_name(att);
  472. const char *pszValue = ::udev_device_get_sysattr_value(dev, pszName);
  473. if(pszName && pszValue && strcmp(pszName, "uevent"))
  474. {
  475. TRACE("%-*s- %s = \"%s\"\n", nIndent + 2, " ", pszName, pszValue);
  476. }
  477. }
  478. }
  479. }
  480. }
  481. #endif
  482. static const char *_FormatByteSize(unsigned long long nCb, char *pszBuf, size_t nCChBuf)
  483. {
  484. if(pszBuf && nCChBuf)
  485. {
  486. int nPrec = 2;
  487. double val = nCb;
  488. if(nCb < _BYTE_SIZE_KIB)
  489. {
  490. snprintf(pszBuf, nCChBuf, "%llu B", nCb); // Byte
  491. }
  492. else if(nCb < _BYTE_SIZE_MIB)
  493. {
  494. val /= _BYTE_SIZE_KIB;
  495. snprintf(pszBuf, nCChBuf, "%.*f KiB", nPrec, val); // KiB
  496. }
  497. else if(nCb < _BYTE_SIZE_GIB)
  498. {
  499. val /= _BYTE_SIZE_MIB;
  500. snprintf(pszBuf, nCChBuf, "%.*f MiB", nPrec, val); // MiB
  501. }
  502. else if(nCb < _BYTE_SIZE_TIB)
  503. {
  504. val /= _BYTE_SIZE_GIB;
  505. snprintf(pszBuf, nCChBuf, "%.*f GiB", nPrec, val); // GiB
  506. }
  507. else if(nCb < _BYTE_SIZE_PIB)
  508. {
  509. val /= _BYTE_SIZE_TIB;
  510. snprintf(pszBuf, nCChBuf, "%.*f TiB", nPrec, val); // TiB
  511. }
  512. else if(nCb < _BYTE_SIZE_EIB)
  513. {
  514. val /= _BYTE_SIZE_PIB;
  515. snprintf(pszBuf, nCChBuf, "%.*f PiB", nPrec, val); // PiB
  516. }
  517. return pszBuf;
  518. }
  519. return NULL;
  520. }
  521. static void _DumpDeviceMap(const GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm)
  522. {
  523. TRACE("\n");
  524. for(size_t i = 0; i < _countof(sdm.disks); ++i)
  525. {
  526. char szByteBuf[16];
  527. const GFA_SYSINFO_DISK &disk = sdm.disks[i];
  528. if(disk.valid && !disk.internal)
  529. {
  530. TRACE("Disk:\n");
  531. TRACE(" |-Label: %s\n", disk.szName);
  532. TRACE(" |-Vendor: %s\n", *disk.szVendor ? disk.szVendor : "n/a");
  533. TRACE(" |-Node: %s\n", disk.szDevNode);
  534. TRACE(" |-Type: %s\n", *disk.szBus ? disk.szBus : "mmc");
  535. for(unsigned int j = 0; j < disk.nPartCount; ++j)
  536. {
  537. int nIndex = disk.aPartIdx[j];
  538. const GFA_SYSINFO_PARTITION &part = sdm.parts[nIndex];
  539. bool bMounted = !!*part.szMntPoint;
  540. TRACE(" |-Partition:\n");
  541. TRACE(" |-Label: %s\n", part.szFsLabel);
  542. TRACE(" |-Node: %s\n", part.szDevNode);
  543. TRACE(" |-PA-Size: %s\n", _FormatByteSize(part.nKiBPartSize * _BYTE_SIZE_KIB, szByteBuf, sizeof(szByteBuf)));
  544. TRACE(" |-Mount: %s\n", bMounted ? part.szMntPoint : "Not mounted");
  545. if(bMounted)
  546. {
  547. TRACE(" |-FS-Type: %s\n", part.szFsType);
  548. TRACE(" |-FS-Ver.: %s\n", part.szFsVersion);
  549. TRACE(" |-FS-Size: %s\n", _FormatByteSize(part.nKiBSize * _BYTE_SIZE_KIB, szByteBuf, sizeof(szByteBuf)));
  550. TRACE(" |-FS-Used: %s\n", _FormatByteSize(part.nKiBUsed * _BYTE_SIZE_KIB, szByteBuf, sizeof(szByteBuf)));
  551. TRACE(" |-FS-Free: %s\n", _FormatByteSize(part.nKiBFree * _BYTE_SIZE_KIB, szByteBuf, sizeof(szByteBuf)));
  552. }
  553. }
  554. }
  555. }
  556. TRACE("\n");
  557. }
  558. static long long _NumberFromString(const char *pszString, int base, bool *pbErr)
  559. {
  560. if(!pszString || !*pszString)
  561. {
  562. if(pbErr)
  563. *pbErr = true;
  564. return 0;
  565. }
  566. char *endptr;
  567. long long nRet = strtoll(pszString, &endptr, base);
  568. if( (((nRet == LLONG_MAX) || (nRet == LLONG_MIN)) && (errno == ERANGE)) ||
  569. ((nRet == 0) && (errno == EINVAL)) ||
  570. (!!*endptr))
  571. {
  572. if(pbErr)
  573. *pbErr = true;
  574. return 0;
  575. }
  576. if(pbErr)
  577. *pbErr = false;
  578. return nRet;
  579. }
  580. static long long _ReadDevPropertyValue(struct udev_device* dev, const char *pszKey, int base, bool *pbErr)
  581. {
  582. char szNum[64];
  583. return _NumberFromString(_ReadDevPropertyValue(dev, pszKey, szNum, sizeof(szNum), false), base, pbErr);
  584. }
  585. static const char* _ReadDevPropertyValue(struct udev_device* dev, const char *pszKey, char *pszValue, size_t nCChValue, bool bTruncate)
  586. {
  587. if(!pszValue || !nCChValue)
  588. return NULL;
  589. memset(pszValue, 0, nCChValue);
  590. const char *pszVal = ::udev_device_get_property_value(dev, pszKey);
  591. if(pszVal)
  592. {
  593. size_t nLen = strlen(pszVal);
  594. if(nLen < nCChValue)
  595. {
  596. strcpy(pszValue, pszVal);
  597. return pszValue;
  598. }
  599. else if(bTruncate)
  600. {
  601. memcpy(pszValue, pszVal, nCChValue);
  602. pszValue[nCChValue - 1] = '\0';
  603. return pszValue;
  604. }
  605. }
  606. return NULL;
  607. }
  608. static void _ProcessPartition(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, MountMap &mm, struct udev_device* dev)
  609. {
  610. if(dev)
  611. {
  612. bool bChange;
  613. GFA_SYSINFO_PARTITION part;
  614. memset(&part, 0, sizeof(part));
  615. part.nDiskIdx = -1;
  616. int nPartIdx = -1;
  617. int nDiskIdx = -1;
  618. const char *pszDevNode = ::udev_device_get_devnode(dev);
  619. if(!pszDevNode)
  620. return;
  621. // if(_IsInternalEmmc(pszDevNode))
  622. // return; // skip internal emmc
  623. bool bInternalEmmc = _IsInternalEmmc(pszDevNode);
  624. strncpy(part.szDevNode, pszDevNode, sizeof(part.szDevNode) - 1);
  625. const char *pszAction = ::udev_device_get_action(dev);
  626. bool bAdd = _STR_EQUALS(pszAction, "add");
  627. bool bRem = _STR_EQUALS(pszAction, "remove");
  628. bool bEnum = !pszAction;
  629. if(bAdd || bEnum)
  630. {
  631. if(_LookupPartition(sdm, part.szDevNode) >= 0)
  632. return;
  633. part.internal = bInternalEmmc;
  634. _ReadDevPropertyValue(dev, "ID_FS_LABEL", part.szFsLabel, sizeof(part.szFsLabel), true);
  635. _ReadDevPropertyValue(dev, "ID_FS_TYPE", part.szFsType, sizeof(part.szFsType), true);
  636. _ReadDevPropertyValue(dev, "ID_FS_VERSION", part.szFsVersion, sizeof(part.szFsVersion), true);
  637. part.nKiBPartSize = _ReadDevPropertyValue(dev, "ID_PART_ENTRY_SIZE") / 2;
  638. _UpdatePartitionFsInfo(mm, part);
  639. struct udev_device* cur = dev;
  640. while((cur = ::udev_device_get_parent(cur)))
  641. {
  642. const char *pszSs = ::udev_device_get_subsystem(cur);
  643. const char *pszDt = ::udev_device_get_devtype(cur);
  644. const char *pszDn = ::udev_device_get_devnode(cur);
  645. if(!pszDn)
  646. break;
  647. if(_STR_EQUALS(pszSs, "usb") || _STR_EQUALS(pszSs, "block"))
  648. {
  649. if(_STR_EQUALS(pszDt, "disk"))
  650. {
  651. GFA_SYSINFO_DISK disk;
  652. memset(&disk, 0, sizeof(disk));
  653. strncpy(disk.szDevNode, pszDn, sizeof(disk.szDevNode) - 1);
  654. disk.internal = bInternalEmmc;
  655. if(!_ReadDevPropertyValue(cur, "ID_NAME", disk.szName, sizeof(disk.szName), true))
  656. _ReadDevPropertyValue(cur, "ID_MODEL", disk.szName, sizeof(disk.szName), true);
  657. _ReadDevPropertyValue(cur, "ID_VENDOR", disk.szVendor, sizeof(disk.szVendor), true);
  658. _ReadDevPropertyValue(cur, "ID_BUS", disk.szBus, sizeof(disk.szBus), true);
  659. disk.nVendorID = _ReadDevPropertyValue(cur, "ID_VENDOR_ID", 16);
  660. disk.nProductID = _ReadDevPropertyValue(cur, "ID_MODEL_ID", 16);
  661. if((nDiskIdx = _AddDisk(sdm, disk, bChange)) >= 0)
  662. {
  663. if((nPartIdx = _AddPartition(sdm, part, bChange)) < 0)
  664. {
  665. if(sdm.disks[nDiskIdx].nPartCount == 0)
  666. _RemoveDisk(sdm, nDiskIdx, bChange);
  667. break;
  668. }
  669. _DiskAddPartition(sdm, nDiskIdx, nPartIdx, bChange);
  670. _PartitionSetDisk(sdm, nPartIdx, nDiskIdx, bChange);
  671. _SetPartitionChange(sdm, nPartIdx);
  672. }
  673. break;
  674. }
  675. }
  676. }
  677. }
  678. else if(bRem)
  679. {
  680. if((nPartIdx = _LookupPartition(sdm, pszDevNode)) >= 0)
  681. {
  682. _RemovePartition(sdm, nPartIdx, bChange);
  683. _SetPartitionChange(sdm, nPartIdx);
  684. if((nDiskIdx = _PartitionGetDisk(sdm, nPartIdx)) >= 0)
  685. {
  686. if(!_DiskRemovePartition(sdm, nDiskIdx, nPartIdx, bChange))
  687. {
  688. _RemoveDisk(sdm, nDiskIdx, bChange);
  689. }
  690. }
  691. }
  692. }
  693. }
  694. }
  695. static void _EnumStorageDevices(GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, MountMap &mm, struct udev *pUdev)
  696. {
  697. struct udev_enumerate *pEnum = ::udev_enumerate_new(pUdev);
  698. ::udev_enumerate_add_match_subsystem(pEnum, "block");
  699. ::udev_enumerate_add_match_property(pEnum, "DEVTYPE", "partition");
  700. ::udev_enumerate_scan_devices(pEnum);
  701. struct udev_list_entry *devices = ::udev_enumerate_get_list_entry(pEnum);
  702. struct udev_list_entry *entry;
  703. udev_list_entry_foreach(entry, devices)
  704. {
  705. const char *pszPath = ::udev_list_entry_get_name(entry);
  706. struct udev_device* dev = ::udev_device_new_from_syspath(pUdev, pszPath);
  707. _ProcessPartition(sdm, mm, dev);
  708. ::udev_device_unref(dev);
  709. }
  710. ::udev_enumerate_unref(pEnum);
  711. }
  712. /////////////////////////////////////////////////////////////////////////////
  713. static void _SigHandler(int sig)
  714. {
  715. UNUSED(sig);
  716. g_fPause = false;
  717. g_fRun = false;
  718. g_fZombie = false;
  719. }
  720. /////////////////////////////////////////////////////////////////////////////
  721. /////////////////////////////////////////////////////////////////////////////
  722. /////////////////////////////////////////////////////////////////////////////
  723. int main(int argc, char *argv[])
  724. {
  725. UNUSED(argc);
  726. UNUSED(argv);
  727. HAPPCTRL hAC = NULL;
  728. HAPPINFO hAI;
  729. CCycleTimer ct(_CYCLE_INTV);
  730. cy_time_t wStart, wEnd, wCur = 0;
  731. struct udev *pUdev = NULL;
  732. struct timeval tv;
  733. memset(&tv, 0, sizeof(tv));
  734. struct udev_monitor *pUdevMon = NULL;
  735. GFA_SYSINFO_STORAGE_DEVICE_MAP sdm;
  736. memset(&sdm, 0, sizeof(sdm));
  737. MountMap mm;
  738. pollfd pfd[2];
  739. memset(&pfd, 0, sizeof(pfd));
  740. /////////////////////////////////////////////////////////////////////////
  741. /////////////////////////////////////////////////////////////////////////
  742. /////////////////////////////////////////////////////////////////////////
  743. // signal handling
  744. struct sigaction sa;
  745. memset(&sa, 0, sizeof(sa));
  746. // handle signals
  747. sa.sa_handler = _SigHandler;
  748. sigaction(SIGHUP, &sa, NULL); // handles user's terminal disconnect
  749. sigaction(SIGQUIT, &sa, NULL); // handles Ctrl + '\'
  750. sigaction(SIGTERM, &sa, NULL); // handles normal termination
  751. sigaction(SIGABRT, &sa, NULL); // handles abnormal termination (i.e. abort())
  752. sigaction(SIGINT, &sa, NULL); // handles Ctrl + 'C'
  753. // ignore signals
  754. sa.sa_handler = SIG_IGN;
  755. sigaction(SIGTSTP, &sa, NULL); // ignores Ctrl + 'Z'
  756. sigaction(SIGCHLD, &sa, NULL); // ignores child process termination
  757. sigaction(0, &sa, NULL); // ignores shell termination
  758. /////////////////////////////////////////////////////////////////////////
  759. /////////////////////////////////////////////////////////////////////////
  760. /////////////////////////////////////////////////////////////////////////
  761. // initialize
  762. do
  763. {
  764. g_fZombie = true;
  765. if(!(hAC = ::GfaIpcAppCtrlAcquire(_APPID, _APPNAME, _CYCLE_INTV * 1000, _CYCLE_INTV * 3000)))
  766. {
  767. TRACE("GfaIpcAppCtrlAcquire failed\n");
  768. break;
  769. }
  770. ::GfaIpcAppCtrlSetState(hAC, GIAS_Initializing);
  771. if(!::GfaIpcAppCtrlCreateSysInfo(hAC))
  772. {
  773. TRACE("GfaIpcAppCtrlCreateSysInfo failed\n");
  774. break;
  775. }
  776. if(!(pUdev = ::udev_new()))
  777. {
  778. TRACE("udev_new failed\n");
  779. break;
  780. }
  781. _UpdateMountMap(mm);
  782. _EnumStorageDevices(sdm, mm, pUdev);
  783. if(!(pUdevMon = ::udev_monitor_new_from_netlink(pUdev, "udev")))
  784. {
  785. TRACE("udev_monitor_new_from_netlink failed\n");
  786. break;
  787. }
  788. if(::udev_monitor_filter_add_match_subsystem_devtype(pUdevMon, "block", "partition") < 0)
  789. {
  790. TRACE("udev_monitor_filter_add_match_subsystem_devtype failed\n");
  791. break;
  792. }
  793. if(::udev_monitor_enable_receiving(pUdevMon) < 0)
  794. {
  795. TRACE("udev_monitor_enable_receiving failed\n");
  796. break;
  797. }
  798. pfd[0].fd = ::udev_monitor_get_fd(pUdevMon);
  799. pfd[0].events = POLLIN;
  800. pfd[0].revents = 0;
  801. pfd[1].fd = open(_MOUNTS_FILE, O_RDONLY, 0);
  802. pfd[1].events = POLLPRI;
  803. pfd[1].revents = 0;
  804. ;;GfaIpcDumpSHMROT();
  805. TRACE("My Name: %s\n", _APPNAME);
  806. TRACE("My AppID: %llu\n", _APPID);
  807. TRACE("My PID: %d\n", getpid());
  808. TRACE("My Cycle: %d\n", _CYCLE_INTV);
  809. g_fZombie = false;
  810. g_fRun = true;
  811. ::GfaIpcAppCtrlSetState(hAC, GIAS_Running);
  812. ::GfaIpcAppCtrlUpdateStorageDeviceMap(hAC, sdm);
  813. // _DumpDeviceMap(sdm);
  814. }
  815. while(false);
  816. /////////////////////////////////////////////////////////////////////////
  817. /////////////////////////////////////////////////////////////////////////
  818. /////////////////////////////////////////////////////////////////////////
  819. // run
  820. while(g_fRun)
  821. {
  822. /////////////////////////////////////////////////////////////////////
  823. // trigger cycle timer
  824. ct.Trigger();
  825. /////////////////////////////////////////////////////////////////////
  826. // update app control info
  827. if((hAI = ::GfaIpcAppCtrlInfoUpdate(hAC, wCur)))
  828. {
  829. _ProcessCtrlMessages(hAC, hAI);
  830. }
  831. /////////////////////////////////////////////////////////////////////
  832. // if not paused, do work
  833. if(!g_fPause && g_fRun)
  834. {
  835. wStart = ct.GetMicroTick();
  836. ::GfaIpcAppCtrlUpdateSysInfo(hAC);
  837. wEnd = ct.GetMicroTick();
  838. wCur = wEnd - wStart;
  839. _ClearMapChanges(sdm);
  840. while(poll(pfd, 2, _CYCLE_INTV / 5) > 0)
  841. {
  842. _UpdateMountMap(mm);
  843. if(pfd[0].revents & POLLIN)
  844. {
  845. struct udev_device* dev;
  846. while((dev = ::udev_monitor_receive_device(pUdevMon)))
  847. {
  848. _ProcessPartition(sdm, mm, dev);
  849. }
  850. }
  851. if(pfd[1].revents & POLLPRI)
  852. {
  853. _ProcessMounts(sdm, mm);
  854. }
  855. }
  856. if(_DeviceMapChanged(sdm))
  857. {
  858. ::GfaIpcAppCtrlUpdateStorageDeviceMap(hAC, sdm);
  859. // _DumpDeviceMap(sdm);
  860. }
  861. }
  862. /////////////////////////////////////////////////////////////////////
  863. // if running, sleep
  864. if(g_fRun)
  865. ct.Sleep1();
  866. }
  867. /////////////////////////////////////////////////////////////////////////
  868. /////////////////////////////////////////////////////////////////////////
  869. /////////////////////////////////////////////////////////////////////////
  870. // terminate
  871. if(pfd[0].fd >= 0)
  872. close(pfd[0].fd);
  873. if(pfd[1].fd >= 0)
  874. close(pfd[1].fd);
  875. if(pUdevMon)
  876. ::udev_monitor_unref(pUdevMon);
  877. if(pUdev)
  878. ::udev_unref(pUdev);
  879. if(g_fZombie)
  880. {
  881. if(hAC)
  882. ::GfaIpcAppCtrlSetState(hAC, GIAS_Zombie);
  883. TRACE("%-8s: State: %s\n", "Me", ::GfaIpcAppCtrlGetStateText(GIAS_Zombie));
  884. pause();
  885. }
  886. if(hAC)
  887. {
  888. ::GfaIpcAppCtrlSetState(hAC, GIAS_Terminating);
  889. ::GfaIpcAppCtrlReleaseSysInfo(hAC);
  890. ::GfaIpcAppCtrlRelease(hAC);
  891. }
  892. return 0;
  893. }