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> 425f4592e4SKonstantin Belousov #include <libutil.h> 435f4592e4SKonstantin Belousov #include <pwd.h> 445f4592e4SKonstantin Belousov #include <stdbool.h> 455f4592e4SKonstantin Belousov #include <stdio.h> 465f4592e4SKonstantin Belousov #include <stdlib.h> 475f4592e4SKonstantin Belousov #include <string.h> 485f4592e4SKonstantin Belousov #include <unistd.h> 495f4592e4SKonstantin Belousov 505f4592e4SKonstantin Belousov static void 515f4592e4SKonstantin Belousov usage(void) 525f4592e4SKonstantin Belousov { 535f4592e4SKonstantin Belousov 545f4592e4SKonstantin Belousov fprintf(stderr, "Usage:\n" 5519fabdb7SKonstantin Belousov "posixshmcontrol create [-m <mode>] [-l <largepage>] <path> ...\n" 565f4592e4SKonstantin Belousov "posixshmcontrol rm <path> ...\n" 575f4592e4SKonstantin Belousov "posixshmcontrol ls [-h] [-n]\n" 585f4592e4SKonstantin Belousov "posixshmcontrol dump <path> ...\n" 595f4592e4SKonstantin Belousov "posixshmcontrol stat [-h] [-n] <path> ...\n" 605f4592e4SKonstantin Belousov "posixshmcontrol truncate [-s <newlen>] <path> ...\n"); 615f4592e4SKonstantin Belousov } 625f4592e4SKonstantin Belousov 635f4592e4SKonstantin Belousov static int 6419fabdb7SKonstantin Belousov create_one_shm(const char *path, long mode, int idx) 655f4592e4SKonstantin Belousov { 665f4592e4SKonstantin Belousov int fd; 675f4592e4SKonstantin Belousov 6819fabdb7SKonstantin Belousov if (idx == -1) { 695f4592e4SKonstantin Belousov fd = shm_open(path, O_RDWR | O_CREAT, mode); 705f4592e4SKonstantin Belousov if (fd == -1) { 715f4592e4SKonstantin Belousov warn("create %s", path); 725f4592e4SKonstantin Belousov return (1); 735f4592e4SKonstantin Belousov } 7419fabdb7SKonstantin Belousov } else { 7519fabdb7SKonstantin Belousov fd = shm_create_largepage(path, O_RDWR, idx, 7619fabdb7SKonstantin Belousov SHM_LARGEPAGE_ALLOC_DEFAULT, mode); 7719fabdb7SKonstantin Belousov if (fd == -1) { 7819fabdb7SKonstantin Belousov warn("shm_create_largepage %s psind %d", path, idx); 7919fabdb7SKonstantin Belousov return (1); 8019fabdb7SKonstantin Belousov } 8119fabdb7SKonstantin Belousov } 825f4592e4SKonstantin Belousov close(fd); 835f4592e4SKonstantin Belousov return (0); 845f4592e4SKonstantin Belousov } 855f4592e4SKonstantin Belousov 865f4592e4SKonstantin Belousov static int 875f4592e4SKonstantin Belousov create_shm(int argc, char **argv) 885f4592e4SKonstantin Belousov { 895f4592e4SKonstantin Belousov char *end; 9019fabdb7SKonstantin Belousov size_t *pagesizes; 915f4592e4SKonstantin Belousov long mode; 9219fabdb7SKonstantin Belousov uint64_t pgsz; 9319fabdb7SKonstantin Belousov int c, i, idx, pn, ret, ret1; 9419fabdb7SKonstantin Belousov bool printed; 955f4592e4SKonstantin Belousov 965f4592e4SKonstantin Belousov mode = 0600; 9719fabdb7SKonstantin Belousov idx = -1; 9819fabdb7SKonstantin Belousov while ((c = getopt(argc, argv, "l:m:")) != -1) { 995f4592e4SKonstantin Belousov switch (c) { 1005f4592e4SKonstantin Belousov case 'm': 1015f4592e4SKonstantin Belousov errno = 0; 1025f4592e4SKonstantin Belousov mode = strtol(optarg, &end, 0); 1035f4592e4SKonstantin Belousov if (mode == 0 && errno != 0) 10419fabdb7SKonstantin Belousov err(1, "mode"); 1055f4592e4SKonstantin Belousov if (*end != '\0') 1065f4592e4SKonstantin Belousov errx(1, "non-integer mode"); 1075f4592e4SKonstantin Belousov break; 10819fabdb7SKonstantin Belousov case 'l': 10919fabdb7SKonstantin Belousov if (expand_number(optarg, &pgsz) == -1) 11019fabdb7SKonstantin Belousov err(1, "size"); 11119fabdb7SKonstantin Belousov pn = getpagesizes(NULL, 0); 11219fabdb7SKonstantin Belousov if (pn == -1) 11319fabdb7SKonstantin Belousov err(1, "getpagesizes"); 11419fabdb7SKonstantin Belousov pagesizes = malloc(sizeof(size_t) * pn); 11519fabdb7SKonstantin Belousov if (pagesizes == NULL) 11619fabdb7SKonstantin Belousov err(1, "malloc"); 11719fabdb7SKonstantin Belousov if (getpagesizes(pagesizes, pn) == -1) 11819fabdb7SKonstantin Belousov err(1, "gtpagesizes"); 11919fabdb7SKonstantin Belousov for (idx = 0; idx < pn; idx++) { 12019fabdb7SKonstantin Belousov if (pagesizes[idx] == pgsz) 12119fabdb7SKonstantin Belousov break; 12219fabdb7SKonstantin Belousov } 12319fabdb7SKonstantin Belousov if (idx == pn) { 12419fabdb7SKonstantin Belousov fprintf(stderr, 12519fabdb7SKonstantin Belousov "pagesize should be superpagesize, supported sizes:"); 12619fabdb7SKonstantin Belousov printed = false; 12719fabdb7SKonstantin Belousov for (i = 0; i < pn; i++) { 12819fabdb7SKonstantin Belousov if (pagesizes[i] == 0 || 12919fabdb7SKonstantin Belousov pagesizes[i] == (size_t) 13019fabdb7SKonstantin Belousov getpagesize()) 13119fabdb7SKonstantin Belousov continue; 13219fabdb7SKonstantin Belousov printed = true; 13319fabdb7SKonstantin Belousov fprintf(stderr, " %zu", pagesizes[i]); 13419fabdb7SKonstantin Belousov } 13519fabdb7SKonstantin Belousov if (!printed) 13619fabdb7SKonstantin Belousov fprintf(stderr, " none"); 13719fabdb7SKonstantin Belousov fprintf(stderr, "\n"); 13819fabdb7SKonstantin Belousov exit(1); 13919fabdb7SKonstantin Belousov } 14019fabdb7SKonstantin Belousov if (pgsz == (uint64_t)getpagesize()) 14119fabdb7SKonstantin Belousov errx(1, "pagesize should be large"); 14219fabdb7SKonstantin Belousov free(pagesizes); 14319fabdb7SKonstantin Belousov break; 1445f4592e4SKonstantin Belousov case '?': 1455f4592e4SKonstantin Belousov default: 1465f4592e4SKonstantin Belousov usage(); 1475f4592e4SKonstantin Belousov return (2); 1485f4592e4SKonstantin Belousov } 1495f4592e4SKonstantin Belousov } 1505f4592e4SKonstantin Belousov argc -= optind; 1515f4592e4SKonstantin Belousov argv += optind; 152*c6dce83dSMark Johnston 153*c6dce83dSMark Johnston if (argc == 0) { 154*c6dce83dSMark Johnston usage(); 155*c6dce83dSMark Johnston return (2); 156*c6dce83dSMark Johnston } 157*c6dce83dSMark Johnston 1585f4592e4SKonstantin Belousov ret = 0; 1595f4592e4SKonstantin Belousov for (i = 0; i < argc; i++) { 16019fabdb7SKonstantin Belousov ret1 = create_one_shm(argv[i], mode, idx); 1615f4592e4SKonstantin Belousov if (ret1 != 0 && ret == 0) 1625f4592e4SKonstantin Belousov ret = ret1; 1635f4592e4SKonstantin Belousov } 1645f4592e4SKonstantin Belousov return (ret); 1655f4592e4SKonstantin Belousov } 1665f4592e4SKonstantin Belousov 1675f4592e4SKonstantin Belousov static int 1685f4592e4SKonstantin Belousov delete_one_shm(const char *path) 1695f4592e4SKonstantin Belousov { 1705f4592e4SKonstantin Belousov int error, ret; 1715f4592e4SKonstantin Belousov 1725f4592e4SKonstantin Belousov error = shm_unlink(path); 1735f4592e4SKonstantin Belousov if (error != 0) { 1745f4592e4SKonstantin Belousov warn("unlink of %s failed", path); 1755f4592e4SKonstantin Belousov ret = 1; 1765f4592e4SKonstantin Belousov } else { 1775f4592e4SKonstantin Belousov ret = 0; 1785f4592e4SKonstantin Belousov } 1795f4592e4SKonstantin Belousov return (ret); 1805f4592e4SKonstantin Belousov } 1815f4592e4SKonstantin Belousov 1825f4592e4SKonstantin Belousov static int 1835f4592e4SKonstantin Belousov delete_shm(int argc, char **argv) 1845f4592e4SKonstantin Belousov { 1855f4592e4SKonstantin Belousov int i, ret, ret1; 1865f4592e4SKonstantin Belousov 187*c6dce83dSMark Johnston if (argc == 1) { 188*c6dce83dSMark Johnston usage(); 189*c6dce83dSMark Johnston return (2); 190*c6dce83dSMark Johnston } 191*c6dce83dSMark Johnston 1925f4592e4SKonstantin Belousov ret = 0; 1935f4592e4SKonstantin Belousov for (i = 1; i < argc; i++) { 1945f4592e4SKonstantin Belousov ret1 = delete_one_shm(argv[i]); 1955f4592e4SKonstantin Belousov if (ret1 != 0 && ret == 0) 1965f4592e4SKonstantin Belousov ret = ret1; 1975f4592e4SKonstantin Belousov } 1985f4592e4SKonstantin Belousov return (ret); 1995f4592e4SKonstantin Belousov } 2005f4592e4SKonstantin Belousov 2015f4592e4SKonstantin Belousov static const char listmib[] = "kern.ipc.posix_shm_list"; 2025f4592e4SKonstantin Belousov 2035f4592e4SKonstantin Belousov static void 2045f4592e4SKonstantin Belousov shm_decode_mode(mode_t m, char *str) 2055f4592e4SKonstantin Belousov { 2065f4592e4SKonstantin Belousov int i; 2075f4592e4SKonstantin Belousov 2085f4592e4SKonstantin Belousov i = 0; 2095f4592e4SKonstantin Belousov str[i++] = (m & S_IRUSR) != 0 ? 'r' : '-'; 2105f4592e4SKonstantin Belousov str[i++] = (m & S_IWUSR) != 0 ? 'w' : '-'; 2115f4592e4SKonstantin Belousov str[i++] = (m & S_IXUSR) != 0 ? 'x' : '-'; 2125f4592e4SKonstantin Belousov str[i++] = (m & S_IRGRP) != 0 ? 'r' : '-'; 2135f4592e4SKonstantin Belousov str[i++] = (m & S_IWGRP) != 0 ? 'w' : '-'; 2145f4592e4SKonstantin Belousov str[i++] = (m & S_IXGRP) != 0 ? 'x' : '-'; 2155f4592e4SKonstantin Belousov str[i++] = (m & S_IROTH) != 0 ? 'r' : '-'; 2165f4592e4SKonstantin Belousov str[i++] = (m & S_IWOTH) != 0 ? 'w' : '-'; 2175f4592e4SKonstantin Belousov str[i++] = (m & S_IXOTH) != 0 ? 'x' : '-'; 2185f4592e4SKonstantin Belousov str[i] = '\0'; 2195f4592e4SKonstantin Belousov } 2205f4592e4SKonstantin Belousov 2215f4592e4SKonstantin Belousov static int 2225f4592e4SKonstantin Belousov list_shm(int argc, char **argv) 2235f4592e4SKonstantin Belousov { 224537aac3cSKonstantin Belousov char *buf, *bp, sizebuf[8], str[10]; 2255f4592e4SKonstantin Belousov const struct kinfo_file *kif; 2265f4592e4SKonstantin Belousov struct stat st; 227537aac3cSKonstantin Belousov int c, error, fd, mib[3], ret; 2285f4592e4SKonstantin Belousov size_t len, miblen; 2295f4592e4SKonstantin Belousov bool hsize, uname; 2305f4592e4SKonstantin Belousov 2315f4592e4SKonstantin Belousov hsize = false; 2325f4592e4SKonstantin Belousov uname = true; 2335f4592e4SKonstantin Belousov 2345f4592e4SKonstantin Belousov while ((c = getopt(argc, argv, "hn")) != -1) { 2355f4592e4SKonstantin Belousov switch (c) { 2365f4592e4SKonstantin Belousov case 'h': 2375f4592e4SKonstantin Belousov hsize = true; 2385f4592e4SKonstantin Belousov break; 2395f4592e4SKonstantin Belousov case 'n': 2405f4592e4SKonstantin Belousov uname = false; 2415f4592e4SKonstantin Belousov break; 2425f4592e4SKonstantin Belousov default: 2435f4592e4SKonstantin Belousov usage(); 2445f4592e4SKonstantin Belousov return (2); 2455f4592e4SKonstantin Belousov } 2465f4592e4SKonstantin Belousov } 2475f4592e4SKonstantin Belousov if (argc != optind) { 2485f4592e4SKonstantin Belousov usage(); 2495f4592e4SKonstantin Belousov return (2); 2505f4592e4SKonstantin Belousov } 2515f4592e4SKonstantin Belousov 2525f4592e4SKonstantin Belousov miblen = nitems(mib); 2535f4592e4SKonstantin Belousov error = sysctlnametomib(listmib, mib, &miblen); 2545f4592e4SKonstantin Belousov if (error == -1) { 2555f4592e4SKonstantin Belousov warn("cannot translate %s", listmib); 2565f4592e4SKonstantin Belousov return (1); 2575f4592e4SKonstantin Belousov } 2585f4592e4SKonstantin Belousov len = 0; 2595f4592e4SKonstantin Belousov error = sysctl(mib, miblen, NULL, &len, NULL, 0); 2605f4592e4SKonstantin Belousov if (error == -1) { 2615f4592e4SKonstantin Belousov warn("cannot get %s length", listmib); 2625f4592e4SKonstantin Belousov return (1); 2635f4592e4SKonstantin Belousov } 2645f4592e4SKonstantin Belousov len = len * 4 / 3; 2655f4592e4SKonstantin Belousov buf = malloc(len); 2665f4592e4SKonstantin Belousov if (buf == NULL) { 2675f4592e4SKonstantin Belousov warn("malloc"); 2685f4592e4SKonstantin Belousov return (1); 2695f4592e4SKonstantin Belousov } 2705f4592e4SKonstantin Belousov error = sysctl(mib, miblen, buf, &len, NULL, 0); 2715f4592e4SKonstantin Belousov if (error != 0) { 2725f4592e4SKonstantin Belousov warn("reading %s", listmib); 2735f4592e4SKonstantin Belousov ret = 1; 2745f4592e4SKonstantin Belousov goto out; 2755f4592e4SKonstantin Belousov } 2765f4592e4SKonstantin Belousov ret = 0; 2775f4592e4SKonstantin Belousov printf("MODE \tOWNER\tGROUP\tSIZE\tPATH\n"); 2785f4592e4SKonstantin Belousov for (bp = buf; bp < buf + len; bp += kif->kf_structsize) { 2795f4592e4SKonstantin Belousov kif = (const struct kinfo_file *)(void *)bp; 2805f4592e4SKonstantin Belousov if (kif->kf_structsize == 0) 2815f4592e4SKonstantin Belousov break; 2825f4592e4SKonstantin Belousov fd = shm_open(kif->kf_path, O_RDONLY, 0); 2835f4592e4SKonstantin Belousov if (fd == -1) { 2845f4592e4SKonstantin Belousov warn("open %s", kif->kf_path); 2855f4592e4SKonstantin Belousov ret = 1; 2865f4592e4SKonstantin Belousov continue; 2875f4592e4SKonstantin Belousov } 2885f4592e4SKonstantin Belousov error = fstat(fd, &st); 2895f4592e4SKonstantin Belousov close(fd); 2905f4592e4SKonstantin Belousov if (error != 0) { 2915f4592e4SKonstantin Belousov warn("stat %s", kif->kf_path); 2925f4592e4SKonstantin Belousov ret = 1; 2935f4592e4SKonstantin Belousov continue; 2945f4592e4SKonstantin Belousov } 2955f4592e4SKonstantin Belousov shm_decode_mode(kif->kf_un.kf_file.kf_file_mode, str); 2965f4592e4SKonstantin Belousov printf("%s\t", str); 2975f4592e4SKonstantin Belousov if (uname) { 2985f4592e4SKonstantin Belousov printf("%s\t%s\t", user_from_uid(st.st_uid, 0), 2995f4592e4SKonstantin Belousov group_from_gid(st.st_gid, 0)); 3005f4592e4SKonstantin Belousov } else { 3015f4592e4SKonstantin Belousov printf("%d\t%d\t", st.st_uid, st.st_gid); 3025f4592e4SKonstantin Belousov } 3035f4592e4SKonstantin Belousov if (hsize) { 3045f4592e4SKonstantin Belousov humanize_number(sizebuf, sizeof(sizebuf), 3055f4592e4SKonstantin Belousov kif->kf_un.kf_file.kf_file_size, "", HN_AUTOSCALE, 3065f4592e4SKonstantin Belousov HN_NOSPACE); 3075f4592e4SKonstantin Belousov printf("%s\t", sizebuf); 3085f4592e4SKonstantin Belousov } else { 3095f4592e4SKonstantin Belousov printf("%jd\t", 3105f4592e4SKonstantin Belousov (uintmax_t)kif->kf_un.kf_file.kf_file_size); 3115f4592e4SKonstantin Belousov } 3125f4592e4SKonstantin Belousov printf("%s\n", kif->kf_path); 3135f4592e4SKonstantin Belousov } 3145f4592e4SKonstantin Belousov out: 3155f4592e4SKonstantin Belousov free(buf); 3165f4592e4SKonstantin Belousov return (ret); 3175f4592e4SKonstantin Belousov } 3185f4592e4SKonstantin Belousov 3195f4592e4SKonstantin Belousov static int 3205f4592e4SKonstantin Belousov read_one_shm(const char *path) 3215f4592e4SKonstantin Belousov { 3225f4592e4SKonstantin Belousov char buf[4096]; 3235f4592e4SKonstantin Belousov ssize_t size, se; 3245f4592e4SKonstantin Belousov int fd, ret; 3255f4592e4SKonstantin Belousov 3265f4592e4SKonstantin Belousov ret = 1; 3275f4592e4SKonstantin Belousov fd = shm_open(path, O_RDONLY, 0); 3285f4592e4SKonstantin Belousov if (fd == -1) { 3295f4592e4SKonstantin Belousov warn("open %s", path); 3305f4592e4SKonstantin Belousov goto out; 3315f4592e4SKonstantin Belousov } 3325f4592e4SKonstantin Belousov for (;;) { 3335f4592e4SKonstantin Belousov size = read(fd, buf, sizeof(buf)); 3345f4592e4SKonstantin Belousov if (size > 0) { 3355f4592e4SKonstantin Belousov se = fwrite(buf, 1, size, stdout); 3365f4592e4SKonstantin Belousov if (se < size) { 3375f4592e4SKonstantin Belousov warnx("short write to stdout"); 3385f4592e4SKonstantin Belousov goto out; 3395f4592e4SKonstantin Belousov } 3405f4592e4SKonstantin Belousov } 3415f4592e4SKonstantin Belousov if (size == (ssize_t)sizeof(buf)) 3425f4592e4SKonstantin Belousov continue; 3435f4592e4SKonstantin Belousov if (size >= 0 && size < (ssize_t)sizeof(buf)) { 3445f4592e4SKonstantin Belousov ret = 0; 3455f4592e4SKonstantin Belousov goto out; 3465f4592e4SKonstantin Belousov } 3475f4592e4SKonstantin Belousov warn("read from %s", path); 3485f4592e4SKonstantin Belousov goto out; 3495f4592e4SKonstantin Belousov } 3505f4592e4SKonstantin Belousov out: 3515f4592e4SKonstantin Belousov close(fd); 3525f4592e4SKonstantin Belousov return (ret); 3535f4592e4SKonstantin Belousov } 3545f4592e4SKonstantin Belousov 3555f4592e4SKonstantin Belousov static int 3565f4592e4SKonstantin Belousov read_shm(int argc, char **argv) 3575f4592e4SKonstantin Belousov { 3585f4592e4SKonstantin Belousov int i, ret, ret1; 3595f4592e4SKonstantin Belousov 360*c6dce83dSMark Johnston if (argc == 1) { 361*c6dce83dSMark Johnston usage(); 362*c6dce83dSMark Johnston return (2); 363*c6dce83dSMark Johnston } 364*c6dce83dSMark Johnston 3655f4592e4SKonstantin Belousov ret = 0; 3665f4592e4SKonstantin Belousov for (i = 1; i < argc; i++) { 3675f4592e4SKonstantin Belousov ret1 = read_one_shm(argv[i]); 3685f4592e4SKonstantin Belousov if (ret1 != 0 && ret == 0) 3695f4592e4SKonstantin Belousov ret = ret1; 3705f4592e4SKonstantin Belousov } 3715f4592e4SKonstantin Belousov return (ret); 3725f4592e4SKonstantin Belousov } 3735f4592e4SKonstantin Belousov 3745f4592e4SKonstantin Belousov static int 3755f4592e4SKonstantin Belousov stat_one_shm(const char *path, bool hsize, bool uname) 3765f4592e4SKonstantin Belousov { 3775f4592e4SKonstantin Belousov char sizebuf[8]; 3785f4592e4SKonstantin Belousov struct stat st; 3795f4592e4SKonstantin Belousov int error, fd, ret; 3805f4592e4SKonstantin Belousov 3815f4592e4SKonstantin Belousov fd = shm_open(path, O_RDONLY, 0); 3825f4592e4SKonstantin Belousov if (fd == -1) { 3835f4592e4SKonstantin Belousov warn("open %s", path); 3845f4592e4SKonstantin Belousov return (1); 3855f4592e4SKonstantin Belousov } 3865f4592e4SKonstantin Belousov ret = 0; 3875f4592e4SKonstantin Belousov error = fstat(fd, &st); 3885f4592e4SKonstantin Belousov if (error == -1) { 3895f4592e4SKonstantin Belousov warn("stat %s", path); 3905f4592e4SKonstantin Belousov ret = 1; 3915f4592e4SKonstantin Belousov } else { 3925f4592e4SKonstantin Belousov printf("path\t%s\n", path); 3935f4592e4SKonstantin Belousov printf("inode\t%jd\n", (uintmax_t)st.st_ino); 3945f4592e4SKonstantin Belousov printf("mode\t%#o\n", st.st_mode); 3955f4592e4SKonstantin Belousov printf("nlink\t%jd\n", (uintmax_t)st.st_nlink); 3965f4592e4SKonstantin Belousov if (uname) { 3975f4592e4SKonstantin Belousov printf("owner\t%s\n", user_from_uid(st.st_uid, 0)); 3985f4592e4SKonstantin Belousov printf("group\t%s\n", group_from_gid(st.st_gid, 0)); 3995f4592e4SKonstantin Belousov } else { 4005f4592e4SKonstantin Belousov printf("uid\t%d\n", st.st_uid); 4015f4592e4SKonstantin Belousov printf("gid\t%d\n", st.st_gid); 4025f4592e4SKonstantin Belousov } 4035f4592e4SKonstantin Belousov if (hsize) { 4045f4592e4SKonstantin Belousov humanize_number(sizebuf, sizeof(sizebuf), 4055f4592e4SKonstantin Belousov st.st_size, "", HN_AUTOSCALE, HN_NOSPACE); 4065f4592e4SKonstantin Belousov printf("size\t%s\n", sizebuf); 4075f4592e4SKonstantin Belousov } else { 4085f4592e4SKonstantin Belousov printf("size\t%jd\n", (uintmax_t)st.st_size); 4095f4592e4SKonstantin Belousov } 4105f4592e4SKonstantin Belousov printf("atime\t%ld.%09ld\n", (long)st.st_atime, 4115f4592e4SKonstantin Belousov (long)st.st_atim.tv_nsec); 4125f4592e4SKonstantin Belousov printf("mtime\t%ld.%09ld\n", (long)st.st_mtime, 4135f4592e4SKonstantin Belousov (long)st.st_mtim.tv_nsec); 4145f4592e4SKonstantin Belousov printf("ctime\t%ld.%09ld\n", (long)st.st_ctime, 4155f4592e4SKonstantin Belousov (long)st.st_ctim.tv_nsec); 4165f4592e4SKonstantin Belousov printf("birth\t%ld.%09ld\n", (long)st.st_birthtim.tv_sec, 4175f4592e4SKonstantin Belousov (long)st.st_birthtim.tv_nsec); 41819fabdb7SKonstantin Belousov if (st.st_blocks != 0) 41919fabdb7SKonstantin Belousov printf("pagesz\t%jd\n", roundup((uintmax_t)st.st_size, 42019fabdb7SKonstantin Belousov PAGE_SIZE) / st.st_blocks); 4215f4592e4SKonstantin Belousov } 4225f4592e4SKonstantin Belousov close(fd); 4235f4592e4SKonstantin Belousov return (ret); 4245f4592e4SKonstantin Belousov } 4255f4592e4SKonstantin Belousov 4265f4592e4SKonstantin Belousov static int 4275f4592e4SKonstantin Belousov stat_shm(int argc, char **argv) 4285f4592e4SKonstantin Belousov { 4295f4592e4SKonstantin Belousov int c, i, ret, ret1; 4305f4592e4SKonstantin Belousov bool hsize, uname; 4315f4592e4SKonstantin Belousov 4325f4592e4SKonstantin Belousov hsize = false; 4335f4592e4SKonstantin Belousov uname = true; 4345f4592e4SKonstantin Belousov 4355f4592e4SKonstantin Belousov while ((c = getopt(argc, argv, "hn")) != -1) { 4365f4592e4SKonstantin Belousov switch (c) { 4375f4592e4SKonstantin Belousov case 'h': 4385f4592e4SKonstantin Belousov hsize = true; 4395f4592e4SKonstantin Belousov break; 4405f4592e4SKonstantin Belousov case 'n': 4415f4592e4SKonstantin Belousov uname = false; 4425f4592e4SKonstantin Belousov break; 4435f4592e4SKonstantin Belousov default: 4445f4592e4SKonstantin Belousov usage(); 4455f4592e4SKonstantin Belousov return (2); 4465f4592e4SKonstantin Belousov } 4475f4592e4SKonstantin Belousov } 4485f4592e4SKonstantin Belousov argc -= optind; 4495f4592e4SKonstantin Belousov argv += optind; 4505f4592e4SKonstantin Belousov 451*c6dce83dSMark Johnston if (argc == 0) { 452*c6dce83dSMark Johnston usage(); 453*c6dce83dSMark Johnston return (2); 454*c6dce83dSMark Johnston } 455*c6dce83dSMark Johnston 4565f4592e4SKonstantin Belousov ret = 0; 4575f4592e4SKonstantin Belousov for (i = 0; i < argc; i++) { 4585f4592e4SKonstantin Belousov ret1 = stat_one_shm(argv[i], hsize, uname); 4595f4592e4SKonstantin Belousov if (ret1 != 0 && ret == 0) 4605f4592e4SKonstantin Belousov ret = ret1; 4615f4592e4SKonstantin Belousov } 4625f4592e4SKonstantin Belousov return (ret); 4635f4592e4SKonstantin Belousov } 4645f4592e4SKonstantin Belousov 4655f4592e4SKonstantin Belousov static int 4665f4592e4SKonstantin Belousov truncate_one_shm(const char *path, uint64_t newsize) 4675f4592e4SKonstantin Belousov { 4685f4592e4SKonstantin Belousov int error, fd, ret; 4695f4592e4SKonstantin Belousov 4705f4592e4SKonstantin Belousov ret = 0; 4715f4592e4SKonstantin Belousov fd = shm_open(path, O_RDWR, 0); 4725f4592e4SKonstantin Belousov if (fd == -1) { 4735f4592e4SKonstantin Belousov warn("open %s", path); 4745f4592e4SKonstantin Belousov return (1); 4755f4592e4SKonstantin Belousov } 4765f4592e4SKonstantin Belousov error = ftruncate(fd, newsize); 4775f4592e4SKonstantin Belousov if (error == -1) { 4785f4592e4SKonstantin Belousov warn("truncate %s", path); 4795f4592e4SKonstantin Belousov ret = 1; 4805f4592e4SKonstantin Belousov } 4815f4592e4SKonstantin Belousov close(fd); 4825f4592e4SKonstantin Belousov return (ret); 4835f4592e4SKonstantin Belousov } 4845f4592e4SKonstantin Belousov 4855f4592e4SKonstantin Belousov static int 4865f4592e4SKonstantin Belousov truncate_shm(int argc, char **argv) 4875f4592e4SKonstantin Belousov { 4885f4592e4SKonstantin Belousov uint64_t newsize; 4895f4592e4SKonstantin Belousov int c, i, ret, ret1; 4905f4592e4SKonstantin Belousov 4915f4592e4SKonstantin Belousov newsize = 0; 4925f4592e4SKonstantin Belousov while ((c = getopt(argc, argv, "s:")) != -1) { 4935f4592e4SKonstantin Belousov switch (c) { 4945f4592e4SKonstantin Belousov case 's': 4955f4592e4SKonstantin Belousov if (expand_number(optarg, &newsize) == -1) 496*c6dce83dSMark Johnston err(1, "size"); 4975f4592e4SKonstantin Belousov break; 4985f4592e4SKonstantin Belousov case '?': 4995f4592e4SKonstantin Belousov default: 5005f4592e4SKonstantin Belousov return (2); 5015f4592e4SKonstantin Belousov } 5025f4592e4SKonstantin Belousov } 5035f4592e4SKonstantin Belousov argc -= optind; 5045f4592e4SKonstantin Belousov argv += optind; 505*c6dce83dSMark Johnston 506*c6dce83dSMark Johnston if (argc == 0) { 507*c6dce83dSMark Johnston usage(); 508*c6dce83dSMark Johnston return (2); 509*c6dce83dSMark Johnston } 510*c6dce83dSMark Johnston 5115f4592e4SKonstantin Belousov ret = 0; 5125f4592e4SKonstantin Belousov for (i = 0; i < argc; i++) { 5135f4592e4SKonstantin Belousov ret1 = truncate_one_shm(argv[i], newsize); 5145f4592e4SKonstantin Belousov if (ret1 != 0 && ret == 0) 5155f4592e4SKonstantin Belousov ret = ret1; 5165f4592e4SKonstantin Belousov } 5175f4592e4SKonstantin Belousov return (ret); 5185f4592e4SKonstantin Belousov } 5195f4592e4SKonstantin Belousov 5205f4592e4SKonstantin Belousov struct opmode { 5215f4592e4SKonstantin Belousov const char *cmd; 5225f4592e4SKonstantin Belousov int (*impl)(int argc, char **argv); 5235f4592e4SKonstantin Belousov }; 5245f4592e4SKonstantin Belousov 5255f4592e4SKonstantin Belousov static const struct opmode opmodes[] = { 5265f4592e4SKonstantin Belousov { .cmd = "create", .impl = create_shm}, 5275f4592e4SKonstantin Belousov { .cmd = "rm", .impl = delete_shm, }, 528a24ac0ceSKonstantin Belousov { .cmd = "list", .impl = list_shm }, 5295f4592e4SKonstantin Belousov { .cmd = "ls", .impl = list_shm }, 5305f4592e4SKonstantin Belousov { .cmd = "dump", .impl = read_shm, }, 5315f4592e4SKonstantin Belousov { .cmd = "stat", .impl = stat_shm, }, 5325f4592e4SKonstantin Belousov { .cmd = "truncate", .impl = truncate_shm, }, 5335f4592e4SKonstantin Belousov }; 5345f4592e4SKonstantin Belousov 5355f4592e4SKonstantin Belousov int 5365f4592e4SKonstantin Belousov main(int argc, char *argv[]) 5375f4592e4SKonstantin Belousov { 5385f4592e4SKonstantin Belousov const struct opmode *opmode; 5395f4592e4SKonstantin Belousov int i, ret; 5405f4592e4SKonstantin Belousov 5415f4592e4SKonstantin Belousov ret = 0; 5425f4592e4SKonstantin Belousov opmode = NULL; 5435f4592e4SKonstantin Belousov 5445f4592e4SKonstantin Belousov if (argc < 2) { 5455f4592e4SKonstantin Belousov usage(); 5465f4592e4SKonstantin Belousov exit(2); 5475f4592e4SKonstantin Belousov } 5485f4592e4SKonstantin Belousov for (i = 0; i < (int)nitems(opmodes); i++) { 5495f4592e4SKonstantin Belousov if (strcmp(argv[1], opmodes[i].cmd) == 0) { 5505f4592e4SKonstantin Belousov opmode = &opmodes[i]; 5515f4592e4SKonstantin Belousov break; 5525f4592e4SKonstantin Belousov } 5535f4592e4SKonstantin Belousov } 5545f4592e4SKonstantin Belousov if (opmode == NULL) { 5555f4592e4SKonstantin Belousov usage(); 5565f4592e4SKonstantin Belousov exit(2); 5575f4592e4SKonstantin Belousov } 5585f4592e4SKonstantin Belousov ret = opmode->impl(argc - 1, argv + 1); 5595f4592e4SKonstantin Belousov exit(ret); 5605f4592e4SKonstantin Belousov } 561