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> 335f4592e4SKonstantin Belousov #include <sys/mman.h> 345f4592e4SKonstantin Belousov #include <sys/stat.h> 355f4592e4SKonstantin Belousov #include <sys/sysctl.h> 365f4592e4SKonstantin Belousov #include <sys/user.h> 375f4592e4SKonstantin Belousov #include <err.h> 385f4592e4SKonstantin Belousov #include <fcntl.h> 395f4592e4SKonstantin Belousov #include <grp.h> 405f4592e4SKonstantin Belousov #include <libutil.h> 415f4592e4SKonstantin Belousov #include <pwd.h> 425f4592e4SKonstantin Belousov #include <stdbool.h> 435f4592e4SKonstantin Belousov #include <stdio.h> 445f4592e4SKonstantin Belousov #include <stdlib.h> 455f4592e4SKonstantin Belousov #include <string.h> 465f4592e4SKonstantin Belousov #include <unistd.h> 475f4592e4SKonstantin Belousov 485f4592e4SKonstantin Belousov static void 495f4592e4SKonstantin Belousov usage(void) 505f4592e4SKonstantin Belousov { 515f4592e4SKonstantin Belousov 525f4592e4SKonstantin Belousov fprintf(stderr, "Usage:\n" 535f4592e4SKonstantin Belousov "posixshmcontrol create [-m <mode>] <path> ...\n" 545f4592e4SKonstantin Belousov "posixshmcontrol rm <path> ...\n" 555f4592e4SKonstantin Belousov "posixshmcontrol ls [-h] [-n]\n" 565f4592e4SKonstantin Belousov "posixshmcontrol dump <path> ...\n" 575f4592e4SKonstantin Belousov "posixshmcontrol stat [-h] [-n] <path> ...\n" 585f4592e4SKonstantin Belousov "posixshmcontrol truncate [-s <newlen>] <path> ...\n"); 595f4592e4SKonstantin Belousov } 605f4592e4SKonstantin Belousov 615f4592e4SKonstantin Belousov static int 625f4592e4SKonstantin Belousov create_one_shm(const char *path, long mode) 635f4592e4SKonstantin Belousov { 645f4592e4SKonstantin Belousov int fd; 655f4592e4SKonstantin Belousov 665f4592e4SKonstantin Belousov fd = shm_open(path, O_RDWR | O_CREAT, mode); 675f4592e4SKonstantin Belousov if (fd == -1) { 685f4592e4SKonstantin Belousov warn("create %s", path); 695f4592e4SKonstantin Belousov return (1); 705f4592e4SKonstantin Belousov } 715f4592e4SKonstantin Belousov close(fd); 725f4592e4SKonstantin Belousov return (0); 735f4592e4SKonstantin Belousov } 745f4592e4SKonstantin Belousov 755f4592e4SKonstantin Belousov static int 765f4592e4SKonstantin Belousov create_shm(int argc, char **argv) 775f4592e4SKonstantin Belousov { 785f4592e4SKonstantin Belousov char *end; 795f4592e4SKonstantin Belousov long mode; 805f4592e4SKonstantin Belousov int c, i, ret, ret1; 815f4592e4SKonstantin Belousov 825f4592e4SKonstantin Belousov mode = 0600; 835f4592e4SKonstantin Belousov while ((c = getopt(argc, argv, "m:")) != -1) { 845f4592e4SKonstantin Belousov switch (c) { 855f4592e4SKonstantin Belousov case 'm': 865f4592e4SKonstantin Belousov errno = 0; 875f4592e4SKonstantin Belousov mode = strtol(optarg, &end, 0); 885f4592e4SKonstantin Belousov if (mode == 0 && errno != 0) 895f4592e4SKonstantin Belousov err(1, "mode:"); 905f4592e4SKonstantin Belousov if (*end != '\0') 915f4592e4SKonstantin Belousov errx(1, "non-integer mode"); 925f4592e4SKonstantin Belousov break; 935f4592e4SKonstantin Belousov case '?': 945f4592e4SKonstantin Belousov default: 955f4592e4SKonstantin Belousov usage(); 965f4592e4SKonstantin Belousov return (2); 975f4592e4SKonstantin Belousov } 985f4592e4SKonstantin Belousov } 995f4592e4SKonstantin Belousov 1005f4592e4SKonstantin Belousov argc -= optind; 1015f4592e4SKonstantin Belousov argv += optind; 1025f4592e4SKonstantin Belousov ret = 0; 1035f4592e4SKonstantin Belousov for (i = 0; i < argc; i++) { 1045f4592e4SKonstantin Belousov ret1 = create_one_shm(argv[i], mode); 1055f4592e4SKonstantin Belousov if (ret1 != 0 && ret == 0) 1065f4592e4SKonstantin Belousov ret = ret1; 1075f4592e4SKonstantin Belousov } 1085f4592e4SKonstantin Belousov return (ret); 1095f4592e4SKonstantin Belousov } 1105f4592e4SKonstantin Belousov 1115f4592e4SKonstantin Belousov static int 1125f4592e4SKonstantin Belousov delete_one_shm(const char *path) 1135f4592e4SKonstantin Belousov { 1145f4592e4SKonstantin Belousov int error, ret; 1155f4592e4SKonstantin Belousov 1165f4592e4SKonstantin Belousov error = shm_unlink(path); 1175f4592e4SKonstantin Belousov if (error != 0) { 1185f4592e4SKonstantin Belousov warn("unlink of %s failed", path); 1195f4592e4SKonstantin Belousov ret = 1; 1205f4592e4SKonstantin Belousov } else { 1215f4592e4SKonstantin Belousov ret = 0; 1225f4592e4SKonstantin Belousov } 1235f4592e4SKonstantin Belousov return (ret); 1245f4592e4SKonstantin Belousov } 1255f4592e4SKonstantin Belousov 1265f4592e4SKonstantin Belousov static int 1275f4592e4SKonstantin Belousov delete_shm(int argc, char **argv) 1285f4592e4SKonstantin Belousov { 1295f4592e4SKonstantin Belousov int i, ret, ret1; 1305f4592e4SKonstantin Belousov 1315f4592e4SKonstantin Belousov ret = 0; 1325f4592e4SKonstantin Belousov for (i = 1; i < argc; i++) { 1335f4592e4SKonstantin Belousov ret1 = delete_one_shm(argv[i]); 1345f4592e4SKonstantin Belousov if (ret1 != 0 && ret == 0) 1355f4592e4SKonstantin Belousov ret = ret1; 1365f4592e4SKonstantin Belousov } 1375f4592e4SKonstantin Belousov return (ret); 1385f4592e4SKonstantin Belousov } 1395f4592e4SKonstantin Belousov 1405f4592e4SKonstantin Belousov static const char listmib[] = "kern.ipc.posix_shm_list"; 1415f4592e4SKonstantin Belousov 1425f4592e4SKonstantin Belousov static void 1435f4592e4SKonstantin Belousov shm_decode_mode(mode_t m, char *str) 1445f4592e4SKonstantin Belousov { 1455f4592e4SKonstantin Belousov int i; 1465f4592e4SKonstantin Belousov 1475f4592e4SKonstantin Belousov i = 0; 1485f4592e4SKonstantin Belousov str[i++] = (m & S_IRUSR) != 0 ? 'r' : '-'; 1495f4592e4SKonstantin Belousov str[i++] = (m & S_IWUSR) != 0 ? 'w' : '-'; 1505f4592e4SKonstantin Belousov str[i++] = (m & S_IXUSR) != 0 ? 'x' : '-'; 1515f4592e4SKonstantin Belousov str[i++] = (m & S_IRGRP) != 0 ? 'r' : '-'; 1525f4592e4SKonstantin Belousov str[i++] = (m & S_IWGRP) != 0 ? 'w' : '-'; 1535f4592e4SKonstantin Belousov str[i++] = (m & S_IXGRP) != 0 ? 'x' : '-'; 1545f4592e4SKonstantin Belousov str[i++] = (m & S_IROTH) != 0 ? 'r' : '-'; 1555f4592e4SKonstantin Belousov str[i++] = (m & S_IWOTH) != 0 ? 'w' : '-'; 1565f4592e4SKonstantin Belousov str[i++] = (m & S_IXOTH) != 0 ? 'x' : '-'; 1575f4592e4SKonstantin Belousov str[i] = '\0'; 1585f4592e4SKonstantin Belousov } 1595f4592e4SKonstantin Belousov 1605f4592e4SKonstantin Belousov static int 1615f4592e4SKonstantin Belousov list_shm(int argc, char **argv) 1625f4592e4SKonstantin Belousov { 163537aac3cSKonstantin Belousov char *buf, *bp, sizebuf[8], str[10]; 1645f4592e4SKonstantin Belousov const struct kinfo_file *kif; 1655f4592e4SKonstantin Belousov struct stat st; 166537aac3cSKonstantin Belousov int c, error, fd, mib[3], ret; 1675f4592e4SKonstantin Belousov size_t len, miblen; 1685f4592e4SKonstantin Belousov bool hsize, uname; 1695f4592e4SKonstantin Belousov 1705f4592e4SKonstantin Belousov hsize = false; 1715f4592e4SKonstantin Belousov uname = true; 1725f4592e4SKonstantin Belousov 1735f4592e4SKonstantin Belousov while ((c = getopt(argc, argv, "hn")) != -1) { 1745f4592e4SKonstantin Belousov switch (c) { 1755f4592e4SKonstantin Belousov case 'h': 1765f4592e4SKonstantin Belousov hsize = true; 1775f4592e4SKonstantin Belousov break; 1785f4592e4SKonstantin Belousov case 'n': 1795f4592e4SKonstantin Belousov uname = false; 1805f4592e4SKonstantin Belousov break; 1815f4592e4SKonstantin Belousov default: 1825f4592e4SKonstantin Belousov usage(); 1835f4592e4SKonstantin Belousov return (2); 1845f4592e4SKonstantin Belousov } 1855f4592e4SKonstantin Belousov } 1865f4592e4SKonstantin Belousov if (argc != optind) { 1875f4592e4SKonstantin Belousov usage(); 1885f4592e4SKonstantin Belousov return (2); 1895f4592e4SKonstantin Belousov } 1905f4592e4SKonstantin Belousov 1915f4592e4SKonstantin Belousov miblen = nitems(mib); 1925f4592e4SKonstantin Belousov error = sysctlnametomib(listmib, mib, &miblen); 1935f4592e4SKonstantin Belousov if (error == -1) { 1945f4592e4SKonstantin Belousov warn("cannot translate %s", listmib); 1955f4592e4SKonstantin Belousov return (1); 1965f4592e4SKonstantin Belousov } 1975f4592e4SKonstantin Belousov len = 0; 1985f4592e4SKonstantin Belousov error = sysctl(mib, miblen, NULL, &len, NULL, 0); 1995f4592e4SKonstantin Belousov if (error == -1) { 2005f4592e4SKonstantin Belousov warn("cannot get %s length", listmib); 2015f4592e4SKonstantin Belousov return (1); 2025f4592e4SKonstantin Belousov } 2035f4592e4SKonstantin Belousov len = len * 4 / 3; 2045f4592e4SKonstantin Belousov buf = malloc(len); 2055f4592e4SKonstantin Belousov if (buf == NULL) { 2065f4592e4SKonstantin Belousov warn("malloc"); 2075f4592e4SKonstantin Belousov return (1); 2085f4592e4SKonstantin Belousov } 2095f4592e4SKonstantin Belousov error = sysctl(mib, miblen, buf, &len, NULL, 0); 2105f4592e4SKonstantin Belousov if (error != 0) { 2115f4592e4SKonstantin Belousov warn("reading %s", listmib); 2125f4592e4SKonstantin Belousov ret = 1; 2135f4592e4SKonstantin Belousov goto out; 2145f4592e4SKonstantin Belousov } 2155f4592e4SKonstantin Belousov ret = 0; 2165f4592e4SKonstantin Belousov printf("MODE \tOWNER\tGROUP\tSIZE\tPATH\n"); 2175f4592e4SKonstantin Belousov for (bp = buf; bp < buf + len; bp += kif->kf_structsize) { 2185f4592e4SKonstantin Belousov kif = (const struct kinfo_file *)(void *)bp; 2195f4592e4SKonstantin Belousov if (kif->kf_structsize == 0) 2205f4592e4SKonstantin Belousov break; 2215f4592e4SKonstantin Belousov fd = shm_open(kif->kf_path, O_RDONLY, 0); 2225f4592e4SKonstantin Belousov if (fd == -1) { 2235f4592e4SKonstantin Belousov warn("open %s", kif->kf_path); 2245f4592e4SKonstantin Belousov ret = 1; 2255f4592e4SKonstantin Belousov continue; 2265f4592e4SKonstantin Belousov } 2275f4592e4SKonstantin Belousov error = fstat(fd, &st); 2285f4592e4SKonstantin Belousov close(fd); 2295f4592e4SKonstantin Belousov if (error != 0) { 2305f4592e4SKonstantin Belousov warn("stat %s", kif->kf_path); 2315f4592e4SKonstantin Belousov ret = 1; 2325f4592e4SKonstantin Belousov continue; 2335f4592e4SKonstantin Belousov } 2345f4592e4SKonstantin Belousov shm_decode_mode(kif->kf_un.kf_file.kf_file_mode, str); 2355f4592e4SKonstantin Belousov printf("%s\t", str); 2365f4592e4SKonstantin Belousov if (uname) { 2375f4592e4SKonstantin Belousov printf("%s\t%s\t", user_from_uid(st.st_uid, 0), 2385f4592e4SKonstantin Belousov group_from_gid(st.st_gid, 0)); 2395f4592e4SKonstantin Belousov } else { 2405f4592e4SKonstantin Belousov printf("%d\t%d\t", st.st_uid, st.st_gid); 2415f4592e4SKonstantin Belousov } 2425f4592e4SKonstantin Belousov if (hsize) { 2435f4592e4SKonstantin Belousov humanize_number(sizebuf, sizeof(sizebuf), 2445f4592e4SKonstantin Belousov kif->kf_un.kf_file.kf_file_size, "", HN_AUTOSCALE, 2455f4592e4SKonstantin Belousov HN_NOSPACE); 2465f4592e4SKonstantin Belousov printf("%s\t", sizebuf); 2475f4592e4SKonstantin Belousov } else { 2485f4592e4SKonstantin Belousov printf("%jd\t", 2495f4592e4SKonstantin Belousov (uintmax_t)kif->kf_un.kf_file.kf_file_size); 2505f4592e4SKonstantin Belousov } 2515f4592e4SKonstantin Belousov printf("%s\n", kif->kf_path); 2525f4592e4SKonstantin Belousov } 2535f4592e4SKonstantin Belousov out: 2545f4592e4SKonstantin Belousov free(buf); 2555f4592e4SKonstantin Belousov return (ret); 2565f4592e4SKonstantin Belousov } 2575f4592e4SKonstantin Belousov 2585f4592e4SKonstantin Belousov static int 2595f4592e4SKonstantin Belousov read_one_shm(const char *path) 2605f4592e4SKonstantin Belousov { 2615f4592e4SKonstantin Belousov char buf[4096]; 2625f4592e4SKonstantin Belousov ssize_t size, se; 2635f4592e4SKonstantin Belousov int fd, ret; 2645f4592e4SKonstantin Belousov 2655f4592e4SKonstantin Belousov ret = 1; 2665f4592e4SKonstantin Belousov fd = shm_open(path, O_RDONLY, 0); 2675f4592e4SKonstantin Belousov if (fd == -1) { 2685f4592e4SKonstantin Belousov warn("open %s", path); 2695f4592e4SKonstantin Belousov goto out; 2705f4592e4SKonstantin Belousov } 2715f4592e4SKonstantin Belousov for (;;) { 2725f4592e4SKonstantin Belousov size = read(fd, buf, sizeof(buf)); 2735f4592e4SKonstantin Belousov if (size > 0) { 2745f4592e4SKonstantin Belousov se = fwrite(buf, 1, size, stdout); 2755f4592e4SKonstantin Belousov if (se < size) { 2765f4592e4SKonstantin Belousov warnx("short write to stdout"); 2775f4592e4SKonstantin Belousov goto out; 2785f4592e4SKonstantin Belousov } 2795f4592e4SKonstantin Belousov } 2805f4592e4SKonstantin Belousov if (size == (ssize_t)sizeof(buf)) 2815f4592e4SKonstantin Belousov continue; 2825f4592e4SKonstantin Belousov if (size >= 0 && size < (ssize_t)sizeof(buf)) { 2835f4592e4SKonstantin Belousov ret = 0; 2845f4592e4SKonstantin Belousov goto out; 2855f4592e4SKonstantin Belousov } 2865f4592e4SKonstantin Belousov warn("read from %s", path); 2875f4592e4SKonstantin Belousov goto out; 2885f4592e4SKonstantin Belousov } 2895f4592e4SKonstantin Belousov out: 2905f4592e4SKonstantin Belousov close(fd); 2915f4592e4SKonstantin Belousov return (ret); 2925f4592e4SKonstantin Belousov } 2935f4592e4SKonstantin Belousov 2945f4592e4SKonstantin Belousov static int 2955f4592e4SKonstantin Belousov read_shm(int argc, char **argv) 2965f4592e4SKonstantin Belousov { 2975f4592e4SKonstantin Belousov int i, ret, ret1; 2985f4592e4SKonstantin Belousov 2995f4592e4SKonstantin Belousov ret = 0; 3005f4592e4SKonstantin Belousov for (i = 1; i < argc; i++) { 3015f4592e4SKonstantin Belousov ret1 = read_one_shm(argv[i]); 3025f4592e4SKonstantin Belousov if (ret1 != 0 && ret == 0) 3035f4592e4SKonstantin Belousov ret = ret1; 3045f4592e4SKonstantin Belousov } 3055f4592e4SKonstantin Belousov return (ret); 3065f4592e4SKonstantin Belousov } 3075f4592e4SKonstantin Belousov 3085f4592e4SKonstantin Belousov static int 3095f4592e4SKonstantin Belousov stat_one_shm(const char *path, bool hsize, bool uname) 3105f4592e4SKonstantin Belousov { 3115f4592e4SKonstantin Belousov char sizebuf[8]; 3125f4592e4SKonstantin Belousov struct stat st; 3135f4592e4SKonstantin Belousov int error, fd, ret; 3145f4592e4SKonstantin Belousov 3155f4592e4SKonstantin Belousov fd = shm_open(path, O_RDONLY, 0); 3165f4592e4SKonstantin Belousov if (fd == -1) { 3175f4592e4SKonstantin Belousov warn("open %s", path); 3185f4592e4SKonstantin Belousov return (1); 3195f4592e4SKonstantin Belousov } 3205f4592e4SKonstantin Belousov ret = 0; 3215f4592e4SKonstantin Belousov error = fstat(fd, &st); 3225f4592e4SKonstantin Belousov if (error == -1) { 3235f4592e4SKonstantin Belousov warn("stat %s", path); 3245f4592e4SKonstantin Belousov ret = 1; 3255f4592e4SKonstantin Belousov } else { 3265f4592e4SKonstantin Belousov printf("path\t%s\n", path); 3275f4592e4SKonstantin Belousov printf("inode\t%jd\n", (uintmax_t)st.st_ino); 3285f4592e4SKonstantin Belousov printf("mode\t%#o\n", st.st_mode); 3295f4592e4SKonstantin Belousov printf("nlink\t%jd\n", (uintmax_t)st.st_nlink); 3305f4592e4SKonstantin Belousov if (uname) { 3315f4592e4SKonstantin Belousov printf("owner\t%s\n", user_from_uid(st.st_uid, 0)); 3325f4592e4SKonstantin Belousov printf("group\t%s\n", group_from_gid(st.st_gid, 0)); 3335f4592e4SKonstantin Belousov } else { 3345f4592e4SKonstantin Belousov printf("uid\t%d\n", st.st_uid); 3355f4592e4SKonstantin Belousov printf("gid\t%d\n", st.st_gid); 3365f4592e4SKonstantin Belousov } 3375f4592e4SKonstantin Belousov if (hsize) { 3385f4592e4SKonstantin Belousov humanize_number(sizebuf, sizeof(sizebuf), 3395f4592e4SKonstantin Belousov st.st_size, "", HN_AUTOSCALE, HN_NOSPACE); 3405f4592e4SKonstantin Belousov printf("size\t%s\n", sizebuf); 3415f4592e4SKonstantin Belousov } else { 3425f4592e4SKonstantin Belousov printf("size\t%jd\n", (uintmax_t)st.st_size); 3435f4592e4SKonstantin Belousov } 3445f4592e4SKonstantin Belousov printf("atime\t%ld.%09ld\n", (long)st.st_atime, 3455f4592e4SKonstantin Belousov (long)st.st_atim.tv_nsec); 3465f4592e4SKonstantin Belousov printf("mtime\t%ld.%09ld\n", (long)st.st_mtime, 3475f4592e4SKonstantin Belousov (long)st.st_mtim.tv_nsec); 3485f4592e4SKonstantin Belousov printf("ctime\t%ld.%09ld\n", (long)st.st_ctime, 3495f4592e4SKonstantin Belousov (long)st.st_ctim.tv_nsec); 3505f4592e4SKonstantin Belousov printf("birth\t%ld.%09ld\n", (long)st.st_birthtim.tv_sec, 3515f4592e4SKonstantin Belousov (long)st.st_birthtim.tv_nsec); 3525f4592e4SKonstantin Belousov } 3535f4592e4SKonstantin Belousov close(fd); 3545f4592e4SKonstantin Belousov return (ret); 3555f4592e4SKonstantin Belousov } 3565f4592e4SKonstantin Belousov 3575f4592e4SKonstantin Belousov static int 3585f4592e4SKonstantin Belousov stat_shm(int argc, char **argv) 3595f4592e4SKonstantin Belousov { 3605f4592e4SKonstantin Belousov int c, i, ret, ret1; 3615f4592e4SKonstantin Belousov bool hsize, uname; 3625f4592e4SKonstantin Belousov 3635f4592e4SKonstantin Belousov hsize = false; 3645f4592e4SKonstantin Belousov uname = true; 3655f4592e4SKonstantin Belousov 3665f4592e4SKonstantin Belousov while ((c = getopt(argc, argv, "hn")) != -1) { 3675f4592e4SKonstantin Belousov switch (c) { 3685f4592e4SKonstantin Belousov case 'h': 3695f4592e4SKonstantin Belousov hsize = true; 3705f4592e4SKonstantin Belousov break; 3715f4592e4SKonstantin Belousov case 'n': 3725f4592e4SKonstantin Belousov uname = false; 3735f4592e4SKonstantin Belousov break; 3745f4592e4SKonstantin Belousov default: 3755f4592e4SKonstantin Belousov usage(); 3765f4592e4SKonstantin Belousov return (2); 3775f4592e4SKonstantin Belousov } 3785f4592e4SKonstantin Belousov } 3795f4592e4SKonstantin Belousov argc -= optind; 3805f4592e4SKonstantin Belousov argv += optind; 3815f4592e4SKonstantin Belousov 3825f4592e4SKonstantin Belousov ret = 0; 3835f4592e4SKonstantin Belousov for (i = 0; i < argc; i++) { 3845f4592e4SKonstantin Belousov ret1 = stat_one_shm(argv[i], hsize, uname); 3855f4592e4SKonstantin Belousov if (ret1 != 0 && ret == 0) 3865f4592e4SKonstantin Belousov ret = ret1; 3875f4592e4SKonstantin Belousov } 3885f4592e4SKonstantin Belousov return (ret); 3895f4592e4SKonstantin Belousov } 3905f4592e4SKonstantin Belousov 3915f4592e4SKonstantin Belousov static int 3925f4592e4SKonstantin Belousov truncate_one_shm(const char *path, uint64_t newsize) 3935f4592e4SKonstantin Belousov { 3945f4592e4SKonstantin Belousov int error, fd, ret; 3955f4592e4SKonstantin Belousov 3965f4592e4SKonstantin Belousov ret = 0; 3975f4592e4SKonstantin Belousov fd = shm_open(path, O_RDWR, 0); 3985f4592e4SKonstantin Belousov if (fd == -1) { 3995f4592e4SKonstantin Belousov warn("open %s", path); 4005f4592e4SKonstantin Belousov return (1); 4015f4592e4SKonstantin Belousov } 4025f4592e4SKonstantin Belousov error = ftruncate(fd, newsize); 4035f4592e4SKonstantin Belousov if (error == -1) { 4045f4592e4SKonstantin Belousov warn("truncate %s", path); 4055f4592e4SKonstantin Belousov ret = 1; 4065f4592e4SKonstantin Belousov } 4075f4592e4SKonstantin Belousov close(fd); 4085f4592e4SKonstantin Belousov return (ret); 4095f4592e4SKonstantin Belousov } 4105f4592e4SKonstantin Belousov 4115f4592e4SKonstantin Belousov static int 4125f4592e4SKonstantin Belousov truncate_shm(int argc, char **argv) 4135f4592e4SKonstantin Belousov { 4145f4592e4SKonstantin Belousov uint64_t newsize; 4155f4592e4SKonstantin Belousov int c, i, ret, ret1; 4165f4592e4SKonstantin Belousov 4175f4592e4SKonstantin Belousov newsize = 0; 4185f4592e4SKonstantin Belousov while ((c = getopt(argc, argv, "s:")) != -1) { 4195f4592e4SKonstantin Belousov switch (c) { 4205f4592e4SKonstantin Belousov case 's': 4215f4592e4SKonstantin Belousov if (expand_number(optarg, &newsize) == -1) 4225f4592e4SKonstantin Belousov err(1, "size:"); 4235f4592e4SKonstantin Belousov break; 4245f4592e4SKonstantin Belousov case '?': 4255f4592e4SKonstantin Belousov default: 4265f4592e4SKonstantin Belousov return (2); 4275f4592e4SKonstantin Belousov } 4285f4592e4SKonstantin Belousov } 4295f4592e4SKonstantin Belousov 4305f4592e4SKonstantin Belousov argc -= optind; 4315f4592e4SKonstantin Belousov argv += optind; 4325f4592e4SKonstantin Belousov ret = 0; 4335f4592e4SKonstantin Belousov for (i = 0; i < argc; i++) { 4345f4592e4SKonstantin Belousov ret1 = truncate_one_shm(argv[i], newsize); 4355f4592e4SKonstantin Belousov if (ret1 != 0 && ret == 0) 4365f4592e4SKonstantin Belousov ret = ret1; 4375f4592e4SKonstantin Belousov } 4385f4592e4SKonstantin Belousov return (ret); 4395f4592e4SKonstantin Belousov } 4405f4592e4SKonstantin Belousov 4415f4592e4SKonstantin Belousov struct opmode { 4425f4592e4SKonstantin Belousov const char *cmd; 4435f4592e4SKonstantin Belousov int (*impl)(int argc, char **argv); 4445f4592e4SKonstantin Belousov }; 4455f4592e4SKonstantin Belousov 4465f4592e4SKonstantin Belousov static const struct opmode opmodes[] = { 4475f4592e4SKonstantin Belousov { .cmd = "create", .impl = create_shm}, 4485f4592e4SKonstantin Belousov { .cmd = "rm", .impl = delete_shm, }, 449*a24ac0ceSKonstantin Belousov { .cmd = "list", .impl = list_shm }, 4505f4592e4SKonstantin Belousov { .cmd = "ls", .impl = list_shm }, 4515f4592e4SKonstantin Belousov { .cmd = "dump", .impl = read_shm, }, 4525f4592e4SKonstantin Belousov { .cmd = "stat", .impl = stat_shm, }, 4535f4592e4SKonstantin Belousov { .cmd = "truncate", .impl = truncate_shm, }, 4545f4592e4SKonstantin Belousov }; 4555f4592e4SKonstantin Belousov 4565f4592e4SKonstantin Belousov int 4575f4592e4SKonstantin Belousov main(int argc, char *argv[]) 4585f4592e4SKonstantin Belousov { 4595f4592e4SKonstantin Belousov const struct opmode *opmode; 4605f4592e4SKonstantin Belousov int i, ret; 4615f4592e4SKonstantin Belousov 4625f4592e4SKonstantin Belousov ret = 0; 4635f4592e4SKonstantin Belousov opmode = NULL; 4645f4592e4SKonstantin Belousov 4655f4592e4SKonstantin Belousov if (argc < 2) { 4665f4592e4SKonstantin Belousov usage(); 4675f4592e4SKonstantin Belousov exit(2); 4685f4592e4SKonstantin Belousov } 4695f4592e4SKonstantin Belousov for (i = 0; i < (int)nitems(opmodes); i++) { 4705f4592e4SKonstantin Belousov if (strcmp(argv[1], opmodes[i].cmd) == 0) { 4715f4592e4SKonstantin Belousov opmode = &opmodes[i]; 4725f4592e4SKonstantin Belousov break; 4735f4592e4SKonstantin Belousov } 4745f4592e4SKonstantin Belousov } 4755f4592e4SKonstantin Belousov if (opmode == NULL) { 4765f4592e4SKonstantin Belousov usage(); 4775f4592e4SKonstantin Belousov exit(2); 4785f4592e4SKonstantin Belousov } 4795f4592e4SKonstantin Belousov ret = opmode->impl(argc - 1, argv + 1); 4805f4592e4SKonstantin Belousov exit(ret); 4815f4592e4SKonstantin Belousov } 482