15f4592e4SKonstantin Belousov /*- 25f4592e4SKonstantin Belousov * Copyright (c) 2019 The FreeBSD Foundation 35f4592e4SKonstantin Belousov * 45f4592e4SKonstantin Belousov * This software was developed by Konstantin Belousov <kib@FreeBSD.org> 55f4592e4SKonstantin Belousov * under sponsorship from the FreeBSD Foundation. 65f4592e4SKonstantin Belousov * 75f4592e4SKonstantin Belousov * Redistribution and use in source and binary forms, with or without 85f4592e4SKonstantin Belousov * modification, are permitted provided that the following conditions 95f4592e4SKonstantin Belousov * are met: 105f4592e4SKonstantin Belousov * 1. Redistributions of source code must retain the above copyright 115f4592e4SKonstantin Belousov * notice, this list of conditions and the following disclaimer. 125f4592e4SKonstantin Belousov * 2. Redistributions in binary form must reproduce the above copyright 135f4592e4SKonstantin Belousov * notice, this list of conditions and the following disclaimer in the 145f4592e4SKonstantin Belousov * documentation and/or other materials provided with the distribution. 155f4592e4SKonstantin Belousov * 165f4592e4SKonstantin Belousov * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 175f4592e4SKonstantin Belousov * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 185f4592e4SKonstantin Belousov * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 195f4592e4SKonstantin Belousov * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 205f4592e4SKonstantin Belousov * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 215f4592e4SKonstantin Belousov * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 225f4592e4SKonstantin Belousov * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 235f4592e4SKonstantin Belousov * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 245f4592e4SKonstantin Belousov * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 255f4592e4SKonstantin Belousov * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 265f4592e4SKonstantin Belousov * SUCH DAMAGE. 275f4592e4SKonstantin Belousov */ 285f4592e4SKonstantin Belousov 295f4592e4SKonstantin Belousov #include <sys/cdefs.h> 305f4592e4SKonstantin Belousov __FBSDID("$FreeBSD$"); 315f4592e4SKonstantin Belousov 325f4592e4SKonstantin Belousov #include <sys/param.h> 3319fabdb7SKonstantin Belousov #include <sys/filio.h> 345f4592e4SKonstantin Belousov #include <sys/mman.h> 355f4592e4SKonstantin Belousov #include <sys/stat.h> 3619fabdb7SKonstantin Belousov #include <sys/syscall.h> 375f4592e4SKonstantin Belousov #include <sys/sysctl.h> 385f4592e4SKonstantin Belousov #include <sys/user.h> 395f4592e4SKonstantin Belousov #include <err.h> 405f4592e4SKonstantin Belousov #include <fcntl.h> 415f4592e4SKonstantin Belousov #include <grp.h> 42*be7cf3f4SJamie Gritton #include <jail.h> 435f4592e4SKonstantin Belousov #include <libutil.h> 445f4592e4SKonstantin Belousov #include <pwd.h> 455f4592e4SKonstantin Belousov #include <stdbool.h> 465f4592e4SKonstantin Belousov #include <stdio.h> 475f4592e4SKonstantin Belousov #include <stdlib.h> 485f4592e4SKonstantin Belousov #include <string.h> 495f4592e4SKonstantin Belousov #include <unistd.h> 505f4592e4SKonstantin Belousov 515f4592e4SKonstantin Belousov static void 525f4592e4SKonstantin Belousov usage(void) 535f4592e4SKonstantin Belousov { 545f4592e4SKonstantin Belousov 555f4592e4SKonstantin Belousov fprintf(stderr, "Usage:\n" 5619fabdb7SKonstantin Belousov "posixshmcontrol create [-m <mode>] [-l <largepage>] <path> ...\n" 575f4592e4SKonstantin Belousov "posixshmcontrol rm <path> ...\n" 58*be7cf3f4SJamie Gritton "posixshmcontrol ls [-h] [-n] [-j jail]\n" 595f4592e4SKonstantin Belousov "posixshmcontrol dump <path> ...\n" 605f4592e4SKonstantin Belousov "posixshmcontrol stat [-h] [-n] <path> ...\n" 615f4592e4SKonstantin Belousov "posixshmcontrol truncate [-s <newlen>] <path> ...\n"); 625f4592e4SKonstantin Belousov } 635f4592e4SKonstantin Belousov 645f4592e4SKonstantin Belousov static int 6519fabdb7SKonstantin Belousov create_one_shm(const char *path, long mode, int idx) 665f4592e4SKonstantin Belousov { 675f4592e4SKonstantin Belousov int fd; 685f4592e4SKonstantin Belousov 6919fabdb7SKonstantin Belousov if (idx == -1) { 705f4592e4SKonstantin Belousov fd = shm_open(path, O_RDWR | O_CREAT, mode); 715f4592e4SKonstantin Belousov if (fd == -1) { 725f4592e4SKonstantin Belousov warn("create %s", path); 735f4592e4SKonstantin Belousov return (1); 745f4592e4SKonstantin Belousov } 7519fabdb7SKonstantin Belousov } else { 7619fabdb7SKonstantin Belousov fd = shm_create_largepage(path, O_RDWR, idx, 7719fabdb7SKonstantin Belousov SHM_LARGEPAGE_ALLOC_DEFAULT, mode); 7819fabdb7SKonstantin Belousov if (fd == -1) { 7919fabdb7SKonstantin Belousov warn("shm_create_largepage %s psind %d", path, idx); 8019fabdb7SKonstantin Belousov return (1); 8119fabdb7SKonstantin Belousov } 8219fabdb7SKonstantin Belousov } 835f4592e4SKonstantin Belousov close(fd); 845f4592e4SKonstantin Belousov return (0); 855f4592e4SKonstantin Belousov } 865f4592e4SKonstantin Belousov 875f4592e4SKonstantin Belousov static int 885f4592e4SKonstantin Belousov create_shm(int argc, char **argv) 895f4592e4SKonstantin Belousov { 905f4592e4SKonstantin Belousov char *end; 9119fabdb7SKonstantin Belousov size_t *pagesizes; 925f4592e4SKonstantin Belousov long mode; 9319fabdb7SKonstantin Belousov uint64_t pgsz; 9419fabdb7SKonstantin Belousov int c, i, idx, pn, ret, ret1; 9519fabdb7SKonstantin Belousov bool printed; 965f4592e4SKonstantin Belousov 975f4592e4SKonstantin Belousov mode = 0600; 9819fabdb7SKonstantin Belousov idx = -1; 9919fabdb7SKonstantin Belousov while ((c = getopt(argc, argv, "l:m:")) != -1) { 1005f4592e4SKonstantin Belousov switch (c) { 1015f4592e4SKonstantin Belousov case 'm': 1025f4592e4SKonstantin Belousov errno = 0; 1035f4592e4SKonstantin Belousov mode = strtol(optarg, &end, 0); 1045f4592e4SKonstantin Belousov if (mode == 0 && errno != 0) 10519fabdb7SKonstantin Belousov err(1, "mode"); 1065f4592e4SKonstantin Belousov if (*end != '\0') 1075f4592e4SKonstantin Belousov errx(1, "non-integer mode"); 1085f4592e4SKonstantin Belousov break; 10919fabdb7SKonstantin Belousov case 'l': 11019fabdb7SKonstantin Belousov if (expand_number(optarg, &pgsz) == -1) 11119fabdb7SKonstantin Belousov err(1, "size"); 11219fabdb7SKonstantin Belousov pn = getpagesizes(NULL, 0); 11319fabdb7SKonstantin Belousov if (pn == -1) 11419fabdb7SKonstantin Belousov err(1, "getpagesizes"); 11519fabdb7SKonstantin Belousov pagesizes = malloc(sizeof(size_t) * pn); 11619fabdb7SKonstantin Belousov if (pagesizes == NULL) 11719fabdb7SKonstantin Belousov err(1, "malloc"); 11819fabdb7SKonstantin Belousov if (getpagesizes(pagesizes, pn) == -1) 11919fabdb7SKonstantin Belousov err(1, "gtpagesizes"); 12019fabdb7SKonstantin Belousov for (idx = 0; idx < pn; idx++) { 12119fabdb7SKonstantin Belousov if (pagesizes[idx] == pgsz) 12219fabdb7SKonstantin Belousov break; 12319fabdb7SKonstantin Belousov } 12419fabdb7SKonstantin Belousov if (idx == pn) { 12519fabdb7SKonstantin Belousov fprintf(stderr, 12619fabdb7SKonstantin Belousov "pagesize should be superpagesize, supported sizes:"); 12719fabdb7SKonstantin Belousov printed = false; 12819fabdb7SKonstantin Belousov for (i = 0; i < pn; i++) { 12919fabdb7SKonstantin Belousov if (pagesizes[i] == 0 || 13019fabdb7SKonstantin Belousov pagesizes[i] == (size_t) 13119fabdb7SKonstantin Belousov getpagesize()) 13219fabdb7SKonstantin Belousov continue; 13319fabdb7SKonstantin Belousov printed = true; 13419fabdb7SKonstantin Belousov fprintf(stderr, " %zu", pagesizes[i]); 13519fabdb7SKonstantin Belousov } 13619fabdb7SKonstantin Belousov if (!printed) 13719fabdb7SKonstantin Belousov fprintf(stderr, " none"); 13819fabdb7SKonstantin Belousov fprintf(stderr, "\n"); 13919fabdb7SKonstantin Belousov exit(1); 14019fabdb7SKonstantin Belousov } 14119fabdb7SKonstantin Belousov if (pgsz == (uint64_t)getpagesize()) 14219fabdb7SKonstantin Belousov errx(1, "pagesize should be large"); 14319fabdb7SKonstantin Belousov free(pagesizes); 14419fabdb7SKonstantin Belousov break; 1455f4592e4SKonstantin Belousov case '?': 1465f4592e4SKonstantin Belousov default: 1475f4592e4SKonstantin Belousov usage(); 1485f4592e4SKonstantin Belousov return (2); 1495f4592e4SKonstantin Belousov } 1505f4592e4SKonstantin Belousov } 1515f4592e4SKonstantin Belousov argc -= optind; 1525f4592e4SKonstantin Belousov argv += optind; 153c6dce83dSMark Johnston 154c6dce83dSMark Johnston if (argc == 0) { 155c6dce83dSMark Johnston usage(); 156c6dce83dSMark Johnston return (2); 157c6dce83dSMark Johnston } 158c6dce83dSMark Johnston 1595f4592e4SKonstantin Belousov ret = 0; 1605f4592e4SKonstantin Belousov for (i = 0; i < argc; i++) { 16119fabdb7SKonstantin Belousov ret1 = create_one_shm(argv[i], mode, idx); 1625f4592e4SKonstantin Belousov if (ret1 != 0 && ret == 0) 1635f4592e4SKonstantin Belousov ret = ret1; 1645f4592e4SKonstantin Belousov } 1655f4592e4SKonstantin Belousov return (ret); 1665f4592e4SKonstantin Belousov } 1675f4592e4SKonstantin Belousov 1685f4592e4SKonstantin Belousov static int 1695f4592e4SKonstantin Belousov delete_one_shm(const char *path) 1705f4592e4SKonstantin Belousov { 1715f4592e4SKonstantin Belousov int error, ret; 1725f4592e4SKonstantin Belousov 1735f4592e4SKonstantin Belousov error = shm_unlink(path); 1745f4592e4SKonstantin Belousov if (error != 0) { 1755f4592e4SKonstantin Belousov warn("unlink of %s failed", path); 1765f4592e4SKonstantin Belousov ret = 1; 1775f4592e4SKonstantin Belousov } else { 1785f4592e4SKonstantin Belousov ret = 0; 1795f4592e4SKonstantin Belousov } 1805f4592e4SKonstantin Belousov return (ret); 1815f4592e4SKonstantin Belousov } 1825f4592e4SKonstantin Belousov 1835f4592e4SKonstantin Belousov static int 1845f4592e4SKonstantin Belousov delete_shm(int argc, char **argv) 1855f4592e4SKonstantin Belousov { 1865f4592e4SKonstantin Belousov int i, ret, ret1; 1875f4592e4SKonstantin Belousov 188c6dce83dSMark Johnston if (argc == 1) { 189c6dce83dSMark Johnston usage(); 190c6dce83dSMark Johnston return (2); 191c6dce83dSMark Johnston } 192c6dce83dSMark Johnston 1935f4592e4SKonstantin Belousov ret = 0; 1945f4592e4SKonstantin Belousov for (i = 1; i < argc; i++) { 1955f4592e4SKonstantin Belousov ret1 = delete_one_shm(argv[i]); 1965f4592e4SKonstantin Belousov if (ret1 != 0 && ret == 0) 1975f4592e4SKonstantin Belousov ret = ret1; 1985f4592e4SKonstantin Belousov } 1995f4592e4SKonstantin Belousov return (ret); 2005f4592e4SKonstantin Belousov } 2015f4592e4SKonstantin Belousov 2025f4592e4SKonstantin Belousov static const char listmib[] = "kern.ipc.posix_shm_list"; 2035f4592e4SKonstantin Belousov 2045f4592e4SKonstantin Belousov static void 2055f4592e4SKonstantin Belousov shm_decode_mode(mode_t m, char *str) 2065f4592e4SKonstantin Belousov { 2075f4592e4SKonstantin Belousov int i; 2085f4592e4SKonstantin Belousov 2095f4592e4SKonstantin Belousov i = 0; 2105f4592e4SKonstantin Belousov str[i++] = (m & S_IRUSR) != 0 ? 'r' : '-'; 2115f4592e4SKonstantin Belousov str[i++] = (m & S_IWUSR) != 0 ? 'w' : '-'; 2125f4592e4SKonstantin Belousov str[i++] = (m & S_IXUSR) != 0 ? 'x' : '-'; 2135f4592e4SKonstantin Belousov str[i++] = (m & S_IRGRP) != 0 ? 'r' : '-'; 2145f4592e4SKonstantin Belousov str[i++] = (m & S_IWGRP) != 0 ? 'w' : '-'; 2155f4592e4SKonstantin Belousov str[i++] = (m & S_IXGRP) != 0 ? 'x' : '-'; 2165f4592e4SKonstantin Belousov str[i++] = (m & S_IROTH) != 0 ? 'r' : '-'; 2175f4592e4SKonstantin Belousov str[i++] = (m & S_IWOTH) != 0 ? 'w' : '-'; 2185f4592e4SKonstantin Belousov str[i++] = (m & S_IXOTH) != 0 ? 'x' : '-'; 2195f4592e4SKonstantin Belousov str[i] = '\0'; 2205f4592e4SKonstantin Belousov } 2215f4592e4SKonstantin Belousov 2225f4592e4SKonstantin Belousov static int 2235f4592e4SKonstantin Belousov list_shm(int argc, char **argv) 2245f4592e4SKonstantin Belousov { 225*be7cf3f4SJamie Gritton char *buf, *bp, *ep, jailpath[MAXPATHLEN], sizebuf[8], str[10]; 226*be7cf3f4SJamie Gritton const char *jailparam; 2275f4592e4SKonstantin Belousov const struct kinfo_file *kif; 2285f4592e4SKonstantin Belousov struct stat st; 229*be7cf3f4SJamie Gritton int c, error, fd, jid, mib[3], ret; 230*be7cf3f4SJamie Gritton size_t len, jailpathlen, miblen; 231*be7cf3f4SJamie Gritton bool hsize, jailed, uname; 2325f4592e4SKonstantin Belousov 2335f4592e4SKonstantin Belousov hsize = false; 234*be7cf3f4SJamie Gritton jailed = false; 2355f4592e4SKonstantin Belousov uname = true; 2365f4592e4SKonstantin Belousov 237*be7cf3f4SJamie Gritton while ((c = getopt(argc, argv, "hj:n")) != -1) { 2385f4592e4SKonstantin Belousov switch (c) { 2395f4592e4SKonstantin Belousov case 'h': 2405f4592e4SKonstantin Belousov hsize = true; 2415f4592e4SKonstantin Belousov break; 2425f4592e4SKonstantin Belousov case 'n': 2435f4592e4SKonstantin Belousov uname = false; 2445f4592e4SKonstantin Belousov break; 245*be7cf3f4SJamie Gritton case 'j': 246*be7cf3f4SJamie Gritton jid = strtoul(optarg, &ep, 10); 247*be7cf3f4SJamie Gritton if (ep > optarg && !*ep) { 248*be7cf3f4SJamie Gritton jailparam = "jid"; 249*be7cf3f4SJamie Gritton jailed = jid > 0; 250*be7cf3f4SJamie Gritton } else { 251*be7cf3f4SJamie Gritton jailparam = "name"; 252*be7cf3f4SJamie Gritton jailed = true; 253*be7cf3f4SJamie Gritton } 254*be7cf3f4SJamie Gritton if (jailed) { 255*be7cf3f4SJamie Gritton if (jail_getv(0, jailparam, optarg, "path", 256*be7cf3f4SJamie Gritton jailpath, NULL) < 0) { 257*be7cf3f4SJamie Gritton if (errno == ENOENT) 258*be7cf3f4SJamie Gritton warnx("no such jail: %s", optarg); 259*be7cf3f4SJamie Gritton else 260*be7cf3f4SJamie Gritton warnx("%s", jail_errmsg); 261*be7cf3f4SJamie Gritton return (1); 262*be7cf3f4SJamie Gritton } 263*be7cf3f4SJamie Gritton jailpathlen = strlen(jailpath); 264*be7cf3f4SJamie Gritton jailpath[jailpathlen] = '/'; 265*be7cf3f4SJamie Gritton } 266*be7cf3f4SJamie Gritton break; 2675f4592e4SKonstantin Belousov default: 2685f4592e4SKonstantin Belousov usage(); 2695f4592e4SKonstantin Belousov return (2); 2705f4592e4SKonstantin Belousov } 2715f4592e4SKonstantin Belousov } 2725f4592e4SKonstantin Belousov if (argc != optind) { 2735f4592e4SKonstantin Belousov usage(); 2745f4592e4SKonstantin Belousov return (2); 2755f4592e4SKonstantin Belousov } 2765f4592e4SKonstantin Belousov 2775f4592e4SKonstantin Belousov miblen = nitems(mib); 2785f4592e4SKonstantin Belousov error = sysctlnametomib(listmib, mib, &miblen); 2795f4592e4SKonstantin Belousov if (error == -1) { 2805f4592e4SKonstantin Belousov warn("cannot translate %s", listmib); 2815f4592e4SKonstantin Belousov return (1); 2825f4592e4SKonstantin Belousov } 2835f4592e4SKonstantin Belousov len = 0; 2845f4592e4SKonstantin Belousov error = sysctl(mib, miblen, NULL, &len, NULL, 0); 2855f4592e4SKonstantin Belousov if (error == -1) { 2865f4592e4SKonstantin Belousov warn("cannot get %s length", listmib); 2875f4592e4SKonstantin Belousov return (1); 2885f4592e4SKonstantin Belousov } 2895f4592e4SKonstantin Belousov len = len * 4 / 3; 2905f4592e4SKonstantin Belousov buf = malloc(len); 2915f4592e4SKonstantin Belousov if (buf == NULL) { 2925f4592e4SKonstantin Belousov warn("malloc"); 2935f4592e4SKonstantin Belousov return (1); 2945f4592e4SKonstantin Belousov } 2955f4592e4SKonstantin Belousov error = sysctl(mib, miblen, buf, &len, NULL, 0); 2965f4592e4SKonstantin Belousov if (error != 0) { 2975f4592e4SKonstantin Belousov warn("reading %s", listmib); 2985f4592e4SKonstantin Belousov ret = 1; 2995f4592e4SKonstantin Belousov goto out; 3005f4592e4SKonstantin Belousov } 3015f4592e4SKonstantin Belousov ret = 0; 3025f4592e4SKonstantin Belousov printf("MODE \tOWNER\tGROUP\tSIZE\tPATH\n"); 3035f4592e4SKonstantin Belousov for (bp = buf; bp < buf + len; bp += kif->kf_structsize) { 3045f4592e4SKonstantin Belousov kif = (const struct kinfo_file *)(void *)bp; 3055f4592e4SKonstantin Belousov if (kif->kf_structsize == 0) 3065f4592e4SKonstantin Belousov break; 307*be7cf3f4SJamie Gritton if (jailed && strncmp(kif->kf_path, jailpath, jailpathlen + 1)) 308*be7cf3f4SJamie Gritton continue; 3095f4592e4SKonstantin Belousov fd = shm_open(kif->kf_path, O_RDONLY, 0); 3105f4592e4SKonstantin Belousov if (fd == -1) { 3115f4592e4SKonstantin Belousov warn("open %s", kif->kf_path); 3125f4592e4SKonstantin Belousov ret = 1; 3135f4592e4SKonstantin Belousov continue; 3145f4592e4SKonstantin Belousov } 3155f4592e4SKonstantin Belousov error = fstat(fd, &st); 3165f4592e4SKonstantin Belousov close(fd); 3175f4592e4SKonstantin Belousov if (error != 0) { 3185f4592e4SKonstantin Belousov warn("stat %s", kif->kf_path); 3195f4592e4SKonstantin Belousov ret = 1; 3205f4592e4SKonstantin Belousov continue; 3215f4592e4SKonstantin Belousov } 3225f4592e4SKonstantin Belousov shm_decode_mode(kif->kf_un.kf_file.kf_file_mode, str); 3235f4592e4SKonstantin Belousov printf("%s\t", str); 3245f4592e4SKonstantin Belousov if (uname) { 3255f4592e4SKonstantin Belousov printf("%s\t%s\t", user_from_uid(st.st_uid, 0), 3265f4592e4SKonstantin Belousov group_from_gid(st.st_gid, 0)); 3275f4592e4SKonstantin Belousov } else { 3285f4592e4SKonstantin Belousov printf("%d\t%d\t", st.st_uid, st.st_gid); 3295f4592e4SKonstantin Belousov } 3305f4592e4SKonstantin Belousov if (hsize) { 3315f4592e4SKonstantin Belousov humanize_number(sizebuf, sizeof(sizebuf), 3325f4592e4SKonstantin Belousov kif->kf_un.kf_file.kf_file_size, "", HN_AUTOSCALE, 3335f4592e4SKonstantin Belousov HN_NOSPACE); 3345f4592e4SKonstantin Belousov printf("%s\t", sizebuf); 3355f4592e4SKonstantin Belousov } else { 3365f4592e4SKonstantin Belousov printf("%jd\t", 3375f4592e4SKonstantin Belousov (uintmax_t)kif->kf_un.kf_file.kf_file_size); 3385f4592e4SKonstantin Belousov } 3395f4592e4SKonstantin Belousov printf("%s\n", kif->kf_path); 3405f4592e4SKonstantin Belousov } 3415f4592e4SKonstantin Belousov out: 3425f4592e4SKonstantin Belousov free(buf); 3435f4592e4SKonstantin Belousov return (ret); 3445f4592e4SKonstantin Belousov } 3455f4592e4SKonstantin Belousov 3465f4592e4SKonstantin Belousov static int 3475f4592e4SKonstantin Belousov read_one_shm(const char *path) 3485f4592e4SKonstantin Belousov { 3495f4592e4SKonstantin Belousov char buf[4096]; 3505f4592e4SKonstantin Belousov ssize_t size, se; 3515f4592e4SKonstantin Belousov int fd, ret; 3525f4592e4SKonstantin Belousov 3535f4592e4SKonstantin Belousov ret = 1; 3545f4592e4SKonstantin Belousov fd = shm_open(path, O_RDONLY, 0); 3555f4592e4SKonstantin Belousov if (fd == -1) { 3565f4592e4SKonstantin Belousov warn("open %s", path); 3575f4592e4SKonstantin Belousov goto out; 3585f4592e4SKonstantin Belousov } 3595f4592e4SKonstantin Belousov for (;;) { 3605f4592e4SKonstantin Belousov size = read(fd, buf, sizeof(buf)); 3615f4592e4SKonstantin Belousov if (size > 0) { 3625f4592e4SKonstantin Belousov se = fwrite(buf, 1, size, stdout); 3635f4592e4SKonstantin Belousov if (se < size) { 3645f4592e4SKonstantin Belousov warnx("short write to stdout"); 3655f4592e4SKonstantin Belousov goto out; 3665f4592e4SKonstantin Belousov } 3675f4592e4SKonstantin Belousov } 3685f4592e4SKonstantin Belousov if (size == (ssize_t)sizeof(buf)) 3695f4592e4SKonstantin Belousov continue; 3705f4592e4SKonstantin Belousov if (size >= 0 && size < (ssize_t)sizeof(buf)) { 3715f4592e4SKonstantin Belousov ret = 0; 3725f4592e4SKonstantin Belousov goto out; 3735f4592e4SKonstantin Belousov } 3745f4592e4SKonstantin Belousov warn("read from %s", path); 3755f4592e4SKonstantin Belousov goto out; 3765f4592e4SKonstantin Belousov } 3775f4592e4SKonstantin Belousov out: 3785f4592e4SKonstantin Belousov close(fd); 3795f4592e4SKonstantin Belousov return (ret); 3805f4592e4SKonstantin Belousov } 3815f4592e4SKonstantin Belousov 3825f4592e4SKonstantin Belousov static int 3835f4592e4SKonstantin Belousov read_shm(int argc, char **argv) 3845f4592e4SKonstantin Belousov { 3855f4592e4SKonstantin Belousov int i, ret, ret1; 3865f4592e4SKonstantin Belousov 387c6dce83dSMark Johnston if (argc == 1) { 388c6dce83dSMark Johnston usage(); 389c6dce83dSMark Johnston return (2); 390c6dce83dSMark Johnston } 391c6dce83dSMark Johnston 3925f4592e4SKonstantin Belousov ret = 0; 3935f4592e4SKonstantin Belousov for (i = 1; i < argc; i++) { 3945f4592e4SKonstantin Belousov ret1 = read_one_shm(argv[i]); 3955f4592e4SKonstantin Belousov if (ret1 != 0 && ret == 0) 3965f4592e4SKonstantin Belousov ret = ret1; 3975f4592e4SKonstantin Belousov } 3985f4592e4SKonstantin Belousov return (ret); 3995f4592e4SKonstantin Belousov } 4005f4592e4SKonstantin Belousov 4015f4592e4SKonstantin Belousov static int 4025f4592e4SKonstantin Belousov stat_one_shm(const char *path, bool hsize, bool uname) 4035f4592e4SKonstantin Belousov { 4045f4592e4SKonstantin Belousov char sizebuf[8]; 4055f4592e4SKonstantin Belousov struct stat st; 4065f4592e4SKonstantin Belousov int error, fd, ret; 4075f4592e4SKonstantin Belousov 4085f4592e4SKonstantin Belousov fd = shm_open(path, O_RDONLY, 0); 4095f4592e4SKonstantin Belousov if (fd == -1) { 4105f4592e4SKonstantin Belousov warn("open %s", path); 4115f4592e4SKonstantin Belousov return (1); 4125f4592e4SKonstantin Belousov } 4135f4592e4SKonstantin Belousov ret = 0; 4145f4592e4SKonstantin Belousov error = fstat(fd, &st); 4155f4592e4SKonstantin Belousov if (error == -1) { 4165f4592e4SKonstantin Belousov warn("stat %s", path); 4175f4592e4SKonstantin Belousov ret = 1; 4185f4592e4SKonstantin Belousov } else { 4195f4592e4SKonstantin Belousov printf("path\t%s\n", path); 4205f4592e4SKonstantin Belousov printf("inode\t%jd\n", (uintmax_t)st.st_ino); 4215f4592e4SKonstantin Belousov printf("mode\t%#o\n", st.st_mode); 4225f4592e4SKonstantin Belousov printf("nlink\t%jd\n", (uintmax_t)st.st_nlink); 4235f4592e4SKonstantin Belousov if (uname) { 4245f4592e4SKonstantin Belousov printf("owner\t%s\n", user_from_uid(st.st_uid, 0)); 4255f4592e4SKonstantin Belousov printf("group\t%s\n", group_from_gid(st.st_gid, 0)); 4265f4592e4SKonstantin Belousov } else { 4275f4592e4SKonstantin Belousov printf("uid\t%d\n", st.st_uid); 4285f4592e4SKonstantin Belousov printf("gid\t%d\n", st.st_gid); 4295f4592e4SKonstantin Belousov } 4305f4592e4SKonstantin Belousov if (hsize) { 4315f4592e4SKonstantin Belousov humanize_number(sizebuf, sizeof(sizebuf), 4325f4592e4SKonstantin Belousov st.st_size, "", HN_AUTOSCALE, HN_NOSPACE); 4335f4592e4SKonstantin Belousov printf("size\t%s\n", sizebuf); 4345f4592e4SKonstantin Belousov } else { 4355f4592e4SKonstantin Belousov printf("size\t%jd\n", (uintmax_t)st.st_size); 4365f4592e4SKonstantin Belousov } 4375f4592e4SKonstantin Belousov printf("atime\t%ld.%09ld\n", (long)st.st_atime, 4385f4592e4SKonstantin Belousov (long)st.st_atim.tv_nsec); 4395f4592e4SKonstantin Belousov printf("mtime\t%ld.%09ld\n", (long)st.st_mtime, 4405f4592e4SKonstantin Belousov (long)st.st_mtim.tv_nsec); 4415f4592e4SKonstantin Belousov printf("ctime\t%ld.%09ld\n", (long)st.st_ctime, 4425f4592e4SKonstantin Belousov (long)st.st_ctim.tv_nsec); 4435f4592e4SKonstantin Belousov printf("birth\t%ld.%09ld\n", (long)st.st_birthtim.tv_sec, 4445f4592e4SKonstantin Belousov (long)st.st_birthtim.tv_nsec); 44519fabdb7SKonstantin Belousov if (st.st_blocks != 0) 44619fabdb7SKonstantin Belousov printf("pagesz\t%jd\n", roundup((uintmax_t)st.st_size, 44719fabdb7SKonstantin Belousov PAGE_SIZE) / st.st_blocks); 4485f4592e4SKonstantin Belousov } 4495f4592e4SKonstantin Belousov close(fd); 4505f4592e4SKonstantin Belousov return (ret); 4515f4592e4SKonstantin Belousov } 4525f4592e4SKonstantin Belousov 4535f4592e4SKonstantin Belousov static int 4545f4592e4SKonstantin Belousov stat_shm(int argc, char **argv) 4555f4592e4SKonstantin Belousov { 4565f4592e4SKonstantin Belousov int c, i, ret, ret1; 4575f4592e4SKonstantin Belousov bool hsize, uname; 4585f4592e4SKonstantin Belousov 4595f4592e4SKonstantin Belousov hsize = false; 4605f4592e4SKonstantin Belousov uname = true; 4615f4592e4SKonstantin Belousov 4625f4592e4SKonstantin Belousov while ((c = getopt(argc, argv, "hn")) != -1) { 4635f4592e4SKonstantin Belousov switch (c) { 4645f4592e4SKonstantin Belousov case 'h': 4655f4592e4SKonstantin Belousov hsize = true; 4665f4592e4SKonstantin Belousov break; 4675f4592e4SKonstantin Belousov case 'n': 4685f4592e4SKonstantin Belousov uname = false; 4695f4592e4SKonstantin Belousov break; 4705f4592e4SKonstantin Belousov default: 4715f4592e4SKonstantin Belousov usage(); 4725f4592e4SKonstantin Belousov return (2); 4735f4592e4SKonstantin Belousov } 4745f4592e4SKonstantin Belousov } 4755f4592e4SKonstantin Belousov argc -= optind; 4765f4592e4SKonstantin Belousov argv += optind; 4775f4592e4SKonstantin Belousov 478c6dce83dSMark Johnston if (argc == 0) { 479c6dce83dSMark Johnston usage(); 480c6dce83dSMark Johnston return (2); 481c6dce83dSMark Johnston } 482c6dce83dSMark Johnston 4835f4592e4SKonstantin Belousov ret = 0; 4845f4592e4SKonstantin Belousov for (i = 0; i < argc; i++) { 4855f4592e4SKonstantin Belousov ret1 = stat_one_shm(argv[i], hsize, uname); 4865f4592e4SKonstantin Belousov if (ret1 != 0 && ret == 0) 4875f4592e4SKonstantin Belousov ret = ret1; 4885f4592e4SKonstantin Belousov } 4895f4592e4SKonstantin Belousov return (ret); 4905f4592e4SKonstantin Belousov } 4915f4592e4SKonstantin Belousov 4925f4592e4SKonstantin Belousov static int 4935f4592e4SKonstantin Belousov truncate_one_shm(const char *path, uint64_t newsize) 4945f4592e4SKonstantin Belousov { 4955f4592e4SKonstantin Belousov int error, fd, ret; 4965f4592e4SKonstantin Belousov 4975f4592e4SKonstantin Belousov ret = 0; 4985f4592e4SKonstantin Belousov fd = shm_open(path, O_RDWR, 0); 4995f4592e4SKonstantin Belousov if (fd == -1) { 5005f4592e4SKonstantin Belousov warn("open %s", path); 5015f4592e4SKonstantin Belousov return (1); 5025f4592e4SKonstantin Belousov } 5035f4592e4SKonstantin Belousov error = ftruncate(fd, newsize); 5045f4592e4SKonstantin Belousov if (error == -1) { 5055f4592e4SKonstantin Belousov warn("truncate %s", path); 5065f4592e4SKonstantin Belousov ret = 1; 5075f4592e4SKonstantin Belousov } 5085f4592e4SKonstantin Belousov close(fd); 5095f4592e4SKonstantin Belousov return (ret); 5105f4592e4SKonstantin Belousov } 5115f4592e4SKonstantin Belousov 5125f4592e4SKonstantin Belousov static int 5135f4592e4SKonstantin Belousov truncate_shm(int argc, char **argv) 5145f4592e4SKonstantin Belousov { 5155f4592e4SKonstantin Belousov uint64_t newsize; 5165f4592e4SKonstantin Belousov int c, i, ret, ret1; 5175f4592e4SKonstantin Belousov 5185f4592e4SKonstantin Belousov newsize = 0; 5195f4592e4SKonstantin Belousov while ((c = getopt(argc, argv, "s:")) != -1) { 5205f4592e4SKonstantin Belousov switch (c) { 5215f4592e4SKonstantin Belousov case 's': 5225f4592e4SKonstantin Belousov if (expand_number(optarg, &newsize) == -1) 523c6dce83dSMark Johnston err(1, "size"); 5245f4592e4SKonstantin Belousov break; 5255f4592e4SKonstantin Belousov case '?': 5265f4592e4SKonstantin Belousov default: 5275f4592e4SKonstantin Belousov return (2); 5285f4592e4SKonstantin Belousov } 5295f4592e4SKonstantin Belousov } 5305f4592e4SKonstantin Belousov argc -= optind; 5315f4592e4SKonstantin Belousov argv += optind; 532c6dce83dSMark Johnston 533c6dce83dSMark Johnston if (argc == 0) { 534c6dce83dSMark Johnston usage(); 535c6dce83dSMark Johnston return (2); 536c6dce83dSMark Johnston } 537c6dce83dSMark Johnston 5385f4592e4SKonstantin Belousov ret = 0; 5395f4592e4SKonstantin Belousov for (i = 0; i < argc; i++) { 5405f4592e4SKonstantin Belousov ret1 = truncate_one_shm(argv[i], newsize); 5415f4592e4SKonstantin Belousov if (ret1 != 0 && ret == 0) 5425f4592e4SKonstantin Belousov ret = ret1; 5435f4592e4SKonstantin Belousov } 5445f4592e4SKonstantin Belousov return (ret); 5455f4592e4SKonstantin Belousov } 5465f4592e4SKonstantin Belousov 5475f4592e4SKonstantin Belousov struct opmode { 5485f4592e4SKonstantin Belousov const char *cmd; 5495f4592e4SKonstantin Belousov int (*impl)(int argc, char **argv); 5505f4592e4SKonstantin Belousov }; 5515f4592e4SKonstantin Belousov 5525f4592e4SKonstantin Belousov static const struct opmode opmodes[] = { 5535f4592e4SKonstantin Belousov { .cmd = "create", .impl = create_shm}, 5545f4592e4SKonstantin Belousov { .cmd = "rm", .impl = delete_shm, }, 555a24ac0ceSKonstantin Belousov { .cmd = "list", .impl = list_shm }, 5565f4592e4SKonstantin Belousov { .cmd = "ls", .impl = list_shm }, 5575f4592e4SKonstantin Belousov { .cmd = "dump", .impl = read_shm, }, 5585f4592e4SKonstantin Belousov { .cmd = "stat", .impl = stat_shm, }, 5595f4592e4SKonstantin Belousov { .cmd = "truncate", .impl = truncate_shm, }, 5605f4592e4SKonstantin Belousov }; 5615f4592e4SKonstantin Belousov 5625f4592e4SKonstantin Belousov int 5635f4592e4SKonstantin Belousov main(int argc, char *argv[]) 5645f4592e4SKonstantin Belousov { 5655f4592e4SKonstantin Belousov const struct opmode *opmode; 5665f4592e4SKonstantin Belousov int i, ret; 5675f4592e4SKonstantin Belousov 5685f4592e4SKonstantin Belousov ret = 0; 5695f4592e4SKonstantin Belousov opmode = NULL; 5705f4592e4SKonstantin Belousov 5715f4592e4SKonstantin Belousov if (argc < 2) { 5725f4592e4SKonstantin Belousov usage(); 5735f4592e4SKonstantin Belousov exit(2); 5745f4592e4SKonstantin Belousov } 5755f4592e4SKonstantin Belousov for (i = 0; i < (int)nitems(opmodes); i++) { 5765f4592e4SKonstantin Belousov if (strcmp(argv[1], opmodes[i].cmd) == 0) { 5775f4592e4SKonstantin Belousov opmode = &opmodes[i]; 5785f4592e4SKonstantin Belousov break; 5795f4592e4SKonstantin Belousov } 5805f4592e4SKonstantin Belousov } 5815f4592e4SKonstantin Belousov if (opmode == NULL) { 5825f4592e4SKonstantin Belousov usage(); 5835f4592e4SKonstantin Belousov exit(2); 5845f4592e4SKonstantin Belousov } 5855f4592e4SKonstantin Belousov ret = opmode->impl(argc - 1, argv + 1); 5865f4592e4SKonstantin Belousov exit(ret); 5875f4592e4SKonstantin Belousov } 588