INotifyPosix.cpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Util/INotify.h>
  6. #include <AnKi/Util/Logger.h>
  7. #include <sys/inotify.h>
  8. #include <poll.h>
  9. #include <unistd.h>
  10. namespace anki
  11. {
  12. Error INotify::initInternal()
  13. {
  14. ANKI_ASSERT(m_fd < 0 && m_watch < 0);
  15. Error err = Error::NONE;
  16. m_fd = inotify_init();
  17. if(m_fd < 0)
  18. {
  19. ANKI_UTIL_LOGE("inotify_init() failed: %s", strerror(errno));
  20. err = Error::FUNCTION_FAILED;
  21. }
  22. if(!err)
  23. {
  24. m_watch = inotify_add_watch(m_fd, &m_path[0], IN_MODIFY | IN_CREATE | IN_DELETE | IN_IGNORED | IN_DELETE_SELF);
  25. if(m_watch < 0)
  26. {
  27. ANKI_UTIL_LOGE("inotify_add_watch() failed: %s", strerror(errno));
  28. err = Error::FUNCTION_FAILED;
  29. }
  30. }
  31. if(err)
  32. {
  33. destroyInternal();
  34. }
  35. return err;
  36. }
  37. void INotify::destroyInternal()
  38. {
  39. if(m_watch >= 0)
  40. {
  41. int err = inotify_rm_watch(m_fd, m_watch);
  42. if(err < 0)
  43. {
  44. ANKI_UTIL_LOGE("inotify_rm_watch() failed: %s\n", strerror(errno));
  45. }
  46. m_watch = -1;
  47. }
  48. if(m_fd >= 0)
  49. {
  50. int err = close(m_fd);
  51. if(err < 0)
  52. {
  53. ANKI_UTIL_LOGE("close() failed: %s\n", strerror(errno));
  54. }
  55. m_fd = -1;
  56. }
  57. }
  58. Error INotify::pollEvents(Bool& modified)
  59. {
  60. ANKI_ASSERT(m_fd >= 0 && m_watch >= 0);
  61. Error err = Error::NONE;
  62. modified = false;
  63. while(true)
  64. {
  65. pollfd pfd = {m_fd, POLLIN, 0};
  66. int ret = poll(&pfd, 1, 0);
  67. if(ret < 0)
  68. {
  69. ANKI_UTIL_LOGE("poll() failed: %s", strerror(errno));
  70. err = Error::FUNCTION_FAILED;
  71. break;
  72. }
  73. else if(ret == 0)
  74. {
  75. // No events, move on
  76. break;
  77. }
  78. else
  79. {
  80. // Process the new event
  81. Array<U8, 2_KB> readBuff;
  82. PtrSize nbytes = read(m_fd, &readBuff[0], sizeof(readBuff));
  83. if(nbytes > 0)
  84. {
  85. inotify_event* event = reinterpret_cast<inotify_event*>(&readBuff[0]);
  86. if(event->mask & IN_IGNORED)
  87. {
  88. // File was moved or deleted. Some editors on save they delete the file and move another file to
  89. // its place. In that case the m_fd and the m_watch need to be re-created.
  90. m_watch = -1; // Watch descriptor was removed implicitly
  91. destroyInternal();
  92. err = initInternal();
  93. if(err)
  94. {
  95. break;
  96. }
  97. }
  98. else
  99. {
  100. modified = true;
  101. }
  102. }
  103. else
  104. {
  105. ANKI_UTIL_LOGE("read() failed to read the expected size of data: %s", strerror(errno));
  106. err = Error::FUNCTION_FAILED;
  107. break;
  108. }
  109. }
  110. }
  111. return err;
  112. }
  113. } // end namespace anki