test-util-filemonitor.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. /*
  2. * Tests for util/filemonitor-*.c
  3. *
  4. * Copyright 2018 Red Hat, Inc.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this library; if not, see <http://www.gnu.org/licenses/>.
  18. *
  19. */
  20. #include "qemu/osdep.h"
  21. #include "qemu/main-loop.h"
  22. #include "qapi/error.h"
  23. #include "qemu/filemonitor.h"
  24. #include <utime.h>
  25. enum {
  26. QFILE_MONITOR_TEST_OP_ADD_WATCH,
  27. QFILE_MONITOR_TEST_OP_DEL_WATCH,
  28. QFILE_MONITOR_TEST_OP_EVENT,
  29. QFILE_MONITOR_TEST_OP_CREATE,
  30. QFILE_MONITOR_TEST_OP_APPEND,
  31. QFILE_MONITOR_TEST_OP_TRUNC,
  32. QFILE_MONITOR_TEST_OP_RENAME,
  33. QFILE_MONITOR_TEST_OP_TOUCH,
  34. QFILE_MONITOR_TEST_OP_UNLINK,
  35. QFILE_MONITOR_TEST_OP_MKDIR,
  36. QFILE_MONITOR_TEST_OP_RMDIR,
  37. };
  38. typedef struct {
  39. int type;
  40. const char *filesrc;
  41. const char *filedst;
  42. int64_t *watchid;
  43. int eventid;
  44. /*
  45. * Only valid with OP_EVENT - this event might be
  46. * swapped with the next OP_EVENT
  47. */
  48. bool swapnext;
  49. } QFileMonitorTestOp;
  50. typedef struct {
  51. int64_t id;
  52. QFileMonitorEvent event;
  53. char *filename;
  54. } QFileMonitorTestRecord;
  55. typedef struct {
  56. QemuMutex lock;
  57. GList *records;
  58. } QFileMonitorTestData;
  59. static QemuMutex evlock;
  60. static bool evstopping;
  61. static bool evrunning;
  62. static bool debug;
  63. /*
  64. * Main function for a background thread that is
  65. * running the event loop during the test
  66. */
  67. static void *
  68. qemu_file_monitor_test_event_loop(void *opaque G_GNUC_UNUSED)
  69. {
  70. qemu_mutex_lock(&evlock);
  71. while (!evstopping) {
  72. qemu_mutex_unlock(&evlock);
  73. main_loop_wait(true);
  74. qemu_mutex_lock(&evlock);
  75. }
  76. evrunning = false;
  77. qemu_mutex_unlock(&evlock);
  78. return NULL;
  79. }
  80. /*
  81. * File monitor event handler which simply maintains
  82. * an ordered list of all events that it receives
  83. */
  84. static void
  85. qemu_file_monitor_test_handler(int64_t id,
  86. QFileMonitorEvent event,
  87. const char *filename,
  88. void *opaque)
  89. {
  90. QFileMonitorTestData *data = opaque;
  91. QFileMonitorTestRecord *rec = g_new0(QFileMonitorTestRecord, 1);
  92. if (debug) {
  93. g_printerr("Queue event id %" PRIx64 " event %d file %s\n",
  94. id, event, filename);
  95. }
  96. rec->id = id;
  97. rec->event = event;
  98. rec->filename = g_strdup(filename);
  99. qemu_mutex_lock(&data->lock);
  100. data->records = g_list_append(data->records, rec);
  101. qemu_mutex_unlock(&data->lock);
  102. }
  103. static void
  104. qemu_file_monitor_test_record_free(QFileMonitorTestRecord *rec)
  105. {
  106. g_free(rec->filename);
  107. g_free(rec);
  108. }
  109. /*
  110. * Get the next event record that has been received by
  111. * the file monitor event handler. Since events are
  112. * emitted in the background thread running the event
  113. * loop, we can't assume there is a record available
  114. * immediately. Thus we will sleep for upto 5 seconds
  115. * to wait for the event to be queued for us.
  116. */
  117. static QFileMonitorTestRecord *
  118. qemu_file_monitor_test_next_record(QFileMonitorTestData *data,
  119. QFileMonitorTestRecord *pushback)
  120. {
  121. GTimer *timer = g_timer_new();
  122. QFileMonitorTestRecord *record = NULL;
  123. GList *tmp;
  124. qemu_mutex_lock(&data->lock);
  125. while (!data->records && g_timer_elapsed(timer, NULL) < 5) {
  126. qemu_mutex_unlock(&data->lock);
  127. usleep(10 * 1000);
  128. qemu_mutex_lock(&data->lock);
  129. }
  130. if (data->records) {
  131. record = data->records->data;
  132. if (pushback) {
  133. data->records->data = pushback;
  134. } else {
  135. tmp = data->records;
  136. data->records = g_list_remove_link(data->records, tmp);
  137. g_list_free(tmp);
  138. }
  139. } else if (pushback) {
  140. qemu_file_monitor_test_record_free(pushback);
  141. }
  142. qemu_mutex_unlock(&data->lock);
  143. g_timer_destroy(timer);
  144. return record;
  145. }
  146. /*
  147. * Check whether the event record we retrieved matches
  148. * data we were expecting to see for the event
  149. */
  150. static bool
  151. qemu_file_monitor_test_expect(QFileMonitorTestData *data,
  152. int64_t id,
  153. QFileMonitorEvent event,
  154. const char *filename,
  155. bool swapnext)
  156. {
  157. QFileMonitorTestRecord *rec;
  158. bool ret = false;
  159. rec = qemu_file_monitor_test_next_record(data, NULL);
  160. retry:
  161. if (!rec) {
  162. g_printerr("Missing event watch id %" PRIx64 " event %d file %s\n",
  163. id, event, filename);
  164. return false;
  165. }
  166. if (id != rec->id) {
  167. if (swapnext) {
  168. rec = qemu_file_monitor_test_next_record(data, rec);
  169. swapnext = false;
  170. goto retry;
  171. }
  172. g_printerr("Expected watch id %" PRIx64 " but got %" PRIx64 "\n",
  173. id, rec->id);
  174. goto cleanup;
  175. }
  176. if (event != rec->event) {
  177. g_printerr("Expected event %d but got %d\n", event, rec->event);
  178. goto cleanup;
  179. }
  180. if (!g_str_equal(filename, rec->filename)) {
  181. g_printerr("Expected filename %s but got %s\n",
  182. filename, rec->filename);
  183. goto cleanup;
  184. }
  185. ret = true;
  186. cleanup:
  187. qemu_file_monitor_test_record_free(rec);
  188. return ret;
  189. }
  190. static void
  191. test_file_monitor_events(void)
  192. {
  193. int64_t watch0 = 0;
  194. int64_t watch1 = 0;
  195. int64_t watch2 = 0;
  196. int64_t watch3 = 0;
  197. int64_t watch4 = 0;
  198. int64_t watch5 = 0;
  199. QFileMonitorTestOp ops[] = {
  200. { .type = QFILE_MONITOR_TEST_OP_ADD_WATCH,
  201. .filesrc = NULL, .watchid = &watch0 },
  202. { .type = QFILE_MONITOR_TEST_OP_ADD_WATCH,
  203. .filesrc = "one.txt", .watchid = &watch1 },
  204. { .type = QFILE_MONITOR_TEST_OP_ADD_WATCH,
  205. .filesrc = "two.txt", .watchid = &watch2 },
  206. { .type = QFILE_MONITOR_TEST_OP_CREATE,
  207. .filesrc = "one.txt", },
  208. { .type = QFILE_MONITOR_TEST_OP_EVENT,
  209. .filesrc = "one.txt", .watchid = &watch0,
  210. .eventid = QFILE_MONITOR_EVENT_CREATED },
  211. { .type = QFILE_MONITOR_TEST_OP_EVENT,
  212. .filesrc = "one.txt", .watchid = &watch1,
  213. .eventid = QFILE_MONITOR_EVENT_CREATED },
  214. { .type = QFILE_MONITOR_TEST_OP_CREATE,
  215. .filesrc = "two.txt", },
  216. { .type = QFILE_MONITOR_TEST_OP_EVENT,
  217. .filesrc = "two.txt", .watchid = &watch0,
  218. .eventid = QFILE_MONITOR_EVENT_CREATED },
  219. { .type = QFILE_MONITOR_TEST_OP_EVENT,
  220. .filesrc = "two.txt", .watchid = &watch2,
  221. .eventid = QFILE_MONITOR_EVENT_CREATED },
  222. { .type = QFILE_MONITOR_TEST_OP_CREATE,
  223. .filesrc = "three.txt", },
  224. { .type = QFILE_MONITOR_TEST_OP_EVENT,
  225. .filesrc = "three.txt", .watchid = &watch0,
  226. .eventid = QFILE_MONITOR_EVENT_CREATED },
  227. { .type = QFILE_MONITOR_TEST_OP_UNLINK,
  228. .filesrc = "three.txt", },
  229. { .type = QFILE_MONITOR_TEST_OP_EVENT,
  230. .filesrc = "three.txt", .watchid = &watch0,
  231. .eventid = QFILE_MONITOR_EVENT_DELETED },
  232. { .type = QFILE_MONITOR_TEST_OP_RENAME,
  233. .filesrc = "one.txt", .filedst = "two.txt" },
  234. { .type = QFILE_MONITOR_TEST_OP_EVENT,
  235. .filesrc = "one.txt", .watchid = &watch0,
  236. .eventid = QFILE_MONITOR_EVENT_DELETED },
  237. { .type = QFILE_MONITOR_TEST_OP_EVENT,
  238. .filesrc = "one.txt", .watchid = &watch1,
  239. .eventid = QFILE_MONITOR_EVENT_DELETED },
  240. { .type = QFILE_MONITOR_TEST_OP_EVENT,
  241. .filesrc = "two.txt", .watchid = &watch0,
  242. .eventid = QFILE_MONITOR_EVENT_CREATED },
  243. { .type = QFILE_MONITOR_TEST_OP_EVENT,
  244. .filesrc = "two.txt", .watchid = &watch2,
  245. .eventid = QFILE_MONITOR_EVENT_CREATED },
  246. { .type = QFILE_MONITOR_TEST_OP_APPEND,
  247. .filesrc = "two.txt", },
  248. { .type = QFILE_MONITOR_TEST_OP_EVENT,
  249. .filesrc = "two.txt", .watchid = &watch0,
  250. .eventid = QFILE_MONITOR_EVENT_MODIFIED },
  251. { .type = QFILE_MONITOR_TEST_OP_EVENT,
  252. .filesrc = "two.txt", .watchid = &watch2,
  253. .eventid = QFILE_MONITOR_EVENT_MODIFIED },
  254. { .type = QFILE_MONITOR_TEST_OP_TOUCH,
  255. .filesrc = "two.txt", },
  256. { .type = QFILE_MONITOR_TEST_OP_EVENT,
  257. .filesrc = "two.txt", .watchid = &watch0,
  258. .eventid = QFILE_MONITOR_EVENT_ATTRIBUTES },
  259. { .type = QFILE_MONITOR_TEST_OP_EVENT,
  260. .filesrc = "two.txt", .watchid = &watch2,
  261. .eventid = QFILE_MONITOR_EVENT_ATTRIBUTES },
  262. { .type = QFILE_MONITOR_TEST_OP_DEL_WATCH,
  263. .filesrc = "one.txt", .watchid = &watch1 },
  264. { .type = QFILE_MONITOR_TEST_OP_ADD_WATCH,
  265. .filesrc = "one.txt", .watchid = &watch3 },
  266. { .type = QFILE_MONITOR_TEST_OP_CREATE,
  267. .filesrc = "one.txt", },
  268. { .type = QFILE_MONITOR_TEST_OP_EVENT,
  269. .filesrc = "one.txt", .watchid = &watch0,
  270. .eventid = QFILE_MONITOR_EVENT_CREATED },
  271. { .type = QFILE_MONITOR_TEST_OP_EVENT,
  272. .filesrc = "one.txt", .watchid = &watch3,
  273. .eventid = QFILE_MONITOR_EVENT_CREATED },
  274. { .type = QFILE_MONITOR_TEST_OP_DEL_WATCH,
  275. .filesrc = "one.txt", .watchid = &watch3 },
  276. { .type = QFILE_MONITOR_TEST_OP_UNLINK,
  277. .filesrc = "one.txt", },
  278. { .type = QFILE_MONITOR_TEST_OP_EVENT,
  279. .filesrc = "one.txt", .watchid = &watch0,
  280. .eventid = QFILE_MONITOR_EVENT_DELETED },
  281. { .type = QFILE_MONITOR_TEST_OP_MKDIR,
  282. .filesrc = "fish", },
  283. { .type = QFILE_MONITOR_TEST_OP_EVENT,
  284. .filesrc = "fish", .watchid = &watch0,
  285. .eventid = QFILE_MONITOR_EVENT_CREATED },
  286. { .type = QFILE_MONITOR_TEST_OP_ADD_WATCH,
  287. .filesrc = "fish/", .watchid = &watch4 },
  288. { .type = QFILE_MONITOR_TEST_OP_ADD_WATCH,
  289. .filesrc = "fish/one.txt", .watchid = &watch5 },
  290. { .type = QFILE_MONITOR_TEST_OP_CREATE,
  291. .filesrc = "fish/one.txt", },
  292. { .type = QFILE_MONITOR_TEST_OP_EVENT,
  293. .filesrc = "one.txt", .watchid = &watch4,
  294. .eventid = QFILE_MONITOR_EVENT_CREATED },
  295. { .type = QFILE_MONITOR_TEST_OP_EVENT,
  296. .filesrc = "one.txt", .watchid = &watch5,
  297. .eventid = QFILE_MONITOR_EVENT_CREATED },
  298. { .type = QFILE_MONITOR_TEST_OP_DEL_WATCH,
  299. .filesrc = "fish/one.txt", .watchid = &watch5 },
  300. { .type = QFILE_MONITOR_TEST_OP_RENAME,
  301. .filesrc = "fish/one.txt", .filedst = "two.txt", },
  302. { .type = QFILE_MONITOR_TEST_OP_EVENT,
  303. .filesrc = "one.txt", .watchid = &watch4,
  304. .eventid = QFILE_MONITOR_EVENT_DELETED },
  305. { .type = QFILE_MONITOR_TEST_OP_EVENT,
  306. .filesrc = "two.txt", .watchid = &watch0,
  307. .eventid = QFILE_MONITOR_EVENT_CREATED },
  308. { .type = QFILE_MONITOR_TEST_OP_EVENT,
  309. .filesrc = "two.txt", .watchid = &watch2,
  310. .eventid = QFILE_MONITOR_EVENT_CREATED },
  311. { .type = QFILE_MONITOR_TEST_OP_RMDIR,
  312. .filesrc = "fish", },
  313. { .type = QFILE_MONITOR_TEST_OP_EVENT,
  314. .filesrc = "", .watchid = &watch4,
  315. .eventid = QFILE_MONITOR_EVENT_IGNORED,
  316. .swapnext = true },
  317. { .type = QFILE_MONITOR_TEST_OP_EVENT,
  318. .filesrc = "fish", .watchid = &watch0,
  319. .eventid = QFILE_MONITOR_EVENT_DELETED },
  320. { .type = QFILE_MONITOR_TEST_OP_DEL_WATCH,
  321. .filesrc = "fish", .watchid = &watch4 },
  322. { .type = QFILE_MONITOR_TEST_OP_UNLINK,
  323. .filesrc = "two.txt", },
  324. { .type = QFILE_MONITOR_TEST_OP_EVENT,
  325. .filesrc = "two.txt", .watchid = &watch0,
  326. .eventid = QFILE_MONITOR_EVENT_DELETED },
  327. { .type = QFILE_MONITOR_TEST_OP_EVENT,
  328. .filesrc = "two.txt", .watchid = &watch2,
  329. .eventid = QFILE_MONITOR_EVENT_DELETED },
  330. { .type = QFILE_MONITOR_TEST_OP_DEL_WATCH,
  331. .filesrc = "two.txt", .watchid = &watch2 },
  332. { .type = QFILE_MONITOR_TEST_OP_DEL_WATCH,
  333. .filesrc = NULL, .watchid = &watch0 },
  334. };
  335. Error *local_err = NULL;
  336. GError *gerr = NULL;
  337. QFileMonitor *mon = qemu_file_monitor_new(&local_err);
  338. QemuThread th;
  339. GTimer *timer;
  340. gchar *dir = NULL;
  341. int err = -1;
  342. gsize i;
  343. char *pathsrc = NULL;
  344. char *pathdst = NULL;
  345. QFileMonitorTestData data;
  346. GHashTable *ids = g_hash_table_new(g_int64_hash, g_int64_equal);
  347. qemu_mutex_init(&data.lock);
  348. data.records = NULL;
  349. /*
  350. * The file monitor needs the main loop running in
  351. * order to receive events from inotify. We must
  352. * thus spawn a background thread to run an event
  353. * loop impl, while this thread triggers the
  354. * actual file operations we're testing
  355. */
  356. evrunning = 1;
  357. evstopping = 0;
  358. qemu_thread_create(&th, "event-loop",
  359. qemu_file_monitor_test_event_loop, NULL,
  360. QEMU_THREAD_JOINABLE);
  361. if (local_err) {
  362. g_printerr("File monitoring not available: %s",
  363. error_get_pretty(local_err));
  364. error_free(local_err);
  365. return;
  366. }
  367. dir = g_dir_make_tmp("test-util-filemonitor-XXXXXX",
  368. &gerr);
  369. if (!dir) {
  370. g_printerr("Unable to create tmp dir %s",
  371. gerr->message);
  372. g_error_free(gerr);
  373. abort();
  374. }
  375. /*
  376. * Run through the operation sequence validating events
  377. * as we go
  378. */
  379. for (i = 0; i < G_N_ELEMENTS(ops); i++) {
  380. const QFileMonitorTestOp *op = &(ops[i]);
  381. int fd;
  382. struct utimbuf ubuf;
  383. char *watchdir;
  384. const char *watchfile;
  385. pathsrc = g_strdup_printf("%s/%s", dir, op->filesrc);
  386. if (op->filedst) {
  387. pathdst = g_strdup_printf("%s/%s", dir, op->filedst);
  388. }
  389. switch (op->type) {
  390. case QFILE_MONITOR_TEST_OP_ADD_WATCH:
  391. if (debug) {
  392. g_printerr("Add watch %s %s\n",
  393. dir, op->filesrc);
  394. }
  395. if (op->filesrc && strchr(op->filesrc, '/')) {
  396. watchdir = g_strdup_printf("%s/%s", dir, op->filesrc);
  397. watchfile = strrchr(watchdir, '/');
  398. *(char *)watchfile = '\0';
  399. watchfile++;
  400. if (*watchfile == '\0') {
  401. watchfile = NULL;
  402. }
  403. } else {
  404. watchdir = g_strdup(dir);
  405. watchfile = op->filesrc;
  406. }
  407. *op->watchid =
  408. qemu_file_monitor_add_watch(mon,
  409. watchdir,
  410. watchfile,
  411. qemu_file_monitor_test_handler,
  412. &data,
  413. &local_err);
  414. g_free(watchdir);
  415. if (*op->watchid < 0) {
  416. g_printerr("Unable to add watch %s",
  417. error_get_pretty(local_err));
  418. goto cleanup;
  419. }
  420. if (debug) {
  421. g_printerr("Watch ID %" PRIx64 "\n", *op->watchid);
  422. }
  423. if (g_hash_table_contains(ids, op->watchid)) {
  424. g_printerr("Watch ID %" PRIx64 "already exists", *op->watchid);
  425. goto cleanup;
  426. }
  427. g_hash_table_add(ids, op->watchid);
  428. break;
  429. case QFILE_MONITOR_TEST_OP_DEL_WATCH:
  430. if (debug) {
  431. g_printerr("Del watch %s %" PRIx64 "\n", dir, *op->watchid);
  432. }
  433. if (op->filesrc && strchr(op->filesrc, '/')) {
  434. watchdir = g_strdup_printf("%s/%s", dir, op->filesrc);
  435. watchfile = strrchr(watchdir, '/');
  436. *(char *)watchfile = '\0';
  437. } else {
  438. watchdir = g_strdup(dir);
  439. }
  440. g_hash_table_remove(ids, op->watchid);
  441. qemu_file_monitor_remove_watch(mon,
  442. watchdir,
  443. *op->watchid);
  444. g_free(watchdir);
  445. break;
  446. case QFILE_MONITOR_TEST_OP_EVENT:
  447. if (debug) {
  448. g_printerr("Event id=%" PRIx64 " event=%d file=%s\n",
  449. *op->watchid, op->eventid, op->filesrc);
  450. }
  451. if (!qemu_file_monitor_test_expect(&data, *op->watchid,
  452. op->eventid, op->filesrc,
  453. op->swapnext))
  454. goto cleanup;
  455. break;
  456. case QFILE_MONITOR_TEST_OP_CREATE:
  457. if (debug) {
  458. g_printerr("Create %s\n", pathsrc);
  459. }
  460. fd = open(pathsrc, O_WRONLY | O_CREAT, 0700);
  461. if (fd < 0) {
  462. g_printerr("Unable to create %s: %s",
  463. pathsrc, strerror(errno));
  464. goto cleanup;
  465. }
  466. close(fd);
  467. break;
  468. case QFILE_MONITOR_TEST_OP_APPEND:
  469. if (debug) {
  470. g_printerr("Append %s\n", pathsrc);
  471. }
  472. fd = open(pathsrc, O_WRONLY | O_APPEND, 0700);
  473. if (fd < 0) {
  474. g_printerr("Unable to open %s: %s",
  475. pathsrc, strerror(errno));
  476. goto cleanup;
  477. }
  478. if (write(fd, "Hello World", 10) != 10) {
  479. g_printerr("Unable to write %s: %s",
  480. pathsrc, strerror(errno));
  481. close(fd);
  482. goto cleanup;
  483. }
  484. close(fd);
  485. break;
  486. case QFILE_MONITOR_TEST_OP_TRUNC:
  487. if (debug) {
  488. g_printerr("Truncate %s\n", pathsrc);
  489. }
  490. if (truncate(pathsrc, 4) < 0) {
  491. g_printerr("Unable to truncate %s: %s",
  492. pathsrc, strerror(errno));
  493. goto cleanup;
  494. }
  495. break;
  496. case QFILE_MONITOR_TEST_OP_RENAME:
  497. if (debug) {
  498. g_printerr("Rename %s -> %s\n", pathsrc, pathdst);
  499. }
  500. if (rename(pathsrc, pathdst) < 0) {
  501. g_printerr("Unable to rename %s to %s: %s",
  502. pathsrc, pathdst, strerror(errno));
  503. goto cleanup;
  504. }
  505. break;
  506. case QFILE_MONITOR_TEST_OP_UNLINK:
  507. if (debug) {
  508. g_printerr("Unlink %s\n", pathsrc);
  509. }
  510. if (unlink(pathsrc) < 0) {
  511. g_printerr("Unable to unlink %s: %s",
  512. pathsrc, strerror(errno));
  513. goto cleanup;
  514. }
  515. break;
  516. case QFILE_MONITOR_TEST_OP_TOUCH:
  517. if (debug) {
  518. g_printerr("Touch %s\n", pathsrc);
  519. }
  520. ubuf.actime = 1024;
  521. ubuf.modtime = 1025;
  522. if (utime(pathsrc, &ubuf) < 0) {
  523. g_printerr("Unable to touch %s: %s",
  524. pathsrc, strerror(errno));
  525. goto cleanup;
  526. }
  527. break;
  528. case QFILE_MONITOR_TEST_OP_MKDIR:
  529. if (debug) {
  530. g_printerr("Mkdir %s\n", pathsrc);
  531. }
  532. if (mkdir(pathsrc, 0700) < 0) {
  533. g_printerr("Unable to mkdir %s: %s",
  534. pathsrc, strerror(errno));
  535. goto cleanup;
  536. }
  537. break;
  538. case QFILE_MONITOR_TEST_OP_RMDIR:
  539. if (debug) {
  540. g_printerr("Rmdir %s\n", pathsrc);
  541. }
  542. if (rmdir(pathsrc) < 0) {
  543. g_printerr("Unable to rmdir %s: %s",
  544. pathsrc, strerror(errno));
  545. goto cleanup;
  546. }
  547. break;
  548. default:
  549. g_assert_not_reached();
  550. }
  551. g_free(pathsrc);
  552. g_free(pathdst);
  553. pathsrc = pathdst = NULL;
  554. }
  555. g_assert_cmpint(g_hash_table_size(ids), ==, 0);
  556. err = 0;
  557. cleanup:
  558. g_free(pathsrc);
  559. g_free(pathdst);
  560. qemu_mutex_lock(&evlock);
  561. evstopping = 1;
  562. timer = g_timer_new();
  563. while (evrunning && g_timer_elapsed(timer, NULL) < 5) {
  564. qemu_mutex_unlock(&evlock);
  565. usleep(10 * 1000);
  566. qemu_mutex_lock(&evlock);
  567. }
  568. qemu_mutex_unlock(&evlock);
  569. if (g_timer_elapsed(timer, NULL) >= 5) {
  570. g_printerr("Event loop failed to quit after 5 seconds\n");
  571. }
  572. g_timer_destroy(timer);
  573. qemu_file_monitor_free(mon);
  574. g_list_foreach(data.records,
  575. (GFunc)qemu_file_monitor_test_record_free, NULL);
  576. g_list_free(data.records);
  577. qemu_mutex_destroy(&data.lock);
  578. if (dir) {
  579. for (i = 0; i < G_N_ELEMENTS(ops); i++) {
  580. const QFileMonitorTestOp *op = &(ops[i]);
  581. char *path = g_strdup_printf("%s/%s",
  582. dir, op->filesrc);
  583. if (op->type == QFILE_MONITOR_TEST_OP_MKDIR) {
  584. rmdir(path);
  585. g_free(path);
  586. } else {
  587. unlink(path);
  588. g_free(path);
  589. if (op->filedst) {
  590. path = g_strdup_printf("%s/%s",
  591. dir, op->filedst);
  592. unlink(path);
  593. g_free(path);
  594. }
  595. }
  596. }
  597. if (rmdir(dir) < 0) {
  598. g_printerr("Failed to remove %s: %s\n",
  599. dir, strerror(errno));
  600. abort();
  601. }
  602. }
  603. g_hash_table_unref(ids);
  604. g_free(dir);
  605. g_assert(err == 0);
  606. }
  607. int main(int argc, char **argv)
  608. {
  609. g_test_init(&argc, &argv, NULL);
  610. qemu_init_main_loop(&error_abort);
  611. qemu_mutex_init(&evlock);
  612. debug = getenv("FILEMONITOR_DEBUG") != NULL;
  613. g_test_add_func("/util/filemonitor", test_file_monitor_events);
  614. return g_test_run();
  615. }