Index: sbin/nvmecontrol/comnd.h =================================================================== --- sbin/nvmecontrol/comnd.h +++ sbin/nvmecontrol/comnd.h @@ -96,6 +96,7 @@ int arg_parse(int argc, char * const *argv, const struct cmd *f); void arg_help(int argc, char * const *argv, const struct cmd *f); void cmd_init(void); +void cmd_unload_shlibs(void); void cmd_load_dir(const char *dir, cmd_load_cb_t *cb, void *argp); int cmd_dispatch(int argc, char *argv[], const struct cmd *); Index: sbin/nvmecontrol/comnd.c =================================================================== --- sbin/nvmecontrol/comnd.c +++ sbin/nvmecontrol/comnd.c @@ -47,6 +47,13 @@ #include "comnd.h" +struct shlib { + SLIST_ENTRY(shlib) link; + void *handle; +}; + +static SLIST_HEAD(, shlib) shlibs = SLIST_HEAD_INITIALIZER(shlibs); + static struct cmd top; static void @@ -283,6 +290,22 @@ } /* + * Unloads all the .so's. + */ +void +cmd_unload_shlibs(void) +{ + struct shlib *ent; + struct shlib *tmp; + + SLIST_FOREACH_SAFE(ent, &shlibs, link, tmp) { + SLIST_REMOVE_HEAD(&shlibs, link); + dlclose(ent->handle); + free(ent); + } +} + +/* * Loads all the .so's from the specified directory. */ void @@ -292,6 +315,7 @@ struct dirent *dent; char *path = NULL; void *h; + struct shlib *libent; d = opendir(dir); if (d == NULL) @@ -302,12 +326,20 @@ asprintf(&path, "%s/%s", dir, dent->d_name); if (path == NULL) err(1, "Can't malloc for path, giving up."); + libent = (struct shlib *)malloc(sizeof(struct shlib)); + if (libent == NULL) + err(1, "Can't malloc for libent, giving up."); if ((h = dlopen(path, RTLD_NOW | RTLD_GLOBAL)) == NULL) warnx("Can't load %s: %s", path, dlerror()); else { + libent->handle = h; + SLIST_INSERT_HEAD(&shlibs, libent, link); + /* libent is saved; prevent from being freed below. */ + libent = NULL; if (cb != NULL) cb(argp, h); } + free(libent); free(path); path = NULL; } Index: sbin/nvmecontrol/firmware.c =================================================================== --- sbin/nvmecontrol/firmware.c +++ sbin/nvmecontrol/firmware.c @@ -151,6 +151,7 @@ errx(1, "error reading '%s' (read %d bytes, requested %d bytes)", path, *size, filesize); + close(fd); } static void @@ -188,6 +189,7 @@ resid -= size; off += size; } + free(chunk); } static int Index: sbin/nvmecontrol/identify.c =================================================================== --- sbin/nvmecontrol/identify.c +++ sbin/nvmecontrol/identify.c @@ -94,7 +94,7 @@ NVME_NS_DATA_DPC_PIT3_MASK) ? "Type 3, " : "", ((nsdata->dpc >> NVME_NS_DATA_DPC_PIT2_SHIFT) & NVME_NS_DATA_DPC_PIT2_MASK) ? "Type 2, " : "", - ((nsdata->dpc >> NVME_NS_DATA_DPC_PIT2_MASK) & + ((nsdata->dpc >> NVME_NS_DATA_DPC_PIT1_MASK) & NVME_NS_DATA_DPC_PIT1_MASK) ? "Type 1" : ""); printf("Data Protection Settings: "); ptype = (nsdata->dps >> NVME_NS_DATA_DPS_PIT_SHIFT) & @@ -238,7 +238,8 @@ int fd; uint32_t nsid; - arg_parse(argc, argv, f); + if (arg_parse(argc, argv, f)) + return; open_dev(opt.dev, &fd, 1, 1); get_nsid(fd, &path, &nsid); Index: sbin/nvmecontrol/logpage.c =================================================================== --- sbin/nvmecontrol/logpage.c +++ sbin/nvmecontrol/logpage.c @@ -570,11 +570,11 @@ printf("Unknown"); break; } - p = (ss->sstat & NVME_SS_PAGE_SSTAT_PASSES_SHIFT) >> + p = (ss->sstat >> NVME_SS_PAGE_SSTAT_PASSES_SHIFT) & NVME_SS_PAGE_SSTAT_PASSES_MASK; if (p > 0) printf(", %d passes", p); - if ((ss->sstat & NVME_SS_PAGE_SSTAT_GDE_SHIFT) >> + if ((ss->sstat >> NVME_SS_PAGE_SSTAT_GDE_SHIFT) & NVME_SS_PAGE_SSTAT_GDE_MASK) printf(", Global Data Erased"); printf("\n"); Index: sbin/nvmecontrol/nsid.c =================================================================== --- sbin/nvmecontrol/nsid.c +++ sbin/nvmecontrol/nsid.c @@ -70,7 +70,8 @@ int fd; uint32_t nsid; - arg_parse(argc, argv, f); + if (arg_parse(argc, argv, f)) + return; open_dev(nsid_opt.dev, &fd, 1, 1); get_nsid(fd, &path, &nsid); Index: sbin/nvmecontrol/nvmecontrol.c =================================================================== --- sbin/nvmecontrol/nvmecontrol.c +++ sbin/nvmecontrol/nvmecontrol.c @@ -184,5 +184,6 @@ cmd_dispatch(argc, argv, NULL); + cmd_unload_shlibs(); return (0); } Index: sbin/nvmecontrol/passthru.c =================================================================== --- sbin/nvmecontrol/passthru.c +++ sbin/nvmecontrol/passthru.c @@ -161,7 +161,8 @@ void *data = NULL, *metadata = NULL; struct nvme_pt_command pt; - arg_parse(argc, argv, f); + if (arg_parse(argc, argv, f)) + return; open_dev(argv[optind], &fd, 1, 1); if (opt.read && opt.write) @@ -189,7 +190,7 @@ goto cleanup; } memset(data, opt.prefill, opt.data_len); - if (opt.write && read(ifd, data, opt.data_len) < 0) { + if (opt.write && read(ifd, data, opt.data_len) != opt.data_len) { warn("read %s", *opt.ifn ? opt.ifn : "stdin"); goto cleanup; } @@ -249,6 +250,12 @@ } } cleanup: + if (data != NULL) + free(data); + if (fd > -1) + close(fd); + if (ifd > -1) + close(ifd); if (errno) exit(1); } Index: sbin/nvmecontrol/power.c =================================================================== --- sbin/nvmecontrol/power.c +++ sbin/nvmecontrol/power.c @@ -145,7 +145,8 @@ struct nvme_controller_data cdata; int fd; - arg_parse(argc, argv, f); + if (arg_parse(argc, argv, f)) + return; if (opt.list && opt.power != POWER_NONE) { fprintf(stderr, "Can't set power and list power states\n"); Index: sbin/nvmecontrol/reset.c =================================================================== --- sbin/nvmecontrol/reset.c +++ sbin/nvmecontrol/reset.c @@ -57,7 +57,8 @@ { int fd; - arg_parse(argc, argv, f); + if (arg_parse(argc, argv, f)) + return; open_dev(opt.dev, &fd, 1, 1); if (ioctl(fd, NVME_RESET_CONTROLLER) < 0)