~yolanda.robla/ubuntu/trusty/nodejs/add_distribution

« back to all changes in this revision

Viewing changes to deps/uv/src/unix/linux.c

  • Committer: Package Import Robot
  • Author(s): Jérémy Lal
  • Date: 2013-08-14 00:16:46 UTC
  • mfrom: (7.1.40 sid)
  • Revision ID: package-import@ubuntu.com-20130814001646-bzlysfh8sd6mukbo
Tags: 0.10.15~dfsg1-4
* Update 2005 patch, adding a handful of tests that can fail on
  slow platforms.
* Add 1004 patch to fix test failures when writing NaN to buffer
  on mipsel.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2
 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
3
 
 * of this software and associated documentation files (the "Software"), to
4
 
 * deal in the Software without restriction, including without limitation the
5
 
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
6
 
 * sell copies of the Software, and to permit persons to whom the Software is
7
 
 * furnished to do so, subject to the following conditions:
8
 
 *
9
 
 * The above copyright notice and this permission notice shall be included in
10
 
 * all copies or substantial portions of the Software.
11
 
 *
12
 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13
 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14
 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15
 
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16
 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
17
 
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
18
 
 * IN THE SOFTWARE.
19
 
 */
20
 
 
21
 
#include "uv.h"
22
 
#include "internal.h"
23
 
 
24
 
#include <stdint.h>
25
 
#include <stdlib.h>
26
 
#include <string.h>
27
 
#include <assert.h>
28
 
#include <errno.h>
29
 
 
30
 
#include <sys/sysinfo.h>
31
 
#include <unistd.h>
32
 
#include <fcntl.h>
33
 
#include <time.h>
34
 
 
35
 
#undef NANOSEC
36
 
#define NANOSEC 1000000000
37
 
 
38
 
#undef HAVE_INOTIFY_INIT
39
 
#undef HAVE_INOTIFY_INIT1
40
 
#undef HAVE_INOTIFY_ADD_WATCH
41
 
#undef HAVE_INOTIFY_RM_WATCH
42
 
 
43
 
#if __NR_inotify_init
44
 
# define HAVE_INOTIFY_INIT 1
45
 
#endif
46
 
#if __NR_inotify_init1
47
 
# define HAVE_INOTIFY_INIT1 1
48
 
#endif
49
 
#if __NR_inotify_add_watch
50
 
# define HAVE_INOTIFY_ADD_WATCH 1
51
 
#endif
52
 
#if __NR_inotify_rm_watch
53
 
# define HAVE_INOTIFY_RM_WATCH 1
54
 
#endif
55
 
 
56
 
#if HAVE_INOTIFY_INIT || HAVE_INOTIFY_INIT1
57
 
# undef IN_ACCESS
58
 
# undef IN_MODIFY
59
 
# undef IN_ATTRIB
60
 
# undef IN_CLOSE_WRITE
61
 
# undef IN_CLOSE_NOWRITE
62
 
# undef IN_OPEN
63
 
# undef IN_MOVED_FROM
64
 
# undef IN_MOVED_TO
65
 
# undef IN_CREATE
66
 
# undef IN_DELETE
67
 
# undef IN_DELETE_SELF
68
 
# undef IN_MOVE_SELF
69
 
# define IN_ACCESS         0x001
70
 
# define IN_MODIFY         0x002
71
 
# define IN_ATTRIB         0x004
72
 
# define IN_CLOSE_WRITE    0x008
73
 
# define IN_CLOSE_NOWRITE  0x010
74
 
# define IN_OPEN           0x020
75
 
# define IN_MOVED_FROM     0x040
76
 
# define IN_MOVED_TO       0x080
77
 
# define IN_CREATE         0x100
78
 
# define IN_DELETE         0x200
79
 
# define IN_DELETE_SELF    0x400
80
 
# define IN_MOVE_SELF      0x800
81
 
struct inotify_event {
82
 
  int32_t wd;
83
 
  uint32_t mask;
84
 
  uint32_t cookie;
85
 
  uint32_t len;
86
 
  /* char name[0]; */
87
 
};
88
 
#endif /* HAVE_INOTIFY_INIT || HAVE_INOTIFY_INIT1 */
89
 
 
90
 
#undef IN_CLOEXEC
91
 
#undef IN_NONBLOCK
92
 
 
93
 
#if HAVE_INOTIFY_INIT1
94
 
# define IN_CLOEXEC O_CLOEXEC
95
 
# define IN_NONBLOCK O_NONBLOCK
96
 
#endif /* HAVE_INOTIFY_INIT1 */
97
 
 
98
 
#if HAVE_INOTIFY_INIT
99
 
inline static int inotify_init(void) {
100
 
  return syscall(__NR_inotify_init);
101
 
}
102
 
#endif /* HAVE_INOTIFY_INIT */
103
 
 
104
 
#if HAVE_INOTIFY_INIT1
105
 
inline static int inotify_init1(int flags) {
106
 
  return syscall(__NR_inotify_init1, flags);
107
 
}
108
 
#endif /* HAVE_INOTIFY_INIT1 */
109
 
 
110
 
#if HAVE_INOTIFY_ADD_WATCH
111
 
inline static int inotify_add_watch(int fd, const char* path, uint32_t mask) {
112
 
  return syscall(__NR_inotify_add_watch, fd, path, mask);
113
 
}
114
 
#endif /* HAVE_INOTIFY_ADD_WATCH */
115
 
 
116
 
#if HAVE_INOTIFY_RM_WATCH
117
 
inline static int inotify_rm_watch(int fd, uint32_t wd) {
118
 
  return syscall(__NR_inotify_rm_watch, fd, wd);
119
 
}
120
 
#endif /* HAVE_INOTIFY_RM_WATCH */
121
 
 
122
 
 
123
 
/* Don't look aghast, this is exactly how glibc's basename() works. */
124
 
static char* basename_r(const char* path) {
125
 
  char* s = strrchr(path, '/');
126
 
  return s ? (s + 1) : (char*)path;
127
 
}
128
 
 
129
 
 
130
 
/*
131
 
 * There's probably some way to get time from Linux than gettimeofday(). What
132
 
 * it is, I don't know.
133
 
 */
134
 
uint64_t uv_hrtime() {
135
 
  struct timespec ts;
136
 
  clock_gettime(CLOCK_MONOTONIC, &ts);
137
 
  return (ts.tv_sec * NANOSEC + ts.tv_nsec);
138
 
}
139
 
 
140
 
void uv_loadavg(double avg[3]) {
141
 
  struct sysinfo info;
142
 
 
143
 
  if (sysinfo(&info) < 0) return;
144
 
 
145
 
  avg[0] = (double) info.loads[0] / 65536.0;
146
 
  avg[1] = (double) info.loads[1] / 65536.0;
147
 
  avg[2] = (double) info.loads[2] / 65536.0;
148
 
}
149
 
 
150
 
 
151
 
int uv_exepath(char* buffer, size_t* size) {
152
 
  if (!buffer || !size) {
153
 
    return -1;
154
 
  }
155
 
 
156
 
  *size = readlink("/proc/self/exe", buffer, *size - 1);
157
 
  if (*size <= 0) return -1;
158
 
  buffer[*size] = '\0';
159
 
  return 0;
160
 
}
161
 
 
162
 
uint64_t uv_get_free_memory(void) {
163
 
  return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_AVPHYS_PAGES);
164
 
}
165
 
 
166
 
uint64_t uv_get_total_memory(void) {
167
 
  return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_PHYS_PAGES);
168
 
}
169
 
 
170
 
#if HAVE_INOTIFY_INIT || HAVE_INOTIFY_INIT1
171
 
 
172
 
static int new_inotify_fd(void) {
173
 
  int fd;
174
 
 
175
 
#if HAVE_INOTIFY_INIT1
176
 
  fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
177
 
  if (fd != -1)
178
 
    return fd;
179
 
  if (errno != ENOSYS)
180
 
    return -1;
181
 
#endif
182
 
 
183
 
  if ((fd = inotify_init()) == -1)
184
 
    return -1;
185
 
 
186
 
  if (uv__cloexec(fd, 1) || uv__nonblock(fd, 1)) {
187
 
    SAVE_ERRNO(uv__close(fd));
188
 
    fd = -1;
189
 
  }
190
 
 
191
 
  return fd;
192
 
}
193
 
 
194
 
 
195
 
static void uv__inotify_read(EV_P_ ev_io* w, int revents) {
196
 
  struct inotify_event* e;
197
 
  uv_fs_event_t* handle;
198
 
  const char* filename;
199
 
  ssize_t size;
200
 
  int events;
201
 
  char *p;
202
 
  /* needs to be large enough for sizeof(inotify_event) + strlen(filename) */
203
 
  char buf[4096];
204
 
 
205
 
  handle = container_of(w, uv_fs_event_t, read_watcher);
206
 
 
207
 
  do {
208
 
    do {
209
 
      size = read(handle->fd, buf, sizeof buf);
210
 
    }
211
 
    while (size == -1 && errno == EINTR);
212
 
 
213
 
    if (size == -1) {
214
 
      assert(errno == EAGAIN || errno == EWOULDBLOCK);
215
 
      break;
216
 
    }
217
 
 
218
 
    assert(size > 0); /* pre-2.6.21 thing, size=0 == read buffer too small */
219
 
 
220
 
    /* Now we have one or more inotify_event structs. */
221
 
    for (p = buf; p < buf + size; p += sizeof(*e) + e->len) {
222
 
      e = (void*)p;
223
 
 
224
 
      events = 0;
225
 
      if (e->mask & (IN_ATTRIB|IN_MODIFY))
226
 
        events |= UV_CHANGE;
227
 
      if (e->mask & ~(IN_ATTRIB|IN_MODIFY))
228
 
        events |= UV_RENAME;
229
 
 
230
 
      /* inotify does not return the filename when monitoring a single file
231
 
       * for modifications. Repurpose the filename for API compatibility.
232
 
       * I'm not convinced this is a good thing, maybe it should go.
233
 
       */
234
 
      filename = e->len ? (const char*) (e + 1) : basename_r(handle->filename);
235
 
 
236
 
      handle->cb(handle, filename, events, 0);
237
 
 
238
 
      if (handle->fd == -1)
239
 
        break;
240
 
    }
241
 
  }
242
 
  while (handle->fd != -1); /* handle might've been closed by callback */
243
 
}
244
 
 
245
 
 
246
 
int uv_fs_event_init(uv_loop_t* loop,
247
 
                     uv_fs_event_t* handle,
248
 
                     const char* filename,
249
 
                     uv_fs_event_cb cb,
250
 
                     int flags) {
251
 
  int events;
252
 
  int fd;
253
 
 
254
 
  loop->counters.fs_event_init++;
255
 
 
256
 
  /* We don't support any flags yet. */
257
 
  assert(!flags);
258
 
 
259
 
  /*
260
 
   * TODO share a single inotify fd across the event loop?
261
 
   * We'll run into fs.inotify.max_user_instances if we
262
 
   * keep creating new inotify fds.
263
 
   */
264
 
  if ((fd = new_inotify_fd()) == -1) {
265
 
    uv__set_sys_error(loop, errno);
266
 
    return -1;
267
 
  }
268
 
 
269
 
  events = IN_ATTRIB
270
 
         | IN_CREATE
271
 
         | IN_MODIFY
272
 
         | IN_DELETE
273
 
         | IN_DELETE_SELF
274
 
         | IN_MOVE_SELF
275
 
         | IN_MOVED_FROM
276
 
         | IN_MOVED_TO;
277
 
 
278
 
  if (inotify_add_watch(fd, filename, events) == -1) {
279
 
    uv__set_sys_error(loop, errno);
280
 
    uv__close(fd);
281
 
    return -1;
282
 
  }
283
 
 
284
 
  uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT);
285
 
  handle->filename = strdup(filename); /* this should go! */
286
 
  handle->cb = cb;
287
 
  handle->fd = fd;
288
 
 
289
 
  ev_io_init(&handle->read_watcher, uv__inotify_read, fd, EV_READ);
290
 
  ev_io_start(loop->ev, &handle->read_watcher);
291
 
  ev_unref(loop->ev);
292
 
 
293
 
  return 0;
294
 
}
295
 
 
296
 
 
297
 
void uv__fs_event_destroy(uv_fs_event_t* handle) {
298
 
  ev_ref(handle->loop->ev);
299
 
  ev_io_stop(handle->loop->ev, &handle->read_watcher);
300
 
  uv__close(handle->fd);
301
 
  handle->fd = -1;
302
 
  free(handle->filename);
303
 
  handle->filename = NULL;
304
 
}
305
 
 
306
 
#else /* !HAVE_INOTIFY_INIT || HAVE_INOTIFY_INIT1 */
307
 
 
308
 
int uv_fs_event_init(uv_loop_t* loop,
309
 
                     uv_fs_event_t* handle,
310
 
                     const char* filename,
311
 
                     uv_fs_event_cb cb,
312
 
                     int flags) {
313
 
  loop->counters.fs_event_init++;
314
 
  uv__set_sys_error(loop, ENOSYS);
315
 
  return -1;
316
 
}
317
 
 
318
 
 
319
 
void uv__fs_event_destroy(uv_fs_event_t* handle) {
320
 
  assert(0 && "unreachable");
321
 
  abort();
322
 
}
323
 
 
324
 
#endif /* HAVE_INOTIFY_INIT || HAVE_INOTIFY_INIT1 */