void test_list_compare(void) { pn_list_t *a = pn_list(PN_OBJECT, 0); pn_list_t *b = pn_list(PN_OBJECT, 0); assert(pn_equals(a, b)); void *one = pn_class_new(PN_OBJECT, 0); void *two = pn_class_new(PN_OBJECT, 0); void *three = pn_class_new(PN_OBJECT, 0); pn_list_add(a, one); assert(!pn_equals(a, b)); pn_list_add(b, one); assert(pn_equals(a, b)); pn_list_add(b, two); assert(!pn_equals(a, b)); pn_list_add(a, two); assert(pn_equals(a, b)); pn_list_add(a, three); assert(!pn_equals(a, b)); pn_list_add(b, three); assert(pn_equals(a, b)); pn_free(a); pn_free(b); pn_free(one); pn_free(two); pn_free(three); }
void test_list_inspect(void) { pn_list_t *l = build_list(0, END); test_inspect(l, "[]"); pn_free(l); l = build_list(0, pn_string("one"), END); test_inspect(l, "[\"one\"]"); pn_free(l); l = build_list(0, pn_string("one"), pn_string("two"), END); test_inspect(l, "[\"one\", \"two\"]"); pn_free(l); l = build_list(0, pn_string("one"), pn_string("two"), pn_string("three"), END); test_inspect(l, "[\"one\", \"two\", \"three\"]"); pn_free(l); }
static void test_build_map_odd(void) { pn_map_t *m = build_map(0, 0.75, pn_string("key"), pn_string("value"), pn_string("key2"), pn_string("value2"), pn_string("key3"), END); assert(pn_map_size(m) == 3); pn_string_t *key = pn_string(NULL); pn_string_set(key, "key"); assert(pn_strequals(pn_string_get((pn_string_t *) pn_map_get(m, key)), "value")); pn_string_set(key, "key2"); assert(pn_strequals(pn_string_get((pn_string_t *) pn_map_get(m, key)), "value2")); pn_string_set(key, "key3"); assert(pn_map_get(m, key) == NULL); pn_free(m); pn_free(key); }
static void test_map_links(void) { const pn_class_t collider_clazz = PN_CLASS(collider); void *keys[3]; for (int i = 0; i < 3; i++) keys[i] = pn_class_new(&collider_clazz, 0); // test deleting a head, middle link, tail for (int delete_idx=0; delete_idx < 3; delete_idx++) { pn_map_t *map = pn_map(PN_WEAKREF, PN_WEAKREF, 0, 0.75); // create a chain of entries that have same head (from identical key hashcode) for (int i = 0; i < 3; i++) { pn_map_put(map, keys[i], keys[i]); } pn_map_del(map, keys[delete_idx]); for (int i = 0; i < 3; i++) { void *value = (i == delete_idx) ? NULL : keys[i]; assert (pn_map_get(map, keys[i]) == value); } pn_free(map); } for (int i = 0; i < 3; i++) pn_free(keys[i]); }
vnode_t * smb_lookuppathvptovp(smb_request_t *sr, char *path, vnode_t *startvp, vnode_t *rootvp) { pathname_t pn; vnode_t *vp = NULL; int lookup_flags = FOLLOW; if (SMB_TREE_IS_CASEINSENSITIVE(sr)) lookup_flags |= FIGNORECASE; (void) pn_alloc(&pn); if (pn_set(&pn, path) == 0) { VN_HOLD(startvp); if (rootvp != rootdir) VN_HOLD(rootvp); /* lookuppnvp should release the holds */ if (lookuppnvp(&pn, NULL, lookup_flags, NULL, &vp, rootvp, startvp, kcred) != 0) { pn_free(&pn); return (NULL); } } pn_free(&pn); return (vp); }
static void test_compare(void) { static pn_class_t clazz = PN_CLASS(compare); void *a = pn_class_new(&clazz, 0); assert(a); void *b = pn_class_new(&clazz, 0); assert(b); assert(pn_compare(a, b)); assert(!pn_equals(a, b)); assert(!pn_compare(a, a)); assert(pn_equals(a, a)); assert(!pn_compare(b, b)); assert(pn_equals(b, b)); assert(pn_compare(a, b) == (intptr_t) ((uintptr_t) b - (uintptr_t) a)); assert(pn_compare(NULL, b)); assert(!pn_equals(NULL, b)); assert(pn_compare(a, NULL)); assert(!pn_equals(a, NULL)); assert(!pn_compare(NULL, NULL)); assert(pn_equals(NULL, NULL)); pn_free(a); pn_free(b); }
static void complete_connect(connect_result_t *result, HRESULT status) { iocpdesc_t *iocpd = result->base.iocpd; if (iocpd->closing) { pn_free(result); reap_check(iocpd); return; } if (status) { iocpdesc_fail(iocpd, status, "Connect failure"); // Posix sets selectable events as follows: pni_events_update(iocpd, PN_READABLE | PN_EXPIRED); } else { release_sys_sendbuf(iocpd->socket); if (setsockopt(iocpd->socket, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0)) { iocpdesc_fail(iocpd, WSAGetLastError(), "Internal connect failure (update context)"); } else { pni_events_update(iocpd, PN_WRITABLE); start_reading(iocpd); } } pn_free(result); return; }
void test_map_inspect(void) { // note that when there is more than one entry in a map, the order // of the entries is dependent on the hashes involved, it will be // deterministic though pn_map_t *m = build_map(0, 0.75, END); test_inspect(m, "{}"); pn_free(m); m = build_map(0, 0.75, pn_string("key"), pn_string("value"), END); test_inspect(m, "{\"key\": \"value\"}"); pn_free(m); m = build_map(0, 0.75, pn_string("k1"), pn_string("v1"), pn_string("k2"), pn_string("v2"), END); test_inspect(m, "{\"k1\": \"v1\", \"k2\": \"v2\"}"); pn_free(m); m = build_map(0, 0.75, pn_string("k1"), pn_string("v1"), pn_string("k2"), pn_string("v2"), pn_string("k3"), pn_string("v3"), END); test_inspect(m, "{\"k3\": \"v3\", \"k1\": \"v1\", \"k2\": \"v2\"}"); pn_free(m); }
/* * given an absolute pathname, convert it, if possible, to a devfs * name. Examples: * /dev/rsd3a to /pci@1f,4000/glm@3/sd@0,0:a * /dev/dsk/c0t0d0s0 to /pci@1f,4000/glm@3/sd@0,0:a * /devices/pci@1f,4000/glm@3/sd@0,0:a to /pci@1f,4000/glm@3/sd@0,0:a * /pci@1f,4000/glm@3/sd@0,0:a unchanged * * This routine deals with symbolic links, physical pathname with and * without /devices stripped. Returns 0 on success or -1 on failure. */ static int resolve_devfs_name(char *name, char *buffer) { int error; char *fullname = NULL; struct pathname pn, rpn; /* if not a /dev or /device name, prepend /devices */ if (strncmp(name, "/dev/", 5) != 0 && strncmp(name, "/devices/", 9) != 0) { fullname = kmem_alloc(MAXPATHLEN, KM_SLEEP); (void) snprintf(fullname, MAXPATHLEN, "/devices%s", name); name = fullname; } if (pn_get(name, UIO_SYSSPACE, &pn) != 0) { if (fullname) kmem_free(fullname, MAXPATHLEN); return (-1); } pn_alloc(&rpn); error = lookuppn(&pn, &rpn, FOLLOW, NULL, NULL); if (error == 0) bcopy(rpn.pn_path, buffer, rpn.pn_pathlen); pn_free(&pn); pn_free(&rpn); if (fullname) kmem_free(fullname, MAXPATHLEN); return (error); }
void pn_selector_finalize(void *obj) { pn_selector_t *selector = (pn_selector_t *) obj; pn_free(selector->selectables); pn_free(selector->iocp_descriptors); pn_error_free(selector->error); selector->iocp->selector = NULL; }
void pn_subscription_finalize(void *obj) { pn_subscription_t *sub = (pn_subscription_t *) obj; pn_free(sub->scheme); pn_free(sub->host); pn_free(sub->port); pn_free(sub->address); }
void sender_cleanup(pn_handler_t *h) { sender_context_t *sc = sender_context(h); pn_message_free(sc->message); pn_message_free(sc->reply_message); pn_url_free(sc->send_url); pn_free(sc->hostname); pn_free(sc->container_id); free(sc->encoded_data); }
/* * Given a global path (from rootdir), and a vnode that is the current root, * return the portion of the path that is beneath the current root or NULL on * failure. The path MUST be a resolved path (no '..' entries or symlinks), * otherwise this function will fail. */ static char * localpath(char *path, struct vnode *vrootp, cred_t *cr) { vnode_t *vp; vnode_t *cvp; char component[MAXNAMELEN]; char *ret = NULL; pathname_t pn; /* * We use vn_compare() instead of VN_CMP() in order to detect lofs * mounts and stacked vnodes. */ if (vn_compare(vrootp, rootdir)) return (path); if (pn_get(path, UIO_SYSSPACE, &pn) != 0) return (NULL); vp = rootdir; VN_HOLD(vp); if (vn_ismntpt(vp) && traverse(&vp) != 0) { VN_RELE(vp); pn_free(&pn); return (NULL); } while (pn_pathleft(&pn)) { pn_skipslash(&pn); if (pn_getcomponent(&pn, component) != 0) break; if (VOP_LOOKUP(vp, component, &cvp, &pn, 0, rootdir, cr, NULL, NULL, NULL) != 0) break; VN_RELE(vp); vp = cvp; if (vn_ismntpt(vp) && traverse(&vp) != 0) break; if (vn_compare(vp, vrootp)) { ret = path + (pn.pn_path - pn.pn_buf); break; } } VN_RELE(vp); pn_free(&pn); return (ret); }
static void pni_iocpdesc_finalize(void *object) { iocpdesc_t *iocpd = (iocpdesc_t *) object; pn_free(iocpd->acceptor); pn_error_free(iocpd->error); if (iocpd->pipeline) if (write_in_progress(iocpd)) iocp_log("iocp descriptor write leak\n"); else pn_free(iocpd->pipeline); if (iocpd->read_in_progress) iocp_log("iocp descriptor read leak\n"); else free(iocpd->read_result); }
void pn_io_finalize(void *obj) { pn_io_t *io = (pn_io_t *) obj; pn_error_free(io->error); pn_free(io->iocp); WSACleanup(); }
/* * Lookup the user file name, * Handle allocation and freeing of pathname buffer, return error. */ int lookupnameatcred( char *fnamep, /* user pathname */ enum uio_seg seg, /* addr space that name is in */ int followlink, /* follow sym links */ vnode_t **dirvpp, /* ret for ptr to parent dir vnode */ vnode_t **compvpp, /* ret for ptr to component vnode */ vnode_t *startvp, /* start path search from vp */ cred_t *cr) /* credential */ { char namebuf[TYPICALMAXPATHLEN]; struct pathname lookpn; int error; error = pn_get_buf(fnamep, seg, &lookpn, namebuf, sizeof (namebuf)); if (error == 0) { error = lookuppnatcred(&lookpn, NULL, followlink, dirvpp, compvpp, startvp, cr); } if (error == ENAMETOOLONG) { /* * This thread used a pathname > TYPICALMAXPATHLEN bytes long. */ if (error = pn_get(fnamep, seg, &lookpn)) return (error); error = lookuppnatcred(&lookpn, NULL, followlink, dirvpp, compvpp, startvp, cr); pn_free(&lookpn); } return (error); }
void sender_context_init(sender_context_t *sc, Options_t *opts, Statistics_t *stats) { sc->opts = opts; sc->stats = stats; sc->sent = 0; sc->received = 0; sc->id.type = PN_ULONG; sc->reply_message = 0; // 4096 extra bytes should easily cover the message metadata sc->encoded_data_size = sc->opts->msg_size + 4096; sc->encoded_data = (char *)calloc(1, sc->encoded_data_size); check(sc->encoded_data, "failed to allocate encoding buffer"); sc->container_id = pn_string("reactor-send"); // prefer uuid-like name sc->reply_message = (sc->opts->get_replies) ? pn_message() : 0; sc->message = pn_message(); check(sc->message, "failed to allocate a message"); pn_string_t *rpto = pn_string("amqp://"); pn_string_addf(rpto, "%s", pn_string_get(sc->container_id)); pn_message_set_reply_to(sc->message, pn_string_get(rpto)); pn_free(rpto); pn_data_t *body = pn_message_body(sc->message); // borrow the encoding buffer this one time char *data = sc->encoded_data; pn_data_put_binary(body, pn_bytes(sc->opts->msg_size, data)); check(sc->opts->targets.count > 0, "no specified address"); sc->send_url = pn_url_parse(sc->opts->targets.addresses[0]); const char *host = pn_url_get_host(sc->send_url); const char *port = pn_url_get_port(sc->send_url); sc->hostname = pn_string(host); if (port && strlen(port)) pn_string_addf(sc->hostname, ":%s", port); }
void test_inspect(void *o, const char *expected) { pn_string_t *dst = pn_string(NULL); pn_inspect(o, dst); assert(pn_strequals(pn_string_get(dst), expected)); pn_free(dst); }
static void smb_tree_acl_access(cred_t *cred, const char *sharename, vnode_t *pathvp, uint32_t *access) { int rc; vfs_t *vfsp; vnode_t *root = NULL; vnode_t *sharevp = NULL; char *sharepath; struct pathname pnp; size_t size; *access = ACE_ALL_PERMS; /* default to full "UNIX" access */ /* * Using the vnode of the share path, we then find the root * directory of the mounted file system. We will then look to * see if there is a .zfs/shares directory and if there is, * get the access information from the ACL/ACES values and * check against the cred. */ vfsp = pathvp->v_vfsp; if (vfsp != NULL) rc = VFS_ROOT(vfsp, &root); else rc = ENOENT; if (rc != 0) return; /* * Find the share object, if there is one. Need to construct * the path to the .zfs/shares/<sharename> object and look it * up. root is called held but will be released by * lookuppnvp(). */ size = sizeof (SHARES_DIR) + strlen(sharename) + 1; sharepath = kmem_alloc(size, KM_SLEEP); (void) sprintf(sharepath, "%s%s", SHARES_DIR, sharename); pn_alloc(&pnp); (void) pn_set(&pnp, sharepath); rc = lookuppnvp(&pnp, NULL, NO_FOLLOW, NULL, &sharevp, rootdir, root, kcred); pn_free(&pnp); kmem_free(sharepath, size); /* * Now get the effective access value based on cred and ACL * values. */ if (rc == 0) { smb_vop_eaccess(sharevp, (int *)access, V_ACE_MASK, NULL, cred); VN_RELE(sharevp); } }
static int is_nonempty_dir(char *name, char *pathleft, struct sdev_node *dir) { struct match_arg marg; struct pathname pn; struct vnode *gvp; struct sdev_node *gdir = dir->sdev_origin; if (VOP_LOOKUP(SDEVTOV(gdir), name, &gvp, NULL, 0, NULL, kcred, NULL, NULL, NULL) != 0) return (0); if (gvp->v_type != VDIR) { VN_RELE(gvp); return (0); } if (pn_get(pathleft, UIO_SYSSPACE, &pn) != 0) { VN_RELE(gvp); return (0); } marg.expr = kmem_alloc(MAXNAMELEN, KM_SLEEP); (void) pn_getcomponent(&pn, marg.expr); marg.match = 0; walk_dir(gvp, &marg, match_name); VN_RELE(gvp); kmem_free(marg.expr, MAXNAMELEN); pn_free(&pn); return (marg.match); }
void listener_cleanup(pn_handler_t *h) { global_context_t *gc = global_context(h); pn_message_free(gc->message); free(gc->encoded_data); pn_free(gc->active_connections); }
/* * Callback supporting lookup in a GFS XATTR directory. */ static int xattr_lookup_cb(vnode_t *vp, const char *nm, vnode_t **vpp, ino64_t *inop, cred_t *cr, int flags, int *deflags, pathname_t *rpnp) { vnode_t *pvp; struct pathname pn; int error; *vpp = NULL; *inop = 0; error = xattr_dir_realdir(vp, &pvp, LOOKUP_XATTR, cr, NULL); /* * Return ENOENT for EACCES requests during lookup. Once an * attribute create is attempted EACCES will be returned. */ if (error) { if (error == EACCES) return (ENOENT); return (error); } error = pn_get((char *)nm, UIO_SYSSPACE, &pn); if (error == 0) { error = VOP_LOOKUP(pvp, (char *)nm, vpp, &pn, flags, rootvp, cr, NULL, deflags, rpnp); pn_free(&pn); } return (error); }
/* * readdir_xattr_casecmp: given a system attribute name, see if there * is a real xattr with the same normalized name. */ static int readdir_xattr_casecmp(vnode_t *dvp, char *nm, cred_t *cr, caller_context_t *ct, int *eflags) { int error; vnode_t *vp; struct pathname pn; *eflags = 0; error = pn_get(nm, UIO_SYSSPACE, &pn); if (error == 0) { error = VOP_LOOKUP(dvp, nm, &vp, &pn, FIGNORECASE, rootvp, cr, ct, NULL, NULL); if (error == 0) { *eflags = ED_CASE_CONFLICT; VN_RELE(vp); } else if (error == ENOENT) { error = 0; } pn_free(&pn); } return (error); }
static void pni_acceptor_finalize(void *object) { pni_acceptor_t *acceptor = (pni_acceptor_t *) object; size_t len = pn_list_size(acceptor->accepts); for (size_t i = 0; i < len; i++) free(pn_list_get(acceptor->accepts, i)); pn_free(acceptor->accepts); }
static void test_stringn(const char *value, size_t size) { pn_string_t *strn = pn_stringn(value, size); assert(equals(pn_string_get(strn), value)); assert(pn_string_size(strn) == size); pn_string_t *strsetn = pn_string(NULL); pn_string_setn(strsetn, value, size); assert(equals(pn_string_get(strsetn), value)); assert(pn_string_size(strsetn) == size); assert(pn_hashcode(strn) == pn_hashcode(strsetn)); assert(!pn_compare(strn, strsetn)); pn_free(strn); pn_free(strsetn); }
static void test_hashcode(void) { static pn_class_t clazz = PN_CLASS(hashcode); void *obj = pn_class_new(&clazz, 0); assert(obj); assert(pn_hashcode(obj) == (uintptr_t) obj); assert(pn_hashcode(NULL) == 0); pn_free(obj); }
static void test_string_addf(void) { pn_string_t *str = pn_string("hello "); assert(str); int err = pn_string_addf(str, "%s", "this is a string that should be long " "enough to force growth but just in case we'll " "tack this other really long string on for the " "heck of it"); assert(err == 0); pn_free(str); }
/* * Pull a path name from user or kernel space. */ int pn_get(char *str, enum uio_seg seg, struct pathname *pnp) { int error; void *buf; buf = kmem_alloc(MAXPATHLEN, KM_SLEEP); if ((error = pn_get_buf(str, seg, pnp, buf, MAXPATHLEN)) != 0) pn_free(pnp); return (error); }
/* * Look up a logical name in the global zone. * Provides the ability to map the global zone's device name * to an alternate name within a zone. The primary example * is the virtual console device /dev/zcons/[zonename]/zconsole * mapped to /[zonename]/root/dev/zconsole. */ static void prof_lookup_globaldev(struct sdev_node *dir, struct sdev_node *gdir, char *name, char *rename) { int error; struct vnode *avp, *gdv, *gddv; struct sdev_node *newdv; struct vattr vattr = {0}; struct pathname pn; /* check if node already exists */ newdv = sdev_cache_lookup(dir, rename); if (newdv) { ASSERT(newdv->sdev_state != SDEV_ZOMBIE); SDEV_SIMPLE_RELE(newdv); return; } /* sanity check arguments */ if (!gdir || pn_get(name, UIO_SYSSPACE, &pn)) return; /* perform a relative lookup of the global /dev instance */ gddv = SDEVTOV(gdir); VN_HOLD(gddv); error = lookuppnvp(&pn, NULL, FOLLOW, NULLVPP, &gdv, rootdir, gddv, kcred); pn_free(&pn); if (error) { sdcmn_err10(("prof_lookup_globaldev: %s not found\n", name)); return; } ASSERT(gdv && gdv->v_type != VLNK); /* * Found the entry in global /dev, figure out attributes * by looking at backing store. Call into devfs for default. * Note, mapped device is persisted under the new name */ prof_getattr(dir, rename, gdv, &vattr, &avp, NULL); if (gdv->v_type != VDIR) { VN_RELE(gdv); gdir = NULL; } else gdir = VTOSDEV(gdv); if (prof_mknode(dir, rename, &newdv, &vattr, avp, (void *)gdir, kcred) == 0) { ASSERT(newdv->sdev_state != SDEV_ZOMBIE); SDEV_SIMPLE_RELE(newdv); } }
void pni_store_free(pni_store_t *store) { if (!store) return; pn_free(store->tracked); pni_stream_t *stream = store->streams; while (stream) { pni_stream_t *next = stream->next; pni_stream_free(stream); stream = next; } free(store); }