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 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 24*7c478bd9Sstevel@tonic-gate 25*7c478bd9Sstevel@tonic-gate 26*7c478bd9Sstevel@tonic-gate /* 27*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 28*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 29*7c478bd9Sstevel@tonic-gate */ 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate #include <stdio.h> 35*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 36*7c478bd9Sstevel@tonic-gate #include <string.h> 37*7c478bd9Sstevel@tonic-gate #include <locale.h> 38*7c478bd9Sstevel@tonic-gate #include <libintl.h> 39*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 40*7c478bd9Sstevel@tonic-gate #include <ftw.h> 41*7c478bd9Sstevel@tonic-gate #include <errno.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 43*7c478bd9Sstevel@tonic-gate #include <unistd.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/statvfs.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/mnttab.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/mntent.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/vfstab.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/wait.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/mkdev.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/int_limits.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/zone.h> 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate #include "fslib.h" 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate extern char *default_fstype(char *); 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate /* 60*7c478bd9Sstevel@tonic-gate * General notice: 61*7c478bd9Sstevel@tonic-gate * String pointers in this code may point to statically allocated memory 62*7c478bd9Sstevel@tonic-gate * or dynamically allocated memory. Furthermore, a dynamically allocated 63*7c478bd9Sstevel@tonic-gate * string may be pointed to by more than one pointer. This does not pose 64*7c478bd9Sstevel@tonic-gate * a problem because malloc'ed memory is never free'd (so we don't need 65*7c478bd9Sstevel@tonic-gate * to remember which pointers point to malloc'ed memory). 66*7c478bd9Sstevel@tonic-gate */ 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate /* 69*7c478bd9Sstevel@tonic-gate * TRANSLATION_NOTE 70*7c478bd9Sstevel@tonic-gate * Only strings passed as arguments to the TRANSLATE macro need to 71*7c478bd9Sstevel@tonic-gate * be translated. 72*7c478bd9Sstevel@tonic-gate */ 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate #ifndef MNTTYPE_LOFS 75*7c478bd9Sstevel@tonic-gate #define MNTTYPE_LOFS "lofs" 76*7c478bd9Sstevel@tonic-gate #endif 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate #define EQ(s1, s2) (strcmp(s1, s2) == 0) 79*7c478bd9Sstevel@tonic-gate #define NEW(type) xmalloc(sizeof (type)) 80*7c478bd9Sstevel@tonic-gate #define CLEAR(var) (void) memset(&(var), 0, sizeof (var)) 81*7c478bd9Sstevel@tonic-gate #define MAX(a, b) ((a) > (b) ? (a) : (b)) 82*7c478bd9Sstevel@tonic-gate #define MAX3(a, b, c) MAX(a, MAX(b, c)) 83*7c478bd9Sstevel@tonic-gate #define TRANSLATE(s) new_string(gettext(s)) 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate #define MAX_OPTIONS 36 86*7c478bd9Sstevel@tonic-gate #define N_FSTYPES 20 87*7c478bd9Sstevel@tonic-gate #define MOUNT_TABLE_ENTRIES 40 /* initial allocation */ 88*7c478bd9Sstevel@tonic-gate #define MSGBUF_SIZE 1024 89*7c478bd9Sstevel@tonic-gate #define LINEBUF_SIZE 256 /* either input or output lines */ 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate #define BLOCK_SIZE 512 /* when reporting in terms of blocks */ 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate #define DEVNM_CMD "devnm" 94*7c478bd9Sstevel@tonic-gate #define FS_LIBPATH "/usr/lib/fs/" 95*7c478bd9Sstevel@tonic-gate #define MOUNT_TAB "/etc/mnttab" 96*7c478bd9Sstevel@tonic-gate #define VFS_TAB "/etc/vfstab" 97*7c478bd9Sstevel@tonic-gate #define REMOTE_FS "/etc/dfs/fstypes" 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate #define NUL '\0' 100*7c478bd9Sstevel@tonic-gate #define FALSE 0 101*7c478bd9Sstevel@tonic-gate #define TRUE 1 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate /* 104*7c478bd9Sstevel@tonic-gate * Formatting constants 105*7c478bd9Sstevel@tonic-gate */ 106*7c478bd9Sstevel@tonic-gate #define IBCS2_FILESYSTEM_WIDTH 15 /* Truncate to match ISC/SCO */ 107*7c478bd9Sstevel@tonic-gate #define IBCS2_MOUNT_POINT_WIDTH 10 /* Truncate to match ISC/SCO */ 108*7c478bd9Sstevel@tonic-gate #define FILESYSTEM_WIDTH 20 109*7c478bd9Sstevel@tonic-gate #define MOUNT_POINT_WIDTH 19 110*7c478bd9Sstevel@tonic-gate #define SPECIAL_DEVICE_WIDTH 18 111*7c478bd9Sstevel@tonic-gate #define FSTYPE_WIDTH 8 112*7c478bd9Sstevel@tonic-gate #define BLOCK_WIDTH 8 113*7c478bd9Sstevel@tonic-gate #define NFILES_WIDTH 8 114*7c478bd9Sstevel@tonic-gate #ifdef XPG4 115*7c478bd9Sstevel@tonic-gate #define KBYTE_WIDTH 11 116*7c478bd9Sstevel@tonic-gate #define AVAILABLE_WIDTH 10 117*7c478bd9Sstevel@tonic-gate #else 118*7c478bd9Sstevel@tonic-gate #define KBYTE_WIDTH 7 119*7c478bd9Sstevel@tonic-gate #define AVAILABLE_WIDTH 6 120*7c478bd9Sstevel@tonic-gate #endif 121*7c478bd9Sstevel@tonic-gate #define SCALED_WIDTH 6 122*7c478bd9Sstevel@tonic-gate #define CAPACITY_WIDTH 9 123*7c478bd9Sstevel@tonic-gate #define BSIZE_WIDTH 6 124*7c478bd9Sstevel@tonic-gate #define FRAGSIZE_WIDTH 7 125*7c478bd9Sstevel@tonic-gate #define FSID_WIDTH 7 126*7c478bd9Sstevel@tonic-gate #define FLAG_WIDTH 8 127*7c478bd9Sstevel@tonic-gate #define NAMELEN_WIDTH 7 128*7c478bd9Sstevel@tonic-gate #define MNT_SPEC_WIDTH MOUNT_POINT_WIDTH + SPECIAL_DEVICE_WIDTH + 2 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate /* 131*7c478bd9Sstevel@tonic-gate * Flags for the errmsg() function 132*7c478bd9Sstevel@tonic-gate */ 133*7c478bd9Sstevel@tonic-gate #define ERR_NOFLAGS 0x0 134*7c478bd9Sstevel@tonic-gate #define ERR_NONAME 0x1 /* don't include the program name */ 135*7c478bd9Sstevel@tonic-gate /* as a prefix */ 136*7c478bd9Sstevel@tonic-gate #define ERR_FATAL 0x2 /* call exit after printing the */ 137*7c478bd9Sstevel@tonic-gate /* message */ 138*7c478bd9Sstevel@tonic-gate #define ERR_PERROR 0x4 /* append an errno explanation to */ 139*7c478bd9Sstevel@tonic-gate /* the message */ 140*7c478bd9Sstevel@tonic-gate #define ERR_USAGE 0x8 /* print the usage line after the */ 141*7c478bd9Sstevel@tonic-gate /* message */ 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate #define NUMBER_WIDTH 40 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate /* 146*7c478bd9Sstevel@tonic-gate * A numbuf_t is used when converting a number to a string representation 147*7c478bd9Sstevel@tonic-gate */ 148*7c478bd9Sstevel@tonic-gate typedef char numbuf_t[ NUMBER_WIDTH ]; 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate /* 151*7c478bd9Sstevel@tonic-gate * We use bool_int instead of int to make clear which variables are 152*7c478bd9Sstevel@tonic-gate * supposed to be boolean 153*7c478bd9Sstevel@tonic-gate */ 154*7c478bd9Sstevel@tonic-gate typedef int bool_int; 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate struct mtab_entry { 157*7c478bd9Sstevel@tonic-gate bool_int mte_dev_is_valid; 158*7c478bd9Sstevel@tonic-gate dev_t mte_dev; 159*7c478bd9Sstevel@tonic-gate bool_int mte_ignore; /* the "ignore" option was set */ 160*7c478bd9Sstevel@tonic-gate struct extmnttab *mte_mount; 161*7c478bd9Sstevel@tonic-gate }; 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate struct df_request { 165*7c478bd9Sstevel@tonic-gate bool_int dfr_valid; 166*7c478bd9Sstevel@tonic-gate char *dfr_cmd_arg; /* what the user specified */ 167*7c478bd9Sstevel@tonic-gate struct mtab_entry *dfr_mte; 168*7c478bd9Sstevel@tonic-gate char *dfr_fstype; 169*7c478bd9Sstevel@tonic-gate int dfr_index; /* to make qsort stable */ 170*7c478bd9Sstevel@tonic-gate }; 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate #define DFR_MOUNT_POINT(dfrp) (dfrp)->dfr_mte->mte_mount->mnt_mountp 173*7c478bd9Sstevel@tonic-gate #define DFR_SPECIAL(dfrp) (dfrp)->dfr_mte->mte_mount->mnt_special 174*7c478bd9Sstevel@tonic-gate #define DFR_ISMOUNTEDFS(dfrp) ((dfrp)->dfr_mte != NULL) 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate #define DFRP(p) ((struct df_request *)(p)) 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate typedef void (*output_func)(struct df_request *, struct statvfs64 *); 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate struct df_output { 181*7c478bd9Sstevel@tonic-gate output_func dfo_func; /* function that will do the output */ 182*7c478bd9Sstevel@tonic-gate int dfo_flags; 183*7c478bd9Sstevel@tonic-gate }; 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate /* 186*7c478bd9Sstevel@tonic-gate * Output flags 187*7c478bd9Sstevel@tonic-gate */ 188*7c478bd9Sstevel@tonic-gate #define DFO_NOFLAGS 0x0 189*7c478bd9Sstevel@tonic-gate #define DFO_HEADER 0x1 /* output preceded by header */ 190*7c478bd9Sstevel@tonic-gate #define DFO_STATVFS 0x2 /* must do a statvfs64(2) */ 191*7c478bd9Sstevel@tonic-gate 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate static char *program_name; 194*7c478bd9Sstevel@tonic-gate static char df_options[MAX_OPTIONS] = "-"; 195*7c478bd9Sstevel@tonic-gate static size_t df_options_len = 1; 196*7c478bd9Sstevel@tonic-gate static char *o_option_arg; /* arg to the -o option */ 197*7c478bd9Sstevel@tonic-gate static char *FSType; 198*7c478bd9Sstevel@tonic-gate static char *remote_fstypes[N_FSTYPES+1]; /* allocate an extra one */ 199*7c478bd9Sstevel@tonic-gate /* to use as a terminator */ 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate /* 202*7c478bd9Sstevel@tonic-gate * The following three variables support an in-memory copy of the mount table 203*7c478bd9Sstevel@tonic-gate * to speedup searches. 204*7c478bd9Sstevel@tonic-gate */ 205*7c478bd9Sstevel@tonic-gate static struct mtab_entry *mount_table; /* array of mtab_entry's */ 206*7c478bd9Sstevel@tonic-gate static size_t mount_table_entries; 207*7c478bd9Sstevel@tonic-gate static size_t mount_table_allocated_entries; 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate static bool_int F_option; 210*7c478bd9Sstevel@tonic-gate static bool_int V_option; 211*7c478bd9Sstevel@tonic-gate static bool_int P_option; /* Added for XCU4 compliance */ 212*7c478bd9Sstevel@tonic-gate static bool_int Z_option; 213*7c478bd9Sstevel@tonic-gate static bool_int v_option; 214*7c478bd9Sstevel@tonic-gate #ifdef _iBCS2 215*7c478bd9Sstevel@tonic-gate char *sysv3_set; 216*7c478bd9Sstevel@tonic-gate #endif /* _iBCS2 */ 217*7c478bd9Sstevel@tonic-gate static bool_int a_option; 218*7c478bd9Sstevel@tonic-gate static bool_int b_option; 219*7c478bd9Sstevel@tonic-gate static bool_int e_option; 220*7c478bd9Sstevel@tonic-gate static bool_int g_option; 221*7c478bd9Sstevel@tonic-gate static bool_int h_option; 222*7c478bd9Sstevel@tonic-gate static bool_int k_option; 223*7c478bd9Sstevel@tonic-gate static bool_int l_option; 224*7c478bd9Sstevel@tonic-gate static bool_int n_option; 225*7c478bd9Sstevel@tonic-gate static bool_int t_option; 226*7c478bd9Sstevel@tonic-gate static bool_int o_option; 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate static bool_int tty_output; 229*7c478bd9Sstevel@tonic-gate static bool_int use_scaling; 230*7c478bd9Sstevel@tonic-gate static int scale; 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate static void usage(void); 233*7c478bd9Sstevel@tonic-gate static void do_devnm(int, char **); 234*7c478bd9Sstevel@tonic-gate static void do_df(int, char **); 235*7c478bd9Sstevel@tonic-gate static void parse_options(int, char **); 236*7c478bd9Sstevel@tonic-gate static char *basename(char *); 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate void 240*7c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 241*7c478bd9Sstevel@tonic-gate { 242*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 243*7c478bd9Sstevel@tonic-gate 244*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 245*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 246*7c478bd9Sstevel@tonic-gate #endif 247*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate program_name = basename(argv[0]); 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate #ifdef _iBCS2 252*7c478bd9Sstevel@tonic-gate sysv3_set = getenv("SYSV3"); 253*7c478bd9Sstevel@tonic-gate #endif /* _iBCS2 */ 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate if (EQ(program_name, DEVNM_CMD)) 256*7c478bd9Sstevel@tonic-gate do_devnm(argc, argv); 257*7c478bd9Sstevel@tonic-gate 258*7c478bd9Sstevel@tonic-gate parse_options(argc, argv); 259*7c478bd9Sstevel@tonic-gate 260*7c478bd9Sstevel@tonic-gate /* 261*7c478bd9Sstevel@tonic-gate * The k_option implies SunOS 4.x compatibility: when the special 262*7c478bd9Sstevel@tonic-gate * device name is too long the line will be split except when the 263*7c478bd9Sstevel@tonic-gate * output has been redirected. 264*7c478bd9Sstevel@tonic-gate * This is also valid for the -h option. 265*7c478bd9Sstevel@tonic-gate */ 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate if (use_scaling || k_option || P_option || v_option) 268*7c478bd9Sstevel@tonic-gate tty_output = isatty(1); 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate do_df(argc - optind, &argv[optind]); 271*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 272*7c478bd9Sstevel@tonic-gate } 273*7c478bd9Sstevel@tonic-gate 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate /* 276*7c478bd9Sstevel@tonic-gate * Prints an error message to stderr. 277*7c478bd9Sstevel@tonic-gate */ 278*7c478bd9Sstevel@tonic-gate /* VARARGS2 */ 279*7c478bd9Sstevel@tonic-gate static void 280*7c478bd9Sstevel@tonic-gate errmsg(int flags, char *fmt, ...) 281*7c478bd9Sstevel@tonic-gate { 282*7c478bd9Sstevel@tonic-gate char buf[MSGBUF_SIZE]; 283*7c478bd9Sstevel@tonic-gate va_list ap; 284*7c478bd9Sstevel@tonic-gate int cc; 285*7c478bd9Sstevel@tonic-gate int offset; 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate if (flags & ERR_NONAME) 288*7c478bd9Sstevel@tonic-gate offset = 0; 289*7c478bd9Sstevel@tonic-gate else 290*7c478bd9Sstevel@tonic-gate offset = sprintf(buf, "%s: ", program_name); 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate va_start(ap, fmt); 293*7c478bd9Sstevel@tonic-gate cc = vsprintf(&buf[offset], gettext(fmt), ap); 294*7c478bd9Sstevel@tonic-gate offset += cc; 295*7c478bd9Sstevel@tonic-gate va_end(ap); 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate if (flags & ERR_PERROR) { 298*7c478bd9Sstevel@tonic-gate if (buf[offset-1] != ' ') 299*7c478bd9Sstevel@tonic-gate (void) strcat(buf, " "); 300*7c478bd9Sstevel@tonic-gate (void) strcat(buf, strerror(errno)); 301*7c478bd9Sstevel@tonic-gate } 302*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", buf); 303*7c478bd9Sstevel@tonic-gate if (flags & ERR_USAGE) 304*7c478bd9Sstevel@tonic-gate usage(); 305*7c478bd9Sstevel@tonic-gate if (flags & ERR_FATAL) 306*7c478bd9Sstevel@tonic-gate exit(1); 307*7c478bd9Sstevel@tonic-gate } 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate 310*7c478bd9Sstevel@tonic-gate static void 311*7c478bd9Sstevel@tonic-gate usage() 312*7c478bd9Sstevel@tonic-gate { 313*7c478bd9Sstevel@tonic-gate #ifdef XPG4 314*7c478bd9Sstevel@tonic-gate errmsg(ERR_NONAME, 315*7c478bd9Sstevel@tonic-gate "Usage: %s [-F FSType] [-abeghklntPVZ] [-o FSType-specific_options]" 316*7c478bd9Sstevel@tonic-gate " [directory | block_device | resource]", program_name); 317*7c478bd9Sstevel@tonic-gate #else 318*7c478bd9Sstevel@tonic-gate errmsg(ERR_NONAME, 319*7c478bd9Sstevel@tonic-gate "Usage: %s [-F FSType] [-abeghklntVvZ] [-o FSType-specific_options]" 320*7c478bd9Sstevel@tonic-gate " [directory | block_device | resource]", program_name); 321*7c478bd9Sstevel@tonic-gate #endif 322*7c478bd9Sstevel@tonic-gate exit(1); 323*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 324*7c478bd9Sstevel@tonic-gate } 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate 327*7c478bd9Sstevel@tonic-gate static char * 328*7c478bd9Sstevel@tonic-gate new_string(char *s) 329*7c478bd9Sstevel@tonic-gate { 330*7c478bd9Sstevel@tonic-gate char *p = NULL; 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate if (s) { 333*7c478bd9Sstevel@tonic-gate p = strdup(s); 334*7c478bd9Sstevel@tonic-gate if (p) 335*7c478bd9Sstevel@tonic-gate return (p); 336*7c478bd9Sstevel@tonic-gate errmsg(ERR_FATAL, "out of memory"); 337*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 338*7c478bd9Sstevel@tonic-gate } 339*7c478bd9Sstevel@tonic-gate return (p); 340*7c478bd9Sstevel@tonic-gate } 341*7c478bd9Sstevel@tonic-gate 342*7c478bd9Sstevel@tonic-gate 343*7c478bd9Sstevel@tonic-gate /* 344*7c478bd9Sstevel@tonic-gate * Allocate memory using malloc but terminate if the allocation fails 345*7c478bd9Sstevel@tonic-gate */ 346*7c478bd9Sstevel@tonic-gate static void * 347*7c478bd9Sstevel@tonic-gate xmalloc(size_t size) 348*7c478bd9Sstevel@tonic-gate { 349*7c478bd9Sstevel@tonic-gate void *p = malloc(size); 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate if (p) 352*7c478bd9Sstevel@tonic-gate return (p); 353*7c478bd9Sstevel@tonic-gate errmsg(ERR_FATAL, "out of memory"); 354*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 355*7c478bd9Sstevel@tonic-gate } 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate 358*7c478bd9Sstevel@tonic-gate /* 359*7c478bd9Sstevel@tonic-gate * Allocate memory using realloc but terminate if the allocation fails 360*7c478bd9Sstevel@tonic-gate */ 361*7c478bd9Sstevel@tonic-gate static void * 362*7c478bd9Sstevel@tonic-gate xrealloc(void *ptr, size_t size) 363*7c478bd9Sstevel@tonic-gate { 364*7c478bd9Sstevel@tonic-gate void *p = realloc(ptr, size); 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate if (p) 367*7c478bd9Sstevel@tonic-gate return (p); 368*7c478bd9Sstevel@tonic-gate errmsg(ERR_FATAL, "out of memory"); 369*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 370*7c478bd9Sstevel@tonic-gate } 371*7c478bd9Sstevel@tonic-gate 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate /* 374*7c478bd9Sstevel@tonic-gate * fopen the specified file for reading but terminate if the fopen fails 375*7c478bd9Sstevel@tonic-gate */ 376*7c478bd9Sstevel@tonic-gate static FILE * 377*7c478bd9Sstevel@tonic-gate xfopen(char *file) 378*7c478bd9Sstevel@tonic-gate { 379*7c478bd9Sstevel@tonic-gate FILE *fp = fopen(file, "r"); 380*7c478bd9Sstevel@tonic-gate 381*7c478bd9Sstevel@tonic-gate if (fp == NULL) 382*7c478bd9Sstevel@tonic-gate errmsg(ERR_FATAL + ERR_PERROR, "failed to open %s:", file); 383*7c478bd9Sstevel@tonic-gate return (fp); 384*7c478bd9Sstevel@tonic-gate } 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate 387*7c478bd9Sstevel@tonic-gate /* 388*7c478bd9Sstevel@tonic-gate * Read remote file system types from REMOTE_FS into the 389*7c478bd9Sstevel@tonic-gate * remote_fstypes array. 390*7c478bd9Sstevel@tonic-gate */ 391*7c478bd9Sstevel@tonic-gate static void 392*7c478bd9Sstevel@tonic-gate init_remote_fs() 393*7c478bd9Sstevel@tonic-gate { 394*7c478bd9Sstevel@tonic-gate FILE *fp; 395*7c478bd9Sstevel@tonic-gate char line_buf[LINEBUF_SIZE]; 396*7c478bd9Sstevel@tonic-gate size_t fstype_index = 0; 397*7c478bd9Sstevel@tonic-gate 398*7c478bd9Sstevel@tonic-gate if ((fp = fopen(REMOTE_FS, "r")) == NULL) { 399*7c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, 400*7c478bd9Sstevel@tonic-gate "Warning: can't open %s, ignored", REMOTE_FS); 401*7c478bd9Sstevel@tonic-gate return; 402*7c478bd9Sstevel@tonic-gate } 403*7c478bd9Sstevel@tonic-gate 404*7c478bd9Sstevel@tonic-gate while (fgets(line_buf, sizeof (line_buf), fp) != NULL) { 405*7c478bd9Sstevel@tonic-gate char buf[LINEBUF_SIZE]; 406*7c478bd9Sstevel@tonic-gate 407*7c478bd9Sstevel@tonic-gate (void) sscanf(line_buf, "%s", buf); 408*7c478bd9Sstevel@tonic-gate remote_fstypes[fstype_index++] = new_string(buf); 409*7c478bd9Sstevel@tonic-gate 410*7c478bd9Sstevel@tonic-gate if (fstype_index == N_FSTYPES) 411*7c478bd9Sstevel@tonic-gate break; 412*7c478bd9Sstevel@tonic-gate } 413*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate 417*7c478bd9Sstevel@tonic-gate /* 418*7c478bd9Sstevel@tonic-gate * Returns TRUE if fstype is a remote file system type; 419*7c478bd9Sstevel@tonic-gate * otherwise, returns FALSE. 420*7c478bd9Sstevel@tonic-gate */ 421*7c478bd9Sstevel@tonic-gate static int 422*7c478bd9Sstevel@tonic-gate is_remote_fs(char *fstype) 423*7c478bd9Sstevel@tonic-gate { 424*7c478bd9Sstevel@tonic-gate char **p; 425*7c478bd9Sstevel@tonic-gate static bool_int remote_fs_initialized; 426*7c478bd9Sstevel@tonic-gate 427*7c478bd9Sstevel@tonic-gate if (! remote_fs_initialized) { 428*7c478bd9Sstevel@tonic-gate init_remote_fs(); 429*7c478bd9Sstevel@tonic-gate remote_fs_initialized = TRUE; 430*7c478bd9Sstevel@tonic-gate } 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate for (p = remote_fstypes; *p; p++) 433*7c478bd9Sstevel@tonic-gate if (EQ(fstype, *p)) 434*7c478bd9Sstevel@tonic-gate return (TRUE); 435*7c478bd9Sstevel@tonic-gate return (FALSE); 436*7c478bd9Sstevel@tonic-gate } 437*7c478bd9Sstevel@tonic-gate 438*7c478bd9Sstevel@tonic-gate 439*7c478bd9Sstevel@tonic-gate static char * 440*7c478bd9Sstevel@tonic-gate basename(char *s) 441*7c478bd9Sstevel@tonic-gate { 442*7c478bd9Sstevel@tonic-gate char *p = strrchr(s, '/'); 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate return (p ? p+1 : s); 445*7c478bd9Sstevel@tonic-gate } 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate 448*7c478bd9Sstevel@tonic-gate /* 449*7c478bd9Sstevel@tonic-gate * Create a new "struct extmnttab" and make sure that its fields point 450*7c478bd9Sstevel@tonic-gate * to malloc'ed memory 451*7c478bd9Sstevel@tonic-gate */ 452*7c478bd9Sstevel@tonic-gate static struct extmnttab * 453*7c478bd9Sstevel@tonic-gate mntdup(struct extmnttab *old) 454*7c478bd9Sstevel@tonic-gate { 455*7c478bd9Sstevel@tonic-gate struct extmnttab *new = NEW(struct extmnttab); 456*7c478bd9Sstevel@tonic-gate 457*7c478bd9Sstevel@tonic-gate new->mnt_special = new_string(old->mnt_special); 458*7c478bd9Sstevel@tonic-gate new->mnt_mountp = new_string(old->mnt_mountp); 459*7c478bd9Sstevel@tonic-gate new->mnt_fstype = new_string(old->mnt_fstype); 460*7c478bd9Sstevel@tonic-gate new->mnt_mntopts = new_string(old->mnt_mntopts); 461*7c478bd9Sstevel@tonic-gate new->mnt_time = new_string(old->mnt_time); 462*7c478bd9Sstevel@tonic-gate new->mnt_major = old->mnt_major; 463*7c478bd9Sstevel@tonic-gate new->mnt_minor = old->mnt_minor; 464*7c478bd9Sstevel@tonic-gate return (new); 465*7c478bd9Sstevel@tonic-gate } 466*7c478bd9Sstevel@tonic-gate 467*7c478bd9Sstevel@tonic-gate 468*7c478bd9Sstevel@tonic-gate static void 469*7c478bd9Sstevel@tonic-gate mtab_error(char *mtab_file, int status) 470*7c478bd9Sstevel@tonic-gate { 471*7c478bd9Sstevel@tonic-gate if (status == MNT_TOOLONG) 472*7c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, "a line in %s exceeds %d characters", 473*7c478bd9Sstevel@tonic-gate mtab_file, MNT_LINE_MAX); 474*7c478bd9Sstevel@tonic-gate else if (status == MNT_TOOMANY) 475*7c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, 476*7c478bd9Sstevel@tonic-gate "a line in %s has too many fields", mtab_file); 477*7c478bd9Sstevel@tonic-gate else if (status == MNT_TOOFEW) 478*7c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, 479*7c478bd9Sstevel@tonic-gate "a line in %s has too few fields", mtab_file); 480*7c478bd9Sstevel@tonic-gate else 481*7c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, 482*7c478bd9Sstevel@tonic-gate "error while reading %s: %d", mtab_file, status); 483*7c478bd9Sstevel@tonic-gate exit(1); 484*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 485*7c478bd9Sstevel@tonic-gate } 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate 488*7c478bd9Sstevel@tonic-gate /* 489*7c478bd9Sstevel@tonic-gate * Read the mount table from the specified file. 490*7c478bd9Sstevel@tonic-gate * We keep the table in memory for faster lookups. 491*7c478bd9Sstevel@tonic-gate */ 492*7c478bd9Sstevel@tonic-gate static void 493*7c478bd9Sstevel@tonic-gate mtab_read_file() 494*7c478bd9Sstevel@tonic-gate { 495*7c478bd9Sstevel@tonic-gate char *mtab_file = MOUNT_TAB; 496*7c478bd9Sstevel@tonic-gate FILE *fp; 497*7c478bd9Sstevel@tonic-gate struct extmnttab mtab; 498*7c478bd9Sstevel@tonic-gate int status; 499*7c478bd9Sstevel@tonic-gate 500*7c478bd9Sstevel@tonic-gate fp = xfopen(mtab_file); 501*7c478bd9Sstevel@tonic-gate 502*7c478bd9Sstevel@tonic-gate resetmnttab(fp); 503*7c478bd9Sstevel@tonic-gate mount_table_allocated_entries = MOUNT_TABLE_ENTRIES; 504*7c478bd9Sstevel@tonic-gate mount_table_entries = 0; 505*7c478bd9Sstevel@tonic-gate mount_table = xmalloc( 506*7c478bd9Sstevel@tonic-gate mount_table_allocated_entries * sizeof (struct mtab_entry)); 507*7c478bd9Sstevel@tonic-gate 508*7c478bd9Sstevel@tonic-gate while ((status = getextmntent(fp, &mtab, sizeof (struct extmnttab))) 509*7c478bd9Sstevel@tonic-gate == 0) { 510*7c478bd9Sstevel@tonic-gate struct mtab_entry *mtep; 511*7c478bd9Sstevel@tonic-gate 512*7c478bd9Sstevel@tonic-gate if (mount_table_entries == mount_table_allocated_entries) { 513*7c478bd9Sstevel@tonic-gate mount_table_allocated_entries += MOUNT_TABLE_ENTRIES; 514*7c478bd9Sstevel@tonic-gate mount_table = xrealloc(mount_table, 515*7c478bd9Sstevel@tonic-gate mount_table_allocated_entries * 516*7c478bd9Sstevel@tonic-gate sizeof (struct mtab_entry)); 517*7c478bd9Sstevel@tonic-gate } 518*7c478bd9Sstevel@tonic-gate mtep = &mount_table[mount_table_entries++]; 519*7c478bd9Sstevel@tonic-gate mtep->mte_mount = mntdup(&mtab); 520*7c478bd9Sstevel@tonic-gate mtep->mte_dev_is_valid = FALSE; 521*7c478bd9Sstevel@tonic-gate mtep->mte_ignore = (hasmntopt((struct mnttab *)&mtab, 522*7c478bd9Sstevel@tonic-gate MNTOPT_IGNORE) != NULL); 523*7c478bd9Sstevel@tonic-gate } 524*7c478bd9Sstevel@tonic-gate 525*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 526*7c478bd9Sstevel@tonic-gate 527*7c478bd9Sstevel@tonic-gate if (status == -1) /* reached EOF */ 528*7c478bd9Sstevel@tonic-gate return; 529*7c478bd9Sstevel@tonic-gate mtab_error(mtab_file, status); 530*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 531*7c478bd9Sstevel@tonic-gate } 532*7c478bd9Sstevel@tonic-gate 533*7c478bd9Sstevel@tonic-gate 534*7c478bd9Sstevel@tonic-gate /* 535*7c478bd9Sstevel@tonic-gate * We use this macro when we want to record the option for the purpose of 536*7c478bd9Sstevel@tonic-gate * passing it to the FS-specific df 537*7c478bd9Sstevel@tonic-gate */ 538*7c478bd9Sstevel@tonic-gate #define SET_OPTION(opt) opt##_option = TRUE, \ 539*7c478bd9Sstevel@tonic-gate df_options[df_options_len++] = arg 540*7c478bd9Sstevel@tonic-gate 541*7c478bd9Sstevel@tonic-gate static void 542*7c478bd9Sstevel@tonic-gate parse_options(int argc, char *argv[]) 543*7c478bd9Sstevel@tonic-gate { 544*7c478bd9Sstevel@tonic-gate int arg; 545*7c478bd9Sstevel@tonic-gate 546*7c478bd9Sstevel@tonic-gate opterr = 0; /* getopt shouldn't complain about unknown options */ 547*7c478bd9Sstevel@tonic-gate 548*7c478bd9Sstevel@tonic-gate #ifdef XPG4 549*7c478bd9Sstevel@tonic-gate while ((arg = getopt(argc, argv, "F:o:abehkVtgnlPZ")) != EOF) { 550*7c478bd9Sstevel@tonic-gate #else 551*7c478bd9Sstevel@tonic-gate while ((arg = getopt(argc, argv, "F:o:abehkVtgnlvZ")) != EOF) { 552*7c478bd9Sstevel@tonic-gate #endif 553*7c478bd9Sstevel@tonic-gate if (arg == 'F') { 554*7c478bd9Sstevel@tonic-gate if (F_option) 555*7c478bd9Sstevel@tonic-gate errmsg(ERR_FATAL + ERR_USAGE, 556*7c478bd9Sstevel@tonic-gate "more than one FSType specified"); 557*7c478bd9Sstevel@tonic-gate F_option = 1; 558*7c478bd9Sstevel@tonic-gate FSType = optarg; 559*7c478bd9Sstevel@tonic-gate } else if (arg == 'V' && ! V_option) { 560*7c478bd9Sstevel@tonic-gate V_option = TRUE; 561*7c478bd9Sstevel@tonic-gate } else if (arg == 'v' && ! v_option) { 562*7c478bd9Sstevel@tonic-gate v_option = TRUE; 563*7c478bd9Sstevel@tonic-gate #ifdef XPG4 564*7c478bd9Sstevel@tonic-gate } else if (arg == 'P' && ! P_option) { 565*7c478bd9Sstevel@tonic-gate SET_OPTION(P); 566*7c478bd9Sstevel@tonic-gate #endif 567*7c478bd9Sstevel@tonic-gate } else if (arg == 'a' && ! a_option) { 568*7c478bd9Sstevel@tonic-gate SET_OPTION(a); 569*7c478bd9Sstevel@tonic-gate } else if (arg == 'b' && ! b_option) { 570*7c478bd9Sstevel@tonic-gate SET_OPTION(b); 571*7c478bd9Sstevel@tonic-gate } else if (arg == 'e' && ! e_option) { 572*7c478bd9Sstevel@tonic-gate SET_OPTION(e); 573*7c478bd9Sstevel@tonic-gate } else if (arg == 'g' && ! g_option) { 574*7c478bd9Sstevel@tonic-gate SET_OPTION(g); 575*7c478bd9Sstevel@tonic-gate } else if (arg == 'h') { 576*7c478bd9Sstevel@tonic-gate use_scaling = TRUE; 577*7c478bd9Sstevel@tonic-gate scale = 1024; 578*7c478bd9Sstevel@tonic-gate } else if (arg == 'k' && ! k_option) { 579*7c478bd9Sstevel@tonic-gate SET_OPTION(k); 580*7c478bd9Sstevel@tonic-gate } else if (arg == 'l' && ! l_option) { 581*7c478bd9Sstevel@tonic-gate SET_OPTION(l); 582*7c478bd9Sstevel@tonic-gate } else if (arg == 'n' && ! n_option) { 583*7c478bd9Sstevel@tonic-gate SET_OPTION(n); 584*7c478bd9Sstevel@tonic-gate } else if (arg == 't' && ! t_option) { 585*7c478bd9Sstevel@tonic-gate SET_OPTION(t); 586*7c478bd9Sstevel@tonic-gate } else if (arg == 'o') { 587*7c478bd9Sstevel@tonic-gate if (o_option) 588*7c478bd9Sstevel@tonic-gate errmsg(ERR_FATAL + ERR_USAGE, 589*7c478bd9Sstevel@tonic-gate "the -o option can only be specified once"); 590*7c478bd9Sstevel@tonic-gate o_option = TRUE; 591*7c478bd9Sstevel@tonic-gate o_option_arg = optarg; 592*7c478bd9Sstevel@tonic-gate } else if (arg == 'Z') { 593*7c478bd9Sstevel@tonic-gate SET_OPTION(Z); 594*7c478bd9Sstevel@tonic-gate } else if (arg == '?') { 595*7c478bd9Sstevel@tonic-gate errmsg(ERR_USAGE, "unknown option: %c", optopt); 596*7c478bd9Sstevel@tonic-gate } 597*7c478bd9Sstevel@tonic-gate } 598*7c478bd9Sstevel@tonic-gate 599*7c478bd9Sstevel@tonic-gate /* 600*7c478bd9Sstevel@tonic-gate * Option sanity checks 601*7c478bd9Sstevel@tonic-gate */ 602*7c478bd9Sstevel@tonic-gate if (g_option && o_option) 603*7c478bd9Sstevel@tonic-gate errmsg(ERR_FATAL, "-o and -g options are incompatible"); 604*7c478bd9Sstevel@tonic-gate if (l_option && o_option) 605*7c478bd9Sstevel@tonic-gate errmsg(ERR_FATAL, "-o and -l options are incompatible"); 606*7c478bd9Sstevel@tonic-gate if (n_option && o_option) 607*7c478bd9Sstevel@tonic-gate errmsg(ERR_FATAL, "-o and -n options are incompatible"); 608*7c478bd9Sstevel@tonic-gate if (use_scaling && o_option) 609*7c478bd9Sstevel@tonic-gate errmsg(ERR_FATAL, "-o and -h options are incompatible"); 610*7c478bd9Sstevel@tonic-gate } 611*7c478bd9Sstevel@tonic-gate 612*7c478bd9Sstevel@tonic-gate 613*7c478bd9Sstevel@tonic-gate 614*7c478bd9Sstevel@tonic-gate /* 615*7c478bd9Sstevel@tonic-gate * Check if the user-specified argument is a resource name. 616*7c478bd9Sstevel@tonic-gate * A resource name is whatever is placed in the mnt_special field of 617*7c478bd9Sstevel@tonic-gate * struct mnttab. In the case of NFS, a resource name has the form 618*7c478bd9Sstevel@tonic-gate * hostname:pathname 619*7c478bd9Sstevel@tonic-gate * We try to find an exact match between the user-specified argument 620*7c478bd9Sstevel@tonic-gate * and the mnt_special field of a mount table entry. 621*7c478bd9Sstevel@tonic-gate * We also use the heuristic of removing the basename from the user-specified 622*7c478bd9Sstevel@tonic-gate * argument and repeating the test until we get a match. This works 623*7c478bd9Sstevel@tonic-gate * fine for NFS but may fail for other remote file system types. However, 624*7c478bd9Sstevel@tonic-gate * it is guaranteed that the function will not fail if the user specifies 625*7c478bd9Sstevel@tonic-gate * the exact resource name. 626*7c478bd9Sstevel@tonic-gate * If successful, this function sets the 'dfr_mte' field of '*dfrp' 627*7c478bd9Sstevel@tonic-gate */ 628*7c478bd9Sstevel@tonic-gate static void 629*7c478bd9Sstevel@tonic-gate resource_mount_entry(struct df_request *dfrp) 630*7c478bd9Sstevel@tonic-gate { 631*7c478bd9Sstevel@tonic-gate char *name; 632*7c478bd9Sstevel@tonic-gate 633*7c478bd9Sstevel@tonic-gate /* 634*7c478bd9Sstevel@tonic-gate * We need our own copy since we will modify the string 635*7c478bd9Sstevel@tonic-gate */ 636*7c478bd9Sstevel@tonic-gate name = new_string(dfrp->dfr_cmd_arg); 637*7c478bd9Sstevel@tonic-gate 638*7c478bd9Sstevel@tonic-gate for (;;) { 639*7c478bd9Sstevel@tonic-gate char *p; 640*7c478bd9Sstevel@tonic-gate int i; 641*7c478bd9Sstevel@tonic-gate 642*7c478bd9Sstevel@tonic-gate /* 643*7c478bd9Sstevel@tonic-gate * Compare against all known mount points. 644*7c478bd9Sstevel@tonic-gate * We start from the most recent mount, which is at the 645*7c478bd9Sstevel@tonic-gate * end of the array. 646*7c478bd9Sstevel@tonic-gate */ 647*7c478bd9Sstevel@tonic-gate for (i = mount_table_entries - 1; i >= 0; i--) { 648*7c478bd9Sstevel@tonic-gate struct mtab_entry *mtep = &mount_table[i]; 649*7c478bd9Sstevel@tonic-gate 650*7c478bd9Sstevel@tonic-gate if (EQ(name, mtep->mte_mount->mnt_special)) { 651*7c478bd9Sstevel@tonic-gate dfrp->dfr_mte = mtep; 652*7c478bd9Sstevel@tonic-gate break; 653*7c478bd9Sstevel@tonic-gate } 654*7c478bd9Sstevel@tonic-gate } 655*7c478bd9Sstevel@tonic-gate 656*7c478bd9Sstevel@tonic-gate /* 657*7c478bd9Sstevel@tonic-gate * Remove the last component of the pathname. 658*7c478bd9Sstevel@tonic-gate * If there is no such component, this is not a resource name. 659*7c478bd9Sstevel@tonic-gate */ 660*7c478bd9Sstevel@tonic-gate p = strrchr(name, '/'); 661*7c478bd9Sstevel@tonic-gate if (p == NULL) 662*7c478bd9Sstevel@tonic-gate break; 663*7c478bd9Sstevel@tonic-gate *p = NUL; 664*7c478bd9Sstevel@tonic-gate } 665*7c478bd9Sstevel@tonic-gate } 666*7c478bd9Sstevel@tonic-gate 667*7c478bd9Sstevel@tonic-gate 668*7c478bd9Sstevel@tonic-gate 669*7c478bd9Sstevel@tonic-gate /* 670*7c478bd9Sstevel@tonic-gate * Try to match the command line argument which is a block special device 671*7c478bd9Sstevel@tonic-gate * with the special device of one of the mounted file systems. 672*7c478bd9Sstevel@tonic-gate * If one is found, set the appropriate field of 'dfrp' to the mount 673*7c478bd9Sstevel@tonic-gate * table entry. 674*7c478bd9Sstevel@tonic-gate */ 675*7c478bd9Sstevel@tonic-gate static void 676*7c478bd9Sstevel@tonic-gate bdev_mount_entry(struct df_request *dfrp) 677*7c478bd9Sstevel@tonic-gate { 678*7c478bd9Sstevel@tonic-gate int i; 679*7c478bd9Sstevel@tonic-gate char *special = dfrp->dfr_cmd_arg; 680*7c478bd9Sstevel@tonic-gate 681*7c478bd9Sstevel@tonic-gate /* 682*7c478bd9Sstevel@tonic-gate * Compare against all known mount points. 683*7c478bd9Sstevel@tonic-gate * We start from the most recent mount, which is at the 684*7c478bd9Sstevel@tonic-gate * end of the array. 685*7c478bd9Sstevel@tonic-gate */ 686*7c478bd9Sstevel@tonic-gate for (i = mount_table_entries - 1; i >= 0; i--) { 687*7c478bd9Sstevel@tonic-gate struct mtab_entry *mtep = &mount_table[i]; 688*7c478bd9Sstevel@tonic-gate 689*7c478bd9Sstevel@tonic-gate if (EQ(special, mtep->mte_mount->mnt_special)) { 690*7c478bd9Sstevel@tonic-gate dfrp->dfr_mte = mtep; 691*7c478bd9Sstevel@tonic-gate break; 692*7c478bd9Sstevel@tonic-gate } 693*7c478bd9Sstevel@tonic-gate } 694*7c478bd9Sstevel@tonic-gate } 695*7c478bd9Sstevel@tonic-gate 696*7c478bd9Sstevel@tonic-gate static struct mtab_entry * 697*7c478bd9Sstevel@tonic-gate devid_matches(int i, dev_t devno) 698*7c478bd9Sstevel@tonic-gate { 699*7c478bd9Sstevel@tonic-gate struct mtab_entry *mtep = &mount_table[i]; 700*7c478bd9Sstevel@tonic-gate struct extmnttab *mtp = mtep->mte_mount; 701*7c478bd9Sstevel@tonic-gate /* int len = strlen(mtp->mnt_mountp); */ 702*7c478bd9Sstevel@tonic-gate 703*7c478bd9Sstevel@tonic-gate if (EQ(mtp->mnt_fstype, MNTTYPE_SWAP)) 704*7c478bd9Sstevel@tonic-gate return (NULL); 705*7c478bd9Sstevel@tonic-gate /* 706*7c478bd9Sstevel@tonic-gate * check if device numbers match. If there is a cached device number 707*7c478bd9Sstevel@tonic-gate * in the mtab_entry, use it, otherwise get the device number 708*7c478bd9Sstevel@tonic-gate * either from the mnttab entry or by stat'ing the mount point. 709*7c478bd9Sstevel@tonic-gate */ 710*7c478bd9Sstevel@tonic-gate if (! mtep->mte_dev_is_valid) { 711*7c478bd9Sstevel@tonic-gate struct stat64 st; 712*7c478bd9Sstevel@tonic-gate dev_t dev = NODEV; 713*7c478bd9Sstevel@tonic-gate 714*7c478bd9Sstevel@tonic-gate dev = makedev(mtp->mnt_major, mtp->mnt_minor); 715*7c478bd9Sstevel@tonic-gate if (dev == 0) 716*7c478bd9Sstevel@tonic-gate dev = NODEV; 717*7c478bd9Sstevel@tonic-gate if (dev == NODEV) { 718*7c478bd9Sstevel@tonic-gate if (stat64(mtp->mnt_mountp, &st) == -1) { 719*7c478bd9Sstevel@tonic-gate return (NULL); 720*7c478bd9Sstevel@tonic-gate } else { 721*7c478bd9Sstevel@tonic-gate dev = st.st_dev; 722*7c478bd9Sstevel@tonic-gate } 723*7c478bd9Sstevel@tonic-gate } 724*7c478bd9Sstevel@tonic-gate mtep->mte_dev = dev; 725*7c478bd9Sstevel@tonic-gate mtep->mte_dev_is_valid = TRUE; 726*7c478bd9Sstevel@tonic-gate } 727*7c478bd9Sstevel@tonic-gate if (mtep->mte_dev == devno) { 728*7c478bd9Sstevel@tonic-gate return (mtep); 729*7c478bd9Sstevel@tonic-gate } 730*7c478bd9Sstevel@tonic-gate return (NULL); 731*7c478bd9Sstevel@tonic-gate } 732*7c478bd9Sstevel@tonic-gate 733*7c478bd9Sstevel@tonic-gate /* 734*7c478bd9Sstevel@tonic-gate * Find the mount point under which the user-specified path resides 735*7c478bd9Sstevel@tonic-gate * and set the 'dfr_mte' field of '*dfrp' to point to the mount table entry. 736*7c478bd9Sstevel@tonic-gate */ 737*7c478bd9Sstevel@tonic-gate static void 738*7c478bd9Sstevel@tonic-gate path_mount_entry(struct df_request *dfrp, dev_t devno) 739*7c478bd9Sstevel@tonic-gate { 740*7c478bd9Sstevel@tonic-gate char dirpath[MAXPATHLEN]; 741*7c478bd9Sstevel@tonic-gate char *dir = dfrp->dfr_cmd_arg; 742*7c478bd9Sstevel@tonic-gate struct mtab_entry *match, *tmatch; 743*7c478bd9Sstevel@tonic-gate int i; 744*7c478bd9Sstevel@tonic-gate 745*7c478bd9Sstevel@tonic-gate /* 746*7c478bd9Sstevel@tonic-gate * Expand the given path to get a canonical version (i.e. an absolute 747*7c478bd9Sstevel@tonic-gate * path without symbolic links). 748*7c478bd9Sstevel@tonic-gate */ 749*7c478bd9Sstevel@tonic-gate if (realpath(dir, dirpath) == NULL) { 750*7c478bd9Sstevel@tonic-gate errmsg(ERR_PERROR, "cannot canonicalize %s:", dir); 751*7c478bd9Sstevel@tonic-gate return; 752*7c478bd9Sstevel@tonic-gate } 753*7c478bd9Sstevel@tonic-gate /* 754*7c478bd9Sstevel@tonic-gate * If the mnt point is lofs, search from the top of entries from 755*7c478bd9Sstevel@tonic-gate * /etc/mnttab and return the first entry that matches the devid 756*7c478bd9Sstevel@tonic-gate * For non-lofs mount points, return the first entry from the bottom 757*7c478bd9Sstevel@tonic-gate * of the entries in /etc/mnttab that matches on the devid field 758*7c478bd9Sstevel@tonic-gate */ 759*7c478bd9Sstevel@tonic-gate match = NULL; 760*7c478bd9Sstevel@tonic-gate if (dfrp->dfr_fstype && EQ(dfrp->dfr_fstype, MNTTYPE_LOFS)) { 761*7c478bd9Sstevel@tonic-gate for (i = 0; i < mount_table_entries; i++) { 762*7c478bd9Sstevel@tonic-gate if (match = devid_matches(i, devno)) 763*7c478bd9Sstevel@tonic-gate break; 764*7c478bd9Sstevel@tonic-gate } 765*7c478bd9Sstevel@tonic-gate } else { 766*7c478bd9Sstevel@tonic-gate for (i = mount_table_entries - 1; i >= 0; i--) { 767*7c478bd9Sstevel@tonic-gate if (tmatch = devid_matches(i, devno)) { 768*7c478bd9Sstevel@tonic-gate /* 769*7c478bd9Sstevel@tonic-gate * If executing in a zone, there might be lofs 770*7c478bd9Sstevel@tonic-gate * mounts for which the real mount point is 771*7c478bd9Sstevel@tonic-gate * invisible; accept the "best fit" for this 772*7c478bd9Sstevel@tonic-gate * devid. 773*7c478bd9Sstevel@tonic-gate */ 774*7c478bd9Sstevel@tonic-gate match = tmatch; 775*7c478bd9Sstevel@tonic-gate if (!EQ(match->mte_mount->mnt_fstype, 776*7c478bd9Sstevel@tonic-gate MNTTYPE_LOFS)) { 777*7c478bd9Sstevel@tonic-gate break; 778*7c478bd9Sstevel@tonic-gate } 779*7c478bd9Sstevel@tonic-gate } 780*7c478bd9Sstevel@tonic-gate } 781*7c478bd9Sstevel@tonic-gate } 782*7c478bd9Sstevel@tonic-gate if (! match) { 783*7c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, 784*7c478bd9Sstevel@tonic-gate "Could not find mount point for %s", dir); 785*7c478bd9Sstevel@tonic-gate return; 786*7c478bd9Sstevel@tonic-gate } 787*7c478bd9Sstevel@tonic-gate dfrp->dfr_mte = match; 788*7c478bd9Sstevel@tonic-gate } 789*7c478bd9Sstevel@tonic-gate 790*7c478bd9Sstevel@tonic-gate /* 791*7c478bd9Sstevel@tonic-gate * Execute a single FS-specific df command for all given requests 792*7c478bd9Sstevel@tonic-gate * Return 0 if successful, 1 otherwise. 793*7c478bd9Sstevel@tonic-gate */ 794*7c478bd9Sstevel@tonic-gate static int 795*7c478bd9Sstevel@tonic-gate run_fs_specific_df(struct df_request request_list[], int entries) 796*7c478bd9Sstevel@tonic-gate { 797*7c478bd9Sstevel@tonic-gate int i; 798*7c478bd9Sstevel@tonic-gate int argv_index; 799*7c478bd9Sstevel@tonic-gate char **argv; 800*7c478bd9Sstevel@tonic-gate size_t size; 801*7c478bd9Sstevel@tonic-gate pid_t pid; 802*7c478bd9Sstevel@tonic-gate int status; 803*7c478bd9Sstevel@tonic-gate char cmd_path[MAXPATHLEN]; 804*7c478bd9Sstevel@tonic-gate char *fstype; 805*7c478bd9Sstevel@tonic-gate 806*7c478bd9Sstevel@tonic-gate if (entries == 0) 807*7c478bd9Sstevel@tonic-gate return (0); 808*7c478bd9Sstevel@tonic-gate 809*7c478bd9Sstevel@tonic-gate fstype = request_list[0].dfr_fstype; 810*7c478bd9Sstevel@tonic-gate 811*7c478bd9Sstevel@tonic-gate if (F_option && ! EQ(FSType, fstype)) 812*7c478bd9Sstevel@tonic-gate return (0); 813*7c478bd9Sstevel@tonic-gate 814*7c478bd9Sstevel@tonic-gate (void) sprintf(cmd_path, "%s%s/df", FS_LIBPATH, fstype); 815*7c478bd9Sstevel@tonic-gate /* 816*7c478bd9Sstevel@tonic-gate * Argv entries: 817*7c478bd9Sstevel@tonic-gate * 1 for the path 818*7c478bd9Sstevel@tonic-gate * 2 for -o <options> 819*7c478bd9Sstevel@tonic-gate * 1 for the generic options that we propagate 820*7c478bd9Sstevel@tonic-gate * 1 for the terminating NULL pointer 821*7c478bd9Sstevel@tonic-gate * n for the number of user-specified arguments 822*7c478bd9Sstevel@tonic-gate */ 823*7c478bd9Sstevel@tonic-gate size = (5 + entries) * sizeof (char *); 824*7c478bd9Sstevel@tonic-gate argv = xmalloc(size); 825*7c478bd9Sstevel@tonic-gate (void) memset(argv, 0, size); 826*7c478bd9Sstevel@tonic-gate 827*7c478bd9Sstevel@tonic-gate argv[0] = cmd_path; 828*7c478bd9Sstevel@tonic-gate argv_index = 1; 829*7c478bd9Sstevel@tonic-gate if (o_option) { 830*7c478bd9Sstevel@tonic-gate argv[argv_index++] = "-o"; 831*7c478bd9Sstevel@tonic-gate argv[argv_index++] = o_option_arg; 832*7c478bd9Sstevel@tonic-gate } 833*7c478bd9Sstevel@tonic-gate 834*7c478bd9Sstevel@tonic-gate /* 835*7c478bd9Sstevel@tonic-gate * Check if we need to propagate any generic options 836*7c478bd9Sstevel@tonic-gate */ 837*7c478bd9Sstevel@tonic-gate if (df_options_len > 1) 838*7c478bd9Sstevel@tonic-gate argv[argv_index++] = df_options; 839*7c478bd9Sstevel@tonic-gate 840*7c478bd9Sstevel@tonic-gate /* 841*7c478bd9Sstevel@tonic-gate * If there is a user-specified path, we pass that to the 842*7c478bd9Sstevel@tonic-gate * FS-specific df. Otherwise, we are guaranteed to have a mount 843*7c478bd9Sstevel@tonic-gate * point, since a request without a user path implies that 844*7c478bd9Sstevel@tonic-gate * we are reporting only on mounted file systems. 845*7c478bd9Sstevel@tonic-gate */ 846*7c478bd9Sstevel@tonic-gate for (i = 0; i < entries; i++) { 847*7c478bd9Sstevel@tonic-gate struct df_request *dfrp = &request_list[i]; 848*7c478bd9Sstevel@tonic-gate 849*7c478bd9Sstevel@tonic-gate argv[argv_index++] = (dfrp->dfr_cmd_arg == NULL) 850*7c478bd9Sstevel@tonic-gate ? DFR_MOUNT_POINT(dfrp) 851*7c478bd9Sstevel@tonic-gate : dfrp->dfr_cmd_arg; 852*7c478bd9Sstevel@tonic-gate } 853*7c478bd9Sstevel@tonic-gate 854*7c478bd9Sstevel@tonic-gate if (V_option) { 855*7c478bd9Sstevel@tonic-gate for (i = 0; i < argv_index-1; i++) 856*7c478bd9Sstevel@tonic-gate (void) printf("%s ", argv[i]); 857*7c478bd9Sstevel@tonic-gate (void) printf("%s\n", argv[i]); 858*7c478bd9Sstevel@tonic-gate return (0); 859*7c478bd9Sstevel@tonic-gate } 860*7c478bd9Sstevel@tonic-gate 861*7c478bd9Sstevel@tonic-gate pid = fork(); 862*7c478bd9Sstevel@tonic-gate 863*7c478bd9Sstevel@tonic-gate if (pid == -1) { 864*7c478bd9Sstevel@tonic-gate errmsg(ERR_PERROR, "cannot fork process:"); 865*7c478bd9Sstevel@tonic-gate return (1); 866*7c478bd9Sstevel@tonic-gate } else if (pid == 0) { 867*7c478bd9Sstevel@tonic-gate (void) execv(cmd_path, argv); 868*7c478bd9Sstevel@tonic-gate if (errno == ENOENT) 869*7c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, 870*7c478bd9Sstevel@tonic-gate "operation not applicable for FSType %s", 871*7c478bd9Sstevel@tonic-gate fstype); 872*7c478bd9Sstevel@tonic-gate else 873*7c478bd9Sstevel@tonic-gate errmsg(ERR_PERROR, "cannot execute %s:", cmd_path); 874*7c478bd9Sstevel@tonic-gate exit(2); 875*7c478bd9Sstevel@tonic-gate } 876*7c478bd9Sstevel@tonic-gate 877*7c478bd9Sstevel@tonic-gate /* 878*7c478bd9Sstevel@tonic-gate * Reap the child 879*7c478bd9Sstevel@tonic-gate */ 880*7c478bd9Sstevel@tonic-gate for (;;) { 881*7c478bd9Sstevel@tonic-gate pid_t wpid = waitpid(pid, &status, 0); 882*7c478bd9Sstevel@tonic-gate 883*7c478bd9Sstevel@tonic-gate if (wpid == -1) 884*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 885*7c478bd9Sstevel@tonic-gate continue; 886*7c478bd9Sstevel@tonic-gate else { 887*7c478bd9Sstevel@tonic-gate errmsg(ERR_PERROR, "waitpid error:"); 888*7c478bd9Sstevel@tonic-gate return (1); 889*7c478bd9Sstevel@tonic-gate } 890*7c478bd9Sstevel@tonic-gate else 891*7c478bd9Sstevel@tonic-gate break; 892*7c478bd9Sstevel@tonic-gate } 893*7c478bd9Sstevel@tonic-gate 894*7c478bd9Sstevel@tonic-gate return ((WIFEXITED(status) && WEXITSTATUS(status) == 0) ? 0 : 1); 895*7c478bd9Sstevel@tonic-gate } 896*7c478bd9Sstevel@tonic-gate 897*7c478bd9Sstevel@tonic-gate 898*7c478bd9Sstevel@tonic-gate 899*7c478bd9Sstevel@tonic-gate /* 900*7c478bd9Sstevel@tonic-gate * Remove from the request list all requests that do not apply. 901*7c478bd9Sstevel@tonic-gate * Notice that the subsequent processing of the requests depends on 902*7c478bd9Sstevel@tonic-gate * the sanity checking performed by this function. 903*7c478bd9Sstevel@tonic-gate */ 904*7c478bd9Sstevel@tonic-gate static int 905*7c478bd9Sstevel@tonic-gate prune_list(struct df_request request_list[], 906*7c478bd9Sstevel@tonic-gate size_t n_requests, 907*7c478bd9Sstevel@tonic-gate size_t *valid_requests) 908*7c478bd9Sstevel@tonic-gate { 909*7c478bd9Sstevel@tonic-gate size_t i; 910*7c478bd9Sstevel@tonic-gate size_t n_valid = 0; 911*7c478bd9Sstevel@tonic-gate int errors = 0; 912*7c478bd9Sstevel@tonic-gate 913*7c478bd9Sstevel@tonic-gate for (i = 0; i < n_requests; i++) { 914*7c478bd9Sstevel@tonic-gate struct df_request *dfrp = &request_list[i]; 915*7c478bd9Sstevel@tonic-gate 916*7c478bd9Sstevel@tonic-gate /* 917*7c478bd9Sstevel@tonic-gate * Skip file systems that are not mounted if either the 918*7c478bd9Sstevel@tonic-gate * -l or -n options were specified. If none of these options 919*7c478bd9Sstevel@tonic-gate * are present, the appropriate FS-specific df will be invoked. 920*7c478bd9Sstevel@tonic-gate */ 921*7c478bd9Sstevel@tonic-gate if (! DFR_ISMOUNTEDFS(dfrp)) { 922*7c478bd9Sstevel@tonic-gate if (l_option || n_option) { 923*7c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, 924*7c478bd9Sstevel@tonic-gate "%s option incompatible with unmounted special device (%s)", 925*7c478bd9Sstevel@tonic-gate l_option ? "-l" : "-n", dfrp->dfr_cmd_arg); 926*7c478bd9Sstevel@tonic-gate dfrp->dfr_valid = FALSE; 927*7c478bd9Sstevel@tonic-gate errors++; 928*7c478bd9Sstevel@tonic-gate } 929*7c478bd9Sstevel@tonic-gate else 930*7c478bd9Sstevel@tonic-gate n_valid++; 931*7c478bd9Sstevel@tonic-gate continue; 932*7c478bd9Sstevel@tonic-gate } 933*7c478bd9Sstevel@tonic-gate 934*7c478bd9Sstevel@tonic-gate /* 935*7c478bd9Sstevel@tonic-gate * Check for inconsistency between the argument of -F and 936*7c478bd9Sstevel@tonic-gate * the actual file system type. 937*7c478bd9Sstevel@tonic-gate * If there is an inconsistency and the user specified a 938*7c478bd9Sstevel@tonic-gate * path, this is an error since we are asked to interpret 939*7c478bd9Sstevel@tonic-gate * the path using the wrong file system type. If there is 940*7c478bd9Sstevel@tonic-gate * no path associated with this request, we quietly ignore it. 941*7c478bd9Sstevel@tonic-gate */ 942*7c478bd9Sstevel@tonic-gate if (F_option && ! EQ(dfrp->dfr_fstype, FSType)) { 943*7c478bd9Sstevel@tonic-gate dfrp->dfr_valid = FALSE; 944*7c478bd9Sstevel@tonic-gate if (dfrp->dfr_cmd_arg != NULL) { 945*7c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, 946*7c478bd9Sstevel@tonic-gate "Warning: %s mounted as a %s file system", 947*7c478bd9Sstevel@tonic-gate dfrp->dfr_cmd_arg, dfrp->dfr_fstype); 948*7c478bd9Sstevel@tonic-gate errors++; 949*7c478bd9Sstevel@tonic-gate } 950*7c478bd9Sstevel@tonic-gate continue; 951*7c478bd9Sstevel@tonic-gate } 952*7c478bd9Sstevel@tonic-gate 953*7c478bd9Sstevel@tonic-gate /* 954*7c478bd9Sstevel@tonic-gate * Skip remote file systems if the -l option is present 955*7c478bd9Sstevel@tonic-gate */ 956*7c478bd9Sstevel@tonic-gate if (l_option && is_remote_fs(dfrp->dfr_fstype)) { 957*7c478bd9Sstevel@tonic-gate if (dfrp->dfr_cmd_arg != NULL) { 958*7c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, 959*7c478bd9Sstevel@tonic-gate "Warning: %s is not a local file system", 960*7c478bd9Sstevel@tonic-gate dfrp->dfr_cmd_arg); 961*7c478bd9Sstevel@tonic-gate errors++; 962*7c478bd9Sstevel@tonic-gate } 963*7c478bd9Sstevel@tonic-gate dfrp->dfr_valid = FALSE; 964*7c478bd9Sstevel@tonic-gate continue; 965*7c478bd9Sstevel@tonic-gate } 966*7c478bd9Sstevel@tonic-gate 967*7c478bd9Sstevel@tonic-gate /* 968*7c478bd9Sstevel@tonic-gate * Skip file systems mounted as "ignore" unless the -a option 969*7c478bd9Sstevel@tonic-gate * is present, or the user explicitly specified them on 970*7c478bd9Sstevel@tonic-gate * the command line. 971*7c478bd9Sstevel@tonic-gate */ 972*7c478bd9Sstevel@tonic-gate if (dfrp->dfr_mte->mte_ignore && 973*7c478bd9Sstevel@tonic-gate ! (a_option || dfrp->dfr_cmd_arg)) { 974*7c478bd9Sstevel@tonic-gate dfrp->dfr_valid = FALSE; 975*7c478bd9Sstevel@tonic-gate continue; 976*7c478bd9Sstevel@tonic-gate } 977*7c478bd9Sstevel@tonic-gate 978*7c478bd9Sstevel@tonic-gate n_valid++; 979*7c478bd9Sstevel@tonic-gate } 980*7c478bd9Sstevel@tonic-gate *valid_requests = n_valid; 981*7c478bd9Sstevel@tonic-gate return (errors); 982*7c478bd9Sstevel@tonic-gate } 983*7c478bd9Sstevel@tonic-gate 984*7c478bd9Sstevel@tonic-gate 985*7c478bd9Sstevel@tonic-gate /* 986*7c478bd9Sstevel@tonic-gate * Print the appropriate header for the requested output format. 987*7c478bd9Sstevel@tonic-gate * Options are checked in order of their precedence. 988*7c478bd9Sstevel@tonic-gate */ 989*7c478bd9Sstevel@tonic-gate static void 990*7c478bd9Sstevel@tonic-gate print_header() 991*7c478bd9Sstevel@tonic-gate { 992*7c478bd9Sstevel@tonic-gate if (use_scaling) { /* this comes from the -h option */ 993*7c478bd9Sstevel@tonic-gate int arg = 'h'; 994*7c478bd9Sstevel@tonic-gate 995*7c478bd9Sstevel@tonic-gate (void) printf("%-*s %*s %*s %*s %-*s %s\n", 996*7c478bd9Sstevel@tonic-gate FILESYSTEM_WIDTH, TRANSLATE("Filesystem"), 997*7c478bd9Sstevel@tonic-gate #ifdef XPG4 998*7c478bd9Sstevel@tonic-gate SCALED_WIDTH, TRANSLATE("Size"), 999*7c478bd9Sstevel@tonic-gate SCALED_WIDTH, TRANSLATE("Used"), 1000*7c478bd9Sstevel@tonic-gate AVAILABLE_WIDTH, TRANSLATE("Available"), 1001*7c478bd9Sstevel@tonic-gate CAPACITY_WIDTH, TRANSLATE("Capacity"), 1002*7c478bd9Sstevel@tonic-gate #else 1003*7c478bd9Sstevel@tonic-gate SCALED_WIDTH, TRANSLATE("size"), 1004*7c478bd9Sstevel@tonic-gate SCALED_WIDTH, TRANSLATE("used"), 1005*7c478bd9Sstevel@tonic-gate AVAILABLE_WIDTH, TRANSLATE("avail"), 1006*7c478bd9Sstevel@tonic-gate CAPACITY_WIDTH, TRANSLATE("capacity"), 1007*7c478bd9Sstevel@tonic-gate #endif 1008*7c478bd9Sstevel@tonic-gate TRANSLATE("Mounted on")); 1009*7c478bd9Sstevel@tonic-gate SET_OPTION(h); 1010*7c478bd9Sstevel@tonic-gate return; 1011*7c478bd9Sstevel@tonic-gate } 1012*7c478bd9Sstevel@tonic-gate if (k_option) { 1013*7c478bd9Sstevel@tonic-gate int arg = 'h'; 1014*7c478bd9Sstevel@tonic-gate 1015*7c478bd9Sstevel@tonic-gate (void) printf(gettext("%-*s %*s %*s %*s %-*s %s\n"), 1016*7c478bd9Sstevel@tonic-gate FILESYSTEM_WIDTH, TRANSLATE("Filesystem"), 1017*7c478bd9Sstevel@tonic-gate #ifdef XPG4 1018*7c478bd9Sstevel@tonic-gate KBYTE_WIDTH, TRANSLATE("1024-blocks"), 1019*7c478bd9Sstevel@tonic-gate KBYTE_WIDTH, TRANSLATE("Used"), 1020*7c478bd9Sstevel@tonic-gate KBYTE_WIDTH, TRANSLATE("Available"), 1021*7c478bd9Sstevel@tonic-gate CAPACITY_WIDTH, TRANSLATE("Capacity"), 1022*7c478bd9Sstevel@tonic-gate #else 1023*7c478bd9Sstevel@tonic-gate KBYTE_WIDTH, TRANSLATE("kbytes"), 1024*7c478bd9Sstevel@tonic-gate KBYTE_WIDTH, TRANSLATE("used"), 1025*7c478bd9Sstevel@tonic-gate KBYTE_WIDTH, TRANSLATE("avail"), 1026*7c478bd9Sstevel@tonic-gate CAPACITY_WIDTH, TRANSLATE("capacity"), 1027*7c478bd9Sstevel@tonic-gate #endif 1028*7c478bd9Sstevel@tonic-gate TRANSLATE("Mounted on")); 1029*7c478bd9Sstevel@tonic-gate SET_OPTION(h); 1030*7c478bd9Sstevel@tonic-gate return; 1031*7c478bd9Sstevel@tonic-gate } 1032*7c478bd9Sstevel@tonic-gate /* Added for XCU4 compliance */ 1033*7c478bd9Sstevel@tonic-gate if (P_option) { 1034*7c478bd9Sstevel@tonic-gate int arg = 'h'; 1035*7c478bd9Sstevel@tonic-gate 1036*7c478bd9Sstevel@tonic-gate (void) printf(gettext("%-*s %*s %*s %*s %-*s %s\n"), 1037*7c478bd9Sstevel@tonic-gate FILESYSTEM_WIDTH, TRANSLATE("Filesystem"), 1038*7c478bd9Sstevel@tonic-gate KBYTE_WIDTH, TRANSLATE("512-blocks"), 1039*7c478bd9Sstevel@tonic-gate KBYTE_WIDTH, TRANSLATE("Used"), 1040*7c478bd9Sstevel@tonic-gate KBYTE_WIDTH, TRANSLATE("Available"), 1041*7c478bd9Sstevel@tonic-gate CAPACITY_WIDTH, TRANSLATE("Capacity"), 1042*7c478bd9Sstevel@tonic-gate TRANSLATE("Mounted on")); 1043*7c478bd9Sstevel@tonic-gate 1044*7c478bd9Sstevel@tonic-gate SET_OPTION(h); 1045*7c478bd9Sstevel@tonic-gate return; 1046*7c478bd9Sstevel@tonic-gate } 1047*7c478bd9Sstevel@tonic-gate /* End XCU4 */ 1048*7c478bd9Sstevel@tonic-gate if (v_option) { 1049*7c478bd9Sstevel@tonic-gate (void) printf("%-*s %-*s %*s %*s %*s %-*s\n", 1050*7c478bd9Sstevel@tonic-gate IBCS2_MOUNT_POINT_WIDTH, TRANSLATE("Mount Dir"), 1051*7c478bd9Sstevel@tonic-gate IBCS2_FILESYSTEM_WIDTH, TRANSLATE("Filesystem"), 1052*7c478bd9Sstevel@tonic-gate BLOCK_WIDTH, TRANSLATE("blocks"), 1053*7c478bd9Sstevel@tonic-gate BLOCK_WIDTH, TRANSLATE("used"), 1054*7c478bd9Sstevel@tonic-gate BLOCK_WIDTH, TRANSLATE("free"), 1055*7c478bd9Sstevel@tonic-gate CAPACITY_WIDTH, TRANSLATE(" %used")); 1056*7c478bd9Sstevel@tonic-gate return; 1057*7c478bd9Sstevel@tonic-gate } 1058*7c478bd9Sstevel@tonic-gate if (e_option) { 1059*7c478bd9Sstevel@tonic-gate (void) printf(gettext("%-*s %*s\n"), 1060*7c478bd9Sstevel@tonic-gate FILESYSTEM_WIDTH, TRANSLATE("Filesystem"), 1061*7c478bd9Sstevel@tonic-gate BLOCK_WIDTH, TRANSLATE("ifree")); 1062*7c478bd9Sstevel@tonic-gate return; 1063*7c478bd9Sstevel@tonic-gate } 1064*7c478bd9Sstevel@tonic-gate if (b_option) { 1065*7c478bd9Sstevel@tonic-gate (void) printf(gettext("%-*s %*s\n"), 1066*7c478bd9Sstevel@tonic-gate FILESYSTEM_WIDTH, TRANSLATE("Filesystem"), 1067*7c478bd9Sstevel@tonic-gate BLOCK_WIDTH, TRANSLATE("avail")); 1068*7c478bd9Sstevel@tonic-gate return; 1069*7c478bd9Sstevel@tonic-gate } 1070*7c478bd9Sstevel@tonic-gate } 1071*7c478bd9Sstevel@tonic-gate 1072*7c478bd9Sstevel@tonic-gate 1073*7c478bd9Sstevel@tonic-gate /* 1074*7c478bd9Sstevel@tonic-gate * Convert an unsigned long long to a string representation and place the 1075*7c478bd9Sstevel@tonic-gate * result in the caller-supplied buffer. 1076*7c478bd9Sstevel@tonic-gate * The given number is in units of "unit_from" size, but the 1077*7c478bd9Sstevel@tonic-gate * converted number will be in units of "unit_to" size. The unit sizes 1078*7c478bd9Sstevel@tonic-gate * must be powers of 2. 1079*7c478bd9Sstevel@tonic-gate * The value "(unsigned long long)-1" is a special case and is always 1080*7c478bd9Sstevel@tonic-gate * converted to "-1". 1081*7c478bd9Sstevel@tonic-gate * Returns a pointer to the caller-supplied buffer. 1082*7c478bd9Sstevel@tonic-gate */ 1083*7c478bd9Sstevel@tonic-gate static char * 1084*7c478bd9Sstevel@tonic-gate number_to_string( 1085*7c478bd9Sstevel@tonic-gate char *buf, /* put the result here */ 1086*7c478bd9Sstevel@tonic-gate unsigned long long number, /* convert this number */ 1087*7c478bd9Sstevel@tonic-gate int unit_from, /* from units of this size */ 1088*7c478bd9Sstevel@tonic-gate int unit_to) /* to units of this size */ 1089*7c478bd9Sstevel@tonic-gate { 1090*7c478bd9Sstevel@tonic-gate if ((long long)number == (long long)-1) 1091*7c478bd9Sstevel@tonic-gate (void) strcpy(buf, "-1"); 1092*7c478bd9Sstevel@tonic-gate else { 1093*7c478bd9Sstevel@tonic-gate if (unit_from == unit_to) 1094*7c478bd9Sstevel@tonic-gate (void) sprintf(buf, "%llu", number); 1095*7c478bd9Sstevel@tonic-gate else if (unit_from < unit_to) 1096*7c478bd9Sstevel@tonic-gate (void) sprintf(buf, "%llu", 1097*7c478bd9Sstevel@tonic-gate number / (unsigned long long)(unit_to / unit_from)); 1098*7c478bd9Sstevel@tonic-gate else 1099*7c478bd9Sstevel@tonic-gate (void) sprintf(buf, "%llu", 1100*7c478bd9Sstevel@tonic-gate number * (unsigned long long)(unit_from / unit_to)); 1101*7c478bd9Sstevel@tonic-gate } 1102*7c478bd9Sstevel@tonic-gate return (buf); 1103*7c478bd9Sstevel@tonic-gate } 1104*7c478bd9Sstevel@tonic-gate 1105*7c478bd9Sstevel@tonic-gate /* 1106*7c478bd9Sstevel@tonic-gate * Convert an unsigned long long to a string representation and place the 1107*7c478bd9Sstevel@tonic-gate * result in the caller-supplied buffer. 1108*7c478bd9Sstevel@tonic-gate * The given number is in units of "unit_from" size, 1109*7c478bd9Sstevel@tonic-gate * this will first be converted to a number in 1024 or 1000 byte size, 1110*7c478bd9Sstevel@tonic-gate * depending on the scaling factor. 1111*7c478bd9Sstevel@tonic-gate * Then the number is scaled down until it is small enough to be in a good 1112*7c478bd9Sstevel@tonic-gate * human readable format i.e. in the range 0 thru scale-1. 1113*7c478bd9Sstevel@tonic-gate * If it's smaller than 10 there's room enough to provide one decimal place. 1114*7c478bd9Sstevel@tonic-gate * The value "(unsigned long long)-1" is a special case and is always 1115*7c478bd9Sstevel@tonic-gate * converted to "-1". 1116*7c478bd9Sstevel@tonic-gate * Returns a pointer to the caller-supplied buffer. 1117*7c478bd9Sstevel@tonic-gate */ 1118*7c478bd9Sstevel@tonic-gate static char * 1119*7c478bd9Sstevel@tonic-gate number_to_scaled_string( 1120*7c478bd9Sstevel@tonic-gate numbuf_t buf, /* put the result here */ 1121*7c478bd9Sstevel@tonic-gate unsigned long long number, /* convert this number */ 1122*7c478bd9Sstevel@tonic-gate int unit_from, 1123*7c478bd9Sstevel@tonic-gate int scale) 1124*7c478bd9Sstevel@tonic-gate { 1125*7c478bd9Sstevel@tonic-gate unsigned long long save = 0; 1126*7c478bd9Sstevel@tonic-gate char *M = "KMGTPE"; /* Measurement: kilo, mega, giga, tera, peta, exa */ 1127*7c478bd9Sstevel@tonic-gate char *uom = M; /* unit of measurement, initially 'K' (=M[0]) */ 1128*7c478bd9Sstevel@tonic-gate 1129*7c478bd9Sstevel@tonic-gate if ((long long)number == (long long)-1) { 1130*7c478bd9Sstevel@tonic-gate (void) strcpy(buf, "-1"); 1131*7c478bd9Sstevel@tonic-gate return (buf); 1132*7c478bd9Sstevel@tonic-gate } 1133*7c478bd9Sstevel@tonic-gate 1134*7c478bd9Sstevel@tonic-gate /* 1135*7c478bd9Sstevel@tonic-gate * Convert number from unit_from to given scale (1024 or 1000). 1136*7c478bd9Sstevel@tonic-gate * This means multiply number by unit_from and divide by scale. 1137*7c478bd9Sstevel@tonic-gate * 1138*7c478bd9Sstevel@tonic-gate * Would like to multiply by unit_from and then divide by scale, 1139*7c478bd9Sstevel@tonic-gate * but if the first multiplication would overflow, then need to 1140*7c478bd9Sstevel@tonic-gate * divide by scale and then multiply by unit_from. 1141*7c478bd9Sstevel@tonic-gate */ 1142*7c478bd9Sstevel@tonic-gate if (number > (UINT64_MAX / (unsigned long long)unit_from)) { 1143*7c478bd9Sstevel@tonic-gate number = (number / (unsigned long long)scale) * 1144*7c478bd9Sstevel@tonic-gate (unsigned long long)unit_from; 1145*7c478bd9Sstevel@tonic-gate } else { 1146*7c478bd9Sstevel@tonic-gate number = (number * (unsigned long long)unit_from) / 1147*7c478bd9Sstevel@tonic-gate (unsigned long long)scale; 1148*7c478bd9Sstevel@tonic-gate } 1149*7c478bd9Sstevel@tonic-gate 1150*7c478bd9Sstevel@tonic-gate /* 1151*7c478bd9Sstevel@tonic-gate * Now we have number as a count of scale units. 1152*7c478bd9Sstevel@tonic-gate * Stop scaling when we reached exa bytes, then something is 1153*7c478bd9Sstevel@tonic-gate * probably wrong with our number. 1154*7c478bd9Sstevel@tonic-gate */ 1155*7c478bd9Sstevel@tonic-gate 1156*7c478bd9Sstevel@tonic-gate while ((number >= scale) && (*uom != 'E')) { 1157*7c478bd9Sstevel@tonic-gate uom++; /* next unit of measurement */ 1158*7c478bd9Sstevel@tonic-gate save = number; 1159*7c478bd9Sstevel@tonic-gate number = (number + (scale / 2)) / scale; 1160*7c478bd9Sstevel@tonic-gate } 1161*7c478bd9Sstevel@tonic-gate /* check if we should output a decimal place after the point */ 1162*7c478bd9Sstevel@tonic-gate if (save && ((save / scale) < 10)) { 1163*7c478bd9Sstevel@tonic-gate /* sprintf() will round for us */ 1164*7c478bd9Sstevel@tonic-gate float fnum = (float)save / scale; 1165*7c478bd9Sstevel@tonic-gate (void) sprintf(buf, "%2.1f%c", fnum, *uom); 1166*7c478bd9Sstevel@tonic-gate } else { 1167*7c478bd9Sstevel@tonic-gate (void) sprintf(buf, "%4llu%c", number, *uom); 1168*7c478bd9Sstevel@tonic-gate } 1169*7c478bd9Sstevel@tonic-gate return (buf); 1170*7c478bd9Sstevel@tonic-gate } 1171*7c478bd9Sstevel@tonic-gate 1172*7c478bd9Sstevel@tonic-gate 1173*7c478bd9Sstevel@tonic-gate /* 1174*7c478bd9Sstevel@tonic-gate * The output will appear properly columnized regardless of the names of 1175*7c478bd9Sstevel@tonic-gate * the various fields 1176*7c478bd9Sstevel@tonic-gate */ 1177*7c478bd9Sstevel@tonic-gate static void 1178*7c478bd9Sstevel@tonic-gate g_output(struct df_request *dfrp, struct statvfs64 *fsp) 1179*7c478bd9Sstevel@tonic-gate { 1180*7c478bd9Sstevel@tonic-gate fsblkcnt64_t available_blocks = fsp->f_bavail; 1181*7c478bd9Sstevel@tonic-gate numbuf_t total_blocks_buf; 1182*7c478bd9Sstevel@tonic-gate numbuf_t total_files_buf; 1183*7c478bd9Sstevel@tonic-gate numbuf_t free_blocks_buf; 1184*7c478bd9Sstevel@tonic-gate numbuf_t available_blocks_buf; 1185*7c478bd9Sstevel@tonic-gate numbuf_t free_files_buf; 1186*7c478bd9Sstevel@tonic-gate numbuf_t fname_buf; 1187*7c478bd9Sstevel@tonic-gate char *temp_buf; 1188*7c478bd9Sstevel@tonic-gate 1189*7c478bd9Sstevel@tonic-gate #define DEFINE_STR_LEN(var) \ 1190*7c478bd9Sstevel@tonic-gate static char *var##_str; \ 1191*7c478bd9Sstevel@tonic-gate static size_t var##_len 1192*7c478bd9Sstevel@tonic-gate 1193*7c478bd9Sstevel@tonic-gate #define SET_STR_LEN(name, var)\ 1194*7c478bd9Sstevel@tonic-gate if (! var##_str) {\ 1195*7c478bd9Sstevel@tonic-gate var##_str = TRANSLATE(name); \ 1196*7c478bd9Sstevel@tonic-gate var##_len = strlen(var##_str); \ 1197*7c478bd9Sstevel@tonic-gate } 1198*7c478bd9Sstevel@tonic-gate 1199*7c478bd9Sstevel@tonic-gate DEFINE_STR_LEN(block_size); 1200*7c478bd9Sstevel@tonic-gate DEFINE_STR_LEN(frag_size); 1201*7c478bd9Sstevel@tonic-gate DEFINE_STR_LEN(total_blocks); 1202*7c478bd9Sstevel@tonic-gate DEFINE_STR_LEN(free_blocks); 1203*7c478bd9Sstevel@tonic-gate DEFINE_STR_LEN(available); 1204*7c478bd9Sstevel@tonic-gate DEFINE_STR_LEN(total_files); 1205*7c478bd9Sstevel@tonic-gate DEFINE_STR_LEN(free_files); 1206*7c478bd9Sstevel@tonic-gate DEFINE_STR_LEN(fstype); 1207*7c478bd9Sstevel@tonic-gate DEFINE_STR_LEN(fsys_id); 1208*7c478bd9Sstevel@tonic-gate DEFINE_STR_LEN(fname); 1209*7c478bd9Sstevel@tonic-gate DEFINE_STR_LEN(flag); 1210*7c478bd9Sstevel@tonic-gate 1211*7c478bd9Sstevel@tonic-gate /* 1212*7c478bd9Sstevel@tonic-gate * TRANSLATION_NOTE 1213*7c478bd9Sstevel@tonic-gate * The first argument of each of the following macro invocations is a 1214*7c478bd9Sstevel@tonic-gate * string that needs to be translated. 1215*7c478bd9Sstevel@tonic-gate */ 1216*7c478bd9Sstevel@tonic-gate SET_STR_LEN("block size", block_size); 1217*7c478bd9Sstevel@tonic-gate SET_STR_LEN("frag size", frag_size); 1218*7c478bd9Sstevel@tonic-gate SET_STR_LEN("total blocks", total_blocks); 1219*7c478bd9Sstevel@tonic-gate SET_STR_LEN("free blocks", free_blocks); 1220*7c478bd9Sstevel@tonic-gate SET_STR_LEN("available", available); 1221*7c478bd9Sstevel@tonic-gate SET_STR_LEN("total files", total_files); 1222*7c478bd9Sstevel@tonic-gate SET_STR_LEN("free files", free_files); 1223*7c478bd9Sstevel@tonic-gate SET_STR_LEN("fstype", fstype); 1224*7c478bd9Sstevel@tonic-gate SET_STR_LEN("filesys id", fsys_id); 1225*7c478bd9Sstevel@tonic-gate SET_STR_LEN("filename length", fname); 1226*7c478bd9Sstevel@tonic-gate SET_STR_LEN("flag", flag); 1227*7c478bd9Sstevel@tonic-gate 1228*7c478bd9Sstevel@tonic-gate #define NCOL1_WIDTH (int)MAX3(BLOCK_WIDTH, NFILES_WIDTH, FSTYPE_WIDTH) 1229*7c478bd9Sstevel@tonic-gate #define NCOL2_WIDTH (int)MAX3(BLOCK_WIDTH, FSID_WIDTH, FLAG_WIDTH) + 2 1230*7c478bd9Sstevel@tonic-gate #define NCOL3_WIDTH (int)MAX3(BSIZE_WIDTH, BLOCK_WIDTH, NAMELEN_WIDTH) 1231*7c478bd9Sstevel@tonic-gate #define NCOL4_WIDTH (int)MAX(FRAGSIZE_WIDTH, NFILES_WIDTH) 1232*7c478bd9Sstevel@tonic-gate 1233*7c478bd9Sstevel@tonic-gate #define SCOL1_WIDTH (int)MAX3(total_blocks_len, free_files_len, fstype_len) 1234*7c478bd9Sstevel@tonic-gate #define SCOL2_WIDTH (int)MAX3(free_blocks_len, fsys_id_len, flag_len) 1235*7c478bd9Sstevel@tonic-gate #define SCOL3_WIDTH (int)MAX3(block_size_len, available_len, fname_len) 1236*7c478bd9Sstevel@tonic-gate #define SCOL4_WIDTH (int)MAX(frag_size_len, total_files_len) 1237*7c478bd9Sstevel@tonic-gate 1238*7c478bd9Sstevel@tonic-gate temp_buf = xmalloc( 1239*7c478bd9Sstevel@tonic-gate MAX(MOUNT_POINT_WIDTH, strlen(DFR_MOUNT_POINT(dfrp))) 1240*7c478bd9Sstevel@tonic-gate + MAX(SPECIAL_DEVICE_WIDTH, strlen(DFR_SPECIAL(dfrp))) 1241*7c478bd9Sstevel@tonic-gate + 20); /* plus slop - nulls & formatting */ 1242*7c478bd9Sstevel@tonic-gate (void) sprintf(temp_buf, "%-*s(%-*s):", 1243*7c478bd9Sstevel@tonic-gate MOUNT_POINT_WIDTH, DFR_MOUNT_POINT(dfrp), 1244*7c478bd9Sstevel@tonic-gate SPECIAL_DEVICE_WIDTH, DFR_SPECIAL(dfrp)); 1245*7c478bd9Sstevel@tonic-gate 1246*7c478bd9Sstevel@tonic-gate (void) printf("%-*s %*lu %-*s %*lu %-*s\n", 1247*7c478bd9Sstevel@tonic-gate NCOL1_WIDTH + 1 + SCOL1_WIDTH + 1 + NCOL2_WIDTH + 1 + SCOL2_WIDTH, 1248*7c478bd9Sstevel@tonic-gate temp_buf, 1249*7c478bd9Sstevel@tonic-gate NCOL3_WIDTH, fsp->f_bsize, SCOL3_WIDTH, block_size_str, 1250*7c478bd9Sstevel@tonic-gate NCOL4_WIDTH, fsp->f_frsize, SCOL4_WIDTH, frag_size_str); 1251*7c478bd9Sstevel@tonic-gate free(temp_buf); 1252*7c478bd9Sstevel@tonic-gate 1253*7c478bd9Sstevel@tonic-gate /* 1254*7c478bd9Sstevel@tonic-gate * Adjust available_blocks value - it can be less than 0 on 1255*7c478bd9Sstevel@tonic-gate * a 4.x file system. Reset it to 0 in order to avoid printing 1256*7c478bd9Sstevel@tonic-gate * negative numbers. 1257*7c478bd9Sstevel@tonic-gate */ 1258*7c478bd9Sstevel@tonic-gate if ((long long)available_blocks < (long long)0) 1259*7c478bd9Sstevel@tonic-gate available_blocks = (fsblkcnt64_t)0; 1260*7c478bd9Sstevel@tonic-gate 1261*7c478bd9Sstevel@tonic-gate (void) printf("%*s %-*s %*s %-*s %*s %-*s %*s %-*s\n", 1262*7c478bd9Sstevel@tonic-gate NCOL1_WIDTH, number_to_string(total_blocks_buf, 1263*7c478bd9Sstevel@tonic-gate fsp->f_blocks, fsp->f_frsize, 512), 1264*7c478bd9Sstevel@tonic-gate SCOL1_WIDTH, total_blocks_str, 1265*7c478bd9Sstevel@tonic-gate NCOL2_WIDTH, number_to_string(free_blocks_buf, 1266*7c478bd9Sstevel@tonic-gate fsp->f_bfree, fsp->f_frsize, 512), 1267*7c478bd9Sstevel@tonic-gate SCOL2_WIDTH, free_blocks_str, 1268*7c478bd9Sstevel@tonic-gate NCOL3_WIDTH, number_to_string(available_blocks_buf, 1269*7c478bd9Sstevel@tonic-gate available_blocks, fsp->f_frsize, 512), 1270*7c478bd9Sstevel@tonic-gate SCOL3_WIDTH, available_str, 1271*7c478bd9Sstevel@tonic-gate NCOL4_WIDTH, number_to_string(total_files_buf, 1272*7c478bd9Sstevel@tonic-gate fsp->f_files, 1, 1), 1273*7c478bd9Sstevel@tonic-gate SCOL4_WIDTH, total_files_str); 1274*7c478bd9Sstevel@tonic-gate 1275*7c478bd9Sstevel@tonic-gate (void) printf("%*s %-*s %*lu %-*s %s\n", 1276*7c478bd9Sstevel@tonic-gate NCOL1_WIDTH, number_to_string(free_files_buf, 1277*7c478bd9Sstevel@tonic-gate fsp->f_ffree, 1, 1), 1278*7c478bd9Sstevel@tonic-gate SCOL1_WIDTH, free_files_str, 1279*7c478bd9Sstevel@tonic-gate NCOL2_WIDTH, fsp->f_fsid, SCOL2_WIDTH, fsys_id_str, 1280*7c478bd9Sstevel@tonic-gate fsp->f_fstr); 1281*7c478bd9Sstevel@tonic-gate 1282*7c478bd9Sstevel@tonic-gate (void) printf("%*s %-*s %#*.*lx %-*s %*s %-*s\n\n", 1283*7c478bd9Sstevel@tonic-gate NCOL1_WIDTH, fsp->f_basetype, SCOL1_WIDTH, fstype_str, 1284*7c478bd9Sstevel@tonic-gate NCOL2_WIDTH, NCOL2_WIDTH-2, fsp->f_flag, SCOL2_WIDTH, flag_str, 1285*7c478bd9Sstevel@tonic-gate NCOL3_WIDTH, number_to_string(fname_buf, 1286*7c478bd9Sstevel@tonic-gate (unsigned long long)fsp->f_namemax, 1, 1), 1287*7c478bd9Sstevel@tonic-gate SCOL3_WIDTH, fname_str); 1288*7c478bd9Sstevel@tonic-gate } 1289*7c478bd9Sstevel@tonic-gate 1290*7c478bd9Sstevel@tonic-gate 1291*7c478bd9Sstevel@tonic-gate static void 1292*7c478bd9Sstevel@tonic-gate k_output(struct df_request *dfrp, struct statvfs64 *fsp) 1293*7c478bd9Sstevel@tonic-gate { 1294*7c478bd9Sstevel@tonic-gate fsblkcnt64_t total_blocks = fsp->f_blocks; 1295*7c478bd9Sstevel@tonic-gate fsblkcnt64_t free_blocks = fsp->f_bfree; 1296*7c478bd9Sstevel@tonic-gate fsblkcnt64_t available_blocks = fsp->f_bavail; 1297*7c478bd9Sstevel@tonic-gate fsblkcnt64_t used_blocks; 1298*7c478bd9Sstevel@tonic-gate char *file_system = DFR_SPECIAL(dfrp); 1299*7c478bd9Sstevel@tonic-gate numbuf_t total_blocks_buf; 1300*7c478bd9Sstevel@tonic-gate numbuf_t used_blocks_buf; 1301*7c478bd9Sstevel@tonic-gate numbuf_t available_blocks_buf; 1302*7c478bd9Sstevel@tonic-gate char capacity_buf[LINEBUF_SIZE]; 1303*7c478bd9Sstevel@tonic-gate 1304*7c478bd9Sstevel@tonic-gate /* 1305*7c478bd9Sstevel@tonic-gate * If the free block count is -1, don't trust anything but the total 1306*7c478bd9Sstevel@tonic-gate * number of blocks. 1307*7c478bd9Sstevel@tonic-gate */ 1308*7c478bd9Sstevel@tonic-gate if (free_blocks == (fsblkcnt64_t)-1) { 1309*7c478bd9Sstevel@tonic-gate used_blocks = (fsblkcnt64_t)-1; 1310*7c478bd9Sstevel@tonic-gate (void) strcpy(capacity_buf, " 100%"); 1311*7c478bd9Sstevel@tonic-gate } else { 1312*7c478bd9Sstevel@tonic-gate fsblkcnt64_t reserved_blocks = free_blocks - available_blocks; 1313*7c478bd9Sstevel@tonic-gate 1314*7c478bd9Sstevel@tonic-gate used_blocks = total_blocks - free_blocks; 1315*7c478bd9Sstevel@tonic-gate 1316*7c478bd9Sstevel@tonic-gate /* 1317*7c478bd9Sstevel@tonic-gate * The capacity estimation is bogus when available_blocks is 0 1318*7c478bd9Sstevel@tonic-gate * and the super-user has allocated more space. The reason 1319*7c478bd9Sstevel@tonic-gate * is that reserved_blocks is inaccurate in that case, because 1320*7c478bd9Sstevel@tonic-gate * when the super-user allocates space, free_blocks is updated 1321*7c478bd9Sstevel@tonic-gate * but available_blocks is not (since it can't drop below 0). 1322*7c478bd9Sstevel@tonic-gate * 1323*7c478bd9Sstevel@tonic-gate * XCU4 and POSIX.2 require that any fractional result of the 1324*7c478bd9Sstevel@tonic-gate * capacity estimation be rounded to the next highest integer, 1325*7c478bd9Sstevel@tonic-gate * hence the addition of 0.5. 1326*7c478bd9Sstevel@tonic-gate */ 1327*7c478bd9Sstevel@tonic-gate (void) sprintf(capacity_buf, "%5.0f%%", 1328*7c478bd9Sstevel@tonic-gate (total_blocks == 0) ? 0.0 : 1329*7c478bd9Sstevel@tonic-gate ((double)used_blocks / 1330*7c478bd9Sstevel@tonic-gate (double)(total_blocks - reserved_blocks)) 1331*7c478bd9Sstevel@tonic-gate * 100.0 + 0.5); 1332*7c478bd9Sstevel@tonic-gate } 1333*7c478bd9Sstevel@tonic-gate 1334*7c478bd9Sstevel@tonic-gate /* 1335*7c478bd9Sstevel@tonic-gate * The available_blocks can be less than 0 on a 4.x file system. 1336*7c478bd9Sstevel@tonic-gate * Reset it to 0 in order to avoid printing negative numbers. 1337*7c478bd9Sstevel@tonic-gate */ 1338*7c478bd9Sstevel@tonic-gate if ((long long)available_blocks < (long long)0) 1339*7c478bd9Sstevel@tonic-gate available_blocks = (fsblkcnt64_t)0; 1340*7c478bd9Sstevel@tonic-gate /* 1341*7c478bd9Sstevel@tonic-gate * Print long special device names (usually NFS mounts) in a line 1342*7c478bd9Sstevel@tonic-gate * by themselves when the output is directed to a terminal. 1343*7c478bd9Sstevel@tonic-gate */ 1344*7c478bd9Sstevel@tonic-gate if (tty_output && strlen(file_system) > (size_t)FILESYSTEM_WIDTH) { 1345*7c478bd9Sstevel@tonic-gate (void) printf("%s\n", file_system); 1346*7c478bd9Sstevel@tonic-gate file_system = ""; 1347*7c478bd9Sstevel@tonic-gate } 1348*7c478bd9Sstevel@tonic-gate 1349*7c478bd9Sstevel@tonic-gate if (use_scaling) { /* comes from the -h option */ 1350*7c478bd9Sstevel@tonic-gate (void) printf("%-*s %*s %*s %*s %-*s %-s\n", 1351*7c478bd9Sstevel@tonic-gate FILESYSTEM_WIDTH, file_system, 1352*7c478bd9Sstevel@tonic-gate SCALED_WIDTH, number_to_scaled_string(total_blocks_buf, 1353*7c478bd9Sstevel@tonic-gate total_blocks, fsp->f_frsize, scale), 1354*7c478bd9Sstevel@tonic-gate SCALED_WIDTH, number_to_scaled_string(used_blocks_buf, 1355*7c478bd9Sstevel@tonic-gate used_blocks, fsp->f_frsize, scale), 1356*7c478bd9Sstevel@tonic-gate AVAILABLE_WIDTH, number_to_scaled_string(available_blocks_buf, 1357*7c478bd9Sstevel@tonic-gate available_blocks, fsp->f_frsize, scale), 1358*7c478bd9Sstevel@tonic-gate CAPACITY_WIDTH, capacity_buf, 1359*7c478bd9Sstevel@tonic-gate DFR_MOUNT_POINT(dfrp)); 1360*7c478bd9Sstevel@tonic-gate return; 1361*7c478bd9Sstevel@tonic-gate } 1362*7c478bd9Sstevel@tonic-gate 1363*7c478bd9Sstevel@tonic-gate if (v_option) { 1364*7c478bd9Sstevel@tonic-gate (void) printf("%-*.*s %-*.*s %*lld %*lld %*lld %-.*s\n", 1365*7c478bd9Sstevel@tonic-gate IBCS2_MOUNT_POINT_WIDTH, IBCS2_MOUNT_POINT_WIDTH, 1366*7c478bd9Sstevel@tonic-gate DFR_MOUNT_POINT(dfrp), 1367*7c478bd9Sstevel@tonic-gate IBCS2_FILESYSTEM_WIDTH, IBCS2_FILESYSTEM_WIDTH, file_system, 1368*7c478bd9Sstevel@tonic-gate BLOCK_WIDTH, total_blocks, 1369*7c478bd9Sstevel@tonic-gate BLOCK_WIDTH, used_blocks, 1370*7c478bd9Sstevel@tonic-gate BLOCK_WIDTH, available_blocks, 1371*7c478bd9Sstevel@tonic-gate CAPACITY_WIDTH, capacity_buf); 1372*7c478bd9Sstevel@tonic-gate return; 1373*7c478bd9Sstevel@tonic-gate } 1374*7c478bd9Sstevel@tonic-gate 1375*7c478bd9Sstevel@tonic-gate if (P_option && !k_option) { 1376*7c478bd9Sstevel@tonic-gate (void) printf("%-*s %*s %*s %*s %-*s %-s\n", 1377*7c478bd9Sstevel@tonic-gate FILESYSTEM_WIDTH, file_system, 1378*7c478bd9Sstevel@tonic-gate KBYTE_WIDTH, number_to_string(total_blocks_buf, 1379*7c478bd9Sstevel@tonic-gate total_blocks, fsp->f_frsize, 512), 1380*7c478bd9Sstevel@tonic-gate KBYTE_WIDTH, number_to_string(used_blocks_buf, 1381*7c478bd9Sstevel@tonic-gate used_blocks, fsp->f_frsize, 512), 1382*7c478bd9Sstevel@tonic-gate KBYTE_WIDTH, number_to_string(available_blocks_buf, 1383*7c478bd9Sstevel@tonic-gate available_blocks, fsp->f_frsize, 512), 1384*7c478bd9Sstevel@tonic-gate CAPACITY_WIDTH, capacity_buf, 1385*7c478bd9Sstevel@tonic-gate DFR_MOUNT_POINT(dfrp)); 1386*7c478bd9Sstevel@tonic-gate } else { 1387*7c478bd9Sstevel@tonic-gate (void) printf("%-*s %*s %*s %*s %-*s %-s\n", 1388*7c478bd9Sstevel@tonic-gate FILESYSTEM_WIDTH, file_system, 1389*7c478bd9Sstevel@tonic-gate KBYTE_WIDTH, number_to_string(total_blocks_buf, 1390*7c478bd9Sstevel@tonic-gate total_blocks, fsp->f_frsize, 1024), 1391*7c478bd9Sstevel@tonic-gate KBYTE_WIDTH, number_to_string(used_blocks_buf, 1392*7c478bd9Sstevel@tonic-gate used_blocks, fsp->f_frsize, 1024), 1393*7c478bd9Sstevel@tonic-gate KBYTE_WIDTH, number_to_string(available_blocks_buf, 1394*7c478bd9Sstevel@tonic-gate available_blocks, fsp->f_frsize, 1024), 1395*7c478bd9Sstevel@tonic-gate CAPACITY_WIDTH, capacity_buf, 1396*7c478bd9Sstevel@tonic-gate DFR_MOUNT_POINT(dfrp)); 1397*7c478bd9Sstevel@tonic-gate } 1398*7c478bd9Sstevel@tonic-gate } 1399*7c478bd9Sstevel@tonic-gate 1400*7c478bd9Sstevel@tonic-gate /* 1401*7c478bd9Sstevel@tonic-gate * The following is for internationalization support. 1402*7c478bd9Sstevel@tonic-gate */ 1403*7c478bd9Sstevel@tonic-gate static bool_int strings_initialized; 1404*7c478bd9Sstevel@tonic-gate static char *files_str; 1405*7c478bd9Sstevel@tonic-gate static char *blocks_str; 1406*7c478bd9Sstevel@tonic-gate static char *total_str; 1407*7c478bd9Sstevel@tonic-gate static char *kilobytes_str; 1408*7c478bd9Sstevel@tonic-gate 1409*7c478bd9Sstevel@tonic-gate static void 1410*7c478bd9Sstevel@tonic-gate strings_init() 1411*7c478bd9Sstevel@tonic-gate { 1412*7c478bd9Sstevel@tonic-gate total_str = TRANSLATE("total"); 1413*7c478bd9Sstevel@tonic-gate #ifdef _iBCS2 1414*7c478bd9Sstevel@tonic-gate /* ISC/SCO print i-nodes instead of files */ 1415*7c478bd9Sstevel@tonic-gate if (sysv3_set) 1416*7c478bd9Sstevel@tonic-gate files_str = TRANSLATE("i-nodes"); 1417*7c478bd9Sstevel@tonic-gate else 1418*7c478bd9Sstevel@tonic-gate #endif /* _iBCS2 */ 1419*7c478bd9Sstevel@tonic-gate files_str = TRANSLATE("files"); 1420*7c478bd9Sstevel@tonic-gate blocks_str = TRANSLATE("blocks"); 1421*7c478bd9Sstevel@tonic-gate kilobytes_str = TRANSLATE("kilobytes"); 1422*7c478bd9Sstevel@tonic-gate strings_initialized = TRUE; 1423*7c478bd9Sstevel@tonic-gate } 1424*7c478bd9Sstevel@tonic-gate 1425*7c478bd9Sstevel@tonic-gate #define STRINGS_INIT() if (!strings_initialized) strings_init() 1426*7c478bd9Sstevel@tonic-gate 1427*7c478bd9Sstevel@tonic-gate 1428*7c478bd9Sstevel@tonic-gate static void 1429*7c478bd9Sstevel@tonic-gate t_output(struct df_request *dfrp, struct statvfs64 *fsp) 1430*7c478bd9Sstevel@tonic-gate { 1431*7c478bd9Sstevel@tonic-gate numbuf_t total_blocks_buf; 1432*7c478bd9Sstevel@tonic-gate numbuf_t total_files_buf; 1433*7c478bd9Sstevel@tonic-gate numbuf_t free_blocks_buf; 1434*7c478bd9Sstevel@tonic-gate numbuf_t free_files_buf; 1435*7c478bd9Sstevel@tonic-gate 1436*7c478bd9Sstevel@tonic-gate STRINGS_INIT(); 1437*7c478bd9Sstevel@tonic-gate 1438*7c478bd9Sstevel@tonic-gate (void) printf("%-*s(%-*s): %*s %s %*s %s\n", 1439*7c478bd9Sstevel@tonic-gate MOUNT_POINT_WIDTH, DFR_MOUNT_POINT(dfrp), 1440*7c478bd9Sstevel@tonic-gate SPECIAL_DEVICE_WIDTH, DFR_SPECIAL(dfrp), 1441*7c478bd9Sstevel@tonic-gate BLOCK_WIDTH, number_to_string(free_blocks_buf, 1442*7c478bd9Sstevel@tonic-gate fsp->f_bfree, fsp->f_frsize, 512), 1443*7c478bd9Sstevel@tonic-gate blocks_str, 1444*7c478bd9Sstevel@tonic-gate NFILES_WIDTH, number_to_string(free_files_buf, 1445*7c478bd9Sstevel@tonic-gate fsp->f_ffree, 1, 1), 1446*7c478bd9Sstevel@tonic-gate files_str); 1447*7c478bd9Sstevel@tonic-gate /* 1448*7c478bd9Sstevel@tonic-gate * The total column used to use the same space as the mnt pt & special 1449*7c478bd9Sstevel@tonic-gate * dev fields. However, this doesn't work with massive special dev 1450*7c478bd9Sstevel@tonic-gate * fields * (eg > 500 chars) causing an enormous amount of white space 1451*7c478bd9Sstevel@tonic-gate * before the total column (see bug 4100411). So the code was 1452*7c478bd9Sstevel@tonic-gate * simplified to set the total column at the usual gap. 1453*7c478bd9Sstevel@tonic-gate * This had the side effect of fixing a bug where the previously 1454*7c478bd9Sstevel@tonic-gate * used static buffer was overflowed by the same massive special dev. 1455*7c478bd9Sstevel@tonic-gate */ 1456*7c478bd9Sstevel@tonic-gate (void) printf("%*s: %*s %s %*s %s\n", 1457*7c478bd9Sstevel@tonic-gate MNT_SPEC_WIDTH, total_str, 1458*7c478bd9Sstevel@tonic-gate BLOCK_WIDTH, number_to_string(total_blocks_buf, 1459*7c478bd9Sstevel@tonic-gate fsp->f_blocks, fsp->f_frsize, 512), 1460*7c478bd9Sstevel@tonic-gate blocks_str, 1461*7c478bd9Sstevel@tonic-gate NFILES_WIDTH, number_to_string(total_files_buf, 1462*7c478bd9Sstevel@tonic-gate fsp->f_files, 1, 1), 1463*7c478bd9Sstevel@tonic-gate files_str); 1464*7c478bd9Sstevel@tonic-gate } 1465*7c478bd9Sstevel@tonic-gate 1466*7c478bd9Sstevel@tonic-gate 1467*7c478bd9Sstevel@tonic-gate static void 1468*7c478bd9Sstevel@tonic-gate eb_output(struct df_request *dfrp, struct statvfs64 *fsp) 1469*7c478bd9Sstevel@tonic-gate { 1470*7c478bd9Sstevel@tonic-gate numbuf_t free_files_buf; 1471*7c478bd9Sstevel@tonic-gate numbuf_t free_kbytes_buf; 1472*7c478bd9Sstevel@tonic-gate 1473*7c478bd9Sstevel@tonic-gate STRINGS_INIT(); 1474*7c478bd9Sstevel@tonic-gate 1475*7c478bd9Sstevel@tonic-gate (void) printf("%-*s(%-*s): %*s %s\n", 1476*7c478bd9Sstevel@tonic-gate MOUNT_POINT_WIDTH, DFR_MOUNT_POINT(dfrp), 1477*7c478bd9Sstevel@tonic-gate SPECIAL_DEVICE_WIDTH, DFR_SPECIAL(dfrp), 1478*7c478bd9Sstevel@tonic-gate MAX(KBYTE_WIDTH, NFILES_WIDTH), 1479*7c478bd9Sstevel@tonic-gate number_to_string(free_kbytes_buf, 1480*7c478bd9Sstevel@tonic-gate fsp->f_bfree, fsp->f_frsize, 1024), 1481*7c478bd9Sstevel@tonic-gate kilobytes_str); 1482*7c478bd9Sstevel@tonic-gate (void) printf("%-*s(%-*s): %*s %s\n", 1483*7c478bd9Sstevel@tonic-gate MOUNT_POINT_WIDTH, DFR_MOUNT_POINT(dfrp), 1484*7c478bd9Sstevel@tonic-gate SPECIAL_DEVICE_WIDTH, DFR_SPECIAL(dfrp), 1485*7c478bd9Sstevel@tonic-gate MAX(NFILES_WIDTH, NFILES_WIDTH), 1486*7c478bd9Sstevel@tonic-gate number_to_string(free_files_buf, fsp->f_ffree, 1, 1), 1487*7c478bd9Sstevel@tonic-gate files_str); 1488*7c478bd9Sstevel@tonic-gate } 1489*7c478bd9Sstevel@tonic-gate 1490*7c478bd9Sstevel@tonic-gate 1491*7c478bd9Sstevel@tonic-gate static void 1492*7c478bd9Sstevel@tonic-gate e_output(struct df_request *dfrp, struct statvfs64 *fsp) 1493*7c478bd9Sstevel@tonic-gate { 1494*7c478bd9Sstevel@tonic-gate numbuf_t free_files_buf; 1495*7c478bd9Sstevel@tonic-gate 1496*7c478bd9Sstevel@tonic-gate (void) printf("%-*s %*s\n", 1497*7c478bd9Sstevel@tonic-gate FILESYSTEM_WIDTH, DFR_SPECIAL(dfrp), 1498*7c478bd9Sstevel@tonic-gate NFILES_WIDTH, 1499*7c478bd9Sstevel@tonic-gate number_to_string(free_files_buf, fsp->f_ffree, 1, 1)); 1500*7c478bd9Sstevel@tonic-gate } 1501*7c478bd9Sstevel@tonic-gate 1502*7c478bd9Sstevel@tonic-gate 1503*7c478bd9Sstevel@tonic-gate static void 1504*7c478bd9Sstevel@tonic-gate b_output(struct df_request *dfrp, struct statvfs64 *fsp) 1505*7c478bd9Sstevel@tonic-gate { 1506*7c478bd9Sstevel@tonic-gate numbuf_t free_blocks_buf; 1507*7c478bd9Sstevel@tonic-gate 1508*7c478bd9Sstevel@tonic-gate (void) printf("%-*s %*s\n", 1509*7c478bd9Sstevel@tonic-gate FILESYSTEM_WIDTH, DFR_SPECIAL(dfrp), 1510*7c478bd9Sstevel@tonic-gate BLOCK_WIDTH, number_to_string(free_blocks_buf, 1511*7c478bd9Sstevel@tonic-gate fsp->f_bfree, fsp->f_frsize, 1024)); 1512*7c478bd9Sstevel@tonic-gate } 1513*7c478bd9Sstevel@tonic-gate 1514*7c478bd9Sstevel@tonic-gate 1515*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1516*7c478bd9Sstevel@tonic-gate static void 1517*7c478bd9Sstevel@tonic-gate n_output(struct df_request *dfrp, struct statvfs64 *fsp) 1518*7c478bd9Sstevel@tonic-gate { 1519*7c478bd9Sstevel@tonic-gate (void) printf("%-*s: %-*s\n", 1520*7c478bd9Sstevel@tonic-gate MOUNT_POINT_WIDTH, DFR_MOUNT_POINT(dfrp), 1521*7c478bd9Sstevel@tonic-gate FSTYPE_WIDTH, dfrp->dfr_fstype); 1522*7c478bd9Sstevel@tonic-gate } 1523*7c478bd9Sstevel@tonic-gate 1524*7c478bd9Sstevel@tonic-gate 1525*7c478bd9Sstevel@tonic-gate static void 1526*7c478bd9Sstevel@tonic-gate default_output(struct df_request *dfrp, struct statvfs64 *fsp) 1527*7c478bd9Sstevel@tonic-gate { 1528*7c478bd9Sstevel@tonic-gate numbuf_t free_blocks_buf; 1529*7c478bd9Sstevel@tonic-gate numbuf_t free_files_buf; 1530*7c478bd9Sstevel@tonic-gate 1531*7c478bd9Sstevel@tonic-gate STRINGS_INIT(); 1532*7c478bd9Sstevel@tonic-gate 1533*7c478bd9Sstevel@tonic-gate (void) printf("%-*s(%-*s):%*s %s %*s %s\n", 1534*7c478bd9Sstevel@tonic-gate MOUNT_POINT_WIDTH, DFR_MOUNT_POINT(dfrp), 1535*7c478bd9Sstevel@tonic-gate SPECIAL_DEVICE_WIDTH, DFR_SPECIAL(dfrp), 1536*7c478bd9Sstevel@tonic-gate BLOCK_WIDTH, number_to_string(free_blocks_buf, 1537*7c478bd9Sstevel@tonic-gate fsp->f_bfree, fsp->f_frsize, 512), 1538*7c478bd9Sstevel@tonic-gate blocks_str, 1539*7c478bd9Sstevel@tonic-gate NFILES_WIDTH, number_to_string(free_files_buf, 1540*7c478bd9Sstevel@tonic-gate fsp->f_ffree, 1, 1), 1541*7c478bd9Sstevel@tonic-gate files_str); 1542*7c478bd9Sstevel@tonic-gate } 1543*7c478bd9Sstevel@tonic-gate 1544*7c478bd9Sstevel@tonic-gate 1545*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1546*7c478bd9Sstevel@tonic-gate static void 1547*7c478bd9Sstevel@tonic-gate V_output(struct df_request *dfrp, struct statvfs64 *fsp) 1548*7c478bd9Sstevel@tonic-gate { 1549*7c478bd9Sstevel@tonic-gate char temp_buf[LINEBUF_SIZE]; 1550*7c478bd9Sstevel@tonic-gate 1551*7c478bd9Sstevel@tonic-gate if (df_options_len > 1) 1552*7c478bd9Sstevel@tonic-gate (void) strcat(strcpy(temp_buf, df_options), " "); 1553*7c478bd9Sstevel@tonic-gate else 1554*7c478bd9Sstevel@tonic-gate temp_buf[0] = NUL; 1555*7c478bd9Sstevel@tonic-gate 1556*7c478bd9Sstevel@tonic-gate (void) printf("%s -F %s %s%s\n", 1557*7c478bd9Sstevel@tonic-gate program_name, dfrp->dfr_fstype, temp_buf, 1558*7c478bd9Sstevel@tonic-gate dfrp->dfr_cmd_arg ? dfrp->dfr_cmd_arg: DFR_SPECIAL(dfrp)); 1559*7c478bd9Sstevel@tonic-gate } 1560*7c478bd9Sstevel@tonic-gate 1561*7c478bd9Sstevel@tonic-gate 1562*7c478bd9Sstevel@tonic-gate /* 1563*7c478bd9Sstevel@tonic-gate * This function is used to sort the array of df_requests according to fstype 1564*7c478bd9Sstevel@tonic-gate */ 1565*7c478bd9Sstevel@tonic-gate static int 1566*7c478bd9Sstevel@tonic-gate df_reqcomp(const void *p1, const void *p2) 1567*7c478bd9Sstevel@tonic-gate { 1568*7c478bd9Sstevel@tonic-gate int v = strcmp(DFRP(p1)->dfr_fstype, DFRP(p2)->dfr_fstype); 1569*7c478bd9Sstevel@tonic-gate 1570*7c478bd9Sstevel@tonic-gate if (v != 0) 1571*7c478bd9Sstevel@tonic-gate return (v); 1572*7c478bd9Sstevel@tonic-gate else 1573*7c478bd9Sstevel@tonic-gate return (DFRP(p1)->dfr_index - DFRP(p2)->dfr_index); 1574*7c478bd9Sstevel@tonic-gate } 1575*7c478bd9Sstevel@tonic-gate 1576*7c478bd9Sstevel@tonic-gate 1577*7c478bd9Sstevel@tonic-gate static void 1578*7c478bd9Sstevel@tonic-gate vfs_error(char *file, int status) 1579*7c478bd9Sstevel@tonic-gate { 1580*7c478bd9Sstevel@tonic-gate if (status == VFS_TOOLONG) 1581*7c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, "a line in %s exceeds %d characters", 1582*7c478bd9Sstevel@tonic-gate file, MNT_LINE_MAX); 1583*7c478bd9Sstevel@tonic-gate else if (status == VFS_TOOMANY) 1584*7c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, "a line in %s has too many fields", file); 1585*7c478bd9Sstevel@tonic-gate else if (status == VFS_TOOFEW) 1586*7c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, "a line in %s has too few fields", file); 1587*7c478bd9Sstevel@tonic-gate else 1588*7c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, "error while reading %s: %d", file, status); 1589*7c478bd9Sstevel@tonic-gate } 1590*7c478bd9Sstevel@tonic-gate 1591*7c478bd9Sstevel@tonic-gate 1592*7c478bd9Sstevel@tonic-gate /* 1593*7c478bd9Sstevel@tonic-gate * Try to determine the fstype for the specified block device. 1594*7c478bd9Sstevel@tonic-gate * Return in order of decreasing preference: 1595*7c478bd9Sstevel@tonic-gate * file system type from vfstab 1596*7c478bd9Sstevel@tonic-gate * file system type as specified by -F option 1597*7c478bd9Sstevel@tonic-gate * default file system type 1598*7c478bd9Sstevel@tonic-gate */ 1599*7c478bd9Sstevel@tonic-gate static char * 1600*7c478bd9Sstevel@tonic-gate find_fstype(char *special) 1601*7c478bd9Sstevel@tonic-gate { 1602*7c478bd9Sstevel@tonic-gate struct vfstab vtab; 1603*7c478bd9Sstevel@tonic-gate FILE *fp; 1604*7c478bd9Sstevel@tonic-gate int status; 1605*7c478bd9Sstevel@tonic-gate char *vfstab_file = VFS_TAB; 1606*7c478bd9Sstevel@tonic-gate 1607*7c478bd9Sstevel@tonic-gate fp = xfopen(vfstab_file); 1608*7c478bd9Sstevel@tonic-gate status = getvfsspec(fp, &vtab, special); 1609*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 1610*7c478bd9Sstevel@tonic-gate if (status > 0) 1611*7c478bd9Sstevel@tonic-gate vfs_error(vfstab_file, status); 1612*7c478bd9Sstevel@tonic-gate 1613*7c478bd9Sstevel@tonic-gate if (status == 0) { 1614*7c478bd9Sstevel@tonic-gate if (F_option && ! EQ(FSType, vtab.vfs_fstype)) 1615*7c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, 1616*7c478bd9Sstevel@tonic-gate "warning: %s is of type %s", special, vtab.vfs_fstype); 1617*7c478bd9Sstevel@tonic-gate return (new_string(vtab.vfs_fstype)); 1618*7c478bd9Sstevel@tonic-gate } 1619*7c478bd9Sstevel@tonic-gate else 1620*7c478bd9Sstevel@tonic-gate return (F_option ? FSType : default_fstype(special)); 1621*7c478bd9Sstevel@tonic-gate } 1622*7c478bd9Sstevel@tonic-gate 1623*7c478bd9Sstevel@tonic-gate /* 1624*7c478bd9Sstevel@tonic-gate * When this function returns, the following fields are filled for all 1625*7c478bd9Sstevel@tonic-gate * valid entries in the requests[] array: 1626*7c478bd9Sstevel@tonic-gate * dfr_mte (if the file system is mounted) 1627*7c478bd9Sstevel@tonic-gate * dfr_fstype 1628*7c478bd9Sstevel@tonic-gate * dfr_index 1629*7c478bd9Sstevel@tonic-gate * 1630*7c478bd9Sstevel@tonic-gate * The function returns the number of errors that occurred while building 1631*7c478bd9Sstevel@tonic-gate * the request list. 1632*7c478bd9Sstevel@tonic-gate */ 1633*7c478bd9Sstevel@tonic-gate static int 1634*7c478bd9Sstevel@tonic-gate create_request_list( 1635*7c478bd9Sstevel@tonic-gate int argc, 1636*7c478bd9Sstevel@tonic-gate char *argv[], 1637*7c478bd9Sstevel@tonic-gate struct df_request *requests_p[], 1638*7c478bd9Sstevel@tonic-gate size_t *request_count) 1639*7c478bd9Sstevel@tonic-gate { 1640*7c478bd9Sstevel@tonic-gate struct df_request *requests; 1641*7c478bd9Sstevel@tonic-gate struct df_request *dfrp; 1642*7c478bd9Sstevel@tonic-gate size_t size; 1643*7c478bd9Sstevel@tonic-gate size_t i; 1644*7c478bd9Sstevel@tonic-gate size_t request_index = 0; 1645*7c478bd9Sstevel@tonic-gate size_t max_requests; 1646*7c478bd9Sstevel@tonic-gate int errors = 0; 1647*7c478bd9Sstevel@tonic-gate 1648*7c478bd9Sstevel@tonic-gate /* 1649*7c478bd9Sstevel@tonic-gate * If no args, use the mounted file systems, otherwise use the 1650*7c478bd9Sstevel@tonic-gate * user-specified arguments. 1651*7c478bd9Sstevel@tonic-gate */ 1652*7c478bd9Sstevel@tonic-gate if (argc == 0) { 1653*7c478bd9Sstevel@tonic-gate mtab_read_file(); 1654*7c478bd9Sstevel@tonic-gate max_requests = mount_table_entries; 1655*7c478bd9Sstevel@tonic-gate } else 1656*7c478bd9Sstevel@tonic-gate max_requests = argc; 1657*7c478bd9Sstevel@tonic-gate 1658*7c478bd9Sstevel@tonic-gate size = max_requests * sizeof (struct df_request); 1659*7c478bd9Sstevel@tonic-gate requests = xmalloc(size); 1660*7c478bd9Sstevel@tonic-gate (void) memset(requests, 0, size); 1661*7c478bd9Sstevel@tonic-gate 1662*7c478bd9Sstevel@tonic-gate if (argc == 0) { 1663*7c478bd9Sstevel@tonic-gate /* 1664*7c478bd9Sstevel@tonic-gate * If -Z wasn't specified, we skip mounts in other 1665*7c478bd9Sstevel@tonic-gate * zones. This obviously is a noop in a non-global 1666*7c478bd9Sstevel@tonic-gate * zone. 1667*7c478bd9Sstevel@tonic-gate */ 1668*7c478bd9Sstevel@tonic-gate boolean_t showall = (getzoneid() != GLOBAL_ZONEID) || Z_option; 1669*7c478bd9Sstevel@tonic-gate struct zone_summary *zsp; 1670*7c478bd9Sstevel@tonic-gate 1671*7c478bd9Sstevel@tonic-gate if (!showall) { 1672*7c478bd9Sstevel@tonic-gate zsp = fs_get_zone_summaries(); 1673*7c478bd9Sstevel@tonic-gate if (zsp == NULL) 1674*7c478bd9Sstevel@tonic-gate errmsg(ERR_FATAL, 1675*7c478bd9Sstevel@tonic-gate "unable to retrieve list of zones"); 1676*7c478bd9Sstevel@tonic-gate } 1677*7c478bd9Sstevel@tonic-gate 1678*7c478bd9Sstevel@tonic-gate for (i = 0; i < mount_table_entries; i++) { 1679*7c478bd9Sstevel@tonic-gate struct extmnttab *mtp = mount_table[i].mte_mount; 1680*7c478bd9Sstevel@tonic-gate 1681*7c478bd9Sstevel@tonic-gate if (EQ(mtp->mnt_fstype, MNTTYPE_SWAP)) 1682*7c478bd9Sstevel@tonic-gate continue; 1683*7c478bd9Sstevel@tonic-gate 1684*7c478bd9Sstevel@tonic-gate if (!showall) { 1685*7c478bd9Sstevel@tonic-gate if (fs_mount_in_other_zone(zsp, 1686*7c478bd9Sstevel@tonic-gate mtp->mnt_mountp)) 1687*7c478bd9Sstevel@tonic-gate continue; 1688*7c478bd9Sstevel@tonic-gate } 1689*7c478bd9Sstevel@tonic-gate dfrp = &requests[request_index++]; 1690*7c478bd9Sstevel@tonic-gate dfrp->dfr_mte = &mount_table[i]; 1691*7c478bd9Sstevel@tonic-gate dfrp->dfr_fstype = mtp->mnt_fstype; 1692*7c478bd9Sstevel@tonic-gate dfrp->dfr_index = i; 1693*7c478bd9Sstevel@tonic-gate dfrp->dfr_valid = TRUE; 1694*7c478bd9Sstevel@tonic-gate } 1695*7c478bd9Sstevel@tonic-gate } else { 1696*7c478bd9Sstevel@tonic-gate struct stat64 *arg_stat; /* array of stat structures */ 1697*7c478bd9Sstevel@tonic-gate bool_int *valid_stat; /* which structures are valid */ 1698*7c478bd9Sstevel@tonic-gate 1699*7c478bd9Sstevel@tonic-gate arg_stat = xmalloc(argc * sizeof (struct stat64)); 1700*7c478bd9Sstevel@tonic-gate valid_stat = xmalloc(argc * sizeof (bool_int)); 1701*7c478bd9Sstevel@tonic-gate 1702*7c478bd9Sstevel@tonic-gate /* 1703*7c478bd9Sstevel@tonic-gate * Obtain stat64 information for each argument before 1704*7c478bd9Sstevel@tonic-gate * constructing the list of mounted file systems. By 1705*7c478bd9Sstevel@tonic-gate * touching all these places we force the automounter 1706*7c478bd9Sstevel@tonic-gate * to establish any mounts required to access the arguments, 1707*7c478bd9Sstevel@tonic-gate * so that the corresponding mount table entries will exist 1708*7c478bd9Sstevel@tonic-gate * when we look for them. 1709*7c478bd9Sstevel@tonic-gate * It is still possible that the automounter may timeout 1710*7c478bd9Sstevel@tonic-gate * mounts between the time we read the mount table and the 1711*7c478bd9Sstevel@tonic-gate * time we process the request. Even in that case, when 1712*7c478bd9Sstevel@tonic-gate * we issue the statvfs64(2) for the mount point, the file 1713*7c478bd9Sstevel@tonic-gate * system will be mounted again. The only problem will 1714*7c478bd9Sstevel@tonic-gate * occur if the automounter maps change in the meantime 1715*7c478bd9Sstevel@tonic-gate * and the mount point is eliminated. 1716*7c478bd9Sstevel@tonic-gate */ 1717*7c478bd9Sstevel@tonic-gate for (i = 0; i < argc; i++) 1718*7c478bd9Sstevel@tonic-gate valid_stat[i] = (stat64(argv[i], &arg_stat[i]) == 0); 1719*7c478bd9Sstevel@tonic-gate 1720*7c478bd9Sstevel@tonic-gate mtab_read_file(); 1721*7c478bd9Sstevel@tonic-gate 1722*7c478bd9Sstevel@tonic-gate for (i = 0; i < argc; i++) { 1723*7c478bd9Sstevel@tonic-gate char *arg = argv[i]; 1724*7c478bd9Sstevel@tonic-gate 1725*7c478bd9Sstevel@tonic-gate dfrp = &requests[request_index]; 1726*7c478bd9Sstevel@tonic-gate 1727*7c478bd9Sstevel@tonic-gate dfrp->dfr_index = request_index; 1728*7c478bd9Sstevel@tonic-gate dfrp->dfr_cmd_arg = arg; 1729*7c478bd9Sstevel@tonic-gate 1730*7c478bd9Sstevel@tonic-gate if (valid_stat[i]) { 1731*7c478bd9Sstevel@tonic-gate if (S_ISBLK(arg_stat[i].st_mode)) { 1732*7c478bd9Sstevel@tonic-gate bdev_mount_entry(dfrp); 1733*7c478bd9Sstevel@tonic-gate dfrp->dfr_valid = TRUE; 1734*7c478bd9Sstevel@tonic-gate } else if (S_ISDIR(arg_stat[i].st_mode) || 1735*7c478bd9Sstevel@tonic-gate S_ISREG(arg_stat[i].st_mode) || 1736*7c478bd9Sstevel@tonic-gate S_ISFIFO(arg_stat[i].st_mode)) { 1737*7c478bd9Sstevel@tonic-gate path_mount_entry(dfrp, 1738*7c478bd9Sstevel@tonic-gate arg_stat[i].st_dev); 1739*7c478bd9Sstevel@tonic-gate if (! DFR_ISMOUNTEDFS(dfrp)) { 1740*7c478bd9Sstevel@tonic-gate errors++; 1741*7c478bd9Sstevel@tonic-gate continue; 1742*7c478bd9Sstevel@tonic-gate } 1743*7c478bd9Sstevel@tonic-gate dfrp->dfr_valid = TRUE; 1744*7c478bd9Sstevel@tonic-gate } 1745*7c478bd9Sstevel@tonic-gate } else { 1746*7c478bd9Sstevel@tonic-gate resource_mount_entry(dfrp); 1747*7c478bd9Sstevel@tonic-gate dfrp->dfr_valid = DFR_ISMOUNTEDFS(dfrp); 1748*7c478bd9Sstevel@tonic-gate } 1749*7c478bd9Sstevel@tonic-gate 1750*7c478bd9Sstevel@tonic-gate /* 1751*7c478bd9Sstevel@tonic-gate * If we haven't managed to verify that the request 1752*7c478bd9Sstevel@tonic-gate * is valid, we must have gotten a bad argument. 1753*7c478bd9Sstevel@tonic-gate */ 1754*7c478bd9Sstevel@tonic-gate if (!dfrp->dfr_valid) { 1755*7c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, 1756*7c478bd9Sstevel@tonic-gate "(%-10s) not a block device, directory or mounted resource", 1757*7c478bd9Sstevel@tonic-gate arg); 1758*7c478bd9Sstevel@tonic-gate errors++; 1759*7c478bd9Sstevel@tonic-gate continue; 1760*7c478bd9Sstevel@tonic-gate } 1761*7c478bd9Sstevel@tonic-gate 1762*7c478bd9Sstevel@tonic-gate /* 1763*7c478bd9Sstevel@tonic-gate * Determine the file system type. 1764*7c478bd9Sstevel@tonic-gate */ 1765*7c478bd9Sstevel@tonic-gate if (DFR_ISMOUNTEDFS(dfrp)) 1766*7c478bd9Sstevel@tonic-gate dfrp->dfr_fstype = 1767*7c478bd9Sstevel@tonic-gate dfrp->dfr_mte->mte_mount->mnt_fstype; 1768*7c478bd9Sstevel@tonic-gate else 1769*7c478bd9Sstevel@tonic-gate dfrp->dfr_fstype = 1770*7c478bd9Sstevel@tonic-gate find_fstype(dfrp->dfr_cmd_arg); 1771*7c478bd9Sstevel@tonic-gate 1772*7c478bd9Sstevel@tonic-gate request_index++; 1773*7c478bd9Sstevel@tonic-gate } 1774*7c478bd9Sstevel@tonic-gate } 1775*7c478bd9Sstevel@tonic-gate *requests_p = requests; 1776*7c478bd9Sstevel@tonic-gate *request_count = request_index; 1777*7c478bd9Sstevel@tonic-gate return (errors); 1778*7c478bd9Sstevel@tonic-gate } 1779*7c478bd9Sstevel@tonic-gate 1780*7c478bd9Sstevel@tonic-gate 1781*7c478bd9Sstevel@tonic-gate /* 1782*7c478bd9Sstevel@tonic-gate * Select the appropriate function and flags to use for output. 1783*7c478bd9Sstevel@tonic-gate * Notice that using both -e and -b options produces a different form of 1784*7c478bd9Sstevel@tonic-gate * output than either of those two options alone; this is the behavior of 1785*7c478bd9Sstevel@tonic-gate * the SVR4 df. 1786*7c478bd9Sstevel@tonic-gate */ 1787*7c478bd9Sstevel@tonic-gate static struct df_output * 1788*7c478bd9Sstevel@tonic-gate select_output() 1789*7c478bd9Sstevel@tonic-gate { 1790*7c478bd9Sstevel@tonic-gate static struct df_output dfo; 1791*7c478bd9Sstevel@tonic-gate 1792*7c478bd9Sstevel@tonic-gate /* 1793*7c478bd9Sstevel@tonic-gate * The order of checking options follows the option precedence 1794*7c478bd9Sstevel@tonic-gate * rules as they are listed in the man page. 1795*7c478bd9Sstevel@tonic-gate */ 1796*7c478bd9Sstevel@tonic-gate if (use_scaling) { /* comes from the -h option */ 1797*7c478bd9Sstevel@tonic-gate dfo.dfo_func = k_output; 1798*7c478bd9Sstevel@tonic-gate dfo.dfo_flags = DFO_HEADER + DFO_STATVFS; 1799*7c478bd9Sstevel@tonic-gate } else if (V_option) { 1800*7c478bd9Sstevel@tonic-gate dfo.dfo_func = V_output; 1801*7c478bd9Sstevel@tonic-gate dfo.dfo_flags = DFO_NOFLAGS; 1802*7c478bd9Sstevel@tonic-gate } else if (g_option) { 1803*7c478bd9Sstevel@tonic-gate dfo.dfo_func = g_output; 1804*7c478bd9Sstevel@tonic-gate dfo.dfo_flags = DFO_STATVFS; 1805*7c478bd9Sstevel@tonic-gate } else if (k_option || P_option || v_option) { 1806*7c478bd9Sstevel@tonic-gate dfo.dfo_func = k_output; 1807*7c478bd9Sstevel@tonic-gate dfo.dfo_flags = DFO_HEADER + DFO_STATVFS; 1808*7c478bd9Sstevel@tonic-gate } else if (t_option) { 1809*7c478bd9Sstevel@tonic-gate dfo.dfo_func = t_output; 1810*7c478bd9Sstevel@tonic-gate dfo.dfo_flags = DFO_STATVFS; 1811*7c478bd9Sstevel@tonic-gate } else if (b_option && e_option) { 1812*7c478bd9Sstevel@tonic-gate dfo.dfo_func = eb_output; 1813*7c478bd9Sstevel@tonic-gate dfo.dfo_flags = DFO_STATVFS; 1814*7c478bd9Sstevel@tonic-gate } else if (b_option) { 1815*7c478bd9Sstevel@tonic-gate dfo.dfo_func = b_output; 1816*7c478bd9Sstevel@tonic-gate dfo.dfo_flags = DFO_HEADER + DFO_STATVFS; 1817*7c478bd9Sstevel@tonic-gate } else if (e_option) { 1818*7c478bd9Sstevel@tonic-gate dfo.dfo_func = e_output; 1819*7c478bd9Sstevel@tonic-gate dfo.dfo_flags = DFO_HEADER + DFO_STATVFS; 1820*7c478bd9Sstevel@tonic-gate } else if (n_option) { 1821*7c478bd9Sstevel@tonic-gate dfo.dfo_func = n_output; 1822*7c478bd9Sstevel@tonic-gate dfo.dfo_flags = DFO_NOFLAGS; 1823*7c478bd9Sstevel@tonic-gate } else { 1824*7c478bd9Sstevel@tonic-gate dfo.dfo_func = default_output; 1825*7c478bd9Sstevel@tonic-gate dfo.dfo_flags = DFO_STATVFS; 1826*7c478bd9Sstevel@tonic-gate } 1827*7c478bd9Sstevel@tonic-gate return (&dfo); 1828*7c478bd9Sstevel@tonic-gate } 1829*7c478bd9Sstevel@tonic-gate 1830*7c478bd9Sstevel@tonic-gate 1831*7c478bd9Sstevel@tonic-gate /* 1832*7c478bd9Sstevel@tonic-gate * The (argc,argv) pair contains all the non-option arguments 1833*7c478bd9Sstevel@tonic-gate */ 1834*7c478bd9Sstevel@tonic-gate static void 1835*7c478bd9Sstevel@tonic-gate do_df(int argc, char *argv[]) 1836*7c478bd9Sstevel@tonic-gate { 1837*7c478bd9Sstevel@tonic-gate size_t i; 1838*7c478bd9Sstevel@tonic-gate struct df_request *requests; /* array of requests */ 1839*7c478bd9Sstevel@tonic-gate size_t n_requests; 1840*7c478bd9Sstevel@tonic-gate struct df_request *dfrp; 1841*7c478bd9Sstevel@tonic-gate int errors; 1842*7c478bd9Sstevel@tonic-gate 1843*7c478bd9Sstevel@tonic-gate errors = create_request_list(argc, argv, &requests, &n_requests); 1844*7c478bd9Sstevel@tonic-gate 1845*7c478bd9Sstevel@tonic-gate if (n_requests == 0) 1846*7c478bd9Sstevel@tonic-gate exit(errors); 1847*7c478bd9Sstevel@tonic-gate 1848*7c478bd9Sstevel@tonic-gate /* 1849*7c478bd9Sstevel@tonic-gate * If we are going to run the FSType-specific df command, 1850*7c478bd9Sstevel@tonic-gate * rearrange the requests so that we can issue a single command 1851*7c478bd9Sstevel@tonic-gate * per file system type. 1852*7c478bd9Sstevel@tonic-gate */ 1853*7c478bd9Sstevel@tonic-gate if (o_option) { 1854*7c478bd9Sstevel@tonic-gate size_t j; 1855*7c478bd9Sstevel@tonic-gate 1856*7c478bd9Sstevel@tonic-gate /* 1857*7c478bd9Sstevel@tonic-gate * qsort is not a stable sorting method (i.e. requests of 1858*7c478bd9Sstevel@tonic-gate * the same file system type may be swapped, and hence appear 1859*7c478bd9Sstevel@tonic-gate * in the output in a different order from the one in which 1860*7c478bd9Sstevel@tonic-gate * they were listed in the command line). In order to force 1861*7c478bd9Sstevel@tonic-gate * stability, we use the dfr_index field which is unique 1862*7c478bd9Sstevel@tonic-gate * for each request. 1863*7c478bd9Sstevel@tonic-gate */ 1864*7c478bd9Sstevel@tonic-gate qsort(requests, 1865*7c478bd9Sstevel@tonic-gate n_requests, sizeof (struct df_request), df_reqcomp); 1866*7c478bd9Sstevel@tonic-gate for (i = 0; i < n_requests; i = j) { 1867*7c478bd9Sstevel@tonic-gate char *fstype = requests[i].dfr_fstype; 1868*7c478bd9Sstevel@tonic-gate 1869*7c478bd9Sstevel@tonic-gate for (j = i+1; j < n_requests; j++) 1870*7c478bd9Sstevel@tonic-gate if (! EQ(fstype, requests[j].dfr_fstype)) 1871*7c478bd9Sstevel@tonic-gate break; 1872*7c478bd9Sstevel@tonic-gate 1873*7c478bd9Sstevel@tonic-gate /* 1874*7c478bd9Sstevel@tonic-gate * At this point, requests in the range [i,j) are 1875*7c478bd9Sstevel@tonic-gate * of the same type. 1876*7c478bd9Sstevel@tonic-gate * 1877*7c478bd9Sstevel@tonic-gate * If the -F option was used, and the user specified 1878*7c478bd9Sstevel@tonic-gate * arguments, the filesystem types must match 1879*7c478bd9Sstevel@tonic-gate * 1880*7c478bd9Sstevel@tonic-gate * XXX: the alternative of doing this check here is to 1881*7c478bd9Sstevel@tonic-gate * invoke prune_list, but then we have to 1882*7c478bd9Sstevel@tonic-gate * modify this code to ignore invalid requests. 1883*7c478bd9Sstevel@tonic-gate */ 1884*7c478bd9Sstevel@tonic-gate if (F_option && ! EQ(fstype, FSType)) { 1885*7c478bd9Sstevel@tonic-gate size_t k; 1886*7c478bd9Sstevel@tonic-gate 1887*7c478bd9Sstevel@tonic-gate for (k = i; k < j; k++) { 1888*7c478bd9Sstevel@tonic-gate dfrp = &requests[k]; 1889*7c478bd9Sstevel@tonic-gate if (dfrp->dfr_cmd_arg != NULL) { 1890*7c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, 1891*7c478bd9Sstevel@tonic-gate "Warning: %s mounted as a %s file system", 1892*7c478bd9Sstevel@tonic-gate dfrp->dfr_cmd_arg, dfrp->dfr_fstype); 1893*7c478bd9Sstevel@tonic-gate errors++; 1894*7c478bd9Sstevel@tonic-gate } 1895*7c478bd9Sstevel@tonic-gate } 1896*7c478bd9Sstevel@tonic-gate } else 1897*7c478bd9Sstevel@tonic-gate errors += run_fs_specific_df(&requests[i], j-i); 1898*7c478bd9Sstevel@tonic-gate } 1899*7c478bd9Sstevel@tonic-gate } else { 1900*7c478bd9Sstevel@tonic-gate size_t valid_requests; 1901*7c478bd9Sstevel@tonic-gate 1902*7c478bd9Sstevel@tonic-gate /* 1903*7c478bd9Sstevel@tonic-gate * We have to prune the request list to avoid printing a header 1904*7c478bd9Sstevel@tonic-gate * if there are no valid requests 1905*7c478bd9Sstevel@tonic-gate */ 1906*7c478bd9Sstevel@tonic-gate errors += prune_list(requests, n_requests, &valid_requests); 1907*7c478bd9Sstevel@tonic-gate 1908*7c478bd9Sstevel@tonic-gate if (valid_requests) { 1909*7c478bd9Sstevel@tonic-gate struct df_output *dfop = select_output(); 1910*7c478bd9Sstevel@tonic-gate 1911*7c478bd9Sstevel@tonic-gate /* indicates if we already printed out a header line */ 1912*7c478bd9Sstevel@tonic-gate int printed_header = 0; 1913*7c478bd9Sstevel@tonic-gate 1914*7c478bd9Sstevel@tonic-gate for (i = 0; i < n_requests; i++) { 1915*7c478bd9Sstevel@tonic-gate dfrp = &requests[i]; 1916*7c478bd9Sstevel@tonic-gate if (! dfrp->dfr_valid) 1917*7c478bd9Sstevel@tonic-gate continue; 1918*7c478bd9Sstevel@tonic-gate 1919*7c478bd9Sstevel@tonic-gate /* 1920*7c478bd9Sstevel@tonic-gate * If we don't have a mount point, 1921*7c478bd9Sstevel@tonic-gate * this must be a block device. 1922*7c478bd9Sstevel@tonic-gate */ 1923*7c478bd9Sstevel@tonic-gate if (DFR_ISMOUNTEDFS(dfrp)) { 1924*7c478bd9Sstevel@tonic-gate struct statvfs64 stvfs; 1925*7c478bd9Sstevel@tonic-gate 1926*7c478bd9Sstevel@tonic-gate if ((dfop->dfo_flags & DFO_STATVFS) && 1927*7c478bd9Sstevel@tonic-gate statvfs64(DFR_MOUNT_POINT(dfrp), 1928*7c478bd9Sstevel@tonic-gate &stvfs) == -1) { 1929*7c478bd9Sstevel@tonic-gate errmsg(ERR_PERROR, 1930*7c478bd9Sstevel@tonic-gate "cannot statvfs %s:", 1931*7c478bd9Sstevel@tonic-gate DFR_MOUNT_POINT(dfrp)); 1932*7c478bd9Sstevel@tonic-gate errors++; 1933*7c478bd9Sstevel@tonic-gate continue; 1934*7c478bd9Sstevel@tonic-gate } 1935*7c478bd9Sstevel@tonic-gate if ((!printed_header) && 1936*7c478bd9Sstevel@tonic-gate (dfop->dfo_flags & DFO_HEADER)) { 1937*7c478bd9Sstevel@tonic-gate print_header(); 1938*7c478bd9Sstevel@tonic-gate printed_header = 1; 1939*7c478bd9Sstevel@tonic-gate } 1940*7c478bd9Sstevel@tonic-gate 1941*7c478bd9Sstevel@tonic-gate (*dfop->dfo_func)(dfrp, &stvfs); 1942*7c478bd9Sstevel@tonic-gate } else { 1943*7c478bd9Sstevel@tonic-gate /* 1944*7c478bd9Sstevel@tonic-gate * -h option only works for 1945*7c478bd9Sstevel@tonic-gate * mounted filesystems 1946*7c478bd9Sstevel@tonic-gate */ 1947*7c478bd9Sstevel@tonic-gate if (use_scaling) { 1948*7c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, 1949*7c478bd9Sstevel@tonic-gate "-h option incompatible with unmounted special device (%s)", 1950*7c478bd9Sstevel@tonic-gate dfrp->dfr_cmd_arg); 1951*7c478bd9Sstevel@tonic-gate errors++; 1952*7c478bd9Sstevel@tonic-gate continue; 1953*7c478bd9Sstevel@tonic-gate } 1954*7c478bd9Sstevel@tonic-gate errors += run_fs_specific_df(dfrp, 1); 1955*7c478bd9Sstevel@tonic-gate } 1956*7c478bd9Sstevel@tonic-gate } 1957*7c478bd9Sstevel@tonic-gate } 1958*7c478bd9Sstevel@tonic-gate } 1959*7c478bd9Sstevel@tonic-gate exit(errors); 1960*7c478bd9Sstevel@tonic-gate } 1961*7c478bd9Sstevel@tonic-gate 1962*7c478bd9Sstevel@tonic-gate 1963*7c478bd9Sstevel@tonic-gate /* 1964*7c478bd9Sstevel@tonic-gate * The rest of this file implements the devnm command 1965*7c478bd9Sstevel@tonic-gate */ 1966*7c478bd9Sstevel@tonic-gate 1967*7c478bd9Sstevel@tonic-gate static char * 1968*7c478bd9Sstevel@tonic-gate find_dev_name(char *file, dev_t dev) 1969*7c478bd9Sstevel@tonic-gate { 1970*7c478bd9Sstevel@tonic-gate struct df_request dfreq; 1971*7c478bd9Sstevel@tonic-gate 1972*7c478bd9Sstevel@tonic-gate dfreq.dfr_cmd_arg = file; 1973*7c478bd9Sstevel@tonic-gate dfreq.dfr_fstype = 0; 1974*7c478bd9Sstevel@tonic-gate dfreq.dfr_mte = NULL; 1975*7c478bd9Sstevel@tonic-gate path_mount_entry(&dfreq, dev); 1976*7c478bd9Sstevel@tonic-gate return (DFR_ISMOUNTEDFS(&dfreq) ? DFR_SPECIAL(&dfreq) : NULL); 1977*7c478bd9Sstevel@tonic-gate } 1978*7c478bd9Sstevel@tonic-gate 1979*7c478bd9Sstevel@tonic-gate 1980*7c478bd9Sstevel@tonic-gate static void 1981*7c478bd9Sstevel@tonic-gate do_devnm(int argc, char *argv[]) 1982*7c478bd9Sstevel@tonic-gate { 1983*7c478bd9Sstevel@tonic-gate int arg; 1984*7c478bd9Sstevel@tonic-gate int errors = 0; 1985*7c478bd9Sstevel@tonic-gate char *dev_name; 1986*7c478bd9Sstevel@tonic-gate 1987*7c478bd9Sstevel@tonic-gate if (argc == 1) 1988*7c478bd9Sstevel@tonic-gate errmsg(ERR_NONAME, "Usage: %s name ...", DEVNM_CMD); 1989*7c478bd9Sstevel@tonic-gate 1990*7c478bd9Sstevel@tonic-gate mtab_read_file(); 1991*7c478bd9Sstevel@tonic-gate 1992*7c478bd9Sstevel@tonic-gate for (arg = 1; arg < argc; arg++) { 1993*7c478bd9Sstevel@tonic-gate char *file = argv[arg]; 1994*7c478bd9Sstevel@tonic-gate struct stat64 st; 1995*7c478bd9Sstevel@tonic-gate 1996*7c478bd9Sstevel@tonic-gate if (stat64(file, &st) == -1) { 1997*7c478bd9Sstevel@tonic-gate errmsg(ERR_PERROR, "%s: ", file); 1998*7c478bd9Sstevel@tonic-gate errors++; 1999*7c478bd9Sstevel@tonic-gate continue; 2000*7c478bd9Sstevel@tonic-gate } 2001*7c478bd9Sstevel@tonic-gate 2002*7c478bd9Sstevel@tonic-gate if (! is_remote_fs(st.st_fstype) && 2003*7c478bd9Sstevel@tonic-gate ! EQ(st.st_fstype, MNTTYPE_TMPFS) && 2004*7c478bd9Sstevel@tonic-gate (dev_name = find_dev_name(file, st.st_dev))) 2005*7c478bd9Sstevel@tonic-gate (void) printf("%s %s\n", dev_name, file); 2006*7c478bd9Sstevel@tonic-gate else 2007*7c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, 2008*7c478bd9Sstevel@tonic-gate "%s not found", file); 2009*7c478bd9Sstevel@tonic-gate } 2010*7c478bd9Sstevel@tonic-gate exit(errors); 2011*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 2012*7c478bd9Sstevel@tonic-gate } 2013