Rizin
unix-like reverse engineering framework and cli tools
fs-poll.c
Go to the documentation of this file.
1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to
5  * deal in the Software without restriction, including without limitation the
6  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7  * sell copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19  * IN THE SOFTWARE.
20  */
21 
22 #include "uv.h"
23 #include "uv-common.h"
24 
25 #ifdef _WIN32
26 #include "win/internal.h"
27 #include "win/handle-inl.h"
28 #define uv__make_close_pending(h) uv_want_endgame((h)->loop, (h))
29 #else
30 #include "unix/internal.h"
31 #endif
32 
33 #include <assert.h>
34 #include <stdlib.h>
35 #include <string.h>
36 
37 struct poll_ctx {
40  unsigned int interval;
45  uv_fs_t fs_req; /* TODO(bnoordhuis) mark fs_req internal */
47  struct poll_ctx* previous; /* context from previous start()..stop() period */
48  char path[1]; /* variable length */
49 };
50 
51 static int statbuf_eq(const uv_stat_t* a, const uv_stat_t* b);
52 static void poll_cb(uv_fs_t* req);
53 static void timer_cb(uv_timer_t* timer);
54 static void timer_close_cb(uv_handle_t* handle);
55 
57 
58 
60  uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_POLL);
61  handle->poll_ctx = NULL;
62  return 0;
63 }
64 
65 
68  const char* path,
69  unsigned int interval) {
70  struct poll_ctx* ctx;
71  uv_loop_t* loop;
72  size_t len;
73  int err;
74 
76  return 0;
77 
78  loop = handle->loop;
79  len = strlen(path);
80  ctx = uv__calloc(1, sizeof(*ctx) + len);
81 
82  if (ctx == NULL)
83  return UV_ENOMEM;
84 
85  ctx->loop = loop;
86  ctx->poll_cb = cb;
87  ctx->interval = interval ? interval : 1;
88  ctx->start_time = uv_now(loop);
89  ctx->parent_handle = handle;
90  memcpy(ctx->path, path, len + 1);
91 
92  err = uv_timer_init(loop, &ctx->timer_handle);
93  if (err < 0)
94  goto error;
95 
96  ctx->timer_handle.flags |= UV_HANDLE_INTERNAL;
97  uv__handle_unref(&ctx->timer_handle);
98 
99  err = uv_fs_stat(loop, &ctx->fs_req, ctx->path, poll_cb);
100  if (err < 0)
101  goto error;
102 
103  if (handle->poll_ctx != NULL)
104  ctx->previous = handle->poll_ctx;
105  handle->poll_ctx = ctx;
107 
108  return 0;
109 
110 error:
111  uv__free(ctx);
112  return err;
113 }
114 
115 
117  struct poll_ctx* ctx;
118 
120  return 0;
121 
122  ctx = handle->poll_ctx;
123  assert(ctx != NULL);
124  assert(ctx->parent_handle == handle);
125 
126  /* Close the timer if it's active. If it's inactive, there's a stat request
127  * in progress and poll_cb will take care of the cleanup.
128  */
129  if (uv_is_active((uv_handle_t*)&ctx->timer_handle))
130  uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb);
131 
133 
134  return 0;
135 }
136 
137 
139  struct poll_ctx* ctx;
140  size_t required_len;
141 
142  if (!uv_is_active((uv_handle_t*)handle)) {
143  *size = 0;
144  return UV_EINVAL;
145  }
146 
147  ctx = handle->poll_ctx;
148  assert(ctx != NULL);
149 
150  required_len = strlen(ctx->path);
151  if (required_len >= *size) {
152  *size = required_len + 1;
153  return UV_ENOBUFS;
154  }
155 
156  memcpy(buffer, ctx->path, required_len);
157  *size = required_len;
158  buffer[required_len] = '\0';
159 
160  return 0;
161 }
162 
163 
166 
167  if (handle->poll_ctx == NULL)
169 }
170 
171 
172 static void timer_cb(uv_timer_t* timer) {
173  struct poll_ctx* ctx;
174 
175  ctx = container_of(timer, struct poll_ctx, timer_handle);
176  assert(ctx->parent_handle != NULL);
177  assert(ctx->parent_handle->poll_ctx == ctx);
178  ctx->start_time = uv_now(ctx->loop);
179 
180  if (uv_fs_stat(ctx->loop, &ctx->fs_req, ctx->path, poll_cb))
181  abort();
182 }
183 
184 
185 static void poll_cb(uv_fs_t* req) {
187  struct poll_ctx* ctx;
190 
191  ctx = container_of(req, struct poll_ctx, fs_req);
192  handle = ctx->parent_handle;
193 
195  goto out;
196 
197  if (req->result != 0) {
198  if (ctx->busy_polling != req->result) {
199  ctx->poll_cb(ctx->parent_handle,
200  req->result,
201  &ctx->statbuf,
202  &zero_statbuf);
203  ctx->busy_polling = req->result;
204  }
205  goto out;
206  }
207 
208  statbuf = &req->statbuf;
209 
210  if (ctx->busy_polling != 0)
211  if (ctx->busy_polling < 0 || !statbuf_eq(&ctx->statbuf, statbuf))
212  ctx->poll_cb(ctx->parent_handle, 0, &ctx->statbuf, statbuf);
213 
214  ctx->statbuf = *statbuf;
215  ctx->busy_polling = 1;
216 
217 out:
219 
221  uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb);
222  return;
223  }
224 
225  /* Reschedule timer, subtract the delay from doing the stat(). */
226  interval = ctx->interval;
227  interval -= (uv_now(ctx->loop) - ctx->start_time) % interval;
228 
229  if (uv_timer_start(&ctx->timer_handle, timer_cb, interval, 0))
230  abort();
231 }
232 
233 
234 static void timer_close_cb(uv_handle_t* timer) {
235  struct poll_ctx* ctx;
236  struct poll_ctx* it;
237  struct poll_ctx* last;
239 
240  ctx = container_of(timer, struct poll_ctx, timer_handle);
241  handle = ctx->parent_handle;
242  if (ctx == handle->poll_ctx) {
243  handle->poll_ctx = ctx->previous;
244  if (handle->poll_ctx == NULL && uv__is_closing(handle))
246  } else {
247  for (last = handle->poll_ctx, it = last->previous;
248  it != ctx;
249  last = it, it = it->previous) {
250  assert(last->previous != NULL);
251  }
252  last->previous = ctx->previous;
253  }
254  uv__free(ctx);
255 }
256 
257 
258 static int statbuf_eq(const uv_stat_t* a, const uv_stat_t* b) {
259  return a->st_ctim.tv_nsec == b->st_ctim.tv_nsec
260  && a->st_mtim.tv_nsec == b->st_mtim.tv_nsec
261  && a->st_birthtim.tv_nsec == b->st_birthtim.tv_nsec
262  && a->st_ctim.tv_sec == b->st_ctim.tv_sec
263  && a->st_mtim.tv_sec == b->st_mtim.tv_sec
264  && a->st_birthtim.tv_sec == b->st_birthtim.tv_sec
265  && a->st_size == b->st_size
266  && a->st_mode == b->st_mode
267  && a->st_uid == b->st_uid
268  && a->st_gid == b->st_gid
269  && a->st_ino == b->st_ino
270  && a->st_dev == b->st_dev
271  && a->st_flags == b->st_flags
272  && a->st_gen == b->st_gen;
273 }
274 
275 
276 #if defined(_WIN32)
277 
278 #include "win/internal.h"
279 #include "win/handle-inl.h"
280 
282  assert(handle->flags & UV_HANDLE_CLOSING);
283  assert(!(handle->flags & UV_HANDLE_CLOSED));
285 }
286 
287 #endif /* _WIN32 */
size_t len
Definition: 6502dis.c:15
static bool err
Definition: armass.c:435
static mcore_handle handle
Definition: asm_mcore.c:8
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
#define NULL
Definition: cris-opc.c:27
static static fork const void static count static fd const char const char static newpath const char static path const char path
Definition: sflib.h:35
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec req
Definition: sflib.h:128
static void timer_close_cb(uv_handle_t *handle)
Definition: fs-poll.c:234
int uv_fs_poll_init(uv_loop_t *loop, uv_fs_poll_t *handle)
Definition: fs-poll.c:59
static uv_stat_t zero_statbuf
Definition: fs-poll.c:56
static void timer_cb(uv_timer_t *timer)
Definition: fs-poll.c:172
int uv_fs_poll_start(uv_fs_poll_t *handle, uv_fs_poll_cb cb, const char *path, unsigned int interval)
Definition: fs-poll.c:66
int uv_fs_poll_getpath(uv_fs_poll_t *handle, char *buffer, size_t *size)
Definition: fs-poll.c:138
void uv__fs_poll_close(uv_fs_poll_t *handle)
Definition: fs-poll.c:164
int uv_fs_poll_stop(uv_fs_poll_t *handle)
Definition: fs-poll.c:116
static int statbuf_eq(const uv_stat_t *a, const uv_stat_t *b)
Definition: fs-poll.c:258
static void poll_cb(uv_fs_t *req)
Definition: fs-poll.c:185
#define uv__handle_close(handle)
Definition: handle-inl.h:76
voidpf void uLong size
Definition: ioapi.h:138
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
assert(limit<=UINT32_MAX/2)
#define container_of(ptr, type, member)
Definition: rz_types.h:650
unsigned long uint64_t
Definition: sftypes.h:28
#define b(i)
Definition: sha256.c:42
#define a(i)
Definition: sha256.c:41
Definition: buffer.h:15
struct poll_ctx * previous
Definition: fs-poll.c:47
uv_loop_t * loop
Definition: fs-poll.c:42
int busy_polling
Definition: fs-poll.c:39
uv_fs_poll_cb poll_cb
Definition: fs-poll.c:43
uv_fs_t fs_req
Definition: fs-poll.c:45
uint64_t start_time
Definition: fs-poll.c:41
uv_stat_t statbuf
Definition: fs-poll.c:46
unsigned int interval
Definition: fs-poll.c:40
char path[1]
Definition: fs-poll.c:48
uv_timer_t timer_handle
Definition: fs-poll.c:44
uv_fs_poll_t * parent_handle
Definition: fs-poll.c:38
Definition: uv.h:1306
Definition: uv.h:1780
Definition: uv.h:349
Definition: uv.h:860
uv_loop_t * loop
Definition: main.c:7
void uv__make_close_pending(uv_handle_t *handle)
Definition: core.c:208
void uv__fs_poll_endgame(uv_loop_t *loop, uv_fs_poll_t *handle)
void error(const char *msg)
Definition: untgz.c:593
void * uv__calloc(size_t count, size_t size)
Definition: uv-common.c:92
void uv__free(void *ptr)
Definition: uv-common.c:81
@ UV_HANDLE_CLOSING
Definition: uv-common.h:74
@ UV_HANDLE_CLOSED
Definition: uv-common.h:75
@ UV_HANDLE_INTERNAL
Definition: uv-common.h:78
#define uv__handle_unref(h)
Definition: uv-common.h:283
#define uv__is_closing(h)
Definition: uv-common.h:255
#define uv__handle_init(loop_, h, type_)
Definition: uv-common.h:301
#define uv__handle_stop(h)
Definition: uv-common.h:266
#define uv__handle_start(h)
Definition: uv-common.h:258
UV_EXTERN int uv_is_active(const uv_handle_t *handle)
Definition: core.c:430
UV_EXTERN int uv_timer_start(uv_timer_t *handle, uv_timer_cb cb, uint64_t timeout, uint64_t repeat)
Definition: timer.c:66
UV_EXTERN int uv_timer_init(uv_loop_t *, uv_timer_t *handle)
Definition: timer.c:58
UV_EXTERN void uv_fs_req_cleanup(uv_fs_t *req)
Definition: fs.c:2070
void(* uv_fs_poll_cb)(uv_fs_poll_t *handle, int status, const uv_stat_t *prev, const uv_stat_t *curr)
Definition: uv.h:374
UV_EXTERN int uv_fs_stat(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb)
Definition: fs.c:2000
UV_EXTERN uint64_t uv_now(const uv_loop_t *)
Definition: uv-common.c:567
UV_EXTERN void uv_close(uv_handle_t *handle, uv_close_cb close_cb)
Definition: core.c:108
static const char * cb[]
Definition: z80_tab.h:176