static void dl_iterate_phdr_setup(void) { const AuxInfo *aux; _DIAGASSERT(_dlauxinfo() != NULL); for (aux = _dlauxinfo(); aux->a_type != AT_NULL; ++aux) { switch (aux->a_type) { case AT_BASE: dlpi_addr = aux->a_v; break; case AT_PHDR: dlpi_phdr = (void *)aux->a_v; break; case AT_PHNUM: _DIAGASSERT(__type_fit(Elf_Half, aux->a_v)); dlpi_phnum = (Elf_Half)aux->a_v; break; case AT_SUN_EXECNAME: dlpi_name = (void *)aux->a_v; break; } } }
static bool_t /* knows nothing about records! Only about input buffers */ get_input_bytes(RECSTREAM *rstrm, char *addr, u_int len) { u_int current; if (rstrm->nonblock) { if (len > ((uintptr_t)rstrm->in_boundry - (uintptr_t)rstrm->in_finger)) return FALSE; memcpy(addr, rstrm->in_finger, len); rstrm->in_finger += len; return TRUE; } while (len > 0) { uintptr_t d = ((uintptr_t)rstrm->in_boundry - (uintptr_t)rstrm->in_finger); _DIAGASSERT(__type_fit(u_int, d)); current = (u_int)d; if (current == 0) { if (! fill_input_buf(rstrm)) return (FALSE); continue; } current = (len < current) ? len : current; memmove(addr, rstrm->in_finger, current); rstrm->in_finger += current; addr += current; len -= current; } return (TRUE); }
static bool_t xdrrec_putbytes(XDR *xdrs, const char *addr, u_int len) { RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); size_t current; while (len > 0) { current = (size_t)((u_long)rstrm->out_boundry - (u_long)rstrm->out_finger); current = (len < current) ? len : current; memmove(rstrm->out_finger, addr, current); rstrm->out_finger += current; addr += current; _DIAGASSERT(__type_fit(u_int, current)); len -= (u_int)current; if (rstrm->out_finger == rstrm->out_boundry) { rstrm->frag_sent = TRUE; if (! flush_out(rstrm, FALSE)) return (FALSE); } } return (TRUE); }
/* * Converts the number given in 'str', which may be given in a humanized * form (as described in humanize_number(3), but with some limitations), * to an int64_t without units. * In case of success, 0 is returned and *size holds the value. * Otherwise, -1 is returned and *size is untouched. * * TODO: Internationalization, SI units. */ int dehumanize_number(const char *str, int64_t *size) { char *ep, unit; const char *delimit; long multiplier; long long tmp, tmp2; size_t len; len = strlen(str); if (len == 0) { errno = EINVAL; return -1; } multiplier = 1; unit = str[len - 1]; if (isalpha((unsigned char)unit)) { switch (tolower((unsigned char)unit)) { case 'b': multiplier = 1; break; case 'k': multiplier = 1024; break; case 'm': multiplier = 1024 * 1024; break; case 'g': multiplier = 1024 * 1024 * 1024; break; default: errno = EINVAL; return -1; /* Invalid suffix. */ } delimit = &str[len - 1]; } else delimit = NULL; errno = 0; tmp = strtoll(str, &ep, 10); if (str[0] == '\0' || (ep != delimit && *ep != '\0')) return -1; /* Not a number. */ else if (errno == ERANGE && (tmp == LLONG_MAX || tmp == LLONG_MIN)) return -1; /* Out of range. */ tmp2 = tmp * multiplier; tmp2 = tmp2 / multiplier; if (tmp != tmp2) { errno = ERANGE; return -1; /* Out of range. */ } tmp *= multiplier; _DIAGASSERT(__type_fit(int64_t, tmp)); *size = (int64_t)tmp; return 0; }
SVCXPRT * svc_dg_create(int fd, u_int sendsize, u_int recvsize) { SVCXPRT *xprt; struct svc_dg_data *su = NULL; struct __rpc_sockinfo si; struct sockaddr_storage ss; socklen_t slen; if (!__rpc_fd2sockinfo(fd, &si)) { warnx(svc_dg_str, svc_dg_err1); return (NULL); } /* * Find the receive and the send size */ sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize); recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize); if ((sendsize == 0) || (recvsize == 0)) { warnx(svc_dg_str, svc_dg_err2); return (NULL); } xprt = mem_alloc(sizeof (SVCXPRT)); if (xprt == NULL) goto freedata; memset(xprt, 0, sizeof (SVCXPRT)); su = mem_alloc(sizeof (*su)); if (su == NULL) goto freedata; su->su_iosz = ((MAX(sendsize, recvsize) + 3) / 4) * 4; if ((rpc_buffer(xprt) = malloc(su->su_iosz)) == NULL) goto freedata; _DIAGASSERT(__type_fit(u_int, su->su_iosz)); xdrmem_create(&(su->su_xdrs), rpc_buffer(xprt), (u_int)su->su_iosz, XDR_DECODE); su->su_cache = NULL; xprt->xp_fd = fd; xprt->xp_p2 = (caddr_t)(void *)su; xprt->xp_verf.oa_base = su->su_verfbody; svc_dg_ops(xprt); xprt->xp_rtaddr.maxlen = sizeof (struct sockaddr_storage); slen = sizeof ss; if (getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) goto freedata; xprt->xp_ltaddr.buf = mem_alloc(sizeof (struct sockaddr_storage)); xprt->xp_ltaddr.maxlen = sizeof (struct sockaddr_storage); xprt->xp_ltaddr.len = slen; memcpy(xprt->xp_ltaddr.buf, &ss, slen); xprt_register(xprt); return (xprt); freedata: (void) warnx(svc_dg_str, __no_mem_str); if (xprt) { if (su) (void) mem_free(su, sizeof (*su)); (void) mem_free(xprt, sizeof (SVCXPRT)); } return (NULL); }
/* * verifies that the head of the tree in the kernel is the same as the * head of the tree we already got, integrating new stuff and removing * old stuff, if it's not. */ static void relearnhead(void) { struct sysctlnode *h, *i, *o, qnode; size_t si, so; int rc, name; size_t nlen, olen, ni, oi; uint32_t t; /* * if there's nothing there, there's no need to expend any * effort */ if (sysctl_mibroot.sysctl_child == NULL) return; /* * attempt to pull out the head of the tree, starting with the * size we have now, and looping if we need more (or less) * space */ si = 0; so = sysctl_mibroot.sysctl_clen * sizeof(struct sysctlnode); name = CTL_QUERY; memset(&qnode, 0, sizeof(qnode)); qnode.sysctl_flags = SYSCTL_VERSION; do { si = so; h = malloc(si); rc = sysctl(&name, 1, h, &so, &qnode, sizeof(qnode)); if (rc == -1 && errno != ENOMEM) return; if (si < so) free(h); } while (si < so); /* * order the new copy of the head */ nlen = so / sizeof(struct sysctlnode); qsort(h, nlen, sizeof(struct sysctlnode), compar); /* * verify that everything is the same. if it is, we don't * need to do any more work here. */ olen = sysctl_mibroot.sysctl_clen; rc = (nlen == olen) ? 0 : 1; o = sysctl_mibroot.sysctl_child; for (ni = 0; rc == 0 && ni < nlen; ni++) { if (h[ni].sysctl_num != o[ni].sysctl_num || h[ni].sysctl_ver != o[ni].sysctl_ver) rc = 1; } if (rc == 0) { free(h); return; } /* * something changed. h will become the new head, and we need * pull over any subtrees we already have if they're the same * version. */ i = h; ni = oi = 0; while (ni < nlen && oi < olen) { /* * something was inserted or deleted */ if (SYSCTL_TYPE(i[ni].sysctl_flags) == CTLTYPE_NODE) i[ni].sysctl_child = NULL; if (i[ni].sysctl_num != o[oi].sysctl_num) { if (i[ni].sysctl_num < o[oi].sysctl_num) { ni++; } else { free_children(&o[oi]); oi++; } continue; } /* * same number, but different version, so throw away * any accumulated children */ if (i[ni].sysctl_ver != o[oi].sysctl_ver) free_children(&o[oi]); /* * this node is the same, but we only need to * move subtrees. */ else if (SYSCTL_TYPE(i[ni].sysctl_flags) == CTLTYPE_NODE) { /* * move subtree to new parent */ i[ni].sysctl_clen = o[oi].sysctl_clen; i[ni].sysctl_csize = o[oi].sysctl_csize; i[ni].sysctl_child = o[oi].sysctl_child; /* * reparent inherited subtree */ for (t = 0; i[ni].sysctl_child != NULL && t < i[ni].sysctl_clen; t++) i[ni].sysctl_child[t].sysctl_parent = &i[ni]; } ni++; oi++; } /* * left over new nodes need to have empty subtrees cleared */ while (ni < nlen) { if (SYSCTL_TYPE(i[ni].sysctl_flags) == CTLTYPE_NODE) i[ni].sysctl_child = NULL; ni++; } /* * left over old nodes need to be cleaned out */ while (oi < olen) { free_children(&o[oi]); oi++; } /* * pop new head in */ _DIAGASSERT(__type_fit(uint32_t, nlen)); sysctl_mibroot.sysctl_csize = sysctl_mibroot.sysctl_clen = (uint32_t)nlen; sysctl_mibroot.sysctl_child = h; free(o); }