17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5ea8dc4b6Seschrock * Common Development and Distribution License (the "License"). 6ea8dc4b6Seschrock * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 227c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 237c478bd9Sstevel@tonic-gate 247c478bd9Sstevel@tonic-gate 257c478bd9Sstevel@tonic-gate /* 26738059c5SJim Rice * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. 277c478bd9Sstevel@tonic-gate */ 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate 30fa9e4066Sahrens #include <dlfcn.h> 317c478bd9Sstevel@tonic-gate #include <stdio.h> 327c478bd9Sstevel@tonic-gate #include <stdarg.h> 337c478bd9Sstevel@tonic-gate #include <string.h> 347c478bd9Sstevel@tonic-gate #include <locale.h> 357c478bd9Sstevel@tonic-gate #include <libintl.h> 367c478bd9Sstevel@tonic-gate #include <stdlib.h> 377c478bd9Sstevel@tonic-gate #include <ftw.h> 387c478bd9Sstevel@tonic-gate #include <errno.h> 397c478bd9Sstevel@tonic-gate #include <sys/types.h> 407c478bd9Sstevel@tonic-gate #include <unistd.h> 417c478bd9Sstevel@tonic-gate #include <sys/statvfs.h> 427c478bd9Sstevel@tonic-gate #include <sys/stat.h> 437c478bd9Sstevel@tonic-gate #include <sys/param.h> 447c478bd9Sstevel@tonic-gate #include <sys/mnttab.h> 457c478bd9Sstevel@tonic-gate #include <sys/mntent.h> 467c478bd9Sstevel@tonic-gate #include <sys/vfstab.h> 477c478bd9Sstevel@tonic-gate #include <sys/wait.h> 487c478bd9Sstevel@tonic-gate #include <sys/mkdev.h> 497c478bd9Sstevel@tonic-gate #include <sys/int_limits.h> 507c478bd9Sstevel@tonic-gate #include <sys/zone.h> 51fa9e4066Sahrens #include <libzfs.h> 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate #include "fslib.h" 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate extern char *default_fstype(char *); 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate /* 587c478bd9Sstevel@tonic-gate * General notice: 597c478bd9Sstevel@tonic-gate * String pointers in this code may point to statically allocated memory 607c478bd9Sstevel@tonic-gate * or dynamically allocated memory. Furthermore, a dynamically allocated 617c478bd9Sstevel@tonic-gate * string may be pointed to by more than one pointer. This does not pose 627c478bd9Sstevel@tonic-gate * a problem because malloc'ed memory is never free'd (so we don't need 637c478bd9Sstevel@tonic-gate * to remember which pointers point to malloc'ed memory). 647c478bd9Sstevel@tonic-gate */ 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate /* 677c478bd9Sstevel@tonic-gate * TRANSLATION_NOTE 687c478bd9Sstevel@tonic-gate * Only strings passed as arguments to the TRANSLATE macro need to 697c478bd9Sstevel@tonic-gate * be translated. 707c478bd9Sstevel@tonic-gate */ 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate #ifndef MNTTYPE_LOFS 737c478bd9Sstevel@tonic-gate #define MNTTYPE_LOFS "lofs" 747c478bd9Sstevel@tonic-gate #endif 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate #define EQ(s1, s2) (strcmp(s1, s2) == 0) 777c478bd9Sstevel@tonic-gate #define NEW(type) xmalloc(sizeof (type)) 787c478bd9Sstevel@tonic-gate #define CLEAR(var) (void) memset(&(var), 0, sizeof (var)) 797c478bd9Sstevel@tonic-gate #define MAX(a, b) ((a) > (b) ? (a) : (b)) 807c478bd9Sstevel@tonic-gate #define MAX3(a, b, c) MAX(a, MAX(b, c)) 817c478bd9Sstevel@tonic-gate #define TRANSLATE(s) new_string(gettext(s)) 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate #define MAX_OPTIONS 36 847c478bd9Sstevel@tonic-gate #define N_FSTYPES 20 857c478bd9Sstevel@tonic-gate #define MOUNT_TABLE_ENTRIES 40 /* initial allocation */ 867c478bd9Sstevel@tonic-gate #define MSGBUF_SIZE 1024 877c478bd9Sstevel@tonic-gate #define LINEBUF_SIZE 256 /* either input or output lines */ 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate #define BLOCK_SIZE 512 /* when reporting in terms of blocks */ 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate #define DEVNM_CMD "devnm" 927c478bd9Sstevel@tonic-gate #define FS_LIBPATH "/usr/lib/fs/" 937c478bd9Sstevel@tonic-gate #define MOUNT_TAB "/etc/mnttab" 947c478bd9Sstevel@tonic-gate #define VFS_TAB "/etc/vfstab" 957c478bd9Sstevel@tonic-gate #define REMOTE_FS "/etc/dfs/fstypes" 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate #define NUL '\0' 987c478bd9Sstevel@tonic-gate #define FALSE 0 997c478bd9Sstevel@tonic-gate #define TRUE 1 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate /* 1027c478bd9Sstevel@tonic-gate * Formatting constants 1037c478bd9Sstevel@tonic-gate */ 1047c478bd9Sstevel@tonic-gate #define IBCS2_FILESYSTEM_WIDTH 15 /* Truncate to match ISC/SCO */ 1057c478bd9Sstevel@tonic-gate #define IBCS2_MOUNT_POINT_WIDTH 10 /* Truncate to match ISC/SCO */ 1067c478bd9Sstevel@tonic-gate #define FILESYSTEM_WIDTH 20 1077c478bd9Sstevel@tonic-gate #define MOUNT_POINT_WIDTH 19 1087c478bd9Sstevel@tonic-gate #define SPECIAL_DEVICE_WIDTH 18 1097c478bd9Sstevel@tonic-gate #define FSTYPE_WIDTH 8 1107c478bd9Sstevel@tonic-gate #define BLOCK_WIDTH 8 1117c478bd9Sstevel@tonic-gate #define NFILES_WIDTH 8 1127c478bd9Sstevel@tonic-gate #ifdef XPG4 1137c478bd9Sstevel@tonic-gate #define KBYTE_WIDTH 11 1147c478bd9Sstevel@tonic-gate #define AVAILABLE_WIDTH 10 1157c478bd9Sstevel@tonic-gate #else 1167c478bd9Sstevel@tonic-gate #define KBYTE_WIDTH 7 1177c478bd9Sstevel@tonic-gate #define AVAILABLE_WIDTH 6 1187c478bd9Sstevel@tonic-gate #endif 1197c478bd9Sstevel@tonic-gate #define SCALED_WIDTH 6 1207c478bd9Sstevel@tonic-gate #define CAPACITY_WIDTH 9 1217c478bd9Sstevel@tonic-gate #define BSIZE_WIDTH 6 1227c478bd9Sstevel@tonic-gate #define FRAGSIZE_WIDTH 7 1237c478bd9Sstevel@tonic-gate #define FSID_WIDTH 7 1247c478bd9Sstevel@tonic-gate #define FLAG_WIDTH 8 1257c478bd9Sstevel@tonic-gate #define NAMELEN_WIDTH 7 1267c478bd9Sstevel@tonic-gate #define MNT_SPEC_WIDTH MOUNT_POINT_WIDTH + SPECIAL_DEVICE_WIDTH + 2 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate /* 1297c478bd9Sstevel@tonic-gate * Flags for the errmsg() function 1307c478bd9Sstevel@tonic-gate */ 1317c478bd9Sstevel@tonic-gate #define ERR_NOFLAGS 0x0 1327c478bd9Sstevel@tonic-gate #define ERR_NONAME 0x1 /* don't include the program name */ 1337c478bd9Sstevel@tonic-gate /* as a prefix */ 1347c478bd9Sstevel@tonic-gate #define ERR_FATAL 0x2 /* call exit after printing the */ 1357c478bd9Sstevel@tonic-gate /* message */ 1367c478bd9Sstevel@tonic-gate #define ERR_PERROR 0x4 /* append an errno explanation to */ 1377c478bd9Sstevel@tonic-gate /* the message */ 1387c478bd9Sstevel@tonic-gate #define ERR_USAGE 0x8 /* print the usage line after the */ 1397c478bd9Sstevel@tonic-gate /* message */ 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate #define NUMBER_WIDTH 40 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate /* 1447c478bd9Sstevel@tonic-gate * A numbuf_t is used when converting a number to a string representation 1457c478bd9Sstevel@tonic-gate */ 1467c478bd9Sstevel@tonic-gate typedef char numbuf_t[ NUMBER_WIDTH ]; 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate /* 1497c478bd9Sstevel@tonic-gate * We use bool_int instead of int to make clear which variables are 1507c478bd9Sstevel@tonic-gate * supposed to be boolean 1517c478bd9Sstevel@tonic-gate */ 1527c478bd9Sstevel@tonic-gate typedef int bool_int; 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate struct mtab_entry { 1557c478bd9Sstevel@tonic-gate bool_int mte_dev_is_valid; 1567c478bd9Sstevel@tonic-gate dev_t mte_dev; 1577c478bd9Sstevel@tonic-gate bool_int mte_ignore; /* the "ignore" option was set */ 1587c478bd9Sstevel@tonic-gate struct extmnttab *mte_mount; 1597c478bd9Sstevel@tonic-gate }; 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate struct df_request { 1637c478bd9Sstevel@tonic-gate bool_int dfr_valid; 1647c478bd9Sstevel@tonic-gate char *dfr_cmd_arg; /* what the user specified */ 1657c478bd9Sstevel@tonic-gate struct mtab_entry *dfr_mte; 1667c478bd9Sstevel@tonic-gate char *dfr_fstype; 1677c478bd9Sstevel@tonic-gate int dfr_index; /* to make qsort stable */ 1687c478bd9Sstevel@tonic-gate }; 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate #define DFR_MOUNT_POINT(dfrp) (dfrp)->dfr_mte->mte_mount->mnt_mountp 1717c478bd9Sstevel@tonic-gate #define DFR_SPECIAL(dfrp) (dfrp)->dfr_mte->mte_mount->mnt_special 172fa9e4066Sahrens #define DFR_FSTYPE(dfrp) (dfrp)->dfr_mte->mte_mount->mnt_fstype 1737c478bd9Sstevel@tonic-gate #define DFR_ISMOUNTEDFS(dfrp) ((dfrp)->dfr_mte != NULL) 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate #define DFRP(p) ((struct df_request *)(p)) 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate typedef void (*output_func)(struct df_request *, struct statvfs64 *); 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate struct df_output { 1807c478bd9Sstevel@tonic-gate output_func dfo_func; /* function that will do the output */ 1817c478bd9Sstevel@tonic-gate int dfo_flags; 1827c478bd9Sstevel@tonic-gate }; 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate /* 1857c478bd9Sstevel@tonic-gate * Output flags 1867c478bd9Sstevel@tonic-gate */ 1877c478bd9Sstevel@tonic-gate #define DFO_NOFLAGS 0x0 1887c478bd9Sstevel@tonic-gate #define DFO_HEADER 0x1 /* output preceded by header */ 1897c478bd9Sstevel@tonic-gate #define DFO_STATVFS 0x2 /* must do a statvfs64(2) */ 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate static char *program_name; 1937c478bd9Sstevel@tonic-gate static char df_options[MAX_OPTIONS] = "-"; 1947c478bd9Sstevel@tonic-gate static size_t df_options_len = 1; 1957c478bd9Sstevel@tonic-gate static char *o_option_arg; /* arg to the -o option */ 1967c478bd9Sstevel@tonic-gate static char *FSType; 1977c478bd9Sstevel@tonic-gate static char *remote_fstypes[N_FSTYPES+1]; /* allocate an extra one */ 1987c478bd9Sstevel@tonic-gate /* to use as a terminator */ 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate /* 2017c478bd9Sstevel@tonic-gate * The following three variables support an in-memory copy of the mount table 2027c478bd9Sstevel@tonic-gate * to speedup searches. 2037c478bd9Sstevel@tonic-gate */ 2047c478bd9Sstevel@tonic-gate static struct mtab_entry *mount_table; /* array of mtab_entry's */ 2057c478bd9Sstevel@tonic-gate static size_t mount_table_entries; 2067c478bd9Sstevel@tonic-gate static size_t mount_table_allocated_entries; 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate static bool_int F_option; 2097c478bd9Sstevel@tonic-gate static bool_int V_option; 2107c478bd9Sstevel@tonic-gate static bool_int P_option; /* Added for XCU4 compliance */ 2117c478bd9Sstevel@tonic-gate static bool_int Z_option; 2127c478bd9Sstevel@tonic-gate static bool_int v_option; 2137c478bd9Sstevel@tonic-gate static bool_int a_option; 2147c478bd9Sstevel@tonic-gate static bool_int b_option; 2157c478bd9Sstevel@tonic-gate static bool_int e_option; 2167c478bd9Sstevel@tonic-gate static bool_int g_option; 2177c478bd9Sstevel@tonic-gate static bool_int h_option; 2187c478bd9Sstevel@tonic-gate static bool_int k_option; 2197c478bd9Sstevel@tonic-gate static bool_int l_option; 220*790c646cSPaul B. Henson static bool_int m_option; 2217c478bd9Sstevel@tonic-gate static bool_int n_option; 2227c478bd9Sstevel@tonic-gate static bool_int t_option; 2237c478bd9Sstevel@tonic-gate static bool_int o_option; 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate static bool_int tty_output; 2267c478bd9Sstevel@tonic-gate static bool_int use_scaling; 2277c478bd9Sstevel@tonic-gate static int scale; 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate static void usage(void); 2307c478bd9Sstevel@tonic-gate static void do_devnm(int, char **); 23108190127Sdh145677 static void do_df(int, char **) __NORETURN; 2327c478bd9Sstevel@tonic-gate static void parse_options(int, char **); 2337c478bd9Sstevel@tonic-gate static char *basename(char *); 2347c478bd9Sstevel@tonic-gate 23554a91118SChris Kirby static libzfs_handle_t *(*_libzfs_init)(void); 23699653d4eSeschrock static zfs_handle_t *(*_zfs_open)(libzfs_handle_t *, const char *, int); 237fa9e4066Sahrens static void (*_zfs_close)(zfs_handle_t *); 238fa9e4066Sahrens static uint64_t (*_zfs_prop_get_int)(zfs_handle_t *, zfs_prop_t); 23999653d4eSeschrock static libzfs_handle_t *g_zfs; 240fa9e4066Sahrens 241ea8dc4b6Seschrock /* 242ea8dc4b6Seschrock * Dynamically check for libzfs, in case the user hasn't installed the SUNWzfs 243ea8dc4b6Seschrock * packages. A basic utility such as df shouldn't depend on optional 244ea8dc4b6Seschrock * filesystems. 245ea8dc4b6Seschrock */ 24699653d4eSeschrock static boolean_t 247ea8dc4b6Seschrock load_libzfs(void) 2487c478bd9Sstevel@tonic-gate { 249fa9e4066Sahrens void *hdl; 250fa9e4066Sahrens 25199653d4eSeschrock if (_libzfs_init != NULL) 25299653d4eSeschrock return (g_zfs != NULL); 2537c478bd9Sstevel@tonic-gate 254fa9e4066Sahrens if ((hdl = dlopen("libzfs.so", RTLD_LAZY)) != NULL) { 25554a91118SChris Kirby _libzfs_init = (libzfs_handle_t *(*)(void))dlsym(hdl, 25699653d4eSeschrock "libzfs_init"); 257fa9e4066Sahrens _zfs_open = (zfs_handle_t *(*)())dlsym(hdl, "zfs_open"); 258fa9e4066Sahrens _zfs_close = (void (*)())dlsym(hdl, "zfs_close"); 259fa9e4066Sahrens _zfs_prop_get_int = (uint64_t (*)()) 260fa9e4066Sahrens dlsym(hdl, "zfs_prop_get_int"); 261fa9e4066Sahrens 26299653d4eSeschrock if (_libzfs_init != NULL) { 263fa9e4066Sahrens assert(_zfs_open != NULL); 264fa9e4066Sahrens assert(_zfs_close != NULL); 265fa9e4066Sahrens assert(_zfs_prop_get_int != NULL); 266fa9e4066Sahrens 26754a91118SChris Kirby g_zfs = _libzfs_init(); 268fa9e4066Sahrens } 269fa9e4066Sahrens } 270fa9e4066Sahrens 27199653d4eSeschrock return (g_zfs != NULL); 272ea8dc4b6Seschrock } 273ea8dc4b6Seschrock 274ea8dc4b6Seschrock int 275ea8dc4b6Seschrock main(int argc, char *argv[]) 276ea8dc4b6Seschrock { 277ea8dc4b6Seschrock (void) setlocale(LC_ALL, ""); 278ea8dc4b6Seschrock 279ea8dc4b6Seschrock #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 280ea8dc4b6Seschrock #define TEXT_DOMAIN "SYS_TEST" 281ea8dc4b6Seschrock #endif 282ea8dc4b6Seschrock (void) textdomain(TEXT_DOMAIN); 283ea8dc4b6Seschrock 284ea8dc4b6Seschrock program_name = basename(argv[0]); 285ea8dc4b6Seschrock 2867c478bd9Sstevel@tonic-gate if (EQ(program_name, DEVNM_CMD)) 2877c478bd9Sstevel@tonic-gate do_devnm(argc, argv); 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate parse_options(argc, argv); 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate /* 2927c478bd9Sstevel@tonic-gate * The k_option implies SunOS 4.x compatibility: when the special 2937c478bd9Sstevel@tonic-gate * device name is too long the line will be split except when the 2947c478bd9Sstevel@tonic-gate * output has been redirected. 2957c478bd9Sstevel@tonic-gate * This is also valid for the -h option. 2967c478bd9Sstevel@tonic-gate */ 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate if (use_scaling || k_option || P_option || v_option) 2997c478bd9Sstevel@tonic-gate tty_output = isatty(1); 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate do_df(argc - optind, &argv[optind]); 3027c478bd9Sstevel@tonic-gate /* NOTREACHED */ 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate /* 3077c478bd9Sstevel@tonic-gate * Prints an error message to stderr. 3087c478bd9Sstevel@tonic-gate */ 3097c478bd9Sstevel@tonic-gate /* VARARGS2 */ 3107c478bd9Sstevel@tonic-gate static void 3117c478bd9Sstevel@tonic-gate errmsg(int flags, char *fmt, ...) 3127c478bd9Sstevel@tonic-gate { 3137c478bd9Sstevel@tonic-gate char buf[MSGBUF_SIZE]; 3147c478bd9Sstevel@tonic-gate va_list ap; 3157c478bd9Sstevel@tonic-gate int cc; 3167c478bd9Sstevel@tonic-gate int offset; 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate if (flags & ERR_NONAME) 3197c478bd9Sstevel@tonic-gate offset = 0; 3207c478bd9Sstevel@tonic-gate else 3217c478bd9Sstevel@tonic-gate offset = sprintf(buf, "%s: ", program_name); 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate va_start(ap, fmt); 3247c478bd9Sstevel@tonic-gate cc = vsprintf(&buf[offset], gettext(fmt), ap); 3257c478bd9Sstevel@tonic-gate offset += cc; 3267c478bd9Sstevel@tonic-gate va_end(ap); 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate if (flags & ERR_PERROR) { 3297c478bd9Sstevel@tonic-gate if (buf[offset-1] != ' ') 3307c478bd9Sstevel@tonic-gate (void) strcat(buf, " "); 3317c478bd9Sstevel@tonic-gate (void) strcat(buf, strerror(errno)); 3327c478bd9Sstevel@tonic-gate } 3337c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", buf); 3347c478bd9Sstevel@tonic-gate if (flags & ERR_USAGE) 3357c478bd9Sstevel@tonic-gate usage(); 3367c478bd9Sstevel@tonic-gate if (flags & ERR_FATAL) 3377c478bd9Sstevel@tonic-gate exit(1); 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate static void 34208190127Sdh145677 usage(void) 3437c478bd9Sstevel@tonic-gate { 3447c478bd9Sstevel@tonic-gate #ifdef XPG4 3457c478bd9Sstevel@tonic-gate errmsg(ERR_NONAME, 346*790c646cSPaul B. Henson "Usage: %s [-F FSType] [-abeghklmntPVZ]" 347*790c646cSPaul B. Henson " [-o FSType-specific_options]" 3487c478bd9Sstevel@tonic-gate " [directory | block_device | resource]", program_name); 3497c478bd9Sstevel@tonic-gate #else 3507c478bd9Sstevel@tonic-gate errmsg(ERR_NONAME, 351*790c646cSPaul B. Henson "Usage: %s [-F FSType] [-abeghklmntVvZ]" 352*790c646cSPaul B. Henson " [-o FSType-specific_options]" 3537c478bd9Sstevel@tonic-gate " [directory | block_device | resource]", program_name); 3547c478bd9Sstevel@tonic-gate #endif 3557c478bd9Sstevel@tonic-gate exit(1); 3567c478bd9Sstevel@tonic-gate /* NOTREACHED */ 3577c478bd9Sstevel@tonic-gate } 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate static char * 3617c478bd9Sstevel@tonic-gate new_string(char *s) 3627c478bd9Sstevel@tonic-gate { 3637c478bd9Sstevel@tonic-gate char *p = NULL; 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate if (s) { 3667c478bd9Sstevel@tonic-gate p = strdup(s); 3677c478bd9Sstevel@tonic-gate if (p) 3687c478bd9Sstevel@tonic-gate return (p); 3697c478bd9Sstevel@tonic-gate errmsg(ERR_FATAL, "out of memory"); 3707c478bd9Sstevel@tonic-gate /* NOTREACHED */ 3717c478bd9Sstevel@tonic-gate } 3727c478bd9Sstevel@tonic-gate return (p); 3737c478bd9Sstevel@tonic-gate } 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate /* 3777c478bd9Sstevel@tonic-gate * Allocate memory using malloc but terminate if the allocation fails 3787c478bd9Sstevel@tonic-gate */ 3797c478bd9Sstevel@tonic-gate static void * 3807c478bd9Sstevel@tonic-gate xmalloc(size_t size) 3817c478bd9Sstevel@tonic-gate { 3827c478bd9Sstevel@tonic-gate void *p = malloc(size); 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate if (p) 3857c478bd9Sstevel@tonic-gate return (p); 3867c478bd9Sstevel@tonic-gate errmsg(ERR_FATAL, "out of memory"); 3877c478bd9Sstevel@tonic-gate /* NOTREACHED */ 38808190127Sdh145677 return (NULL); 3897c478bd9Sstevel@tonic-gate } 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate /* 3937c478bd9Sstevel@tonic-gate * Allocate memory using realloc but terminate if the allocation fails 3947c478bd9Sstevel@tonic-gate */ 3957c478bd9Sstevel@tonic-gate static void * 3967c478bd9Sstevel@tonic-gate xrealloc(void *ptr, size_t size) 3977c478bd9Sstevel@tonic-gate { 3987c478bd9Sstevel@tonic-gate void *p = realloc(ptr, size); 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate if (p) 4017c478bd9Sstevel@tonic-gate return (p); 4027c478bd9Sstevel@tonic-gate errmsg(ERR_FATAL, "out of memory"); 4037c478bd9Sstevel@tonic-gate /* NOTREACHED */ 40408190127Sdh145677 return (NULL); 4057c478bd9Sstevel@tonic-gate } 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate /* 4097c478bd9Sstevel@tonic-gate * fopen the specified file for reading but terminate if the fopen fails 4107c478bd9Sstevel@tonic-gate */ 4117c478bd9Sstevel@tonic-gate static FILE * 4127c478bd9Sstevel@tonic-gate xfopen(char *file) 4137c478bd9Sstevel@tonic-gate { 4147c478bd9Sstevel@tonic-gate FILE *fp = fopen(file, "r"); 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate if (fp == NULL) 4177c478bd9Sstevel@tonic-gate errmsg(ERR_FATAL + ERR_PERROR, "failed to open %s:", file); 4187c478bd9Sstevel@tonic-gate return (fp); 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate 4227c478bd9Sstevel@tonic-gate /* 4237c478bd9Sstevel@tonic-gate * Read remote file system types from REMOTE_FS into the 4247c478bd9Sstevel@tonic-gate * remote_fstypes array. 4257c478bd9Sstevel@tonic-gate */ 4267c478bd9Sstevel@tonic-gate static void 42708190127Sdh145677 init_remote_fs(void) 4287c478bd9Sstevel@tonic-gate { 4297c478bd9Sstevel@tonic-gate FILE *fp; 4307c478bd9Sstevel@tonic-gate char line_buf[LINEBUF_SIZE]; 4317c478bd9Sstevel@tonic-gate size_t fstype_index = 0; 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate if ((fp = fopen(REMOTE_FS, "r")) == NULL) { 4347c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, 4357c478bd9Sstevel@tonic-gate "Warning: can't open %s, ignored", REMOTE_FS); 4367c478bd9Sstevel@tonic-gate return; 4377c478bd9Sstevel@tonic-gate } 4387c478bd9Sstevel@tonic-gate 4397c478bd9Sstevel@tonic-gate while (fgets(line_buf, sizeof (line_buf), fp) != NULL) { 4407c478bd9Sstevel@tonic-gate char buf[LINEBUF_SIZE]; 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate (void) sscanf(line_buf, "%s", buf); 4437c478bd9Sstevel@tonic-gate remote_fstypes[fstype_index++] = new_string(buf); 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate if (fstype_index == N_FSTYPES) 4467c478bd9Sstevel@tonic-gate break; 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate (void) fclose(fp); 4497c478bd9Sstevel@tonic-gate } 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate /* 4537c478bd9Sstevel@tonic-gate * Returns TRUE if fstype is a remote file system type; 4547c478bd9Sstevel@tonic-gate * otherwise, returns FALSE. 4557c478bd9Sstevel@tonic-gate */ 4567c478bd9Sstevel@tonic-gate static int 4577c478bd9Sstevel@tonic-gate is_remote_fs(char *fstype) 4587c478bd9Sstevel@tonic-gate { 4597c478bd9Sstevel@tonic-gate char **p; 4607c478bd9Sstevel@tonic-gate static bool_int remote_fs_initialized; 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate if (! remote_fs_initialized) { 4637c478bd9Sstevel@tonic-gate init_remote_fs(); 4647c478bd9Sstevel@tonic-gate remote_fs_initialized = TRUE; 4657c478bd9Sstevel@tonic-gate } 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate for (p = remote_fstypes; *p; p++) 4687c478bd9Sstevel@tonic-gate if (EQ(fstype, *p)) 4697c478bd9Sstevel@tonic-gate return (TRUE); 4707c478bd9Sstevel@tonic-gate return (FALSE); 4717c478bd9Sstevel@tonic-gate } 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate static char * 4757c478bd9Sstevel@tonic-gate basename(char *s) 4767c478bd9Sstevel@tonic-gate { 4777c478bd9Sstevel@tonic-gate char *p = strrchr(s, '/'); 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate return (p ? p+1 : s); 4807c478bd9Sstevel@tonic-gate } 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate 4837c478bd9Sstevel@tonic-gate /* 4847c478bd9Sstevel@tonic-gate * Create a new "struct extmnttab" and make sure that its fields point 4857c478bd9Sstevel@tonic-gate * to malloc'ed memory 4867c478bd9Sstevel@tonic-gate */ 4877c478bd9Sstevel@tonic-gate static struct extmnttab * 4887c478bd9Sstevel@tonic-gate mntdup(struct extmnttab *old) 4897c478bd9Sstevel@tonic-gate { 4907c478bd9Sstevel@tonic-gate struct extmnttab *new = NEW(struct extmnttab); 4917c478bd9Sstevel@tonic-gate 4927c478bd9Sstevel@tonic-gate new->mnt_special = new_string(old->mnt_special); 4937c478bd9Sstevel@tonic-gate new->mnt_mountp = new_string(old->mnt_mountp); 4947c478bd9Sstevel@tonic-gate new->mnt_fstype = new_string(old->mnt_fstype); 4957c478bd9Sstevel@tonic-gate new->mnt_mntopts = new_string(old->mnt_mntopts); 4967c478bd9Sstevel@tonic-gate new->mnt_time = new_string(old->mnt_time); 4977c478bd9Sstevel@tonic-gate new->mnt_major = old->mnt_major; 4987c478bd9Sstevel@tonic-gate new->mnt_minor = old->mnt_minor; 4997c478bd9Sstevel@tonic-gate return (new); 5007c478bd9Sstevel@tonic-gate } 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate static void 5047c478bd9Sstevel@tonic-gate mtab_error(char *mtab_file, int status) 5057c478bd9Sstevel@tonic-gate { 5067c478bd9Sstevel@tonic-gate if (status == MNT_TOOLONG) 5077c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, "a line in %s exceeds %d characters", 5087c478bd9Sstevel@tonic-gate mtab_file, MNT_LINE_MAX); 5097c478bd9Sstevel@tonic-gate else if (status == MNT_TOOMANY) 5107c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, 5117c478bd9Sstevel@tonic-gate "a line in %s has too many fields", mtab_file); 5127c478bd9Sstevel@tonic-gate else if (status == MNT_TOOFEW) 5137c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, 5147c478bd9Sstevel@tonic-gate "a line in %s has too few fields", mtab_file); 5157c478bd9Sstevel@tonic-gate else 5167c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, 5177c478bd9Sstevel@tonic-gate "error while reading %s: %d", mtab_file, status); 5187c478bd9Sstevel@tonic-gate exit(1); 5197c478bd9Sstevel@tonic-gate /* NOTREACHED */ 5207c478bd9Sstevel@tonic-gate } 5217c478bd9Sstevel@tonic-gate 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate /* 5247c478bd9Sstevel@tonic-gate * Read the mount table from the specified file. 5257c478bd9Sstevel@tonic-gate * We keep the table in memory for faster lookups. 5267c478bd9Sstevel@tonic-gate */ 5277c478bd9Sstevel@tonic-gate static void 52808190127Sdh145677 mtab_read_file(void) 5297c478bd9Sstevel@tonic-gate { 5307c478bd9Sstevel@tonic-gate char *mtab_file = MOUNT_TAB; 5317c478bd9Sstevel@tonic-gate FILE *fp; 5327c478bd9Sstevel@tonic-gate struct extmnttab mtab; 5337c478bd9Sstevel@tonic-gate int status; 5347c478bd9Sstevel@tonic-gate 5357c478bd9Sstevel@tonic-gate fp = xfopen(mtab_file); 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate resetmnttab(fp); 5387c478bd9Sstevel@tonic-gate mount_table_allocated_entries = MOUNT_TABLE_ENTRIES; 5397c478bd9Sstevel@tonic-gate mount_table_entries = 0; 5407c478bd9Sstevel@tonic-gate mount_table = xmalloc( 5417c478bd9Sstevel@tonic-gate mount_table_allocated_entries * sizeof (struct mtab_entry)); 5427c478bd9Sstevel@tonic-gate 5437c478bd9Sstevel@tonic-gate while ((status = getextmntent(fp, &mtab, sizeof (struct extmnttab))) 5447c478bd9Sstevel@tonic-gate == 0) { 5457c478bd9Sstevel@tonic-gate struct mtab_entry *mtep; 5467c478bd9Sstevel@tonic-gate 5477c478bd9Sstevel@tonic-gate if (mount_table_entries == mount_table_allocated_entries) { 5487c478bd9Sstevel@tonic-gate mount_table_allocated_entries += MOUNT_TABLE_ENTRIES; 5497c478bd9Sstevel@tonic-gate mount_table = xrealloc(mount_table, 5507c478bd9Sstevel@tonic-gate mount_table_allocated_entries * 5517c478bd9Sstevel@tonic-gate sizeof (struct mtab_entry)); 5527c478bd9Sstevel@tonic-gate } 5537c478bd9Sstevel@tonic-gate mtep = &mount_table[mount_table_entries++]; 5547c478bd9Sstevel@tonic-gate mtep->mte_mount = mntdup(&mtab); 5557c478bd9Sstevel@tonic-gate mtep->mte_dev_is_valid = FALSE; 5567c478bd9Sstevel@tonic-gate mtep->mte_ignore = (hasmntopt((struct mnttab *)&mtab, 5577c478bd9Sstevel@tonic-gate MNTOPT_IGNORE) != NULL); 5587c478bd9Sstevel@tonic-gate } 5597c478bd9Sstevel@tonic-gate 5607c478bd9Sstevel@tonic-gate (void) fclose(fp); 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate if (status == -1) /* reached EOF */ 5637c478bd9Sstevel@tonic-gate return; 5647c478bd9Sstevel@tonic-gate mtab_error(mtab_file, status); 5657c478bd9Sstevel@tonic-gate /* NOTREACHED */ 5667c478bd9Sstevel@tonic-gate } 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate 5697c478bd9Sstevel@tonic-gate /* 5707c478bd9Sstevel@tonic-gate * We use this macro when we want to record the option for the purpose of 5717c478bd9Sstevel@tonic-gate * passing it to the FS-specific df 5727c478bd9Sstevel@tonic-gate */ 5737c478bd9Sstevel@tonic-gate #define SET_OPTION(opt) opt##_option = TRUE, \ 5747c478bd9Sstevel@tonic-gate df_options[df_options_len++] = arg 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate static void 5777c478bd9Sstevel@tonic-gate parse_options(int argc, char *argv[]) 5787c478bd9Sstevel@tonic-gate { 5797c478bd9Sstevel@tonic-gate int arg; 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate opterr = 0; /* getopt shouldn't complain about unknown options */ 5827c478bd9Sstevel@tonic-gate 5837c478bd9Sstevel@tonic-gate #ifdef XPG4 584*790c646cSPaul B. Henson while ((arg = getopt(argc, argv, "F:o:abehkVtgnlmPZ")) != EOF) { 5857c478bd9Sstevel@tonic-gate #else 586*790c646cSPaul B. Henson while ((arg = getopt(argc, argv, "F:o:abehkVtgnlmvZ")) != EOF) { 5877c478bd9Sstevel@tonic-gate #endif 5887c478bd9Sstevel@tonic-gate if (arg == 'F') { 5897c478bd9Sstevel@tonic-gate if (F_option) 5907c478bd9Sstevel@tonic-gate errmsg(ERR_FATAL + ERR_USAGE, 5917c478bd9Sstevel@tonic-gate "more than one FSType specified"); 5927c478bd9Sstevel@tonic-gate F_option = 1; 5937c478bd9Sstevel@tonic-gate FSType = optarg; 5947c478bd9Sstevel@tonic-gate } else if (arg == 'V' && ! V_option) { 5957c478bd9Sstevel@tonic-gate V_option = TRUE; 5967c478bd9Sstevel@tonic-gate } else if (arg == 'v' && ! v_option) { 5977c478bd9Sstevel@tonic-gate v_option = TRUE; 5987c478bd9Sstevel@tonic-gate #ifdef XPG4 5997c478bd9Sstevel@tonic-gate } else if (arg == 'P' && ! P_option) { 6007c478bd9Sstevel@tonic-gate SET_OPTION(P); 6017c478bd9Sstevel@tonic-gate #endif 6027c478bd9Sstevel@tonic-gate } else if (arg == 'a' && ! a_option) { 6037c478bd9Sstevel@tonic-gate SET_OPTION(a); 6047c478bd9Sstevel@tonic-gate } else if (arg == 'b' && ! b_option) { 6057c478bd9Sstevel@tonic-gate SET_OPTION(b); 6067c478bd9Sstevel@tonic-gate } else if (arg == 'e' && ! e_option) { 6077c478bd9Sstevel@tonic-gate SET_OPTION(e); 6087c478bd9Sstevel@tonic-gate } else if (arg == 'g' && ! g_option) { 6097c478bd9Sstevel@tonic-gate SET_OPTION(g); 6107c478bd9Sstevel@tonic-gate } else if (arg == 'h') { 6117c478bd9Sstevel@tonic-gate use_scaling = TRUE; 6127c478bd9Sstevel@tonic-gate scale = 1024; 6137c478bd9Sstevel@tonic-gate } else if (arg == 'k' && ! k_option) { 6147c478bd9Sstevel@tonic-gate SET_OPTION(k); 6157c478bd9Sstevel@tonic-gate } else if (arg == 'l' && ! l_option) { 6167c478bd9Sstevel@tonic-gate SET_OPTION(l); 617*790c646cSPaul B. Henson } else if (arg == 'm' && ! m_option) { 618*790c646cSPaul B. Henson SET_OPTION(m); 6197c478bd9Sstevel@tonic-gate } else if (arg == 'n' && ! n_option) { 6207c478bd9Sstevel@tonic-gate SET_OPTION(n); 6217c478bd9Sstevel@tonic-gate } else if (arg == 't' && ! t_option) { 6227c478bd9Sstevel@tonic-gate SET_OPTION(t); 6237c478bd9Sstevel@tonic-gate } else if (arg == 'o') { 6247c478bd9Sstevel@tonic-gate if (o_option) 6257c478bd9Sstevel@tonic-gate errmsg(ERR_FATAL + ERR_USAGE, 6267c478bd9Sstevel@tonic-gate "the -o option can only be specified once"); 6277c478bd9Sstevel@tonic-gate o_option = TRUE; 6287c478bd9Sstevel@tonic-gate o_option_arg = optarg; 6297c478bd9Sstevel@tonic-gate } else if (arg == 'Z') { 6307c478bd9Sstevel@tonic-gate SET_OPTION(Z); 6317c478bd9Sstevel@tonic-gate } else if (arg == '?') { 6327c478bd9Sstevel@tonic-gate errmsg(ERR_USAGE, "unknown option: %c", optopt); 6337c478bd9Sstevel@tonic-gate } 6347c478bd9Sstevel@tonic-gate } 6357c478bd9Sstevel@tonic-gate 6367c478bd9Sstevel@tonic-gate /* 6377c478bd9Sstevel@tonic-gate * Option sanity checks 6387c478bd9Sstevel@tonic-gate */ 6397c478bd9Sstevel@tonic-gate if (g_option && o_option) 6407c478bd9Sstevel@tonic-gate errmsg(ERR_FATAL, "-o and -g options are incompatible"); 6417c478bd9Sstevel@tonic-gate if (l_option && o_option) 6427c478bd9Sstevel@tonic-gate errmsg(ERR_FATAL, "-o and -l options are incompatible"); 6437c478bd9Sstevel@tonic-gate if (n_option && o_option) 6447c478bd9Sstevel@tonic-gate errmsg(ERR_FATAL, "-o and -n options are incompatible"); 6457c478bd9Sstevel@tonic-gate if (use_scaling && o_option) 6467c478bd9Sstevel@tonic-gate errmsg(ERR_FATAL, "-o and -h options are incompatible"); 6477c478bd9Sstevel@tonic-gate } 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate 6517c478bd9Sstevel@tonic-gate /* 6527c478bd9Sstevel@tonic-gate * Check if the user-specified argument is a resource name. 6537c478bd9Sstevel@tonic-gate * A resource name is whatever is placed in the mnt_special field of 6547c478bd9Sstevel@tonic-gate * struct mnttab. In the case of NFS, a resource name has the form 6557c478bd9Sstevel@tonic-gate * hostname:pathname 6567c478bd9Sstevel@tonic-gate * We try to find an exact match between the user-specified argument 6577c478bd9Sstevel@tonic-gate * and the mnt_special field of a mount table entry. 6587c478bd9Sstevel@tonic-gate * We also use the heuristic of removing the basename from the user-specified 6597c478bd9Sstevel@tonic-gate * argument and repeating the test until we get a match. This works 6607c478bd9Sstevel@tonic-gate * fine for NFS but may fail for other remote file system types. However, 6617c478bd9Sstevel@tonic-gate * it is guaranteed that the function will not fail if the user specifies 6627c478bd9Sstevel@tonic-gate * the exact resource name. 6637c478bd9Sstevel@tonic-gate * If successful, this function sets the 'dfr_mte' field of '*dfrp' 6647c478bd9Sstevel@tonic-gate */ 6657c478bd9Sstevel@tonic-gate static void 6667c478bd9Sstevel@tonic-gate resource_mount_entry(struct df_request *dfrp) 6677c478bd9Sstevel@tonic-gate { 6687c478bd9Sstevel@tonic-gate char *name; 6697c478bd9Sstevel@tonic-gate 6707c478bd9Sstevel@tonic-gate /* 6717c478bd9Sstevel@tonic-gate * We need our own copy since we will modify the string 6727c478bd9Sstevel@tonic-gate */ 6737c478bd9Sstevel@tonic-gate name = new_string(dfrp->dfr_cmd_arg); 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate for (;;) { 6767c478bd9Sstevel@tonic-gate char *p; 6777c478bd9Sstevel@tonic-gate int i; 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate /* 6807c478bd9Sstevel@tonic-gate * Compare against all known mount points. 6817c478bd9Sstevel@tonic-gate * We start from the most recent mount, which is at the 6827c478bd9Sstevel@tonic-gate * end of the array. 6837c478bd9Sstevel@tonic-gate */ 6847c478bd9Sstevel@tonic-gate for (i = mount_table_entries - 1; i >= 0; i--) { 6857c478bd9Sstevel@tonic-gate struct mtab_entry *mtep = &mount_table[i]; 6867c478bd9Sstevel@tonic-gate 6877c478bd9Sstevel@tonic-gate if (EQ(name, mtep->mte_mount->mnt_special)) { 6887c478bd9Sstevel@tonic-gate dfrp->dfr_mte = mtep; 6897c478bd9Sstevel@tonic-gate break; 6907c478bd9Sstevel@tonic-gate } 6917c478bd9Sstevel@tonic-gate } 6927c478bd9Sstevel@tonic-gate 6937c478bd9Sstevel@tonic-gate /* 6947c478bd9Sstevel@tonic-gate * Remove the last component of the pathname. 6957c478bd9Sstevel@tonic-gate * If there is no such component, this is not a resource name. 6967c478bd9Sstevel@tonic-gate */ 6977c478bd9Sstevel@tonic-gate p = strrchr(name, '/'); 6987c478bd9Sstevel@tonic-gate if (p == NULL) 6997c478bd9Sstevel@tonic-gate break; 7007c478bd9Sstevel@tonic-gate *p = NUL; 7017c478bd9Sstevel@tonic-gate } 7027c478bd9Sstevel@tonic-gate } 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate 7067c478bd9Sstevel@tonic-gate /* 7077c478bd9Sstevel@tonic-gate * Try to match the command line argument which is a block special device 7087c478bd9Sstevel@tonic-gate * with the special device of one of the mounted file systems. 7097c478bd9Sstevel@tonic-gate * If one is found, set the appropriate field of 'dfrp' to the mount 7107c478bd9Sstevel@tonic-gate * table entry. 7117c478bd9Sstevel@tonic-gate */ 7127c478bd9Sstevel@tonic-gate static void 7137c478bd9Sstevel@tonic-gate bdev_mount_entry(struct df_request *dfrp) 7147c478bd9Sstevel@tonic-gate { 7157c478bd9Sstevel@tonic-gate int i; 7167c478bd9Sstevel@tonic-gate char *special = dfrp->dfr_cmd_arg; 7177c478bd9Sstevel@tonic-gate 7187c478bd9Sstevel@tonic-gate /* 7197c478bd9Sstevel@tonic-gate * Compare against all known mount points. 7207c478bd9Sstevel@tonic-gate * We start from the most recent mount, which is at the 7217c478bd9Sstevel@tonic-gate * end of the array. 7227c478bd9Sstevel@tonic-gate */ 7237c478bd9Sstevel@tonic-gate for (i = mount_table_entries - 1; i >= 0; i--) { 7247c478bd9Sstevel@tonic-gate struct mtab_entry *mtep = &mount_table[i]; 7257c478bd9Sstevel@tonic-gate 7267c478bd9Sstevel@tonic-gate if (EQ(special, mtep->mte_mount->mnt_special)) { 7277c478bd9Sstevel@tonic-gate dfrp->dfr_mte = mtep; 7287c478bd9Sstevel@tonic-gate break; 7297c478bd9Sstevel@tonic-gate } 7307c478bd9Sstevel@tonic-gate } 7317c478bd9Sstevel@tonic-gate } 7327c478bd9Sstevel@tonic-gate 7337c478bd9Sstevel@tonic-gate static struct mtab_entry * 7347c478bd9Sstevel@tonic-gate devid_matches(int i, dev_t devno) 7357c478bd9Sstevel@tonic-gate { 7367c478bd9Sstevel@tonic-gate struct mtab_entry *mtep = &mount_table[i]; 7377c478bd9Sstevel@tonic-gate struct extmnttab *mtp = mtep->mte_mount; 7387c478bd9Sstevel@tonic-gate /* int len = strlen(mtp->mnt_mountp); */ 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate if (EQ(mtp->mnt_fstype, MNTTYPE_SWAP)) 7417c478bd9Sstevel@tonic-gate return (NULL); 7427c478bd9Sstevel@tonic-gate /* 7437c478bd9Sstevel@tonic-gate * check if device numbers match. If there is a cached device number 7447c478bd9Sstevel@tonic-gate * in the mtab_entry, use it, otherwise get the device number 7457c478bd9Sstevel@tonic-gate * either from the mnttab entry or by stat'ing the mount point. 7467c478bd9Sstevel@tonic-gate */ 7477c478bd9Sstevel@tonic-gate if (! mtep->mte_dev_is_valid) { 7487c478bd9Sstevel@tonic-gate struct stat64 st; 7497c478bd9Sstevel@tonic-gate dev_t dev = NODEV; 7507c478bd9Sstevel@tonic-gate 7517c478bd9Sstevel@tonic-gate dev = makedev(mtp->mnt_major, mtp->mnt_minor); 7527c478bd9Sstevel@tonic-gate if (dev == 0) 7537c478bd9Sstevel@tonic-gate dev = NODEV; 7547c478bd9Sstevel@tonic-gate if (dev == NODEV) { 7557c478bd9Sstevel@tonic-gate if (stat64(mtp->mnt_mountp, &st) == -1) { 7567c478bd9Sstevel@tonic-gate return (NULL); 7577c478bd9Sstevel@tonic-gate } else { 7587c478bd9Sstevel@tonic-gate dev = st.st_dev; 7597c478bd9Sstevel@tonic-gate } 7607c478bd9Sstevel@tonic-gate } 7617c478bd9Sstevel@tonic-gate mtep->mte_dev = dev; 7627c478bd9Sstevel@tonic-gate mtep->mte_dev_is_valid = TRUE; 7637c478bd9Sstevel@tonic-gate } 7647c478bd9Sstevel@tonic-gate if (mtep->mte_dev == devno) { 7657c478bd9Sstevel@tonic-gate return (mtep); 7667c478bd9Sstevel@tonic-gate } 7677c478bd9Sstevel@tonic-gate return (NULL); 7687c478bd9Sstevel@tonic-gate } 7697c478bd9Sstevel@tonic-gate 7707c478bd9Sstevel@tonic-gate /* 7717c478bd9Sstevel@tonic-gate * Find the mount point under which the user-specified path resides 7727c478bd9Sstevel@tonic-gate * and set the 'dfr_mte' field of '*dfrp' to point to the mount table entry. 7737c478bd9Sstevel@tonic-gate */ 7747c478bd9Sstevel@tonic-gate static void 7757c478bd9Sstevel@tonic-gate path_mount_entry(struct df_request *dfrp, dev_t devno) 7767c478bd9Sstevel@tonic-gate { 7777c478bd9Sstevel@tonic-gate char dirpath[MAXPATHLEN]; 7787c478bd9Sstevel@tonic-gate char *dir = dfrp->dfr_cmd_arg; 7797c478bd9Sstevel@tonic-gate struct mtab_entry *match, *tmatch; 7807c478bd9Sstevel@tonic-gate int i; 7817c478bd9Sstevel@tonic-gate 7827c478bd9Sstevel@tonic-gate /* 7837c478bd9Sstevel@tonic-gate * Expand the given path to get a canonical version (i.e. an absolute 7847c478bd9Sstevel@tonic-gate * path without symbolic links). 7857c478bd9Sstevel@tonic-gate */ 7867c478bd9Sstevel@tonic-gate if (realpath(dir, dirpath) == NULL) { 7877c478bd9Sstevel@tonic-gate errmsg(ERR_PERROR, "cannot canonicalize %s:", dir); 7887c478bd9Sstevel@tonic-gate return; 7897c478bd9Sstevel@tonic-gate } 7907c478bd9Sstevel@tonic-gate /* 7917c478bd9Sstevel@tonic-gate * If the mnt point is lofs, search from the top of entries from 792738059c5SJim Rice * /etc/mnttab and return the entry that best matches the pathname. 7937c478bd9Sstevel@tonic-gate * For non-lofs mount points, return the first entry from the bottom 7947c478bd9Sstevel@tonic-gate * of the entries in /etc/mnttab that matches on the devid field 7957c478bd9Sstevel@tonic-gate */ 7967c478bd9Sstevel@tonic-gate match = NULL; 7977c478bd9Sstevel@tonic-gate if (dfrp->dfr_fstype && EQ(dfrp->dfr_fstype, MNTTYPE_LOFS)) { 798738059c5SJim Rice struct extmnttab *entryp; 799738059c5SJim Rice char *path, *mountp; 800738059c5SJim Rice char p, m; 801738059c5SJim Rice int score; 802738059c5SJim Rice int best_score = 0; 803738059c5SJim Rice int best_index = -1; 804738059c5SJim Rice 8057c478bd9Sstevel@tonic-gate for (i = 0; i < mount_table_entries; i++) { 806738059c5SJim Rice entryp = mount_table[i].mte_mount; 807738059c5SJim Rice 808738059c5SJim Rice if (!EQ(entryp->mnt_fstype, MNTTYPE_LOFS)) 809738059c5SJim Rice continue; 810738059c5SJim Rice 811738059c5SJim Rice path = dirpath; 812738059c5SJim Rice mountp = entryp->mnt_mountp; 813738059c5SJim Rice score = 0; 814738059c5SJim Rice /* 815738059c5SJim Rice * Count the number of matching characters 816738059c5SJim Rice * until either path or mountpoint is exhausted 817738059c5SJim Rice */ 818738059c5SJim Rice while ((p = *path++) == (m = *mountp++)) { 819738059c5SJim Rice score++; 820738059c5SJim Rice 821738059c5SJim Rice if (p == '\0' || m == '\0') 8227c478bd9Sstevel@tonic-gate break; 8237c478bd9Sstevel@tonic-gate } 824738059c5SJim Rice 825738059c5SJim Rice /* Both exhausted so we have a match */ 826738059c5SJim Rice if (p == '\0' && m == '\0') { 827738059c5SJim Rice best_index = i; 828738059c5SJim Rice break; 829738059c5SJim Rice } 830738059c5SJim Rice 831738059c5SJim Rice /* 832738059c5SJim Rice * We have exhausted the mountpoint and the current 833738059c5SJim Rice * character in the path is a '/' hence the full path 834738059c5SJim Rice * traverses this mountpoint. 835738059c5SJim Rice * Record this as the best candidate so far. 836738059c5SJim Rice */ 837738059c5SJim Rice if (p == '/' && m == '\0') { 838738059c5SJim Rice if (score > best_score) { 839738059c5SJim Rice best_index = i; 840738059c5SJim Rice best_score = score; 841738059c5SJim Rice } 842738059c5SJim Rice } 843738059c5SJim Rice } 844738059c5SJim Rice 845738059c5SJim Rice if (best_index > -1) 846738059c5SJim Rice match = &mount_table[best_index]; 8477c478bd9Sstevel@tonic-gate } else { 8487c478bd9Sstevel@tonic-gate for (i = mount_table_entries - 1; i >= 0; i--) { 8497c478bd9Sstevel@tonic-gate if (tmatch = devid_matches(i, devno)) { 8507c478bd9Sstevel@tonic-gate /* 8517c478bd9Sstevel@tonic-gate * If executing in a zone, there might be lofs 8527c478bd9Sstevel@tonic-gate * mounts for which the real mount point is 8537c478bd9Sstevel@tonic-gate * invisible; accept the "best fit" for this 8547c478bd9Sstevel@tonic-gate * devid. 8557c478bd9Sstevel@tonic-gate */ 8567c478bd9Sstevel@tonic-gate match = tmatch; 8577c478bd9Sstevel@tonic-gate if (!EQ(match->mte_mount->mnt_fstype, 8587c478bd9Sstevel@tonic-gate MNTTYPE_LOFS)) { 8597c478bd9Sstevel@tonic-gate break; 8607c478bd9Sstevel@tonic-gate } 8617c478bd9Sstevel@tonic-gate } 8627c478bd9Sstevel@tonic-gate } 8637c478bd9Sstevel@tonic-gate } 8647c478bd9Sstevel@tonic-gate if (! match) { 8657c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, 8667c478bd9Sstevel@tonic-gate "Could not find mount point for %s", dir); 8677c478bd9Sstevel@tonic-gate return; 8687c478bd9Sstevel@tonic-gate } 8697c478bd9Sstevel@tonic-gate dfrp->dfr_mte = match; 8707c478bd9Sstevel@tonic-gate } 8717c478bd9Sstevel@tonic-gate 8727c478bd9Sstevel@tonic-gate /* 8737c478bd9Sstevel@tonic-gate * Execute a single FS-specific df command for all given requests 8747c478bd9Sstevel@tonic-gate * Return 0 if successful, 1 otherwise. 8757c478bd9Sstevel@tonic-gate */ 8767c478bd9Sstevel@tonic-gate static int 8777c478bd9Sstevel@tonic-gate run_fs_specific_df(struct df_request request_list[], int entries) 8787c478bd9Sstevel@tonic-gate { 8797c478bd9Sstevel@tonic-gate int i; 8807c478bd9Sstevel@tonic-gate int argv_index; 8817c478bd9Sstevel@tonic-gate char **argv; 8827c478bd9Sstevel@tonic-gate size_t size; 8837c478bd9Sstevel@tonic-gate pid_t pid; 8847c478bd9Sstevel@tonic-gate int status; 8857c478bd9Sstevel@tonic-gate char cmd_path[MAXPATHLEN]; 8867c478bd9Sstevel@tonic-gate char *fstype; 8877c478bd9Sstevel@tonic-gate 8887c478bd9Sstevel@tonic-gate if (entries == 0) 8897c478bd9Sstevel@tonic-gate return (0); 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate fstype = request_list[0].dfr_fstype; 8927c478bd9Sstevel@tonic-gate 8937c478bd9Sstevel@tonic-gate if (F_option && ! EQ(FSType, fstype)) 8947c478bd9Sstevel@tonic-gate return (0); 8957c478bd9Sstevel@tonic-gate 8967c478bd9Sstevel@tonic-gate (void) sprintf(cmd_path, "%s%s/df", FS_LIBPATH, fstype); 8977c478bd9Sstevel@tonic-gate /* 8987c478bd9Sstevel@tonic-gate * Argv entries: 8997c478bd9Sstevel@tonic-gate * 1 for the path 9007c478bd9Sstevel@tonic-gate * 2 for -o <options> 9017c478bd9Sstevel@tonic-gate * 1 for the generic options that we propagate 9027c478bd9Sstevel@tonic-gate * 1 for the terminating NULL pointer 9037c478bd9Sstevel@tonic-gate * n for the number of user-specified arguments 9047c478bd9Sstevel@tonic-gate */ 9057c478bd9Sstevel@tonic-gate size = (5 + entries) * sizeof (char *); 9067c478bd9Sstevel@tonic-gate argv = xmalloc(size); 9077c478bd9Sstevel@tonic-gate (void) memset(argv, 0, size); 9087c478bd9Sstevel@tonic-gate 9097c478bd9Sstevel@tonic-gate argv[0] = cmd_path; 9107c478bd9Sstevel@tonic-gate argv_index = 1; 9117c478bd9Sstevel@tonic-gate if (o_option) { 9127c478bd9Sstevel@tonic-gate argv[argv_index++] = "-o"; 9137c478bd9Sstevel@tonic-gate argv[argv_index++] = o_option_arg; 9147c478bd9Sstevel@tonic-gate } 9157c478bd9Sstevel@tonic-gate 9167c478bd9Sstevel@tonic-gate /* 9177c478bd9Sstevel@tonic-gate * Check if we need to propagate any generic options 9187c478bd9Sstevel@tonic-gate */ 9197c478bd9Sstevel@tonic-gate if (df_options_len > 1) 9207c478bd9Sstevel@tonic-gate argv[argv_index++] = df_options; 9217c478bd9Sstevel@tonic-gate 9227c478bd9Sstevel@tonic-gate /* 9237c478bd9Sstevel@tonic-gate * If there is a user-specified path, we pass that to the 9247c478bd9Sstevel@tonic-gate * FS-specific df. Otherwise, we are guaranteed to have a mount 9257c478bd9Sstevel@tonic-gate * point, since a request without a user path implies that 9267c478bd9Sstevel@tonic-gate * we are reporting only on mounted file systems. 9277c478bd9Sstevel@tonic-gate */ 9287c478bd9Sstevel@tonic-gate for (i = 0; i < entries; i++) { 9297c478bd9Sstevel@tonic-gate struct df_request *dfrp = &request_list[i]; 9307c478bd9Sstevel@tonic-gate 9317c478bd9Sstevel@tonic-gate argv[argv_index++] = (dfrp->dfr_cmd_arg == NULL) 9327c478bd9Sstevel@tonic-gate ? DFR_MOUNT_POINT(dfrp) 9337c478bd9Sstevel@tonic-gate : dfrp->dfr_cmd_arg; 9347c478bd9Sstevel@tonic-gate } 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate if (V_option) { 9377c478bd9Sstevel@tonic-gate for (i = 0; i < argv_index-1; i++) 9387c478bd9Sstevel@tonic-gate (void) printf("%s ", argv[i]); 9397c478bd9Sstevel@tonic-gate (void) printf("%s\n", argv[i]); 9407c478bd9Sstevel@tonic-gate return (0); 9417c478bd9Sstevel@tonic-gate } 9427c478bd9Sstevel@tonic-gate 9437c478bd9Sstevel@tonic-gate pid = fork(); 9447c478bd9Sstevel@tonic-gate 9457c478bd9Sstevel@tonic-gate if (pid == -1) { 9467c478bd9Sstevel@tonic-gate errmsg(ERR_PERROR, "cannot fork process:"); 9477c478bd9Sstevel@tonic-gate return (1); 9487c478bd9Sstevel@tonic-gate } else if (pid == 0) { 9497c478bd9Sstevel@tonic-gate (void) execv(cmd_path, argv); 9507c478bd9Sstevel@tonic-gate if (errno == ENOENT) 9517c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, 9527c478bd9Sstevel@tonic-gate "operation not applicable for FSType %s", 9537c478bd9Sstevel@tonic-gate fstype); 9547c478bd9Sstevel@tonic-gate else 9557c478bd9Sstevel@tonic-gate errmsg(ERR_PERROR, "cannot execute %s:", cmd_path); 9567c478bd9Sstevel@tonic-gate exit(2); 9577c478bd9Sstevel@tonic-gate } 9587c478bd9Sstevel@tonic-gate 9597c478bd9Sstevel@tonic-gate /* 9607c478bd9Sstevel@tonic-gate * Reap the child 9617c478bd9Sstevel@tonic-gate */ 9627c478bd9Sstevel@tonic-gate for (;;) { 9637c478bd9Sstevel@tonic-gate pid_t wpid = waitpid(pid, &status, 0); 9647c478bd9Sstevel@tonic-gate 9657c478bd9Sstevel@tonic-gate if (wpid == -1) 9667c478bd9Sstevel@tonic-gate if (errno == EINTR) 9677c478bd9Sstevel@tonic-gate continue; 9687c478bd9Sstevel@tonic-gate else { 9697c478bd9Sstevel@tonic-gate errmsg(ERR_PERROR, "waitpid error:"); 9707c478bd9Sstevel@tonic-gate return (1); 9717c478bd9Sstevel@tonic-gate } 9727c478bd9Sstevel@tonic-gate else 9737c478bd9Sstevel@tonic-gate break; 9747c478bd9Sstevel@tonic-gate } 9757c478bd9Sstevel@tonic-gate 9767c478bd9Sstevel@tonic-gate return ((WIFEXITED(status) && WEXITSTATUS(status) == 0) ? 0 : 1); 9777c478bd9Sstevel@tonic-gate } 9787c478bd9Sstevel@tonic-gate 9797c478bd9Sstevel@tonic-gate 9807c478bd9Sstevel@tonic-gate 9817c478bd9Sstevel@tonic-gate /* 9827c478bd9Sstevel@tonic-gate * Remove from the request list all requests that do not apply. 9837c478bd9Sstevel@tonic-gate * Notice that the subsequent processing of the requests depends on 9847c478bd9Sstevel@tonic-gate * the sanity checking performed by this function. 9857c478bd9Sstevel@tonic-gate */ 9867c478bd9Sstevel@tonic-gate static int 9877c478bd9Sstevel@tonic-gate prune_list(struct df_request request_list[], 9887c478bd9Sstevel@tonic-gate size_t n_requests, 9897c478bd9Sstevel@tonic-gate size_t *valid_requests) 9907c478bd9Sstevel@tonic-gate { 9917c478bd9Sstevel@tonic-gate size_t i; 9927c478bd9Sstevel@tonic-gate size_t n_valid = 0; 9937c478bd9Sstevel@tonic-gate int errors = 0; 9947c478bd9Sstevel@tonic-gate 9957c478bd9Sstevel@tonic-gate for (i = 0; i < n_requests; i++) { 9967c478bd9Sstevel@tonic-gate struct df_request *dfrp = &request_list[i]; 9977c478bd9Sstevel@tonic-gate 9987c478bd9Sstevel@tonic-gate /* 9997c478bd9Sstevel@tonic-gate * Skip file systems that are not mounted if either the 10007c478bd9Sstevel@tonic-gate * -l or -n options were specified. If none of these options 10017c478bd9Sstevel@tonic-gate * are present, the appropriate FS-specific df will be invoked. 10027c478bd9Sstevel@tonic-gate */ 10037c478bd9Sstevel@tonic-gate if (! DFR_ISMOUNTEDFS(dfrp)) { 10047c478bd9Sstevel@tonic-gate if (l_option || n_option) { 10057c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, 1006990b4856Slling "%s option incompatible with unmounted " 1007990b4856Slling "special device (%s)", 10087c478bd9Sstevel@tonic-gate l_option ? "-l" : "-n", dfrp->dfr_cmd_arg); 10097c478bd9Sstevel@tonic-gate dfrp->dfr_valid = FALSE; 10107c478bd9Sstevel@tonic-gate errors++; 10117c478bd9Sstevel@tonic-gate } 10127c478bd9Sstevel@tonic-gate else 10137c478bd9Sstevel@tonic-gate n_valid++; 10147c478bd9Sstevel@tonic-gate continue; 10157c478bd9Sstevel@tonic-gate } 10167c478bd9Sstevel@tonic-gate 10177c478bd9Sstevel@tonic-gate /* 10187c478bd9Sstevel@tonic-gate * Check for inconsistency between the argument of -F and 10197c478bd9Sstevel@tonic-gate * the actual file system type. 10207c478bd9Sstevel@tonic-gate * If there is an inconsistency and the user specified a 10217c478bd9Sstevel@tonic-gate * path, this is an error since we are asked to interpret 10227c478bd9Sstevel@tonic-gate * the path using the wrong file system type. If there is 10237c478bd9Sstevel@tonic-gate * no path associated with this request, we quietly ignore it. 10247c478bd9Sstevel@tonic-gate */ 10257c478bd9Sstevel@tonic-gate if (F_option && ! EQ(dfrp->dfr_fstype, FSType)) { 10267c478bd9Sstevel@tonic-gate dfrp->dfr_valid = FALSE; 10277c478bd9Sstevel@tonic-gate if (dfrp->dfr_cmd_arg != NULL) { 10287c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, 10297c478bd9Sstevel@tonic-gate "Warning: %s mounted as a %s file system", 10307c478bd9Sstevel@tonic-gate dfrp->dfr_cmd_arg, dfrp->dfr_fstype); 10317c478bd9Sstevel@tonic-gate errors++; 10327c478bd9Sstevel@tonic-gate } 10337c478bd9Sstevel@tonic-gate continue; 10347c478bd9Sstevel@tonic-gate } 10357c478bd9Sstevel@tonic-gate 10367c478bd9Sstevel@tonic-gate /* 10377c478bd9Sstevel@tonic-gate * Skip remote file systems if the -l option is present 10387c478bd9Sstevel@tonic-gate */ 10397c478bd9Sstevel@tonic-gate if (l_option && is_remote_fs(dfrp->dfr_fstype)) { 10407c478bd9Sstevel@tonic-gate if (dfrp->dfr_cmd_arg != NULL) { 10417c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, 10427c478bd9Sstevel@tonic-gate "Warning: %s is not a local file system", 10437c478bd9Sstevel@tonic-gate dfrp->dfr_cmd_arg); 10447c478bd9Sstevel@tonic-gate errors++; 10457c478bd9Sstevel@tonic-gate } 10467c478bd9Sstevel@tonic-gate dfrp->dfr_valid = FALSE; 10477c478bd9Sstevel@tonic-gate continue; 10487c478bd9Sstevel@tonic-gate } 10497c478bd9Sstevel@tonic-gate 10507c478bd9Sstevel@tonic-gate /* 10517c478bd9Sstevel@tonic-gate * Skip file systems mounted as "ignore" unless the -a option 10527c478bd9Sstevel@tonic-gate * is present, or the user explicitly specified them on 10537c478bd9Sstevel@tonic-gate * the command line. 10547c478bd9Sstevel@tonic-gate */ 10557c478bd9Sstevel@tonic-gate if (dfrp->dfr_mte->mte_ignore && 10567c478bd9Sstevel@tonic-gate ! (a_option || dfrp->dfr_cmd_arg)) { 10577c478bd9Sstevel@tonic-gate dfrp->dfr_valid = FALSE; 10587c478bd9Sstevel@tonic-gate continue; 10597c478bd9Sstevel@tonic-gate } 10607c478bd9Sstevel@tonic-gate 10617c478bd9Sstevel@tonic-gate n_valid++; 10627c478bd9Sstevel@tonic-gate } 10637c478bd9Sstevel@tonic-gate *valid_requests = n_valid; 10647c478bd9Sstevel@tonic-gate return (errors); 10657c478bd9Sstevel@tonic-gate } 10667c478bd9Sstevel@tonic-gate 10677c478bd9Sstevel@tonic-gate 10687c478bd9Sstevel@tonic-gate /* 10697c478bd9Sstevel@tonic-gate * Print the appropriate header for the requested output format. 10707c478bd9Sstevel@tonic-gate * Options are checked in order of their precedence. 10717c478bd9Sstevel@tonic-gate */ 10727c478bd9Sstevel@tonic-gate static void 107308190127Sdh145677 print_header(void) 10747c478bd9Sstevel@tonic-gate { 10757c478bd9Sstevel@tonic-gate if (use_scaling) { /* this comes from the -h option */ 10767c478bd9Sstevel@tonic-gate int arg = 'h'; 10777c478bd9Sstevel@tonic-gate 10787c478bd9Sstevel@tonic-gate (void) printf("%-*s %*s %*s %*s %-*s %s\n", 10797c478bd9Sstevel@tonic-gate FILESYSTEM_WIDTH, TRANSLATE("Filesystem"), 10807c478bd9Sstevel@tonic-gate #ifdef XPG4 10817c478bd9Sstevel@tonic-gate SCALED_WIDTH, TRANSLATE("Size"), 10827c478bd9Sstevel@tonic-gate SCALED_WIDTH, TRANSLATE("Used"), 10837c478bd9Sstevel@tonic-gate AVAILABLE_WIDTH, TRANSLATE("Available"), 10847c478bd9Sstevel@tonic-gate CAPACITY_WIDTH, TRANSLATE("Capacity"), 10857c478bd9Sstevel@tonic-gate #else 10867c478bd9Sstevel@tonic-gate SCALED_WIDTH, TRANSLATE("size"), 10877c478bd9Sstevel@tonic-gate SCALED_WIDTH, TRANSLATE("used"), 10887c478bd9Sstevel@tonic-gate AVAILABLE_WIDTH, TRANSLATE("avail"), 10897c478bd9Sstevel@tonic-gate CAPACITY_WIDTH, TRANSLATE("capacity"), 10907c478bd9Sstevel@tonic-gate #endif 10917c478bd9Sstevel@tonic-gate TRANSLATE("Mounted on")); 10927c478bd9Sstevel@tonic-gate SET_OPTION(h); 10937c478bd9Sstevel@tonic-gate return; 10947c478bd9Sstevel@tonic-gate } 10957c478bd9Sstevel@tonic-gate if (k_option) { 10967c478bd9Sstevel@tonic-gate int arg = 'h'; 10977c478bd9Sstevel@tonic-gate 10987c478bd9Sstevel@tonic-gate (void) printf(gettext("%-*s %*s %*s %*s %-*s %s\n"), 10997c478bd9Sstevel@tonic-gate FILESYSTEM_WIDTH, TRANSLATE("Filesystem"), 11007c478bd9Sstevel@tonic-gate #ifdef XPG4 11017c478bd9Sstevel@tonic-gate KBYTE_WIDTH, TRANSLATE("1024-blocks"), 11027c478bd9Sstevel@tonic-gate KBYTE_WIDTH, TRANSLATE("Used"), 11037c478bd9Sstevel@tonic-gate KBYTE_WIDTH, TRANSLATE("Available"), 11047c478bd9Sstevel@tonic-gate CAPACITY_WIDTH, TRANSLATE("Capacity"), 11057c478bd9Sstevel@tonic-gate #else 11067c478bd9Sstevel@tonic-gate KBYTE_WIDTH, TRANSLATE("kbytes"), 11077c478bd9Sstevel@tonic-gate KBYTE_WIDTH, TRANSLATE("used"), 11087c478bd9Sstevel@tonic-gate KBYTE_WIDTH, TRANSLATE("avail"), 11097c478bd9Sstevel@tonic-gate CAPACITY_WIDTH, TRANSLATE("capacity"), 11107c478bd9Sstevel@tonic-gate #endif 11117c478bd9Sstevel@tonic-gate TRANSLATE("Mounted on")); 11127c478bd9Sstevel@tonic-gate SET_OPTION(h); 11137c478bd9Sstevel@tonic-gate return; 11147c478bd9Sstevel@tonic-gate } 1115*790c646cSPaul B. Henson if (m_option) { 1116*790c646cSPaul B. Henson int arg = 'h'; 1117*790c646cSPaul B. Henson 1118*790c646cSPaul B. Henson (void) printf(gettext("%-*s %*s %*s %*s %-*s %s\n"), 1119*790c646cSPaul B. Henson FILESYSTEM_WIDTH, TRANSLATE("Filesystem"), 1120*790c646cSPaul B. Henson KBYTE_WIDTH, TRANSLATE("mbytes"), 1121*790c646cSPaul B. Henson KBYTE_WIDTH, TRANSLATE("used"), 1122*790c646cSPaul B. Henson KBYTE_WIDTH, TRANSLATE("avail"), 1123*790c646cSPaul B. Henson CAPACITY_WIDTH, TRANSLATE("capacity"), 1124*790c646cSPaul B. Henson TRANSLATE("Mounted on")); 1125*790c646cSPaul B. Henson SET_OPTION(h); 1126*790c646cSPaul B. Henson return; 1127*790c646cSPaul B. Henson } 11287c478bd9Sstevel@tonic-gate /* Added for XCU4 compliance */ 11297c478bd9Sstevel@tonic-gate if (P_option) { 11307c478bd9Sstevel@tonic-gate int arg = 'h'; 11317c478bd9Sstevel@tonic-gate 11327c478bd9Sstevel@tonic-gate (void) printf(gettext("%-*s %*s %*s %*s %-*s %s\n"), 11337c478bd9Sstevel@tonic-gate FILESYSTEM_WIDTH, TRANSLATE("Filesystem"), 11347c478bd9Sstevel@tonic-gate KBYTE_WIDTH, TRANSLATE("512-blocks"), 11357c478bd9Sstevel@tonic-gate KBYTE_WIDTH, TRANSLATE("Used"), 11367c478bd9Sstevel@tonic-gate KBYTE_WIDTH, TRANSLATE("Available"), 11377c478bd9Sstevel@tonic-gate CAPACITY_WIDTH, TRANSLATE("Capacity"), 11387c478bd9Sstevel@tonic-gate TRANSLATE("Mounted on")); 11397c478bd9Sstevel@tonic-gate 11407c478bd9Sstevel@tonic-gate SET_OPTION(h); 11417c478bd9Sstevel@tonic-gate return; 11427c478bd9Sstevel@tonic-gate } 11437c478bd9Sstevel@tonic-gate /* End XCU4 */ 11447c478bd9Sstevel@tonic-gate if (v_option) { 11457c478bd9Sstevel@tonic-gate (void) printf("%-*s %-*s %*s %*s %*s %-*s\n", 11467c478bd9Sstevel@tonic-gate IBCS2_MOUNT_POINT_WIDTH, TRANSLATE("Mount Dir"), 11477c478bd9Sstevel@tonic-gate IBCS2_FILESYSTEM_WIDTH, TRANSLATE("Filesystem"), 11487c478bd9Sstevel@tonic-gate BLOCK_WIDTH, TRANSLATE("blocks"), 11497c478bd9Sstevel@tonic-gate BLOCK_WIDTH, TRANSLATE("used"), 11507c478bd9Sstevel@tonic-gate BLOCK_WIDTH, TRANSLATE("free"), 11517c478bd9Sstevel@tonic-gate CAPACITY_WIDTH, TRANSLATE(" %used")); 11527c478bd9Sstevel@tonic-gate return; 11537c478bd9Sstevel@tonic-gate } 11547c478bd9Sstevel@tonic-gate if (e_option) { 11557c478bd9Sstevel@tonic-gate (void) printf(gettext("%-*s %*s\n"), 11567c478bd9Sstevel@tonic-gate FILESYSTEM_WIDTH, TRANSLATE("Filesystem"), 11577c478bd9Sstevel@tonic-gate BLOCK_WIDTH, TRANSLATE("ifree")); 11587c478bd9Sstevel@tonic-gate return; 11597c478bd9Sstevel@tonic-gate } 11607c478bd9Sstevel@tonic-gate if (b_option) { 11617c478bd9Sstevel@tonic-gate (void) printf(gettext("%-*s %*s\n"), 11627c478bd9Sstevel@tonic-gate FILESYSTEM_WIDTH, TRANSLATE("Filesystem"), 11637c478bd9Sstevel@tonic-gate BLOCK_WIDTH, TRANSLATE("avail")); 11647c478bd9Sstevel@tonic-gate return; 11657c478bd9Sstevel@tonic-gate } 11667c478bd9Sstevel@tonic-gate } 11677c478bd9Sstevel@tonic-gate 11687c478bd9Sstevel@tonic-gate 11697c478bd9Sstevel@tonic-gate /* 11707c478bd9Sstevel@tonic-gate * Convert an unsigned long long to a string representation and place the 11717c478bd9Sstevel@tonic-gate * result in the caller-supplied buffer. 11727c478bd9Sstevel@tonic-gate * The given number is in units of "unit_from" size, but the 11737c478bd9Sstevel@tonic-gate * converted number will be in units of "unit_to" size. The unit sizes 11747c478bd9Sstevel@tonic-gate * must be powers of 2. 11757c478bd9Sstevel@tonic-gate * The value "(unsigned long long)-1" is a special case and is always 11767c478bd9Sstevel@tonic-gate * converted to "-1". 11777c478bd9Sstevel@tonic-gate * Returns a pointer to the caller-supplied buffer. 11787c478bd9Sstevel@tonic-gate */ 11797c478bd9Sstevel@tonic-gate static char * 11807c478bd9Sstevel@tonic-gate number_to_string( 11817c478bd9Sstevel@tonic-gate char *buf, /* put the result here */ 11827c478bd9Sstevel@tonic-gate unsigned long long number, /* convert this number */ 11837c478bd9Sstevel@tonic-gate int unit_from, /* from units of this size */ 11847c478bd9Sstevel@tonic-gate int unit_to) /* to units of this size */ 11857c478bd9Sstevel@tonic-gate { 11867c478bd9Sstevel@tonic-gate if ((long long)number == (long long)-1) 11877c478bd9Sstevel@tonic-gate (void) strcpy(buf, "-1"); 11887c478bd9Sstevel@tonic-gate else { 11897c478bd9Sstevel@tonic-gate if (unit_from == unit_to) 11907c478bd9Sstevel@tonic-gate (void) sprintf(buf, "%llu", number); 11917c478bd9Sstevel@tonic-gate else if (unit_from < unit_to) 11927c478bd9Sstevel@tonic-gate (void) sprintf(buf, "%llu", 11937c478bd9Sstevel@tonic-gate number / (unsigned long long)(unit_to / unit_from)); 11947c478bd9Sstevel@tonic-gate else 11957c478bd9Sstevel@tonic-gate (void) sprintf(buf, "%llu", 11967c478bd9Sstevel@tonic-gate number * (unsigned long long)(unit_from / unit_to)); 11977c478bd9Sstevel@tonic-gate } 11987c478bd9Sstevel@tonic-gate return (buf); 11997c478bd9Sstevel@tonic-gate } 12007c478bd9Sstevel@tonic-gate 12017c478bd9Sstevel@tonic-gate /* 12027c478bd9Sstevel@tonic-gate * Convert an unsigned long long to a string representation and place the 12037c478bd9Sstevel@tonic-gate * result in the caller-supplied buffer. 12047c478bd9Sstevel@tonic-gate * The given number is in units of "unit_from" size, 12057c478bd9Sstevel@tonic-gate * this will first be converted to a number in 1024 or 1000 byte size, 12067c478bd9Sstevel@tonic-gate * depending on the scaling factor. 12077c478bd9Sstevel@tonic-gate * Then the number is scaled down until it is small enough to be in a good 12087c478bd9Sstevel@tonic-gate * human readable format i.e. in the range 0 thru scale-1. 12097c478bd9Sstevel@tonic-gate * If it's smaller than 10 there's room enough to provide one decimal place. 12107c478bd9Sstevel@tonic-gate * The value "(unsigned long long)-1" is a special case and is always 12117c478bd9Sstevel@tonic-gate * converted to "-1". 12127c478bd9Sstevel@tonic-gate * Returns a pointer to the caller-supplied buffer. 12137c478bd9Sstevel@tonic-gate */ 12147c478bd9Sstevel@tonic-gate static char * 12157c478bd9Sstevel@tonic-gate number_to_scaled_string( 12167c478bd9Sstevel@tonic-gate numbuf_t buf, /* put the result here */ 12177c478bd9Sstevel@tonic-gate unsigned long long number, /* convert this number */ 12187c478bd9Sstevel@tonic-gate int unit_from, 12197c478bd9Sstevel@tonic-gate int scale) 12207c478bd9Sstevel@tonic-gate { 12217c478bd9Sstevel@tonic-gate unsigned long long save = 0; 12227c478bd9Sstevel@tonic-gate char *M = "KMGTPE"; /* Measurement: kilo, mega, giga, tera, peta, exa */ 12237c478bd9Sstevel@tonic-gate char *uom = M; /* unit of measurement, initially 'K' (=M[0]) */ 12247c478bd9Sstevel@tonic-gate 12257c478bd9Sstevel@tonic-gate if ((long long)number == (long long)-1) { 12267c478bd9Sstevel@tonic-gate (void) strcpy(buf, "-1"); 12277c478bd9Sstevel@tonic-gate return (buf); 12287c478bd9Sstevel@tonic-gate } 12297c478bd9Sstevel@tonic-gate 12307c478bd9Sstevel@tonic-gate /* 12317c478bd9Sstevel@tonic-gate * Convert number from unit_from to given scale (1024 or 1000). 12327c478bd9Sstevel@tonic-gate * This means multiply number by unit_from and divide by scale. 12337c478bd9Sstevel@tonic-gate * 12347c478bd9Sstevel@tonic-gate * Would like to multiply by unit_from and then divide by scale, 12357c478bd9Sstevel@tonic-gate * but if the first multiplication would overflow, then need to 12367c478bd9Sstevel@tonic-gate * divide by scale and then multiply by unit_from. 12377c478bd9Sstevel@tonic-gate */ 12387c478bd9Sstevel@tonic-gate if (number > (UINT64_MAX / (unsigned long long)unit_from)) { 12397c478bd9Sstevel@tonic-gate number = (number / (unsigned long long)scale) * 12407c478bd9Sstevel@tonic-gate (unsigned long long)unit_from; 12417c478bd9Sstevel@tonic-gate } else { 12427c478bd9Sstevel@tonic-gate number = (number * (unsigned long long)unit_from) / 12437c478bd9Sstevel@tonic-gate (unsigned long long)scale; 12447c478bd9Sstevel@tonic-gate } 12457c478bd9Sstevel@tonic-gate 12467c478bd9Sstevel@tonic-gate /* 12477c478bd9Sstevel@tonic-gate * Now we have number as a count of scale units. 12487c478bd9Sstevel@tonic-gate * Stop scaling when we reached exa bytes, then something is 12497c478bd9Sstevel@tonic-gate * probably wrong with our number. 12507c478bd9Sstevel@tonic-gate */ 12517c478bd9Sstevel@tonic-gate 12527c478bd9Sstevel@tonic-gate while ((number >= scale) && (*uom != 'E')) { 12537c478bd9Sstevel@tonic-gate uom++; /* next unit of measurement */ 12547c478bd9Sstevel@tonic-gate save = number; 12557c478bd9Sstevel@tonic-gate number = (number + (scale / 2)) / scale; 12567c478bd9Sstevel@tonic-gate } 12577c478bd9Sstevel@tonic-gate /* check if we should output a decimal place after the point */ 12587c478bd9Sstevel@tonic-gate if (save && ((save / scale) < 10)) { 12597c478bd9Sstevel@tonic-gate /* sprintf() will round for us */ 12607c478bd9Sstevel@tonic-gate float fnum = (float)save / scale; 12617c478bd9Sstevel@tonic-gate (void) sprintf(buf, "%2.1f%c", fnum, *uom); 12627c478bd9Sstevel@tonic-gate } else { 12637c478bd9Sstevel@tonic-gate (void) sprintf(buf, "%4llu%c", number, *uom); 12647c478bd9Sstevel@tonic-gate } 12657c478bd9Sstevel@tonic-gate return (buf); 12667c478bd9Sstevel@tonic-gate } 12677c478bd9Sstevel@tonic-gate 1268fa9e4066Sahrens /* 1269fa9e4066Sahrens * The statvfs() implementation allows us to return only two values, the total 1270fa9e4066Sahrens * number of blocks and the number of blocks free. The equation 'used = total - 1271fa9e4066Sahrens * free' will not work for ZFS filesystems, due to the nature of pooled storage. 1272fa9e4066Sahrens * We choose to return values in the statvfs structure that will produce correct 1273fa9e4066Sahrens * results for 'used' and 'available', but not 'total'. This function will open 1274fa9e4066Sahrens * the underlying ZFS dataset if necessary and get the real value. 1275fa9e4066Sahrens */ 1276fa9e4066Sahrens static void 1277fa9e4066Sahrens adjust_total_blocks(struct df_request *dfrp, fsblkcnt64_t *total, 1278fa9e4066Sahrens uint64_t blocksize) 1279fa9e4066Sahrens { 1280fa9e4066Sahrens char *dataset, *slash; 1281a9799022Sck153898 boolean_t first = TRUE; 1282a9799022Sck153898 uint64_t quota = 0; 1283fa9e4066Sahrens 1284a9799022Sck153898 if (strcmp(DFR_FSTYPE(dfrp), MNTTYPE_ZFS) != 0 || !load_libzfs()) 1285fa9e4066Sahrens return; 1286fa9e4066Sahrens 1287fa9e4066Sahrens /* 1288fa9e4066Sahrens * We want to get the total size for this filesystem as bounded by any 1289fa9e4066Sahrens * quotas. In order to do this, we start at the current filesystem and 1290a9799022Sck153898 * work upwards looking for the smallest quota. When we reach the 1291a9799022Sck153898 * pool itself, the quota is the amount used plus the amount 1292fa9e4066Sahrens * available. 1293fa9e4066Sahrens */ 1294fa9e4066Sahrens if ((dataset = strdup(DFR_SPECIAL(dfrp))) == NULL) 1295fa9e4066Sahrens return; 1296fa9e4066Sahrens 1297fa9e4066Sahrens slash = dataset + strlen(dataset); 1298a9799022Sck153898 while (slash != NULL) { 1299a9799022Sck153898 zfs_handle_t *zhp; 1300a9799022Sck153898 uint64_t this_quota; 1301a9799022Sck153898 1302fa9e4066Sahrens *slash = '\0'; 1303fa9e4066Sahrens 1304a9799022Sck153898 zhp = _zfs_open(g_zfs, dataset, ZFS_TYPE_DATASET); 1305a9799022Sck153898 if (zhp == NULL) 1306a9799022Sck153898 break; 1307a9799022Sck153898 1308a9799022Sck153898 /* true at first iteration of loop */ 1309a9799022Sck153898 if (first) { 1310a9799022Sck153898 quota = _zfs_prop_get_int(zhp, ZFS_PROP_REFQUOTA); 1311a9799022Sck153898 if (quota == 0) 1312a9799022Sck153898 quota = UINT64_MAX; 1313a9799022Sck153898 first = FALSE; 1314fa9e4066Sahrens } 1315fa9e4066Sahrens 1316a9799022Sck153898 this_quota = _zfs_prop_get_int(zhp, ZFS_PROP_QUOTA); 1317a9799022Sck153898 if (this_quota && this_quota < quota) 1318a9799022Sck153898 quota = this_quota; 1319a9799022Sck153898 1320a9799022Sck153898 /* true at last iteration of loop */ 1321a9799022Sck153898 if ((slash = strrchr(dataset, '/')) == NULL) { 1322a9799022Sck153898 uint64_t size; 1323a9799022Sck153898 1324a9799022Sck153898 size = _zfs_prop_get_int(zhp, ZFS_PROP_USED) + 1325a9799022Sck153898 _zfs_prop_get_int(zhp, ZFS_PROP_AVAILABLE); 1326a9799022Sck153898 if (size < quota) 1327a9799022Sck153898 quota = size; 1328a9799022Sck153898 } 1329a9799022Sck153898 1330a9799022Sck153898 _zfs_close(zhp); 1331a9799022Sck153898 } 1332a9799022Sck153898 13333305de37SSanjeev Bagewadi /* 13343305de37SSanjeev Bagewadi * Modify total only if we managed to get some stats from libzfs. 13353305de37SSanjeev Bagewadi */ 13363305de37SSanjeev Bagewadi if (quota != 0) 1337fa9e4066Sahrens *total = quota / blocksize; 1338fa9e4066Sahrens free(dataset); 1339fa9e4066Sahrens } 13407c478bd9Sstevel@tonic-gate 13417c478bd9Sstevel@tonic-gate /* 13427c478bd9Sstevel@tonic-gate * The output will appear properly columnized regardless of the names of 13437c478bd9Sstevel@tonic-gate * the various fields 13447c478bd9Sstevel@tonic-gate */ 13457c478bd9Sstevel@tonic-gate static void 13467c478bd9Sstevel@tonic-gate g_output(struct df_request *dfrp, struct statvfs64 *fsp) 13477c478bd9Sstevel@tonic-gate { 13487c478bd9Sstevel@tonic-gate fsblkcnt64_t available_blocks = fsp->f_bavail; 1349fa9e4066Sahrens fsblkcnt64_t total_blocks = fsp->f_blocks; 13507c478bd9Sstevel@tonic-gate numbuf_t total_blocks_buf; 13517c478bd9Sstevel@tonic-gate numbuf_t total_files_buf; 13527c478bd9Sstevel@tonic-gate numbuf_t free_blocks_buf; 13537c478bd9Sstevel@tonic-gate numbuf_t available_blocks_buf; 13547c478bd9Sstevel@tonic-gate numbuf_t free_files_buf; 13557c478bd9Sstevel@tonic-gate numbuf_t fname_buf; 13567c478bd9Sstevel@tonic-gate char *temp_buf; 13577c478bd9Sstevel@tonic-gate 13587c478bd9Sstevel@tonic-gate #define DEFINE_STR_LEN(var) \ 13597c478bd9Sstevel@tonic-gate static char *var##_str; \ 13607c478bd9Sstevel@tonic-gate static size_t var##_len 13617c478bd9Sstevel@tonic-gate 13627c478bd9Sstevel@tonic-gate #define SET_STR_LEN(name, var)\ 13637c478bd9Sstevel@tonic-gate if (! var##_str) {\ 13647c478bd9Sstevel@tonic-gate var##_str = TRANSLATE(name); \ 13657c478bd9Sstevel@tonic-gate var##_len = strlen(var##_str); \ 13667c478bd9Sstevel@tonic-gate } 13677c478bd9Sstevel@tonic-gate 13687c478bd9Sstevel@tonic-gate DEFINE_STR_LEN(block_size); 13697c478bd9Sstevel@tonic-gate DEFINE_STR_LEN(frag_size); 13707c478bd9Sstevel@tonic-gate DEFINE_STR_LEN(total_blocks); 13717c478bd9Sstevel@tonic-gate DEFINE_STR_LEN(free_blocks); 13727c478bd9Sstevel@tonic-gate DEFINE_STR_LEN(available); 13737c478bd9Sstevel@tonic-gate DEFINE_STR_LEN(total_files); 13747c478bd9Sstevel@tonic-gate DEFINE_STR_LEN(free_files); 13757c478bd9Sstevel@tonic-gate DEFINE_STR_LEN(fstype); 13767c478bd9Sstevel@tonic-gate DEFINE_STR_LEN(fsys_id); 13777c478bd9Sstevel@tonic-gate DEFINE_STR_LEN(fname); 13787c478bd9Sstevel@tonic-gate DEFINE_STR_LEN(flag); 13797c478bd9Sstevel@tonic-gate 13807c478bd9Sstevel@tonic-gate /* 13817c478bd9Sstevel@tonic-gate * TRANSLATION_NOTE 13827c478bd9Sstevel@tonic-gate * The first argument of each of the following macro invocations is a 13837c478bd9Sstevel@tonic-gate * string that needs to be translated. 13847c478bd9Sstevel@tonic-gate */ 13857c478bd9Sstevel@tonic-gate SET_STR_LEN("block size", block_size); 13867c478bd9Sstevel@tonic-gate SET_STR_LEN("frag size", frag_size); 13877c478bd9Sstevel@tonic-gate SET_STR_LEN("total blocks", total_blocks); 13887c478bd9Sstevel@tonic-gate SET_STR_LEN("free blocks", free_blocks); 13897c478bd9Sstevel@tonic-gate SET_STR_LEN("available", available); 13907c478bd9Sstevel@tonic-gate SET_STR_LEN("total files", total_files); 13917c478bd9Sstevel@tonic-gate SET_STR_LEN("free files", free_files); 13927c478bd9Sstevel@tonic-gate SET_STR_LEN("fstype", fstype); 13937c478bd9Sstevel@tonic-gate SET_STR_LEN("filesys id", fsys_id); 13947c478bd9Sstevel@tonic-gate SET_STR_LEN("filename length", fname); 13957c478bd9Sstevel@tonic-gate SET_STR_LEN("flag", flag); 13967c478bd9Sstevel@tonic-gate 13977c478bd9Sstevel@tonic-gate #define NCOL1_WIDTH (int)MAX3(BLOCK_WIDTH, NFILES_WIDTH, FSTYPE_WIDTH) 13987c478bd9Sstevel@tonic-gate #define NCOL2_WIDTH (int)MAX3(BLOCK_WIDTH, FSID_WIDTH, FLAG_WIDTH) + 2 13997c478bd9Sstevel@tonic-gate #define NCOL3_WIDTH (int)MAX3(BSIZE_WIDTH, BLOCK_WIDTH, NAMELEN_WIDTH) 14007c478bd9Sstevel@tonic-gate #define NCOL4_WIDTH (int)MAX(FRAGSIZE_WIDTH, NFILES_WIDTH) 14017c478bd9Sstevel@tonic-gate 14027c478bd9Sstevel@tonic-gate #define SCOL1_WIDTH (int)MAX3(total_blocks_len, free_files_len, fstype_len) 14037c478bd9Sstevel@tonic-gate #define SCOL2_WIDTH (int)MAX3(free_blocks_len, fsys_id_len, flag_len) 14047c478bd9Sstevel@tonic-gate #define SCOL3_WIDTH (int)MAX3(block_size_len, available_len, fname_len) 14057c478bd9Sstevel@tonic-gate #define SCOL4_WIDTH (int)MAX(frag_size_len, total_files_len) 14067c478bd9Sstevel@tonic-gate 14077c478bd9Sstevel@tonic-gate temp_buf = xmalloc( 14087c478bd9Sstevel@tonic-gate MAX(MOUNT_POINT_WIDTH, strlen(DFR_MOUNT_POINT(dfrp))) 14097c478bd9Sstevel@tonic-gate + MAX(SPECIAL_DEVICE_WIDTH, strlen(DFR_SPECIAL(dfrp))) 14107c478bd9Sstevel@tonic-gate + 20); /* plus slop - nulls & formatting */ 14117c478bd9Sstevel@tonic-gate (void) sprintf(temp_buf, "%-*s(%-*s):", 14127c478bd9Sstevel@tonic-gate MOUNT_POINT_WIDTH, DFR_MOUNT_POINT(dfrp), 14137c478bd9Sstevel@tonic-gate SPECIAL_DEVICE_WIDTH, DFR_SPECIAL(dfrp)); 14147c478bd9Sstevel@tonic-gate 14157c478bd9Sstevel@tonic-gate (void) printf("%-*s %*lu %-*s %*lu %-*s\n", 14167c478bd9Sstevel@tonic-gate NCOL1_WIDTH + 1 + SCOL1_WIDTH + 1 + NCOL2_WIDTH + 1 + SCOL2_WIDTH, 14177c478bd9Sstevel@tonic-gate temp_buf, 14187c478bd9Sstevel@tonic-gate NCOL3_WIDTH, fsp->f_bsize, SCOL3_WIDTH, block_size_str, 14197c478bd9Sstevel@tonic-gate NCOL4_WIDTH, fsp->f_frsize, SCOL4_WIDTH, frag_size_str); 14207c478bd9Sstevel@tonic-gate free(temp_buf); 14217c478bd9Sstevel@tonic-gate 14227c478bd9Sstevel@tonic-gate /* 14237c478bd9Sstevel@tonic-gate * Adjust available_blocks value - it can be less than 0 on 14247c478bd9Sstevel@tonic-gate * a 4.x file system. Reset it to 0 in order to avoid printing 14257c478bd9Sstevel@tonic-gate * negative numbers. 14267c478bd9Sstevel@tonic-gate */ 14277c478bd9Sstevel@tonic-gate if ((long long)available_blocks < (long long)0) 14287c478bd9Sstevel@tonic-gate available_blocks = (fsblkcnt64_t)0; 14297c478bd9Sstevel@tonic-gate 1430fa9e4066Sahrens adjust_total_blocks(dfrp, &total_blocks, fsp->f_frsize); 1431fa9e4066Sahrens 14327c478bd9Sstevel@tonic-gate (void) printf("%*s %-*s %*s %-*s %*s %-*s %*s %-*s\n", 14337c478bd9Sstevel@tonic-gate NCOL1_WIDTH, number_to_string(total_blocks_buf, 1434fa9e4066Sahrens total_blocks, fsp->f_frsize, 512), 14357c478bd9Sstevel@tonic-gate SCOL1_WIDTH, total_blocks_str, 14367c478bd9Sstevel@tonic-gate NCOL2_WIDTH, number_to_string(free_blocks_buf, 14377c478bd9Sstevel@tonic-gate fsp->f_bfree, fsp->f_frsize, 512), 14387c478bd9Sstevel@tonic-gate SCOL2_WIDTH, free_blocks_str, 14397c478bd9Sstevel@tonic-gate NCOL3_WIDTH, number_to_string(available_blocks_buf, 14407c478bd9Sstevel@tonic-gate available_blocks, fsp->f_frsize, 512), 14417c478bd9Sstevel@tonic-gate SCOL3_WIDTH, available_str, 14427c478bd9Sstevel@tonic-gate NCOL4_WIDTH, number_to_string(total_files_buf, 14437c478bd9Sstevel@tonic-gate fsp->f_files, 1, 1), 14447c478bd9Sstevel@tonic-gate SCOL4_WIDTH, total_files_str); 14457c478bd9Sstevel@tonic-gate 14467c478bd9Sstevel@tonic-gate (void) printf("%*s %-*s %*lu %-*s %s\n", 14477c478bd9Sstevel@tonic-gate NCOL1_WIDTH, number_to_string(free_files_buf, 14487c478bd9Sstevel@tonic-gate fsp->f_ffree, 1, 1), 14497c478bd9Sstevel@tonic-gate SCOL1_WIDTH, free_files_str, 14507c478bd9Sstevel@tonic-gate NCOL2_WIDTH, fsp->f_fsid, SCOL2_WIDTH, fsys_id_str, 14517c478bd9Sstevel@tonic-gate fsp->f_fstr); 14527c478bd9Sstevel@tonic-gate 14537c478bd9Sstevel@tonic-gate (void) printf("%*s %-*s %#*.*lx %-*s %*s %-*s\n\n", 14547c478bd9Sstevel@tonic-gate NCOL1_WIDTH, fsp->f_basetype, SCOL1_WIDTH, fstype_str, 14557c478bd9Sstevel@tonic-gate NCOL2_WIDTH, NCOL2_WIDTH-2, fsp->f_flag, SCOL2_WIDTH, flag_str, 14567c478bd9Sstevel@tonic-gate NCOL3_WIDTH, number_to_string(fname_buf, 14577c478bd9Sstevel@tonic-gate (unsigned long long)fsp->f_namemax, 1, 1), 14587c478bd9Sstevel@tonic-gate SCOL3_WIDTH, fname_str); 14597c478bd9Sstevel@tonic-gate } 14607c478bd9Sstevel@tonic-gate 14617c478bd9Sstevel@tonic-gate 14627c478bd9Sstevel@tonic-gate static void 14637c478bd9Sstevel@tonic-gate k_output(struct df_request *dfrp, struct statvfs64 *fsp) 14647c478bd9Sstevel@tonic-gate { 14657c478bd9Sstevel@tonic-gate fsblkcnt64_t total_blocks = fsp->f_blocks; 14667c478bd9Sstevel@tonic-gate fsblkcnt64_t free_blocks = fsp->f_bfree; 14677c478bd9Sstevel@tonic-gate fsblkcnt64_t available_blocks = fsp->f_bavail; 14687c478bd9Sstevel@tonic-gate fsblkcnt64_t used_blocks; 14697c478bd9Sstevel@tonic-gate char *file_system = DFR_SPECIAL(dfrp); 14707c478bd9Sstevel@tonic-gate numbuf_t total_blocks_buf; 14717c478bd9Sstevel@tonic-gate numbuf_t used_blocks_buf; 14727c478bd9Sstevel@tonic-gate numbuf_t available_blocks_buf; 14737c478bd9Sstevel@tonic-gate char capacity_buf[LINEBUF_SIZE]; 14747c478bd9Sstevel@tonic-gate 14757c478bd9Sstevel@tonic-gate /* 14767c478bd9Sstevel@tonic-gate * If the free block count is -1, don't trust anything but the total 14777c478bd9Sstevel@tonic-gate * number of blocks. 14787c478bd9Sstevel@tonic-gate */ 14797c478bd9Sstevel@tonic-gate if (free_blocks == (fsblkcnt64_t)-1) { 14807c478bd9Sstevel@tonic-gate used_blocks = (fsblkcnt64_t)-1; 14817c478bd9Sstevel@tonic-gate (void) strcpy(capacity_buf, " 100%"); 14827c478bd9Sstevel@tonic-gate } else { 14837c478bd9Sstevel@tonic-gate fsblkcnt64_t reserved_blocks = free_blocks - available_blocks; 14847c478bd9Sstevel@tonic-gate 14857c478bd9Sstevel@tonic-gate used_blocks = total_blocks - free_blocks; 14867c478bd9Sstevel@tonic-gate 14877c478bd9Sstevel@tonic-gate /* 14887c478bd9Sstevel@tonic-gate * The capacity estimation is bogus when available_blocks is 0 14897c478bd9Sstevel@tonic-gate * and the super-user has allocated more space. The reason 14907c478bd9Sstevel@tonic-gate * is that reserved_blocks is inaccurate in that case, because 14917c478bd9Sstevel@tonic-gate * when the super-user allocates space, free_blocks is updated 14927c478bd9Sstevel@tonic-gate * but available_blocks is not (since it can't drop below 0). 14937c478bd9Sstevel@tonic-gate * 14947c478bd9Sstevel@tonic-gate * XCU4 and POSIX.2 require that any fractional result of the 14957c478bd9Sstevel@tonic-gate * capacity estimation be rounded to the next highest integer, 14967c478bd9Sstevel@tonic-gate * hence the addition of 0.5. 14977c478bd9Sstevel@tonic-gate */ 14987c478bd9Sstevel@tonic-gate (void) sprintf(capacity_buf, "%5.0f%%", 14997c478bd9Sstevel@tonic-gate (total_blocks == 0) ? 0.0 : 15007c478bd9Sstevel@tonic-gate ((double)used_blocks / 15017c478bd9Sstevel@tonic-gate (double)(total_blocks - reserved_blocks)) 15027c478bd9Sstevel@tonic-gate * 100.0 + 0.5); 15037c478bd9Sstevel@tonic-gate } 15047c478bd9Sstevel@tonic-gate 15057c478bd9Sstevel@tonic-gate /* 15067c478bd9Sstevel@tonic-gate * The available_blocks can be less than 0 on a 4.x file system. 15077c478bd9Sstevel@tonic-gate * Reset it to 0 in order to avoid printing negative numbers. 15087c478bd9Sstevel@tonic-gate */ 15097c478bd9Sstevel@tonic-gate if ((long long)available_blocks < (long long)0) 15107c478bd9Sstevel@tonic-gate available_blocks = (fsblkcnt64_t)0; 15117c478bd9Sstevel@tonic-gate /* 15127c478bd9Sstevel@tonic-gate * Print long special device names (usually NFS mounts) in a line 15137c478bd9Sstevel@tonic-gate * by themselves when the output is directed to a terminal. 15147c478bd9Sstevel@tonic-gate */ 15157c478bd9Sstevel@tonic-gate if (tty_output && strlen(file_system) > (size_t)FILESYSTEM_WIDTH) { 15167c478bd9Sstevel@tonic-gate (void) printf("%s\n", file_system); 15177c478bd9Sstevel@tonic-gate file_system = ""; 15187c478bd9Sstevel@tonic-gate } 15197c478bd9Sstevel@tonic-gate 1520fa9e4066Sahrens adjust_total_blocks(dfrp, &total_blocks, fsp->f_frsize); 1521fa9e4066Sahrens 15227c478bd9Sstevel@tonic-gate if (use_scaling) { /* comes from the -h option */ 15237c478bd9Sstevel@tonic-gate (void) printf("%-*s %*s %*s %*s %-*s %-s\n", 15247c478bd9Sstevel@tonic-gate FILESYSTEM_WIDTH, file_system, 15257c478bd9Sstevel@tonic-gate SCALED_WIDTH, number_to_scaled_string(total_blocks_buf, 15267c478bd9Sstevel@tonic-gate total_blocks, fsp->f_frsize, scale), 15277c478bd9Sstevel@tonic-gate SCALED_WIDTH, number_to_scaled_string(used_blocks_buf, 15287c478bd9Sstevel@tonic-gate used_blocks, fsp->f_frsize, scale), 15297c478bd9Sstevel@tonic-gate AVAILABLE_WIDTH, number_to_scaled_string(available_blocks_buf, 15307c478bd9Sstevel@tonic-gate available_blocks, fsp->f_frsize, scale), 15317c478bd9Sstevel@tonic-gate CAPACITY_WIDTH, capacity_buf, 15327c478bd9Sstevel@tonic-gate DFR_MOUNT_POINT(dfrp)); 15337c478bd9Sstevel@tonic-gate return; 15347c478bd9Sstevel@tonic-gate } 15357c478bd9Sstevel@tonic-gate 15367c478bd9Sstevel@tonic-gate if (v_option) { 15377c478bd9Sstevel@tonic-gate (void) printf("%-*.*s %-*.*s %*lld %*lld %*lld %-.*s\n", 15387c478bd9Sstevel@tonic-gate IBCS2_MOUNT_POINT_WIDTH, IBCS2_MOUNT_POINT_WIDTH, 15397c478bd9Sstevel@tonic-gate DFR_MOUNT_POINT(dfrp), 15407c478bd9Sstevel@tonic-gate IBCS2_FILESYSTEM_WIDTH, IBCS2_FILESYSTEM_WIDTH, file_system, 15417c478bd9Sstevel@tonic-gate BLOCK_WIDTH, total_blocks, 15427c478bd9Sstevel@tonic-gate BLOCK_WIDTH, used_blocks, 15437c478bd9Sstevel@tonic-gate BLOCK_WIDTH, available_blocks, 15447c478bd9Sstevel@tonic-gate CAPACITY_WIDTH, capacity_buf); 15457c478bd9Sstevel@tonic-gate return; 15467c478bd9Sstevel@tonic-gate } 15477c478bd9Sstevel@tonic-gate 1548*790c646cSPaul B. Henson if (P_option && !k_option && !m_option) { 15497c478bd9Sstevel@tonic-gate (void) printf("%-*s %*s %*s %*s %-*s %-s\n", 15507c478bd9Sstevel@tonic-gate FILESYSTEM_WIDTH, file_system, 15517c478bd9Sstevel@tonic-gate KBYTE_WIDTH, number_to_string(total_blocks_buf, 15527c478bd9Sstevel@tonic-gate total_blocks, fsp->f_frsize, 512), 15537c478bd9Sstevel@tonic-gate KBYTE_WIDTH, number_to_string(used_blocks_buf, 15547c478bd9Sstevel@tonic-gate used_blocks, fsp->f_frsize, 512), 15557c478bd9Sstevel@tonic-gate KBYTE_WIDTH, number_to_string(available_blocks_buf, 15567c478bd9Sstevel@tonic-gate available_blocks, fsp->f_frsize, 512), 15577c478bd9Sstevel@tonic-gate CAPACITY_WIDTH, capacity_buf, 15587c478bd9Sstevel@tonic-gate DFR_MOUNT_POINT(dfrp)); 1559*790c646cSPaul B. Henson } else if (m_option) { 1560*790c646cSPaul B. Henson (void) printf("%-*s %*s %*s %*s %-*s %-s\n", 1561*790c646cSPaul B. Henson FILESYSTEM_WIDTH, file_system, 1562*790c646cSPaul B. Henson KBYTE_WIDTH, number_to_string(total_blocks_buf, 1563*790c646cSPaul B. Henson total_blocks, fsp->f_frsize, 1024*1024), 1564*790c646cSPaul B. Henson KBYTE_WIDTH, number_to_string(used_blocks_buf, 1565*790c646cSPaul B. Henson used_blocks, fsp->f_frsize, 1024*1024), 1566*790c646cSPaul B. Henson KBYTE_WIDTH, number_to_string(available_blocks_buf, 1567*790c646cSPaul B. Henson available_blocks, fsp->f_frsize, 1024*1024), 1568*790c646cSPaul B. Henson CAPACITY_WIDTH, capacity_buf, 1569*790c646cSPaul B. Henson DFR_MOUNT_POINT(dfrp)); 15707c478bd9Sstevel@tonic-gate } else { 15717c478bd9Sstevel@tonic-gate (void) printf("%-*s %*s %*s %*s %-*s %-s\n", 15727c478bd9Sstevel@tonic-gate FILESYSTEM_WIDTH, file_system, 15737c478bd9Sstevel@tonic-gate KBYTE_WIDTH, number_to_string(total_blocks_buf, 15747c478bd9Sstevel@tonic-gate total_blocks, fsp->f_frsize, 1024), 15757c478bd9Sstevel@tonic-gate KBYTE_WIDTH, number_to_string(used_blocks_buf, 15767c478bd9Sstevel@tonic-gate used_blocks, fsp->f_frsize, 1024), 15777c478bd9Sstevel@tonic-gate KBYTE_WIDTH, number_to_string(available_blocks_buf, 15787c478bd9Sstevel@tonic-gate available_blocks, fsp->f_frsize, 1024), 15797c478bd9Sstevel@tonic-gate CAPACITY_WIDTH, capacity_buf, 15807c478bd9Sstevel@tonic-gate DFR_MOUNT_POINT(dfrp)); 15817c478bd9Sstevel@tonic-gate } 15827c478bd9Sstevel@tonic-gate } 15837c478bd9Sstevel@tonic-gate 15847c478bd9Sstevel@tonic-gate /* 15857c478bd9Sstevel@tonic-gate * The following is for internationalization support. 15867c478bd9Sstevel@tonic-gate */ 15877c478bd9Sstevel@tonic-gate static bool_int strings_initialized; 15887c478bd9Sstevel@tonic-gate static char *files_str; 15897c478bd9Sstevel@tonic-gate static char *blocks_str; 15907c478bd9Sstevel@tonic-gate static char *total_str; 15917c478bd9Sstevel@tonic-gate static char *kilobytes_str; 15927c478bd9Sstevel@tonic-gate 15937c478bd9Sstevel@tonic-gate static void 159408190127Sdh145677 strings_init(void) 15957c478bd9Sstevel@tonic-gate { 15967c478bd9Sstevel@tonic-gate total_str = TRANSLATE("total"); 15977c478bd9Sstevel@tonic-gate files_str = TRANSLATE("files"); 15987c478bd9Sstevel@tonic-gate blocks_str = TRANSLATE("blocks"); 15997c478bd9Sstevel@tonic-gate kilobytes_str = TRANSLATE("kilobytes"); 16007c478bd9Sstevel@tonic-gate strings_initialized = TRUE; 16017c478bd9Sstevel@tonic-gate } 16027c478bd9Sstevel@tonic-gate 16037c478bd9Sstevel@tonic-gate #define STRINGS_INIT() if (!strings_initialized) strings_init() 16047c478bd9Sstevel@tonic-gate 16057c478bd9Sstevel@tonic-gate 16067c478bd9Sstevel@tonic-gate static void 16077c478bd9Sstevel@tonic-gate t_output(struct df_request *dfrp, struct statvfs64 *fsp) 16087c478bd9Sstevel@tonic-gate { 1609fa9e4066Sahrens fsblkcnt64_t total_blocks = fsp->f_blocks; 16107c478bd9Sstevel@tonic-gate numbuf_t total_blocks_buf; 16117c478bd9Sstevel@tonic-gate numbuf_t total_files_buf; 16127c478bd9Sstevel@tonic-gate numbuf_t free_blocks_buf; 16137c478bd9Sstevel@tonic-gate numbuf_t free_files_buf; 16147c478bd9Sstevel@tonic-gate 16157c478bd9Sstevel@tonic-gate STRINGS_INIT(); 16167c478bd9Sstevel@tonic-gate 1617fa9e4066Sahrens adjust_total_blocks(dfrp, &total_blocks, fsp->f_frsize); 1618fa9e4066Sahrens 16197c478bd9Sstevel@tonic-gate (void) printf("%-*s(%-*s): %*s %s %*s %s\n", 16207c478bd9Sstevel@tonic-gate MOUNT_POINT_WIDTH, DFR_MOUNT_POINT(dfrp), 16217c478bd9Sstevel@tonic-gate SPECIAL_DEVICE_WIDTH, DFR_SPECIAL(dfrp), 16227c478bd9Sstevel@tonic-gate BLOCK_WIDTH, number_to_string(free_blocks_buf, 16237c478bd9Sstevel@tonic-gate fsp->f_bfree, fsp->f_frsize, 512), 16247c478bd9Sstevel@tonic-gate blocks_str, 16257c478bd9Sstevel@tonic-gate NFILES_WIDTH, number_to_string(free_files_buf, 16267c478bd9Sstevel@tonic-gate fsp->f_ffree, 1, 1), 16277c478bd9Sstevel@tonic-gate files_str); 16287c478bd9Sstevel@tonic-gate /* 16297c478bd9Sstevel@tonic-gate * The total column used to use the same space as the mnt pt & special 16307c478bd9Sstevel@tonic-gate * dev fields. However, this doesn't work with massive special dev 16317c478bd9Sstevel@tonic-gate * fields * (eg > 500 chars) causing an enormous amount of white space 16327c478bd9Sstevel@tonic-gate * before the total column (see bug 4100411). So the code was 16337c478bd9Sstevel@tonic-gate * simplified to set the total column at the usual gap. 16347c478bd9Sstevel@tonic-gate * This had the side effect of fixing a bug where the previously 16357c478bd9Sstevel@tonic-gate * used static buffer was overflowed by the same massive special dev. 16367c478bd9Sstevel@tonic-gate */ 16377c478bd9Sstevel@tonic-gate (void) printf("%*s: %*s %s %*s %s\n", 16387c478bd9Sstevel@tonic-gate MNT_SPEC_WIDTH, total_str, 16397c478bd9Sstevel@tonic-gate BLOCK_WIDTH, number_to_string(total_blocks_buf, 1640fa9e4066Sahrens total_blocks, fsp->f_frsize, 512), 16417c478bd9Sstevel@tonic-gate blocks_str, 16427c478bd9Sstevel@tonic-gate NFILES_WIDTH, number_to_string(total_files_buf, 16437c478bd9Sstevel@tonic-gate fsp->f_files, 1, 1), 16447c478bd9Sstevel@tonic-gate files_str); 16457c478bd9Sstevel@tonic-gate } 16467c478bd9Sstevel@tonic-gate 16477c478bd9Sstevel@tonic-gate 16487c478bd9Sstevel@tonic-gate static void 16497c478bd9Sstevel@tonic-gate eb_output(struct df_request *dfrp, struct statvfs64 *fsp) 16507c478bd9Sstevel@tonic-gate { 16517c478bd9Sstevel@tonic-gate numbuf_t free_files_buf; 16527c478bd9Sstevel@tonic-gate numbuf_t free_kbytes_buf; 16537c478bd9Sstevel@tonic-gate 16547c478bd9Sstevel@tonic-gate STRINGS_INIT(); 16557c478bd9Sstevel@tonic-gate 16567c478bd9Sstevel@tonic-gate (void) printf("%-*s(%-*s): %*s %s\n", 16577c478bd9Sstevel@tonic-gate MOUNT_POINT_WIDTH, DFR_MOUNT_POINT(dfrp), 16587c478bd9Sstevel@tonic-gate SPECIAL_DEVICE_WIDTH, DFR_SPECIAL(dfrp), 16597c478bd9Sstevel@tonic-gate MAX(KBYTE_WIDTH, NFILES_WIDTH), 16607c478bd9Sstevel@tonic-gate number_to_string(free_kbytes_buf, 16617c478bd9Sstevel@tonic-gate fsp->f_bfree, fsp->f_frsize, 1024), 16627c478bd9Sstevel@tonic-gate kilobytes_str); 16637c478bd9Sstevel@tonic-gate (void) printf("%-*s(%-*s): %*s %s\n", 16647c478bd9Sstevel@tonic-gate MOUNT_POINT_WIDTH, DFR_MOUNT_POINT(dfrp), 16657c478bd9Sstevel@tonic-gate SPECIAL_DEVICE_WIDTH, DFR_SPECIAL(dfrp), 16667c478bd9Sstevel@tonic-gate MAX(NFILES_WIDTH, NFILES_WIDTH), 16677c478bd9Sstevel@tonic-gate number_to_string(free_files_buf, fsp->f_ffree, 1, 1), 16687c478bd9Sstevel@tonic-gate files_str); 16697c478bd9Sstevel@tonic-gate } 16707c478bd9Sstevel@tonic-gate 16717c478bd9Sstevel@tonic-gate 16727c478bd9Sstevel@tonic-gate static void 16737c478bd9Sstevel@tonic-gate e_output(struct df_request *dfrp, struct statvfs64 *fsp) 16747c478bd9Sstevel@tonic-gate { 16757c478bd9Sstevel@tonic-gate numbuf_t free_files_buf; 16767c478bd9Sstevel@tonic-gate 16777c478bd9Sstevel@tonic-gate (void) printf("%-*s %*s\n", 16787c478bd9Sstevel@tonic-gate FILESYSTEM_WIDTH, DFR_SPECIAL(dfrp), 16797c478bd9Sstevel@tonic-gate NFILES_WIDTH, 16807c478bd9Sstevel@tonic-gate number_to_string(free_files_buf, fsp->f_ffree, 1, 1)); 16817c478bd9Sstevel@tonic-gate } 16827c478bd9Sstevel@tonic-gate 16837c478bd9Sstevel@tonic-gate 16847c478bd9Sstevel@tonic-gate static void 16857c478bd9Sstevel@tonic-gate b_output(struct df_request *dfrp, struct statvfs64 *fsp) 16867c478bd9Sstevel@tonic-gate { 16877c478bd9Sstevel@tonic-gate numbuf_t free_blocks_buf; 16887c478bd9Sstevel@tonic-gate 16897c478bd9Sstevel@tonic-gate (void) printf("%-*s %*s\n", 16907c478bd9Sstevel@tonic-gate FILESYSTEM_WIDTH, DFR_SPECIAL(dfrp), 16917c478bd9Sstevel@tonic-gate BLOCK_WIDTH, number_to_string(free_blocks_buf, 16927c478bd9Sstevel@tonic-gate fsp->f_bfree, fsp->f_frsize, 1024)); 16937c478bd9Sstevel@tonic-gate } 16947c478bd9Sstevel@tonic-gate 16957c478bd9Sstevel@tonic-gate 16967c478bd9Sstevel@tonic-gate /* ARGSUSED */ 16977c478bd9Sstevel@tonic-gate static void 16987c478bd9Sstevel@tonic-gate n_output(struct df_request *dfrp, struct statvfs64 *fsp) 16997c478bd9Sstevel@tonic-gate { 17007c478bd9Sstevel@tonic-gate (void) printf("%-*s: %-*s\n", 17017c478bd9Sstevel@tonic-gate MOUNT_POINT_WIDTH, DFR_MOUNT_POINT(dfrp), 17027c478bd9Sstevel@tonic-gate FSTYPE_WIDTH, dfrp->dfr_fstype); 17037c478bd9Sstevel@tonic-gate } 17047c478bd9Sstevel@tonic-gate 17057c478bd9Sstevel@tonic-gate 17067c478bd9Sstevel@tonic-gate static void 17077c478bd9Sstevel@tonic-gate default_output(struct df_request *dfrp, struct statvfs64 *fsp) 17087c478bd9Sstevel@tonic-gate { 17097c478bd9Sstevel@tonic-gate numbuf_t free_blocks_buf; 17107c478bd9Sstevel@tonic-gate numbuf_t free_files_buf; 17117c478bd9Sstevel@tonic-gate 17127c478bd9Sstevel@tonic-gate STRINGS_INIT(); 17137c478bd9Sstevel@tonic-gate 17147c478bd9Sstevel@tonic-gate (void) printf("%-*s(%-*s):%*s %s %*s %s\n", 17157c478bd9Sstevel@tonic-gate MOUNT_POINT_WIDTH, DFR_MOUNT_POINT(dfrp), 17167c478bd9Sstevel@tonic-gate SPECIAL_DEVICE_WIDTH, DFR_SPECIAL(dfrp), 17177c478bd9Sstevel@tonic-gate BLOCK_WIDTH, number_to_string(free_blocks_buf, 17187c478bd9Sstevel@tonic-gate fsp->f_bfree, fsp->f_frsize, 512), 17197c478bd9Sstevel@tonic-gate blocks_str, 17207c478bd9Sstevel@tonic-gate NFILES_WIDTH, number_to_string(free_files_buf, 17217c478bd9Sstevel@tonic-gate fsp->f_ffree, 1, 1), 17227c478bd9Sstevel@tonic-gate files_str); 17237c478bd9Sstevel@tonic-gate } 17247c478bd9Sstevel@tonic-gate 17257c478bd9Sstevel@tonic-gate 17267c478bd9Sstevel@tonic-gate /* ARGSUSED */ 17277c478bd9Sstevel@tonic-gate static void 17287c478bd9Sstevel@tonic-gate V_output(struct df_request *dfrp, struct statvfs64 *fsp) 17297c478bd9Sstevel@tonic-gate { 17307c478bd9Sstevel@tonic-gate char temp_buf[LINEBUF_SIZE]; 17317c478bd9Sstevel@tonic-gate 17327c478bd9Sstevel@tonic-gate if (df_options_len > 1) 17337c478bd9Sstevel@tonic-gate (void) strcat(strcpy(temp_buf, df_options), " "); 17347c478bd9Sstevel@tonic-gate else 17357c478bd9Sstevel@tonic-gate temp_buf[0] = NUL; 17367c478bd9Sstevel@tonic-gate 17377c478bd9Sstevel@tonic-gate (void) printf("%s -F %s %s%s\n", 17387c478bd9Sstevel@tonic-gate program_name, dfrp->dfr_fstype, temp_buf, 17397c478bd9Sstevel@tonic-gate dfrp->dfr_cmd_arg ? dfrp->dfr_cmd_arg: DFR_SPECIAL(dfrp)); 17407c478bd9Sstevel@tonic-gate } 17417c478bd9Sstevel@tonic-gate 17427c478bd9Sstevel@tonic-gate 17437c478bd9Sstevel@tonic-gate /* 17447c478bd9Sstevel@tonic-gate * This function is used to sort the array of df_requests according to fstype 17457c478bd9Sstevel@tonic-gate */ 17467c478bd9Sstevel@tonic-gate static int 17477c478bd9Sstevel@tonic-gate df_reqcomp(const void *p1, const void *p2) 17487c478bd9Sstevel@tonic-gate { 17497c478bd9Sstevel@tonic-gate int v = strcmp(DFRP(p1)->dfr_fstype, DFRP(p2)->dfr_fstype); 17507c478bd9Sstevel@tonic-gate 17517c478bd9Sstevel@tonic-gate if (v != 0) 17527c478bd9Sstevel@tonic-gate return (v); 17537c478bd9Sstevel@tonic-gate else 17547c478bd9Sstevel@tonic-gate return (DFRP(p1)->dfr_index - DFRP(p2)->dfr_index); 17557c478bd9Sstevel@tonic-gate } 17567c478bd9Sstevel@tonic-gate 17577c478bd9Sstevel@tonic-gate 17587c478bd9Sstevel@tonic-gate static void 17597c478bd9Sstevel@tonic-gate vfs_error(char *file, int status) 17607c478bd9Sstevel@tonic-gate { 17617c478bd9Sstevel@tonic-gate if (status == VFS_TOOLONG) 17627c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, "a line in %s exceeds %d characters", 17637c478bd9Sstevel@tonic-gate file, MNT_LINE_MAX); 17647c478bd9Sstevel@tonic-gate else if (status == VFS_TOOMANY) 17657c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, "a line in %s has too many fields", file); 17667c478bd9Sstevel@tonic-gate else if (status == VFS_TOOFEW) 17677c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, "a line in %s has too few fields", file); 17687c478bd9Sstevel@tonic-gate else 17697c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, "error while reading %s: %d", file, status); 17707c478bd9Sstevel@tonic-gate } 17717c478bd9Sstevel@tonic-gate 17727c478bd9Sstevel@tonic-gate 17737c478bd9Sstevel@tonic-gate /* 17747c478bd9Sstevel@tonic-gate * Try to determine the fstype for the specified block device. 17757c478bd9Sstevel@tonic-gate * Return in order of decreasing preference: 17767c478bd9Sstevel@tonic-gate * file system type from vfstab 17777c478bd9Sstevel@tonic-gate * file system type as specified by -F option 17787c478bd9Sstevel@tonic-gate * default file system type 17797c478bd9Sstevel@tonic-gate */ 17807c478bd9Sstevel@tonic-gate static char * 17817c478bd9Sstevel@tonic-gate find_fstype(char *special) 17827c478bd9Sstevel@tonic-gate { 17837c478bd9Sstevel@tonic-gate struct vfstab vtab; 17847c478bd9Sstevel@tonic-gate FILE *fp; 17857c478bd9Sstevel@tonic-gate int status; 17867c478bd9Sstevel@tonic-gate char *vfstab_file = VFS_TAB; 17877c478bd9Sstevel@tonic-gate 17887c478bd9Sstevel@tonic-gate fp = xfopen(vfstab_file); 17897c478bd9Sstevel@tonic-gate status = getvfsspec(fp, &vtab, special); 17907c478bd9Sstevel@tonic-gate (void) fclose(fp); 17917c478bd9Sstevel@tonic-gate if (status > 0) 17927c478bd9Sstevel@tonic-gate vfs_error(vfstab_file, status); 17937c478bd9Sstevel@tonic-gate 17947c478bd9Sstevel@tonic-gate if (status == 0) { 17957c478bd9Sstevel@tonic-gate if (F_option && ! EQ(FSType, vtab.vfs_fstype)) 17967c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, 17977c478bd9Sstevel@tonic-gate "warning: %s is of type %s", special, vtab.vfs_fstype); 17987c478bd9Sstevel@tonic-gate return (new_string(vtab.vfs_fstype)); 17997c478bd9Sstevel@tonic-gate } 18007c478bd9Sstevel@tonic-gate else 18017c478bd9Sstevel@tonic-gate return (F_option ? FSType : default_fstype(special)); 18027c478bd9Sstevel@tonic-gate } 18037c478bd9Sstevel@tonic-gate 18047c478bd9Sstevel@tonic-gate /* 18057c478bd9Sstevel@tonic-gate * When this function returns, the following fields are filled for all 18067c478bd9Sstevel@tonic-gate * valid entries in the requests[] array: 18077c478bd9Sstevel@tonic-gate * dfr_mte (if the file system is mounted) 18087c478bd9Sstevel@tonic-gate * dfr_fstype 18097c478bd9Sstevel@tonic-gate * dfr_index 18107c478bd9Sstevel@tonic-gate * 18117c478bd9Sstevel@tonic-gate * The function returns the number of errors that occurred while building 18127c478bd9Sstevel@tonic-gate * the request list. 18137c478bd9Sstevel@tonic-gate */ 18147c478bd9Sstevel@tonic-gate static int 18157c478bd9Sstevel@tonic-gate create_request_list( 18167c478bd9Sstevel@tonic-gate int argc, 18177c478bd9Sstevel@tonic-gate char *argv[], 18187c478bd9Sstevel@tonic-gate struct df_request *requests_p[], 18197c478bd9Sstevel@tonic-gate size_t *request_count) 18207c478bd9Sstevel@tonic-gate { 18217c478bd9Sstevel@tonic-gate struct df_request *requests; 18227c478bd9Sstevel@tonic-gate struct df_request *dfrp; 18237c478bd9Sstevel@tonic-gate size_t size; 18247c478bd9Sstevel@tonic-gate size_t i; 18257c478bd9Sstevel@tonic-gate size_t request_index = 0; 18267c478bd9Sstevel@tonic-gate size_t max_requests; 18277c478bd9Sstevel@tonic-gate int errors = 0; 18287c478bd9Sstevel@tonic-gate 18297c478bd9Sstevel@tonic-gate /* 18307c478bd9Sstevel@tonic-gate * If no args, use the mounted file systems, otherwise use the 18317c478bd9Sstevel@tonic-gate * user-specified arguments. 18327c478bd9Sstevel@tonic-gate */ 18337c478bd9Sstevel@tonic-gate if (argc == 0) { 18347c478bd9Sstevel@tonic-gate mtab_read_file(); 18357c478bd9Sstevel@tonic-gate max_requests = mount_table_entries; 18367c478bd9Sstevel@tonic-gate } else 18377c478bd9Sstevel@tonic-gate max_requests = argc; 18387c478bd9Sstevel@tonic-gate 18397c478bd9Sstevel@tonic-gate size = max_requests * sizeof (struct df_request); 18407c478bd9Sstevel@tonic-gate requests = xmalloc(size); 18417c478bd9Sstevel@tonic-gate (void) memset(requests, 0, size); 18427c478bd9Sstevel@tonic-gate 18437c478bd9Sstevel@tonic-gate if (argc == 0) { 18447c478bd9Sstevel@tonic-gate /* 18457c478bd9Sstevel@tonic-gate * If -Z wasn't specified, we skip mounts in other 18467c478bd9Sstevel@tonic-gate * zones. This obviously is a noop in a non-global 18477c478bd9Sstevel@tonic-gate * zone. 18487c478bd9Sstevel@tonic-gate */ 18497c478bd9Sstevel@tonic-gate boolean_t showall = (getzoneid() != GLOBAL_ZONEID) || Z_option; 18507c478bd9Sstevel@tonic-gate struct zone_summary *zsp; 18517c478bd9Sstevel@tonic-gate 18527c478bd9Sstevel@tonic-gate if (!showall) { 18537c478bd9Sstevel@tonic-gate zsp = fs_get_zone_summaries(); 18547c478bd9Sstevel@tonic-gate if (zsp == NULL) 18557c478bd9Sstevel@tonic-gate errmsg(ERR_FATAL, 18567c478bd9Sstevel@tonic-gate "unable to retrieve list of zones"); 18577c478bd9Sstevel@tonic-gate } 18587c478bd9Sstevel@tonic-gate 18597c478bd9Sstevel@tonic-gate for (i = 0; i < mount_table_entries; i++) { 18607c478bd9Sstevel@tonic-gate struct extmnttab *mtp = mount_table[i].mte_mount; 18617c478bd9Sstevel@tonic-gate 18627c478bd9Sstevel@tonic-gate if (EQ(mtp->mnt_fstype, MNTTYPE_SWAP)) 18637c478bd9Sstevel@tonic-gate continue; 18647c478bd9Sstevel@tonic-gate 18657c478bd9Sstevel@tonic-gate if (!showall) { 18667c478bd9Sstevel@tonic-gate if (fs_mount_in_other_zone(zsp, 18677c478bd9Sstevel@tonic-gate mtp->mnt_mountp)) 18687c478bd9Sstevel@tonic-gate continue; 18697c478bd9Sstevel@tonic-gate } 18707c478bd9Sstevel@tonic-gate dfrp = &requests[request_index++]; 18717c478bd9Sstevel@tonic-gate dfrp->dfr_mte = &mount_table[i]; 18727c478bd9Sstevel@tonic-gate dfrp->dfr_fstype = mtp->mnt_fstype; 18737c478bd9Sstevel@tonic-gate dfrp->dfr_index = i; 18747c478bd9Sstevel@tonic-gate dfrp->dfr_valid = TRUE; 18757c478bd9Sstevel@tonic-gate } 18767c478bd9Sstevel@tonic-gate } else { 18777c478bd9Sstevel@tonic-gate struct stat64 *arg_stat; /* array of stat structures */ 18787c478bd9Sstevel@tonic-gate bool_int *valid_stat; /* which structures are valid */ 18797c478bd9Sstevel@tonic-gate 18807c478bd9Sstevel@tonic-gate arg_stat = xmalloc(argc * sizeof (struct stat64)); 18817c478bd9Sstevel@tonic-gate valid_stat = xmalloc(argc * sizeof (bool_int)); 18827c478bd9Sstevel@tonic-gate 18837c478bd9Sstevel@tonic-gate /* 18847c478bd9Sstevel@tonic-gate * Obtain stat64 information for each argument before 18857c478bd9Sstevel@tonic-gate * constructing the list of mounted file systems. By 18867c478bd9Sstevel@tonic-gate * touching all these places we force the automounter 18877c478bd9Sstevel@tonic-gate * to establish any mounts required to access the arguments, 18887c478bd9Sstevel@tonic-gate * so that the corresponding mount table entries will exist 18897c478bd9Sstevel@tonic-gate * when we look for them. 18907c478bd9Sstevel@tonic-gate * It is still possible that the automounter may timeout 18917c478bd9Sstevel@tonic-gate * mounts between the time we read the mount table and the 18927c478bd9Sstevel@tonic-gate * time we process the request. Even in that case, when 18937c478bd9Sstevel@tonic-gate * we issue the statvfs64(2) for the mount point, the file 18947c478bd9Sstevel@tonic-gate * system will be mounted again. The only problem will 18957c478bd9Sstevel@tonic-gate * occur if the automounter maps change in the meantime 18967c478bd9Sstevel@tonic-gate * and the mount point is eliminated. 18977c478bd9Sstevel@tonic-gate */ 18987c478bd9Sstevel@tonic-gate for (i = 0; i < argc; i++) 18997c478bd9Sstevel@tonic-gate valid_stat[i] = (stat64(argv[i], &arg_stat[i]) == 0); 19007c478bd9Sstevel@tonic-gate 19017c478bd9Sstevel@tonic-gate mtab_read_file(); 19027c478bd9Sstevel@tonic-gate 19037c478bd9Sstevel@tonic-gate for (i = 0; i < argc; i++) { 19047c478bd9Sstevel@tonic-gate char *arg = argv[i]; 19057c478bd9Sstevel@tonic-gate 19067c478bd9Sstevel@tonic-gate dfrp = &requests[request_index]; 19077c478bd9Sstevel@tonic-gate 19087c478bd9Sstevel@tonic-gate dfrp->dfr_index = request_index; 19097c478bd9Sstevel@tonic-gate dfrp->dfr_cmd_arg = arg; 19107c478bd9Sstevel@tonic-gate 19117c478bd9Sstevel@tonic-gate if (valid_stat[i]) { 1912738059c5SJim Rice dfrp->dfr_fstype = arg_stat[i].st_fstype; 19137c478bd9Sstevel@tonic-gate if (S_ISBLK(arg_stat[i].st_mode)) { 19147c478bd9Sstevel@tonic-gate bdev_mount_entry(dfrp); 19157c478bd9Sstevel@tonic-gate dfrp->dfr_valid = TRUE; 19167c478bd9Sstevel@tonic-gate } else if (S_ISDIR(arg_stat[i].st_mode) || 19177c478bd9Sstevel@tonic-gate S_ISREG(arg_stat[i].st_mode) || 19187c478bd9Sstevel@tonic-gate S_ISFIFO(arg_stat[i].st_mode)) { 19197c478bd9Sstevel@tonic-gate path_mount_entry(dfrp, 19207c478bd9Sstevel@tonic-gate arg_stat[i].st_dev); 19217c478bd9Sstevel@tonic-gate if (! DFR_ISMOUNTEDFS(dfrp)) { 19227c478bd9Sstevel@tonic-gate errors++; 19237c478bd9Sstevel@tonic-gate continue; 19247c478bd9Sstevel@tonic-gate } 19257c478bd9Sstevel@tonic-gate dfrp->dfr_valid = TRUE; 19267c478bd9Sstevel@tonic-gate } 19277c478bd9Sstevel@tonic-gate } else { 19287c478bd9Sstevel@tonic-gate resource_mount_entry(dfrp); 19297c478bd9Sstevel@tonic-gate dfrp->dfr_valid = DFR_ISMOUNTEDFS(dfrp); 19307c478bd9Sstevel@tonic-gate } 19317c478bd9Sstevel@tonic-gate 19327c478bd9Sstevel@tonic-gate /* 19337c478bd9Sstevel@tonic-gate * If we haven't managed to verify that the request 19347c478bd9Sstevel@tonic-gate * is valid, we must have gotten a bad argument. 19357c478bd9Sstevel@tonic-gate */ 19367c478bd9Sstevel@tonic-gate if (!dfrp->dfr_valid) { 19377c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, 1938990b4856Slling "(%-10s) not a block device, directory or " 1939990b4856Slling "mounted resource", arg); 19407c478bd9Sstevel@tonic-gate errors++; 19417c478bd9Sstevel@tonic-gate continue; 19427c478bd9Sstevel@tonic-gate } 19437c478bd9Sstevel@tonic-gate 19447c478bd9Sstevel@tonic-gate /* 19457c478bd9Sstevel@tonic-gate * Determine the file system type. 19467c478bd9Sstevel@tonic-gate */ 19477c478bd9Sstevel@tonic-gate if (DFR_ISMOUNTEDFS(dfrp)) 19487c478bd9Sstevel@tonic-gate dfrp->dfr_fstype = 19497c478bd9Sstevel@tonic-gate dfrp->dfr_mte->mte_mount->mnt_fstype; 19507c478bd9Sstevel@tonic-gate else 19517c478bd9Sstevel@tonic-gate dfrp->dfr_fstype = 19527c478bd9Sstevel@tonic-gate find_fstype(dfrp->dfr_cmd_arg); 19537c478bd9Sstevel@tonic-gate 19547c478bd9Sstevel@tonic-gate request_index++; 19557c478bd9Sstevel@tonic-gate } 19567c478bd9Sstevel@tonic-gate } 19577c478bd9Sstevel@tonic-gate *requests_p = requests; 19587c478bd9Sstevel@tonic-gate *request_count = request_index; 19597c478bd9Sstevel@tonic-gate return (errors); 19607c478bd9Sstevel@tonic-gate } 19617c478bd9Sstevel@tonic-gate 19627c478bd9Sstevel@tonic-gate 19637c478bd9Sstevel@tonic-gate /* 19647c478bd9Sstevel@tonic-gate * Select the appropriate function and flags to use for output. 19657c478bd9Sstevel@tonic-gate * Notice that using both -e and -b options produces a different form of 19667c478bd9Sstevel@tonic-gate * output than either of those two options alone; this is the behavior of 19677c478bd9Sstevel@tonic-gate * the SVR4 df. 19687c478bd9Sstevel@tonic-gate */ 19697c478bd9Sstevel@tonic-gate static struct df_output * 197008190127Sdh145677 select_output(void) 19717c478bd9Sstevel@tonic-gate { 19727c478bd9Sstevel@tonic-gate static struct df_output dfo; 19737c478bd9Sstevel@tonic-gate 19747c478bd9Sstevel@tonic-gate /* 19757c478bd9Sstevel@tonic-gate * The order of checking options follows the option precedence 19767c478bd9Sstevel@tonic-gate * rules as they are listed in the man page. 19777c478bd9Sstevel@tonic-gate */ 19787c478bd9Sstevel@tonic-gate if (use_scaling) { /* comes from the -h option */ 19797c478bd9Sstevel@tonic-gate dfo.dfo_func = k_output; 19807c478bd9Sstevel@tonic-gate dfo.dfo_flags = DFO_HEADER + DFO_STATVFS; 19817c478bd9Sstevel@tonic-gate } else if (V_option) { 19827c478bd9Sstevel@tonic-gate dfo.dfo_func = V_output; 19837c478bd9Sstevel@tonic-gate dfo.dfo_flags = DFO_NOFLAGS; 19847c478bd9Sstevel@tonic-gate } else if (g_option) { 19857c478bd9Sstevel@tonic-gate dfo.dfo_func = g_output; 19867c478bd9Sstevel@tonic-gate dfo.dfo_flags = DFO_STATVFS; 1987*790c646cSPaul B. Henson } else if (k_option || m_option || P_option || v_option) { 19887c478bd9Sstevel@tonic-gate dfo.dfo_func = k_output; 19897c478bd9Sstevel@tonic-gate dfo.dfo_flags = DFO_HEADER + DFO_STATVFS; 19907c478bd9Sstevel@tonic-gate } else if (t_option) { 19917c478bd9Sstevel@tonic-gate dfo.dfo_func = t_output; 19927c478bd9Sstevel@tonic-gate dfo.dfo_flags = DFO_STATVFS; 19937c478bd9Sstevel@tonic-gate } else if (b_option && e_option) { 19947c478bd9Sstevel@tonic-gate dfo.dfo_func = eb_output; 19957c478bd9Sstevel@tonic-gate dfo.dfo_flags = DFO_STATVFS; 19967c478bd9Sstevel@tonic-gate } else if (b_option) { 19977c478bd9Sstevel@tonic-gate dfo.dfo_func = b_output; 19987c478bd9Sstevel@tonic-gate dfo.dfo_flags = DFO_HEADER + DFO_STATVFS; 19997c478bd9Sstevel@tonic-gate } else if (e_option) { 20007c478bd9Sstevel@tonic-gate dfo.dfo_func = e_output; 20017c478bd9Sstevel@tonic-gate dfo.dfo_flags = DFO_HEADER + DFO_STATVFS; 20027c478bd9Sstevel@tonic-gate } else if (n_option) { 20037c478bd9Sstevel@tonic-gate dfo.dfo_func = n_output; 20047c478bd9Sstevel@tonic-gate dfo.dfo_flags = DFO_NOFLAGS; 20057c478bd9Sstevel@tonic-gate } else { 20067c478bd9Sstevel@tonic-gate dfo.dfo_func = default_output; 20077c478bd9Sstevel@tonic-gate dfo.dfo_flags = DFO_STATVFS; 20087c478bd9Sstevel@tonic-gate } 20097c478bd9Sstevel@tonic-gate return (&dfo); 20107c478bd9Sstevel@tonic-gate } 20117c478bd9Sstevel@tonic-gate 20127c478bd9Sstevel@tonic-gate 20137c478bd9Sstevel@tonic-gate /* 20147c478bd9Sstevel@tonic-gate * The (argc,argv) pair contains all the non-option arguments 20157c478bd9Sstevel@tonic-gate */ 20167c478bd9Sstevel@tonic-gate static void 20177c478bd9Sstevel@tonic-gate do_df(int argc, char *argv[]) 20187c478bd9Sstevel@tonic-gate { 20197c478bd9Sstevel@tonic-gate size_t i; 20207c478bd9Sstevel@tonic-gate struct df_request *requests; /* array of requests */ 20217c478bd9Sstevel@tonic-gate size_t n_requests; 20227c478bd9Sstevel@tonic-gate struct df_request *dfrp; 20237c478bd9Sstevel@tonic-gate int errors; 20247c478bd9Sstevel@tonic-gate 20257c478bd9Sstevel@tonic-gate errors = create_request_list(argc, argv, &requests, &n_requests); 20267c478bd9Sstevel@tonic-gate 20277c478bd9Sstevel@tonic-gate if (n_requests == 0) 20287c478bd9Sstevel@tonic-gate exit(errors); 20297c478bd9Sstevel@tonic-gate 20307c478bd9Sstevel@tonic-gate /* 20317c478bd9Sstevel@tonic-gate * If we are going to run the FSType-specific df command, 20327c478bd9Sstevel@tonic-gate * rearrange the requests so that we can issue a single command 20337c478bd9Sstevel@tonic-gate * per file system type. 20347c478bd9Sstevel@tonic-gate */ 20357c478bd9Sstevel@tonic-gate if (o_option) { 20367c478bd9Sstevel@tonic-gate size_t j; 20377c478bd9Sstevel@tonic-gate 20387c478bd9Sstevel@tonic-gate /* 20397c478bd9Sstevel@tonic-gate * qsort is not a stable sorting method (i.e. requests of 20407c478bd9Sstevel@tonic-gate * the same file system type may be swapped, and hence appear 20417c478bd9Sstevel@tonic-gate * in the output in a different order from the one in which 20427c478bd9Sstevel@tonic-gate * they were listed in the command line). In order to force 20437c478bd9Sstevel@tonic-gate * stability, we use the dfr_index field which is unique 20447c478bd9Sstevel@tonic-gate * for each request. 20457c478bd9Sstevel@tonic-gate */ 20467c478bd9Sstevel@tonic-gate qsort(requests, 20477c478bd9Sstevel@tonic-gate n_requests, sizeof (struct df_request), df_reqcomp); 20487c478bd9Sstevel@tonic-gate for (i = 0; i < n_requests; i = j) { 20497c478bd9Sstevel@tonic-gate char *fstype = requests[i].dfr_fstype; 20507c478bd9Sstevel@tonic-gate 20517c478bd9Sstevel@tonic-gate for (j = i+1; j < n_requests; j++) 20527c478bd9Sstevel@tonic-gate if (! EQ(fstype, requests[j].dfr_fstype)) 20537c478bd9Sstevel@tonic-gate break; 20547c478bd9Sstevel@tonic-gate 20557c478bd9Sstevel@tonic-gate /* 20567c478bd9Sstevel@tonic-gate * At this point, requests in the range [i,j) are 20577c478bd9Sstevel@tonic-gate * of the same type. 20587c478bd9Sstevel@tonic-gate * 20597c478bd9Sstevel@tonic-gate * If the -F option was used, and the user specified 20607c478bd9Sstevel@tonic-gate * arguments, the filesystem types must match 20617c478bd9Sstevel@tonic-gate * 20627c478bd9Sstevel@tonic-gate * XXX: the alternative of doing this check here is to 20637c478bd9Sstevel@tonic-gate * invoke prune_list, but then we have to 20647c478bd9Sstevel@tonic-gate * modify this code to ignore invalid requests. 20657c478bd9Sstevel@tonic-gate */ 20667c478bd9Sstevel@tonic-gate if (F_option && ! EQ(fstype, FSType)) { 20677c478bd9Sstevel@tonic-gate size_t k; 20687c478bd9Sstevel@tonic-gate 20697c478bd9Sstevel@tonic-gate for (k = i; k < j; k++) { 20707c478bd9Sstevel@tonic-gate dfrp = &requests[k]; 20717c478bd9Sstevel@tonic-gate if (dfrp->dfr_cmd_arg != NULL) { 20727c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, 2073990b4856Slling "Warning: %s mounted as a " 2074990b4856Slling "%s file system", 2075990b4856Slling dfrp->dfr_cmd_arg, 2076990b4856Slling dfrp->dfr_fstype); 20777c478bd9Sstevel@tonic-gate errors++; 20787c478bd9Sstevel@tonic-gate } 20797c478bd9Sstevel@tonic-gate } 20807c478bd9Sstevel@tonic-gate } else 20817c478bd9Sstevel@tonic-gate errors += run_fs_specific_df(&requests[i], j-i); 20827c478bd9Sstevel@tonic-gate } 20837c478bd9Sstevel@tonic-gate } else { 20847c478bd9Sstevel@tonic-gate size_t valid_requests; 20857c478bd9Sstevel@tonic-gate 20867c478bd9Sstevel@tonic-gate /* 20877c478bd9Sstevel@tonic-gate * We have to prune the request list to avoid printing a header 20887c478bd9Sstevel@tonic-gate * if there are no valid requests 20897c478bd9Sstevel@tonic-gate */ 20907c478bd9Sstevel@tonic-gate errors += prune_list(requests, n_requests, &valid_requests); 20917c478bd9Sstevel@tonic-gate 20927c478bd9Sstevel@tonic-gate if (valid_requests) { 20937c478bd9Sstevel@tonic-gate struct df_output *dfop = select_output(); 20947c478bd9Sstevel@tonic-gate 20957c478bd9Sstevel@tonic-gate /* indicates if we already printed out a header line */ 20967c478bd9Sstevel@tonic-gate int printed_header = 0; 20977c478bd9Sstevel@tonic-gate 20987c478bd9Sstevel@tonic-gate for (i = 0; i < n_requests; i++) { 20997c478bd9Sstevel@tonic-gate dfrp = &requests[i]; 21007c478bd9Sstevel@tonic-gate if (! dfrp->dfr_valid) 21017c478bd9Sstevel@tonic-gate continue; 21027c478bd9Sstevel@tonic-gate 21037c478bd9Sstevel@tonic-gate /* 21047c478bd9Sstevel@tonic-gate * If we don't have a mount point, 21057c478bd9Sstevel@tonic-gate * this must be a block device. 21067c478bd9Sstevel@tonic-gate */ 21077c478bd9Sstevel@tonic-gate if (DFR_ISMOUNTEDFS(dfrp)) { 21087c478bd9Sstevel@tonic-gate struct statvfs64 stvfs; 21097c478bd9Sstevel@tonic-gate 21107c478bd9Sstevel@tonic-gate if ((dfop->dfo_flags & DFO_STATVFS) && 21117c478bd9Sstevel@tonic-gate statvfs64(DFR_MOUNT_POINT(dfrp), 21127c478bd9Sstevel@tonic-gate &stvfs) == -1) { 21137c478bd9Sstevel@tonic-gate errmsg(ERR_PERROR, 21147c478bd9Sstevel@tonic-gate "cannot statvfs %s:", 21157c478bd9Sstevel@tonic-gate DFR_MOUNT_POINT(dfrp)); 21167c478bd9Sstevel@tonic-gate errors++; 21177c478bd9Sstevel@tonic-gate continue; 21187c478bd9Sstevel@tonic-gate } 21197c478bd9Sstevel@tonic-gate if ((!printed_header) && 21207c478bd9Sstevel@tonic-gate (dfop->dfo_flags & DFO_HEADER)) { 21217c478bd9Sstevel@tonic-gate print_header(); 21227c478bd9Sstevel@tonic-gate printed_header = 1; 21237c478bd9Sstevel@tonic-gate } 21247c478bd9Sstevel@tonic-gate 21257c478bd9Sstevel@tonic-gate (*dfop->dfo_func)(dfrp, &stvfs); 21267c478bd9Sstevel@tonic-gate } else { 21277c478bd9Sstevel@tonic-gate /* 21287c478bd9Sstevel@tonic-gate * -h option only works for 21297c478bd9Sstevel@tonic-gate * mounted filesystems 21307c478bd9Sstevel@tonic-gate */ 21317c478bd9Sstevel@tonic-gate if (use_scaling) { 21327c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, 21337c478bd9Sstevel@tonic-gate "-h option incompatible with unmounted special device (%s)", 21347c478bd9Sstevel@tonic-gate dfrp->dfr_cmd_arg); 21357c478bd9Sstevel@tonic-gate errors++; 21367c478bd9Sstevel@tonic-gate continue; 21377c478bd9Sstevel@tonic-gate } 21387c478bd9Sstevel@tonic-gate errors += run_fs_specific_df(dfrp, 1); 21397c478bd9Sstevel@tonic-gate } 21407c478bd9Sstevel@tonic-gate } 21417c478bd9Sstevel@tonic-gate } 21427c478bd9Sstevel@tonic-gate } 21437c478bd9Sstevel@tonic-gate exit(errors); 21447c478bd9Sstevel@tonic-gate } 21457c478bd9Sstevel@tonic-gate 21467c478bd9Sstevel@tonic-gate 21477c478bd9Sstevel@tonic-gate /* 21487c478bd9Sstevel@tonic-gate * The rest of this file implements the devnm command 21497c478bd9Sstevel@tonic-gate */ 21507c478bd9Sstevel@tonic-gate 21517c478bd9Sstevel@tonic-gate static char * 21527c478bd9Sstevel@tonic-gate find_dev_name(char *file, dev_t dev) 21537c478bd9Sstevel@tonic-gate { 21547c478bd9Sstevel@tonic-gate struct df_request dfreq; 21557c478bd9Sstevel@tonic-gate 21567c478bd9Sstevel@tonic-gate dfreq.dfr_cmd_arg = file; 21577c478bd9Sstevel@tonic-gate dfreq.dfr_fstype = 0; 21587c478bd9Sstevel@tonic-gate dfreq.dfr_mte = NULL; 21597c478bd9Sstevel@tonic-gate path_mount_entry(&dfreq, dev); 21607c478bd9Sstevel@tonic-gate return (DFR_ISMOUNTEDFS(&dfreq) ? DFR_SPECIAL(&dfreq) : NULL); 21617c478bd9Sstevel@tonic-gate } 21627c478bd9Sstevel@tonic-gate 21637c478bd9Sstevel@tonic-gate 21647c478bd9Sstevel@tonic-gate static void 21657c478bd9Sstevel@tonic-gate do_devnm(int argc, char *argv[]) 21667c478bd9Sstevel@tonic-gate { 21677c478bd9Sstevel@tonic-gate int arg; 21687c478bd9Sstevel@tonic-gate int errors = 0; 21697c478bd9Sstevel@tonic-gate char *dev_name; 21707c478bd9Sstevel@tonic-gate 21717c478bd9Sstevel@tonic-gate if (argc == 1) 21727c478bd9Sstevel@tonic-gate errmsg(ERR_NONAME, "Usage: %s name ...", DEVNM_CMD); 21737c478bd9Sstevel@tonic-gate 21747c478bd9Sstevel@tonic-gate mtab_read_file(); 21757c478bd9Sstevel@tonic-gate 21767c478bd9Sstevel@tonic-gate for (arg = 1; arg < argc; arg++) { 21777c478bd9Sstevel@tonic-gate char *file = argv[arg]; 21787c478bd9Sstevel@tonic-gate struct stat64 st; 21797c478bd9Sstevel@tonic-gate 21807c478bd9Sstevel@tonic-gate if (stat64(file, &st) == -1) { 21817c478bd9Sstevel@tonic-gate errmsg(ERR_PERROR, "%s: ", file); 21827c478bd9Sstevel@tonic-gate errors++; 21837c478bd9Sstevel@tonic-gate continue; 21847c478bd9Sstevel@tonic-gate } 21857c478bd9Sstevel@tonic-gate 21867c478bd9Sstevel@tonic-gate if (! is_remote_fs(st.st_fstype) && 21877c478bd9Sstevel@tonic-gate ! EQ(st.st_fstype, MNTTYPE_TMPFS) && 21887c478bd9Sstevel@tonic-gate (dev_name = find_dev_name(file, st.st_dev))) 21897c478bd9Sstevel@tonic-gate (void) printf("%s %s\n", dev_name, file); 21907c478bd9Sstevel@tonic-gate else 21917c478bd9Sstevel@tonic-gate errmsg(ERR_NOFLAGS, 21927c478bd9Sstevel@tonic-gate "%s not found", file); 21937c478bd9Sstevel@tonic-gate } 21947c478bd9Sstevel@tonic-gate exit(errors); 21957c478bd9Sstevel@tonic-gate /* NOTREACHED */ 21967c478bd9Sstevel@tonic-gate } 2197