1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright (c) 2000-2001 by Sun Microsystems, Inc. 24*7c478bd9Sstevel@tonic-gate * All rights reserved. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * Routines to support fssnap subcommand of switchout. See switchout.c for 31*7c478bd9Sstevel@tonic-gate * the real fssnap command. 32*7c478bd9Sstevel@tonic-gate */ 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate #include <stdio.h> 35*7c478bd9Sstevel@tonic-gate #include <kstat.h> 36*7c478bd9Sstevel@tonic-gate #include <libintl.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/fssnap_if.h> 38*7c478bd9Sstevel@tonic-gate #include <string.h> 39*7c478bd9Sstevel@tonic-gate #include <errno.h> 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate static void fssnap_display_info(ulong_t, int *, int); 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate #define MAX_INFO_DESCRIPTORS (10) 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate static char *infosubopts[] = { 46*7c478bd9Sstevel@tonic-gate #define INFO_SNAPSHOT (0) 47*7c478bd9Sstevel@tonic-gate "snapnumber", 48*7c478bd9Sstevel@tonic-gate #define INFO_BLKDEV (1) 49*7c478bd9Sstevel@tonic-gate "blockdevname", 50*7c478bd9Sstevel@tonic-gate #define INFO_CHARDEV (2) 51*7c478bd9Sstevel@tonic-gate "rawdevname", 52*7c478bd9Sstevel@tonic-gate #define INFO_MNTPT (3) 53*7c478bd9Sstevel@tonic-gate "mountpoint", 54*7c478bd9Sstevel@tonic-gate #define INFO_STATE (4) 55*7c478bd9Sstevel@tonic-gate "state", 56*7c478bd9Sstevel@tonic-gate #define INFO_BACKPATH (5) 57*7c478bd9Sstevel@tonic-gate "backing-store", 58*7c478bd9Sstevel@tonic-gate #define INFO_BACKSIZE (6) 59*7c478bd9Sstevel@tonic-gate "backing-store-len", 60*7c478bd9Sstevel@tonic-gate #define INFO_MAXSIZE (7) 61*7c478bd9Sstevel@tonic-gate "maxsize", 62*7c478bd9Sstevel@tonic-gate #define INFO_CREATETIME (8) 63*7c478bd9Sstevel@tonic-gate "createtime", 64*7c478bd9Sstevel@tonic-gate #define INFO_CHUNKSIZE (9) 65*7c478bd9Sstevel@tonic-gate "chunksize", 66*7c478bd9Sstevel@tonic-gate NULL 67*7c478bd9Sstevel@tonic-gate }; 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate #define BLOCK_PATH "/dev/" SNAP_BLOCK_NAME "/" 70*7c478bd9Sstevel@tonic-gate #define CHAR_PATH "/dev/" SNAP_CHAR_NAME "/" 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate /* labels are truncated to this many characters when displayed */ 73*7c478bd9Sstevel@tonic-gate #define MAX_LABEL_LEN (30) 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate /* 76*7c478bd9Sstevel@tonic-gate * fssnap_show_status() - display file system snapshot status 77*7c478bd9Sstevel@tonic-gate * 78*7c478bd9Sstevel@tonic-gate * displays snapshot information. If mountpoint is set, information is 79*7c478bd9Sstevel@tonic-gate * only displayed for the snapshot (if one exists) on that file system. 80*7c478bd9Sstevel@tonic-gate * If mountpoint is NULL, information is displayed for all snapshots. 81*7c478bd9Sstevel@tonic-gate * 82*7c478bd9Sstevel@tonic-gate * If opts is defined, it is parsed as a list of suboptions (via 83*7c478bd9Sstevel@tonic-gate * getsubopt()) corresponding to the options list defined above. These 84*7c478bd9Sstevel@tonic-gate * options determine what data should be displayed and in what order. An 85*7c478bd9Sstevel@tonic-gate * option may appear more than once. 86*7c478bd9Sstevel@tonic-gate * 87*7c478bd9Sstevel@tonic-gate * The labels parameter is a boolean that determines whether labels 88*7c478bd9Sstevel@tonic-gate * (internationalized) are displayed before each data element. If it is 89*7c478bd9Sstevel@tonic-gate * 0, labels are not displayed, otherwise they are. The labels parameter 90*7c478bd9Sstevel@tonic-gate * is ignored if brief is nonzero. 91*7c478bd9Sstevel@tonic-gate * 92*7c478bd9Sstevel@tonic-gate * The brief parameter is also a boolean and specifies a mode where only 93*7c478bd9Sstevel@tonic-gate * the snapshot number and mount point are displayed, regardless of the 94*7c478bd9Sstevel@tonic-gate * value of labels. This could be used for listing all active snapshots. 95*7c478bd9Sstevel@tonic-gate * 96*7c478bd9Sstevel@tonic-gate * Based on these parameters, an order list is created that tells 97*7c478bd9Sstevel@tonic-gate * fssnap_display_info() what info to display and in what order. 98*7c478bd9Sstevel@tonic-gate * 99*7c478bd9Sstevel@tonic-gate * Note that when labels are not specified, the assumption is that the 100*7c478bd9Sstevel@tonic-gate * output is made for script readable consumption. For this reason, text 101*7c478bd9Sstevel@tonic-gate * is not I18N'd and numbers are left as bytes instead of converted to KB. 102*7c478bd9Sstevel@tonic-gate */ 103*7c478bd9Sstevel@tonic-gate void 104*7c478bd9Sstevel@tonic-gate fssnap_show_status(char *mountpoint, char *opts, int labels, int brief) 105*7c478bd9Sstevel@tonic-gate { 106*7c478bd9Sstevel@tonic-gate int *order, orderlen = MAX_INFO_DESCRIPTORS+1; 107*7c478bd9Sstevel@tonic-gate kstat_ctl_t *kslib; 108*7c478bd9Sstevel@tonic-gate kstat_t *mnt; 109*7c478bd9Sstevel@tonic-gate kstat_t *kshigh; 110*7c478bd9Sstevel@tonic-gate kstat_named_t *highp; 111*7c478bd9Sstevel@tonic-gate char *suboptions, *v, *n; 112*7c478bd9Sstevel@tonic-gate int i = 0; 113*7c478bd9Sstevel@tonic-gate int num, usenum = 0; 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate kslib = kstat_open(); 116*7c478bd9Sstevel@tonic-gate kshigh = kstat_lookup(kslib, SNAP_NAME, 0, FSSNAP_KSTAT_HIGHWATER); 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate /* 119*7c478bd9Sstevel@tonic-gate * First check and see if they gave us a mount point or a device 120*7c478bd9Sstevel@tonic-gate * name (ie /dev/fssnap/X or /dev/rfssnap/X). 121*7c478bd9Sstevel@tonic-gate */ 122*7c478bd9Sstevel@tonic-gate if (mountpoint) { 123*7c478bd9Sstevel@tonic-gate if (strncmp(BLOCK_PATH, mountpoint, strlen(BLOCK_PATH)) == 0 || 124*7c478bd9Sstevel@tonic-gate strncmp(CHAR_PATH, mountpoint, strlen(CHAR_PATH)) == 0) { 125*7c478bd9Sstevel@tonic-gate n = strrchr(mountpoint, '/'); 126*7c478bd9Sstevel@tonic-gate n++; 127*7c478bd9Sstevel@tonic-gate if (isdigit(*n)) { 128*7c478bd9Sstevel@tonic-gate errno = 0; 129*7c478bd9Sstevel@tonic-gate num = (int)strtol(n, NULL, 10); 130*7c478bd9Sstevel@tonic-gate if (errno == 0) { 131*7c478bd9Sstevel@tonic-gate usenum++; 132*7c478bd9Sstevel@tonic-gate } 133*7c478bd9Sstevel@tonic-gate } 134*7c478bd9Sstevel@tonic-gate } 135*7c478bd9Sstevel@tonic-gate } 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate if (opts) { 138*7c478bd9Sstevel@tonic-gate i = 0; 139*7c478bd9Sstevel@tonic-gate order = (int *)malloc(orderlen * sizeof (int)); 140*7c478bd9Sstevel@tonic-gate if (order == NULL) { 141*7c478bd9Sstevel@tonic-gate fprintf(stderr, 142*7c478bd9Sstevel@tonic-gate gettext("cannot allocate order list.\n")); 143*7c478bd9Sstevel@tonic-gate return; 144*7c478bd9Sstevel@tonic-gate } 145*7c478bd9Sstevel@tonic-gate suboptions = opts; 146*7c478bd9Sstevel@tonic-gate while (*suboptions != '\0') { 147*7c478bd9Sstevel@tonic-gate /* 148*7c478bd9Sstevel@tonic-gate * -1 means invalid option, MAX_INFO_DESCRIPTORS is 149*7c478bd9Sstevel@tonic-gate * the end. 150*7c478bd9Sstevel@tonic-gate */ 151*7c478bd9Sstevel@tonic-gate order[i++] = getsubopt(&suboptions, infosubopts, &v); 152*7c478bd9Sstevel@tonic-gate if (i >= orderlen) { 153*7c478bd9Sstevel@tonic-gate order = (int *)realloc(order, 154*7c478bd9Sstevel@tonic-gate sizeof (int) * (orderlen *= 2)); 155*7c478bd9Sstevel@tonic-gate if (order == NULL) { 156*7c478bd9Sstevel@tonic-gate fprintf(stderr, 157*7c478bd9Sstevel@tonic-gate gettext("cannot reallocate order " 158*7c478bd9Sstevel@tonic-gate "list.\n")); 159*7c478bd9Sstevel@tonic-gate return; 160*7c478bd9Sstevel@tonic-gate } 161*7c478bd9Sstevel@tonic-gate } 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate } 164*7c478bd9Sstevel@tonic-gate order[i] = MAX_INFO_DESCRIPTORS; 165*7c478bd9Sstevel@tonic-gate } else { 166*7c478bd9Sstevel@tonic-gate order = (int *)malloc(orderlen * sizeof (int)); 167*7c478bd9Sstevel@tonic-gate if (order == NULL) { 168*7c478bd9Sstevel@tonic-gate fprintf(stderr, 169*7c478bd9Sstevel@tonic-gate gettext("cannot allocate order list.\n")); 170*7c478bd9Sstevel@tonic-gate return; 171*7c478bd9Sstevel@tonic-gate } 172*7c478bd9Sstevel@tonic-gate for (i = 0; i <= MAX_INFO_DESCRIPTORS; i++) 173*7c478bd9Sstevel@tonic-gate order[i] = i; 174*7c478bd9Sstevel@tonic-gate } 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate /* check if fssnap module is loaded */ 177*7c478bd9Sstevel@tonic-gate if (kshigh == NULL) { 178*7c478bd9Sstevel@tonic-gate kstat_close(kslib); 179*7c478bd9Sstevel@tonic-gate return; 180*7c478bd9Sstevel@tonic-gate } 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate (void) kstat_read(kslib, kshigh, NULL); 183*7c478bd9Sstevel@tonic-gate highp = kstat_data_lookup(kshigh, FSSNAP_KSTAT_HIGHWATER); 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate /* Loop up to the maximum number of snapshots */ 186*7c478bd9Sstevel@tonic-gate for (i = 0; i <= highp->value.ui32; i++) { 187*7c478bd9Sstevel@tonic-gate mnt = kstat_lookup(kslib, SNAP_NAME, i, FSSNAP_KSTAT_MNTPT); 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate /* if this snapshot is not allocated, skip to the next */ 190*7c478bd9Sstevel@tonic-gate if (mnt == NULL) 191*7c478bd9Sstevel@tonic-gate continue; 192*7c478bd9Sstevel@tonic-gate if (kstat_read(kslib, mnt, NULL) == -1) 193*7c478bd9Sstevel@tonic-gate continue; 194*7c478bd9Sstevel@tonic-gate if (mountpoint != NULL) { 195*7c478bd9Sstevel@tonic-gate if ((usenum && i != num) || 196*7c478bd9Sstevel@tonic-gate (!usenum && strcmp(mountpoint, mnt->ks_data) != 0)) 197*7c478bd9Sstevel@tonic-gate continue; 198*7c478bd9Sstevel@tonic-gate } 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate if (brief) 201*7c478bd9Sstevel@tonic-gate printf("%4d\t%s\n", i, (char *)mnt->ks_data); 202*7c478bd9Sstevel@tonic-gate else 203*7c478bd9Sstevel@tonic-gate fssnap_display_info(i, order, labels); 204*7c478bd9Sstevel@tonic-gate } 205*7c478bd9Sstevel@tonic-gate } 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate static void 208*7c478bd9Sstevel@tonic-gate fssnap_display_info(ulong_t snapnum, int *order, int labels) 209*7c478bd9Sstevel@tonic-gate { 210*7c478bd9Sstevel@tonic-gate kstat_ctl_t *kslib; 211*7c478bd9Sstevel@tonic-gate kstat_t *back, *num; 212*7c478bd9Sstevel@tonic-gate kstat_named_t *numvalp; 213*7c478bd9Sstevel@tonic-gate kstat_t *mnt; 214*7c478bd9Sstevel@tonic-gate u_longlong_t inuse, size = 0; 215*7c478bd9Sstevel@tonic-gate char buf[BUFSIZ], *first; 216*7c478bd9Sstevel@tonic-gate int i; 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate /* load num kstat */ 219*7c478bd9Sstevel@tonic-gate kslib = kstat_open(); 220*7c478bd9Sstevel@tonic-gate num = kstat_lookup(kslib, SNAP_NAME, snapnum, FSSNAP_KSTAT_NUM); 221*7c478bd9Sstevel@tonic-gate if (num == NULL) 222*7c478bd9Sstevel@tonic-gate return; 223*7c478bd9Sstevel@tonic-gate 224*7c478bd9Sstevel@tonic-gate if (kstat_read(kslib, num, NULL) == -1) 225*7c478bd9Sstevel@tonic-gate return; 226*7c478bd9Sstevel@tonic-gate 227*7c478bd9Sstevel@tonic-gate for (i = 0; order[i] != MAX_INFO_DESCRIPTORS; i++) { 228*7c478bd9Sstevel@tonic-gate switch (order[i]) { 229*7c478bd9Sstevel@tonic-gate case INFO_SNAPSHOT: 230*7c478bd9Sstevel@tonic-gate if (labels) 231*7c478bd9Sstevel@tonic-gate printf("%-*s: %lu\n", MAX_LABEL_LEN, 232*7c478bd9Sstevel@tonic-gate gettext("Snapshot number"), snapnum); 233*7c478bd9Sstevel@tonic-gate else 234*7c478bd9Sstevel@tonic-gate printf("%lu\n", snapnum); 235*7c478bd9Sstevel@tonic-gate break; 236*7c478bd9Sstevel@tonic-gate case INFO_BLKDEV: 237*7c478bd9Sstevel@tonic-gate if (labels) 238*7c478bd9Sstevel@tonic-gate printf("%-*s: /dev/%s/%lu\n", MAX_LABEL_LEN, 239*7c478bd9Sstevel@tonic-gate gettext("Block Device"), SNAP_BLOCK_NAME, 240*7c478bd9Sstevel@tonic-gate snapnum); 241*7c478bd9Sstevel@tonic-gate else 242*7c478bd9Sstevel@tonic-gate printf("/dev/%s/%lu\n", SNAP_BLOCK_NAME, 243*7c478bd9Sstevel@tonic-gate snapnum); 244*7c478bd9Sstevel@tonic-gate break; 245*7c478bd9Sstevel@tonic-gate case INFO_CHARDEV: 246*7c478bd9Sstevel@tonic-gate if (labels) 247*7c478bd9Sstevel@tonic-gate printf("%-*s: /dev/%s/%lu\n", MAX_LABEL_LEN, 248*7c478bd9Sstevel@tonic-gate gettext("Raw Device"), SNAP_CHAR_NAME, 249*7c478bd9Sstevel@tonic-gate snapnum); 250*7c478bd9Sstevel@tonic-gate else 251*7c478bd9Sstevel@tonic-gate printf("/dev/%s/%lu\n", SNAP_CHAR_NAME, 252*7c478bd9Sstevel@tonic-gate snapnum); 253*7c478bd9Sstevel@tonic-gate break; 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate case INFO_MNTPT: 256*7c478bd9Sstevel@tonic-gate mnt = kstat_lookup(kslib, SNAP_NAME, snapnum, 257*7c478bd9Sstevel@tonic-gate FSSNAP_KSTAT_MNTPT); 258*7c478bd9Sstevel@tonic-gate if (mnt == NULL) { 259*7c478bd9Sstevel@tonic-gate fprintf(stderr, 260*7c478bd9Sstevel@tonic-gate gettext("cannot read mount point kstat\n")); 261*7c478bd9Sstevel@tonic-gate continue; 262*7c478bd9Sstevel@tonic-gate } 263*7c478bd9Sstevel@tonic-gate if (kstat_read(kslib, mnt, NULL) == -1) { 264*7c478bd9Sstevel@tonic-gate continue; 265*7c478bd9Sstevel@tonic-gate } 266*7c478bd9Sstevel@tonic-gate if (labels) 267*7c478bd9Sstevel@tonic-gate printf("%-*s: %s\n", MAX_LABEL_LEN, 268*7c478bd9Sstevel@tonic-gate gettext("Mount point"), 269*7c478bd9Sstevel@tonic-gate (char *)mnt->ks_data); 270*7c478bd9Sstevel@tonic-gate else 271*7c478bd9Sstevel@tonic-gate printf("%s\n", (char *)mnt->ks_data); 272*7c478bd9Sstevel@tonic-gate break; 273*7c478bd9Sstevel@tonic-gate case INFO_STATE: 274*7c478bd9Sstevel@tonic-gate /* state */ 275*7c478bd9Sstevel@tonic-gate numvalp = kstat_data_lookup(num, 276*7c478bd9Sstevel@tonic-gate FSSNAP_KSTAT_NUM_STATE); 277*7c478bd9Sstevel@tonic-gate if (numvalp == NULL) { 278*7c478bd9Sstevel@tonic-gate fprintf(stderr, 279*7c478bd9Sstevel@tonic-gate gettext("cannot read state kstat\n")); 280*7c478bd9Sstevel@tonic-gate continue; 281*7c478bd9Sstevel@tonic-gate } 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate if (labels) { 284*7c478bd9Sstevel@tonic-gate printf("%-*s: ", MAX_LABEL_LEN, 285*7c478bd9Sstevel@tonic-gate gettext("Device state")); 286*7c478bd9Sstevel@tonic-gate switch (numvalp->value.i32) { 287*7c478bd9Sstevel@tonic-gate case 0: printf(gettext("creating\n")); 288*7c478bd9Sstevel@tonic-gate break; 289*7c478bd9Sstevel@tonic-gate case 1: printf(gettext("idle\n")); 290*7c478bd9Sstevel@tonic-gate break; 291*7c478bd9Sstevel@tonic-gate case 2: printf(gettext("active\n")); 292*7c478bd9Sstevel@tonic-gate break; 293*7c478bd9Sstevel@tonic-gate case 3: printf(gettext("disabled\n")); 294*7c478bd9Sstevel@tonic-gate break; 295*7c478bd9Sstevel@tonic-gate default: printf(gettext("unknown\n")); 296*7c478bd9Sstevel@tonic-gate break; 297*7c478bd9Sstevel@tonic-gate } 298*7c478bd9Sstevel@tonic-gate } else { 299*7c478bd9Sstevel@tonic-gate switch (numvalp->value.i32) { 300*7c478bd9Sstevel@tonic-gate case 0: printf("creating\n"); 301*7c478bd9Sstevel@tonic-gate break; 302*7c478bd9Sstevel@tonic-gate case 1: printf("idle\n"); 303*7c478bd9Sstevel@tonic-gate break; 304*7c478bd9Sstevel@tonic-gate case 2: printf("active\n"); 305*7c478bd9Sstevel@tonic-gate break; 306*7c478bd9Sstevel@tonic-gate case 3: printf("disabled\n"); 307*7c478bd9Sstevel@tonic-gate break; 308*7c478bd9Sstevel@tonic-gate default: printf("unknown\n"); 309*7c478bd9Sstevel@tonic-gate break; 310*7c478bd9Sstevel@tonic-gate } 311*7c478bd9Sstevel@tonic-gate } 312*7c478bd9Sstevel@tonic-gate break; 313*7c478bd9Sstevel@tonic-gate 314*7c478bd9Sstevel@tonic-gate case INFO_BACKPATH: 315*7c478bd9Sstevel@tonic-gate /* backing file kstat */ 316*7c478bd9Sstevel@tonic-gate back = kstat_lookup(kslib, SNAP_NAME, snapnum, 317*7c478bd9Sstevel@tonic-gate FSSNAP_KSTAT_BFNAME); 318*7c478bd9Sstevel@tonic-gate if (back == NULL || 319*7c478bd9Sstevel@tonic-gate (kstat_read(kslib, back, NULL) == -1) || 320*7c478bd9Sstevel@tonic-gate (back->ks_data == NULL)) { 321*7c478bd9Sstevel@tonic-gate fprintf(stderr, 322*7c478bd9Sstevel@tonic-gate gettext("cannot read backing file name " 323*7c478bd9Sstevel@tonic-gate "kstat from kernel\n")); 324*7c478bd9Sstevel@tonic-gate continue; 325*7c478bd9Sstevel@tonic-gate } 326*7c478bd9Sstevel@tonic-gate if (labels) 327*7c478bd9Sstevel@tonic-gate printf("%-*s: %s\n", MAX_LABEL_LEN, 328*7c478bd9Sstevel@tonic-gate gettext("Backing store path"), 329*7c478bd9Sstevel@tonic-gate (char *)back->ks_data); 330*7c478bd9Sstevel@tonic-gate else 331*7c478bd9Sstevel@tonic-gate printf("%s\n", (char *)back->ks_data); 332*7c478bd9Sstevel@tonic-gate break; 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate case INFO_BACKSIZE: 335*7c478bd9Sstevel@tonic-gate numvalp = kstat_data_lookup(num, 336*7c478bd9Sstevel@tonic-gate FSSNAP_KSTAT_NUM_BFSIZE); 337*7c478bd9Sstevel@tonic-gate if (numvalp == NULL) { 338*7c478bd9Sstevel@tonic-gate fprintf(stderr, 339*7c478bd9Sstevel@tonic-gate gettext("cannot read backing file size " 340*7c478bd9Sstevel@tonic-gate "kstat from kernel\n")); 341*7c478bd9Sstevel@tonic-gate continue; 342*7c478bd9Sstevel@tonic-gate } 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate size = numvalp->value.ui64; 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate if (labels) 347*7c478bd9Sstevel@tonic-gate printf("%-*s: %llu KB\n", MAX_LABEL_LEN, 348*7c478bd9Sstevel@tonic-gate gettext("Backing store size"), 349*7c478bd9Sstevel@tonic-gate size / 1024LL); 350*7c478bd9Sstevel@tonic-gate else 351*7c478bd9Sstevel@tonic-gate printf("%llu\n", size); 352*7c478bd9Sstevel@tonic-gate break; 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate case INFO_MAXSIZE: 355*7c478bd9Sstevel@tonic-gate numvalp = kstat_data_lookup(num, 356*7c478bd9Sstevel@tonic-gate FSSNAP_KSTAT_NUM_MAXSIZE); 357*7c478bd9Sstevel@tonic-gate if (numvalp == NULL) { 358*7c478bd9Sstevel@tonic-gate fprintf(stderr, 359*7c478bd9Sstevel@tonic-gate gettext("cannot read backing file maxsize " 360*7c478bd9Sstevel@tonic-gate "kstat from kernel\n")); 361*7c478bd9Sstevel@tonic-gate continue; 362*7c478bd9Sstevel@tonic-gate } 363*7c478bd9Sstevel@tonic-gate if (labels) { 364*7c478bd9Sstevel@tonic-gate printf("%-*s: ", MAX_LABEL_LEN, 365*7c478bd9Sstevel@tonic-gate gettext("Maximum backing store size")); 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate if (numvalp->value.ui64 == 0LL) 368*7c478bd9Sstevel@tonic-gate printf(gettext("Unlimited\n")); 369*7c478bd9Sstevel@tonic-gate else 370*7c478bd9Sstevel@tonic-gate printf("%llu KB\n", 371*7c478bd9Sstevel@tonic-gate numvalp->value.ui64 / 1024LL); 372*7c478bd9Sstevel@tonic-gate } else { 373*7c478bd9Sstevel@tonic-gate printf("%llu\n", numvalp->value.ui64); 374*7c478bd9Sstevel@tonic-gate } 375*7c478bd9Sstevel@tonic-gate break; 376*7c478bd9Sstevel@tonic-gate 377*7c478bd9Sstevel@tonic-gate case INFO_CREATETIME: 378*7c478bd9Sstevel@tonic-gate { 379*7c478bd9Sstevel@tonic-gate /* snapshot creation time */ 380*7c478bd9Sstevel@tonic-gate char buf[256]; 381*7c478bd9Sstevel@tonic-gate struct tm *tm; 382*7c478bd9Sstevel@tonic-gate char *p; 383*7c478bd9Sstevel@tonic-gate 384*7c478bd9Sstevel@tonic-gate numvalp = kstat_data_lookup(num, 385*7c478bd9Sstevel@tonic-gate FSSNAP_KSTAT_NUM_CREATETIME); 386*7c478bd9Sstevel@tonic-gate if (numvalp == NULL) { 387*7c478bd9Sstevel@tonic-gate fprintf(stderr, 388*7c478bd9Sstevel@tonic-gate gettext("cannot read snapshot create time " 389*7c478bd9Sstevel@tonic-gate "kstat from kernel\n")); 390*7c478bd9Sstevel@tonic-gate continue; 391*7c478bd9Sstevel@tonic-gate } 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate if (labels) { 394*7c478bd9Sstevel@tonic-gate printf("%-*s: ", MAX_LABEL_LEN, 395*7c478bd9Sstevel@tonic-gate gettext("Snapshot create time")); 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate /* get the localized time */ 398*7c478bd9Sstevel@tonic-gate tm = localtime(&numvalp->value.l); 399*7c478bd9Sstevel@tonic-gate if (strftime(buf, sizeof (buf), 400*7c478bd9Sstevel@tonic-gate "%c\n", tm) == 0) 401*7c478bd9Sstevel@tonic-gate /* Wouldn't fit in buf, fall back */ 402*7c478bd9Sstevel@tonic-gate p = ctime(&numvalp->value.l); 403*7c478bd9Sstevel@tonic-gate else 404*7c478bd9Sstevel@tonic-gate p = buf; 405*7c478bd9Sstevel@tonic-gate } else { 406*7c478bd9Sstevel@tonic-gate /* 407*7c478bd9Sstevel@tonic-gate * for script-readable options we want 408*7c478bd9Sstevel@tonic-gate * the locale-independent time only. 409*7c478bd9Sstevel@tonic-gate */ 410*7c478bd9Sstevel@tonic-gate p = ctime(&numvalp->value.l); 411*7c478bd9Sstevel@tonic-gate } 412*7c478bd9Sstevel@tonic-gate /* p should already have a \n appended */ 413*7c478bd9Sstevel@tonic-gate printf("%s", p); 414*7c478bd9Sstevel@tonic-gate break; 415*7c478bd9Sstevel@tonic-gate } 416*7c478bd9Sstevel@tonic-gate 417*7c478bd9Sstevel@tonic-gate case INFO_CHUNKSIZE: 418*7c478bd9Sstevel@tonic-gate numvalp = kstat_data_lookup(num, 419*7c478bd9Sstevel@tonic-gate FSSNAP_KSTAT_NUM_CHUNKSIZE); 420*7c478bd9Sstevel@tonic-gate if (numvalp == NULL) { 421*7c478bd9Sstevel@tonic-gate fprintf(stderr, 422*7c478bd9Sstevel@tonic-gate gettext("cannot read chunksize kstat\n")); 423*7c478bd9Sstevel@tonic-gate continue; 424*7c478bd9Sstevel@tonic-gate } 425*7c478bd9Sstevel@tonic-gate if (labels) 426*7c478bd9Sstevel@tonic-gate printf("%-*s: %lu KB\n", MAX_LABEL_LEN, 427*7c478bd9Sstevel@tonic-gate gettext("Copy-on-write granularity"), 428*7c478bd9Sstevel@tonic-gate numvalp->value.ui32 / 1024L); 429*7c478bd9Sstevel@tonic-gate else 430*7c478bd9Sstevel@tonic-gate printf("%lu\n", numvalp->value.ui32); 431*7c478bd9Sstevel@tonic-gate break; 432*7c478bd9Sstevel@tonic-gate 433*7c478bd9Sstevel@tonic-gate case -1: 434*7c478bd9Sstevel@tonic-gate /* 435*7c478bd9Sstevel@tonic-gate * Print a place holder for unknown options so that 436*7c478bd9Sstevel@tonic-gate * the user can determine which option was not 437*7c478bd9Sstevel@tonic-gate * understood and the number outputted is the same 438*7c478bd9Sstevel@tonic-gate * number they requested. 439*7c478bd9Sstevel@tonic-gate */ 440*7c478bd9Sstevel@tonic-gate printf("?\n"); 441*7c478bd9Sstevel@tonic-gate break; 442*7c478bd9Sstevel@tonic-gate 443*7c478bd9Sstevel@tonic-gate default: 444*7c478bd9Sstevel@tonic-gate printf(gettext("No such data type %d.\n"), order[i]); 445*7c478bd9Sstevel@tonic-gate break; 446*7c478bd9Sstevel@tonic-gate } 447*7c478bd9Sstevel@tonic-gate } 448*7c478bd9Sstevel@tonic-gate } 449