Rizin
unix-like reverse engineering framework and cli tools
os390-syscalls.c
Go to the documentation of this file.
1 /* Copyright libuv project 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 
23 #include "os390-syscalls.h"
24 #include <errno.h>
25 #include <stdlib.h>
26 #include <search.h>
27 #include <termios.h>
28 #include <sys/msg.h>
29 
30 #define CW_INTRPT 1
31 #define CW_CONDVAR 32
32 
33 #pragma linkage(BPX4CTW, OS)
34 #pragma linkage(BPX1CTW, OS)
35 
39 
40 int scandir(const char* maindir, struct dirent*** namelist,
41  int (*filter)(const struct dirent*),
42  int (*compar)(const struct dirent**,
43  const struct dirent **)) {
44  struct dirent** nl;
45  struct dirent** nl_copy;
46  struct dirent* dirent;
47  unsigned count;
48  size_t allocated;
49  DIR* mdir;
50 
51  nl = NULL;
52  count = 0;
53  allocated = 0;
54  mdir = opendir(maindir);
55  if (!mdir)
56  return -1;
57 
58  while (1) {
59  dirent = readdir(mdir);
60  if (!dirent)
61  break;
62  if (!filter || filter(dirent)) {
63  struct dirent* copy;
64  copy = uv__malloc(sizeof(*copy));
65  if (!copy)
66  goto error;
67  memcpy(copy, dirent, sizeof(*copy));
68 
69  nl_copy = uv__realloc(nl, sizeof(*copy) * (count + 1));
70  if (nl_copy == NULL) {
71  uv__free(copy);
72  goto error;
73  }
74 
75  nl = nl_copy;
76  nl[count++] = copy;
77  }
78  }
79 
80  qsort(nl, count, sizeof(struct dirent *),
81  (int (*)(const void *, const void *)) compar);
82 
83  closedir(mdir);
84 
85  *namelist = nl;
86  return count;
87 
88 error:
89  while (count > 0) {
90  dirent = nl[--count];
92  }
93  uv__free(nl);
94  closedir(mdir);
95  errno = ENOMEM;
96  return -1;
97 }
98 
99 
100 static unsigned int next_power_of_two(unsigned int val) {
101  val -= 1;
102  val |= val >> 1;
103  val |= val >> 2;
104  val |= val >> 4;
105  val |= val >> 8;
106  val |= val >> 16;
107  val += 1;
108  return val;
109 }
110 
111 
112 static void maybe_resize(uv__os390_epoll* lst, unsigned int len) {
113  unsigned int newsize;
114  unsigned int i;
115  struct pollfd* newlst;
116  struct pollfd event;
117 
118  if (len <= lst->size)
119  return;
120 
121  if (lst->size == 0)
122  event.fd = -1;
123  else {
124  /* Extract the message queue at the end. */
125  event = lst->items[lst->size - 1];
126  lst->items[lst->size - 1].fd = -1;
127  }
128 
129  newsize = next_power_of_two(len);
130  newlst = uv__reallocf(lst->items, newsize * sizeof(lst->items[0]));
131 
132  if (newlst == NULL)
133  abort();
134  for (i = lst->size; i < newsize; ++i)
135  newlst[i].fd = -1;
136 
137  /* Restore the message queue at the end */
138  newlst[newsize - 1] = event;
139 
140  lst->items = newlst;
141  lst->size = newsize;
142 }
143 
144 
146  struct {
147  long int header;
148  char body;
149  } msg;
150 
151  /* initialize message queue */
152  lst->msg_queue = msgget(IPC_PRIVATE, 0600 | IPC_CREAT);
153  if (lst->msg_queue == -1)
154  abort();
155 
156  /*
157  On z/OS, the message queue will be affiliated with the process only
158  when a send is performed on it. Once this is done, the system
159  can be queried for all message queues belonging to our process id.
160  */
161  msg.header = 1;
162  if (msgsnd(lst->msg_queue, &msg, sizeof(msg.body), 0) != 0)
163  abort();
164 
165  /* Clean up the dummy message sent above */
166  if (msgrcv(lst->msg_queue, &msg, sizeof(msg.body), 0, 0) != sizeof(msg.body))
167  abort();
168 }
169 
170 
171 static void before_fork(void) {
173 }
174 
175 
176 static void after_fork(void) {
178 }
179 
180 
181 static void child_fork(void) {
182  QUEUE* q;
183  uv_once_t child_once = UV_ONCE_INIT;
184 
185  /* reset once */
186  memcpy(&once, &child_once, sizeof(child_once));
187 
188  /* reset epoll list */
189  while (!QUEUE_EMPTY(&global_epoll_queue)) {
190  uv__os390_epoll* lst;
192  QUEUE_REMOVE(q);
193  lst = QUEUE_DATA(q, uv__os390_epoll, member);
194  uv__free(lst->items);
195  lst->items = NULL;
196  lst->size = 0;
197  }
198 
201 }
202 
203 
204 static void epoll_init(void) {
207  abort();
208 
209  if (pthread_atfork(&before_fork, &after_fork, &child_fork))
210  abort();
211 }
212 
213 
215  uv__os390_epoll* lst;
216 
217  lst = uv__malloc(sizeof(*lst));
218  if (lst != NULL) {
219  /* initialize list */
220  lst->size = 0;
221  lst->items = NULL;
222  init_message_queue(lst);
223  maybe_resize(lst, 1);
224  lst->items[lst->size - 1].fd = lst->msg_queue;
225  lst->items[lst->size - 1].events = POLLIN;
226  lst->items[lst->size - 1].revents = 0;
231  }
232 
233  return lst;
234 }
235 
236 
238  int op,
239  int fd,
240  struct epoll_event *event) {
242 
243  if (op == EPOLL_CTL_DEL) {
244  if (fd >= lst->size || lst->items[fd].fd == -1) {
246  errno = ENOENT;
247  return -1;
248  }
249  lst->items[fd].fd = -1;
250  } else if (op == EPOLL_CTL_ADD) {
251 
252  /* Resizing to 'fd + 1' would expand the list to contain at least
253  * 'fd'. But we need to guarantee that the last index on the list
254  * is reserved for the message queue. So specify 'fd + 2' instead.
255  */
256  maybe_resize(lst, fd + 2);
257  if (lst->items[fd].fd != -1) {
259  errno = EEXIST;
260  return -1;
261  }
262  lst->items[fd].fd = fd;
263  lst->items[fd].events = event->events;
264  lst->items[fd].revents = 0;
265  } else if (op == EPOLL_CTL_MOD) {
266  if (fd >= lst->size - 1 || lst->items[fd].fd == -1) {
268  errno = ENOENT;
269  return -1;
270  }
271  lst->items[fd].events = event->events;
272  lst->items[fd].revents = 0;
273  } else
274  abort();
275 
277  return 0;
278 }
279 
280 #define EP_MAX_PFDS (ULONG_MAX / sizeof(struct pollfd))
281 #define EP_MAX_EVENTS (INT_MAX / sizeof(struct epoll_event))
282 
283 int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events,
284  int maxevents, int timeout) {
285  nmsgsfds_t size;
286  struct pollfd* pfds;
287  int pollret;
288  int reventcount;
289  int nevents;
290  struct pollfd msg_fd;
291  int i;
292 
293  if (!lst || !lst->items || !events) {
294  errno = EFAULT;
295  return -1;
296  }
297 
298  if (lst->size > EP_MAX_PFDS) {
299  errno = EINVAL;
300  return -1;
301  }
302 
303  if (maxevents <= 0 || maxevents > EP_MAX_EVENTS) {
304  errno = EINVAL;
305  return -1;
306  }
307 
308  if (lst->size > 0)
309  _SET_FDS_MSGS(size, 1, lst->size - 1);
310  else
311  _SET_FDS_MSGS(size, 0, 0);
312  pfds = lst->items;
313  pollret = poll(pfds, size, timeout);
314  if (pollret <= 0)
315  return pollret;
316 
317  assert(lst->size > 0);
318 
319  pollret = _NFDS(pollret) + _NMSGS(pollret);
320 
321  reventcount = 0;
322  nevents = 0;
323  msg_fd = pfds[lst->size - 1];
324  for (i = 0;
325  i < lst->size && i < maxevents && reventcount < pollret; ++i) {
326  struct epoll_event ev;
327  struct pollfd* pfd;
328 
329  pfd = &pfds[i];
330  if (pfd->fd == -1 || pfd->revents == 0)
331  continue;
332 
333  ev.fd = pfd->fd;
334  ev.events = pfd->revents;
335  ev.is_msg = 0;
336  if (pfd->revents & POLLIN && pfd->revents & POLLOUT)
337  reventcount += 2;
338  else if (pfd->revents & (POLLIN | POLLOUT))
339  ++reventcount;
340 
341  pfd->revents = 0;
342  events[nevents++] = ev;
343  }
344 
345  if (msg_fd.revents != 0 && msg_fd.fd != -1)
346  if (i == lst->size)
347  events[nevents - 1].is_msg = 1;
348 
349  return nevents;
350 }
351 
352 
354  QUEUE* q;
355 
359  uv__os390_epoll* lst;
360 
361  lst = QUEUE_DATA(q, uv__os390_epoll, member);
362  if (fd < lst->size && lst->items != NULL && lst->items[fd].fd != -1)
363  lst->items[fd].fd = -1;
364  }
365 
367  return 0;
368 }
369 
371  /* Remove epoll instance from global queue */
373  QUEUE_REMOVE(&lst->member);
375 
376  /* Free resources */
377  msgctl(lst->msg_queue, IPC_RMID, NULL);
378  lst->msg_queue = -1;
379  uv__free(lst->items);
380  lst->items = NULL;
381 }
382 
383 
384 int nanosleep(const struct timespec* req, struct timespec* rem) {
385  unsigned nano;
386  unsigned seconds;
387  unsigned events;
388  unsigned secrem;
389  unsigned nanorem;
390  int rv;
391  int err;
392  int rsn;
393 
394  nano = (int)req->tv_nsec;
395  seconds = req->tv_sec;
396  events = CW_CONDVAR | CW_INTRPT;
397  secrem = 0;
398  nanorem = 0;
399 
400 #if defined(_LP64)
401  BPX4CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &err, &rsn);
402 #else
403  BPX1CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &err, &rsn);
404 #endif
405 
406  /* Don't clobber errno unless BPX1CTW/BPX4CTW errored.
407  * Don't leak EAGAIN, that just means the timeout expired.
408  */
409  if (rv == -1)
410  if (err == EAGAIN)
411  rv = 0;
412  else
413  errno = err;
414 
415  if (rem != NULL && (rv == 0 || err == EINTR)) {
416  rem->tv_nsec = nanorem;
417  rem->tv_sec = secrem;
418  }
419 
420  return rv;
421 }
422 
423 
424 char* mkdtemp(char* path) {
425  static const char* tempchars =
426  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
427  static const size_t num_chars = 62;
428  static const size_t num_x = 6;
429  char *ep, *cp;
430  unsigned int tries, i;
431  size_t len;
432  uint64_t v;
433  int fd;
434  int retval;
435  int saved_errno;
436 
437  len = strlen(path);
438  ep = path + len;
439  if (len < num_x || strncmp(ep - num_x, "XXXXXX", num_x)) {
440  errno = EINVAL;
441  return NULL;
442  }
443 
444  fd = open("/dev/urandom", O_RDONLY);
445  if (fd == -1)
446  return NULL;
447 
448  tries = TMP_MAX;
449  retval = -1;
450  do {
451  if (read(fd, &v, sizeof(v)) != sizeof(v))
452  break;
453 
454  cp = ep - num_x;
455  for (i = 0; i < num_x; i++) {
456  *cp++ = tempchars[v % num_chars];
457  v /= num_chars;
458  }
459 
460  if (mkdir(path, S_IRWXU) == 0) {
461  retval = 0;
462  break;
463  }
464  else if (errno != EEXIST)
465  break;
466  } while (--tries);
467 
468  saved_errno = errno;
469  uv__close(fd);
470  if (tries == 0) {
471  errno = EEXIST;
472  return NULL;
473  }
474 
475  if (retval == -1) {
476  errno = saved_errno;
477  return NULL;
478  }
479 
480  return path;
481 }
482 
483 
484 ssize_t os390_readlink(const char* path, char* buf, size_t len) {
485  ssize_t rlen;
486  ssize_t vlen;
487  ssize_t plen;
488  char* delimiter;
489  char old_delim;
490  char* tmpbuf;
491  char realpathstr[PATH_MAX + 1];
492 
493  tmpbuf = uv__malloc(len + 1);
494  if (tmpbuf == NULL) {
495  errno = ENOMEM;
496  return -1;
497  }
498 
499  rlen = readlink(path, tmpbuf, len);
500  if (rlen < 0) {
501  uv__free(tmpbuf);
502  return rlen;
503  }
504 
505  if (rlen < 3 || strncmp("/$", tmpbuf, 2) != 0) {
506  /* Straightforward readlink. */
507  memcpy(buf, tmpbuf, rlen);
508  uv__free(tmpbuf);
509  return rlen;
510  }
511 
512  /*
513  * There is a parmlib variable at the beginning
514  * which needs interpretation.
515  */
516  tmpbuf[rlen] = '\0';
517  delimiter = strchr(tmpbuf + 2, '/');
518  if (delimiter == NULL)
519  /* No slash at the end */
520  delimiter = strchr(tmpbuf + 2, '\0');
521 
522  /* Read real path of the variable. */
523  old_delim = *delimiter;
524  *delimiter = '\0';
525  if (realpath(tmpbuf, realpathstr) == NULL) {
526  uv__free(tmpbuf);
527  return -1;
528  }
529 
530  /* realpathstr is not guaranteed to end with null byte.*/
531  realpathstr[PATH_MAX] = '\0';
532 
533  /* Reset the delimiter and fill up the buffer. */
534  *delimiter = old_delim;
535  plen = strlen(delimiter);
536  vlen = strlen(realpathstr);
537  rlen = plen + vlen;
538  if (rlen > len) {
539  uv__free(tmpbuf);
540  errno = ENAMETOOLONG;
541  return -1;
542  }
543  memcpy(buf, realpathstr, vlen);
544  memcpy(buf + vlen, delimiter, plen);
545 
546  /* Done using temporary buffer. */
547  uv__free(tmpbuf);
548 
549  return rlen;
550 }
551 
552 
553 size_t strnlen(const char* str, size_t maxlen) {
554  char* p = memchr(str, 0, maxlen);
555  if (p == NULL)
556  return maxlen;
557  else
558  return p - str;
559 }
560 
561 
562 int sem_init(UV_PLATFORM_SEM_T* semid, int pshared, unsigned int value) {
563  UNREACHABLE();
564 }
565 
566 
568  UNREACHABLE();
569 }
570 
571 
573  UNREACHABLE();
574 }
575 
576 
578  UNREACHABLE();
579 }
580 
581 
583  UNREACHABLE();
584 }
size_t len
Definition: 6502dis.c:15
lzma_index ** i
Definition: index.h:629
ut16 val
Definition: armass64_const.h:6
static bool err
Definition: armass.c:435
static int value
Definition: cmd_api.c:93
#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 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 count
Definition: sflib.h:98
static static sync static getppid static getegid const char static filename char static len readlink
Definition: sflib.h:65
const char * v
Definition: dsignal.c:12
voidpf void uLong size
Definition: ioapi.h:138
voidpf void * buf
Definition: ioapi.h:138
void * p
Definition: libc.cpp:67
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig mkdir
Definition: sflib.h:66
static const char struct stat static buf struct stat static buf static vhangup int struct rusage static rusage struct sysinfo static info unsigned static __unused struct utsname static buf const char static size const char static name static pid unsigned static persona static fsgid const void static flags const struct iovec static count static fd const void static len static munlockall struct sched_param static p static sched_yield static policy const struct timespec struct timespec static rem uid_t uid_t uid_t static suid poll
Definition: sflib.h:196
static static fork const void static count static fd const char static mode const char static pathname const char static path const char static dev const char static group static getpid static getuid void void static data static pause const char static mode static sync const char const char static newpath const char static pathname unsigned long static filedes void static end_data_segment static handler static getegid char static len static pgid const char static path static newfd static getpgrp static euid const sigset_t static mask const char static len const gid_t static list const char const char static newpath const char static library readdir
Definition: sflib.h:120
static void struct sockaddr socklen_t static fromlen static backlog static fork char char char static envp int struct rusage static rusage struct utsname static buf semid
Definition: sflib.h:97
#define header(is_bt, len_min, ret_op)
assert(limit<=UINT32_MAX/2)
int sem_wait(UV_PLATFORM_SEM_T *semid)
int nanosleep(const struct timespec *req, struct timespec *rem)
int sem_destroy(UV_PLATFORM_SEM_T *semid)
void epoll_queue_close(uv__os390_epoll *lst)
static QUEUE global_epoll_queue
static void init_message_queue(uv__os390_epoll *lst)
static void maybe_resize(uv__os390_epoll *lst, unsigned int len)
#define CW_INTRPT
int sem_trywait(UV_PLATFORM_SEM_T *semid)
#define EP_MAX_PFDS
int sem_post(UV_PLATFORM_SEM_T *semid)
ssize_t os390_readlink(const char *path, char *buf, size_t len)
static void child_fork(void)
static unsigned int next_power_of_two(unsigned int val)
int epoll_file_close(int fd)
int scandir(const char *maindir, struct dirent ***namelist, int(*filter)(const struct dirent *), int(*compar)(const struct dirent **, const struct dirent **))
static uv_once_t once
static void epoll_init(void)
int sem_init(UV_PLATFORM_SEM_T *semid, int pshared, unsigned int value)
int epoll_wait(uv__os390_epoll *lst, struct epoll_event *events, int maxevents, int timeout)
int epoll_ctl(uv__os390_epoll *lst, int op, int fd, struct epoll_event *event)
#define CW_CONDVAR
static void after_fork(void)
size_t strnlen(const char *str, size_t maxlen)
static void before_fork(void)
uv__os390_epoll * epoll_create1(int flags)
static uv_mutex_t global_epoll_lock
char * mkdtemp(char *path)
#define EP_MAX_EVENTS
#define EPOLL_CTL_ADD
#define EPOLL_CTL_MOD
#define EPOLL_CTL_DEL
#define UV_PLATFORM_SEM_T
Definition: os390.h:25
static bool filter(RzParse *p, ut64 addr, RzFlag *f, RzAnalysisHint *hint, char *data, char *str, int len, bool big_endian)
Definition: filter.c:185
void qsort(void *a, size_t n, size_t es, int(*cmp)(const void *, const void *))
Definition: qsort.h:130
#define QUEUE_FOREACH(q, h)
Definition: queue.h:36
#define QUEUE_DATA(ptr, type, field)
Definition: queue.h:30
#define QUEUE_EMPTY(q)
Definition: queue.h:39
#define QUEUE_HEAD(q)
Definition: queue.h:42
#define QUEUE_INSERT_TAIL(h, q)
Definition: queue.h:92
#define QUEUE_INIT(q)
Definition: queue.h:45
void * QUEUE[2]
Definition: queue.h:21
#define QUEUE_REMOVE(q)
Definition: queue.h:101
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
static int
Definition: sfsocketcall.h:114
static struct sockaddr static addrlen static backlog const void msg
Definition: sfsocketcall.h:119
#define ENOENT
Definition: sftypes.h:112
#define EEXIST
Definition: sftypes.h:127
#define EINVAL
Definition: sftypes.h:132
#define EFAULT
Definition: sftypes.h:124
#define EINTR
Definition: sftypes.h:114
#define ENOMEM
Definition: sftypes.h:122
#define O_RDONLY
Definition: sftypes.h:486
unsigned long uint64_t
Definition: sftypes.h:28
#define EAGAIN
Definition: sftypes.h:121
int ssize_t
Definition: sftypes.h:39
Definition: sftypes.h:48
Definition: sftypes.h:75
long tv_nsec
Definition: sftypes.h:90
time_t tv_sec
Definition: sftypes.h:89
struct pollfd * items
unsigned long size
uv_timer_t timeout
Definition: main.c:9
int uv__close(int fd)
Definition: core.c:569
#define UNREACHABLE()
Definition: internal.h:85
ut64 maxlen
Definition: core.c:76
Definition: dis.c:32
pthread_mutex_t uv_mutex_t
Definition: unix.h:137
pthread_once_t uv_once_t
Definition: unix.h:135
#define UV_ONCE_INIT
Definition: unix.h:133
void error(const char *msg)
Definition: untgz.c:593
void * uv__reallocf(void *ptr, size_t size)
Definition: uv-common.c:103
void * uv__realloc(void *ptr, size_t size)
Definition: uv-common.c:96
void * uv__malloc(size_t size)
Definition: uv-common.c:75
void uv__free(void *ptr)
Definition: uv-common.c:81
UV_EXTERN void uv_mutex_lock(uv_mutex_t *handle)
Definition: thread.c:330
UV_EXTERN void uv_once(uv_once_t *guard, void(*callback)(void))
Definition: thread.c:419
UV_EXTERN void uv_mutex_destroy(uv_mutex_t *handle)
Definition: thread.c:324
UV_EXTERN void uv_mutex_unlock(uv_mutex_t *handle)
Definition: thread.c:350
UV_EXTERN int uv_mutex_init(uv_mutex_t *handle)
Definition: thread.c:282
static const z80_opcode fd[]
Definition: z80_tab.h:997
int read(izstream &zs, T *x, Items items)
Definition: zstream.h:115