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 57f4f06d2Spetede * Common Development and Distribution License (the "License"). 67f4f06d2Spetede * 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 /* 22a576ab5bSrab * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* 277c478bd9Sstevel@tonic-gate * File Descriptor I/O Backend 287c478bd9Sstevel@tonic-gate * 297c478bd9Sstevel@tonic-gate * Simple backend to pass though io_ops to the corresponding system calls on 307c478bd9Sstevel@tonic-gate * an underlying fd. We provide functions to create fdio objects using file 317c478bd9Sstevel@tonic-gate * descriptors, explicit file names, and path lookups. We save the complete 327c478bd9Sstevel@tonic-gate * filename so that mdb_iob_name can be used to report the complete filename 337c478bd9Sstevel@tonic-gate * of an open macro file in syntax error messages. 347c478bd9Sstevel@tonic-gate */ 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate #include <sys/param.h> 377c478bd9Sstevel@tonic-gate #include <sys/stat.h> 387c478bd9Sstevel@tonic-gate #include <sys/dkio.h> 397c478bd9Sstevel@tonic-gate #include <unistd.h> 407c478bd9Sstevel@tonic-gate #include <string.h> 417c478bd9Sstevel@tonic-gate #include <errno.h> 427c478bd9Sstevel@tonic-gate #include <fcntl.h> 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate #include <mdb/mdb_modapi.h> 457c478bd9Sstevel@tonic-gate #include <mdb/mdb_err.h> 467c478bd9Sstevel@tonic-gate #include <mdb/mdb_io_impl.h> 477c478bd9Sstevel@tonic-gate #include <mdb/mdb.h> 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate typedef struct fd_data { 507c478bd9Sstevel@tonic-gate char fd_name[MAXPATHLEN]; /* Save filename for error messages */ 517c478bd9Sstevel@tonic-gate int fd_fd; /* File descriptor */ 527c478bd9Sstevel@tonic-gate } fd_data_t; 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate static ssize_t 557c478bd9Sstevel@tonic-gate fdio_read(mdb_io_t *io, void *buf, size_t nbytes) 567c478bd9Sstevel@tonic-gate { 577c478bd9Sstevel@tonic-gate fd_data_t *fdp = io->io_data; 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate if (io->io_next == NULL) 607c478bd9Sstevel@tonic-gate return (read(fdp->fd_fd, buf, nbytes)); 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate return (IOP_READ(io->io_next, buf, nbytes)); 637c478bd9Sstevel@tonic-gate } 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate static ssize_t 667c478bd9Sstevel@tonic-gate fdio_write(mdb_io_t *io, const void *buf, size_t nbytes) 677c478bd9Sstevel@tonic-gate { 687c478bd9Sstevel@tonic-gate fd_data_t *fdp = io->io_data; 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate if (io->io_next == NULL) 717c478bd9Sstevel@tonic-gate return (write(fdp->fd_fd, buf, nbytes)); 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate return (IOP_WRITE(io->io_next, buf, nbytes)); 747c478bd9Sstevel@tonic-gate } 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate static off64_t 777c478bd9Sstevel@tonic-gate fdio_seek(mdb_io_t *io, off64_t offset, int whence) 787c478bd9Sstevel@tonic-gate { 797c478bd9Sstevel@tonic-gate fd_data_t *fdp = io->io_data; 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate if (io->io_next == NULL) 827c478bd9Sstevel@tonic-gate return (lseek64(fdp->fd_fd, offset, whence)); 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate return (IOP_SEEK(io->io_next, offset, whence)); 857c478bd9Sstevel@tonic-gate } 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate static int 887c478bd9Sstevel@tonic-gate fdio_ctl(mdb_io_t *io, int req, void *arg) 897c478bd9Sstevel@tonic-gate { 907c478bd9Sstevel@tonic-gate fd_data_t *fdp = io->io_data; 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate if (io->io_next != NULL) 937c478bd9Sstevel@tonic-gate return (IOP_CTL(io->io_next, req, arg)); 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate if (req == MDB_IOC_GETFD) 967c478bd9Sstevel@tonic-gate return (fdp->fd_fd); 977c478bd9Sstevel@tonic-gate else 987c478bd9Sstevel@tonic-gate return (ioctl(fdp->fd_fd, req, arg)); 997c478bd9Sstevel@tonic-gate } 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate static void 1027c478bd9Sstevel@tonic-gate fdio_close(mdb_io_t *io) 1037c478bd9Sstevel@tonic-gate { 1047c478bd9Sstevel@tonic-gate fd_data_t *fdp = io->io_data; 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate (void) close(fdp->fd_fd); 1077c478bd9Sstevel@tonic-gate mdb_free(fdp, sizeof (fd_data_t)); 1087c478bd9Sstevel@tonic-gate } 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate static const char * 1117c478bd9Sstevel@tonic-gate fdio_name(mdb_io_t *io) 1127c478bd9Sstevel@tonic-gate { 1137c478bd9Sstevel@tonic-gate fd_data_t *fdp = io->io_data; 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate if (io->io_next == NULL) 1167c478bd9Sstevel@tonic-gate return (fdp->fd_name); 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate return (IOP_NAME(io->io_next)); 1197c478bd9Sstevel@tonic-gate } 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate mdb_io_t * 1227c478bd9Sstevel@tonic-gate mdb_fdio_create_path(const char *path[], const char *fname, 1237c478bd9Sstevel@tonic-gate int flags, mode_t mode) 1247c478bd9Sstevel@tonic-gate { 1257c478bd9Sstevel@tonic-gate int fd; 1267f4f06d2Spetede char buf[MAXPATHLEN]; 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate if (path != NULL && strchr(fname, '/') == NULL) { 1297c478bd9Sstevel@tonic-gate int i; 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate for (fd = -1, i = 0; path[i] != NULL; i++) { 1327c478bd9Sstevel@tonic-gate (void) mdb_iob_snprintf(buf, MAXPATHLEN, "%s/%s", 1337c478bd9Sstevel@tonic-gate path[i], fname); 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate if (access(buf, F_OK) == 0) { 1367c478bd9Sstevel@tonic-gate fd = open64(buf, flags, mode); 1377c478bd9Sstevel@tonic-gate fname = buf; 1387c478bd9Sstevel@tonic-gate break; 1397c478bd9Sstevel@tonic-gate } 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate if (fd == -1) 1437c478bd9Sstevel@tonic-gate (void) set_errno(ENOENT); 1447c478bd9Sstevel@tonic-gate } else 1457c478bd9Sstevel@tonic-gate fd = open64(fname, flags, mode); 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate if (fd >= 0) 1487c478bd9Sstevel@tonic-gate return (mdb_fdio_create_named(fd, fname)); 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate return (NULL); 1517c478bd9Sstevel@tonic-gate } 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate static const mdb_io_ops_t fdio_file_ops = { 1547c478bd9Sstevel@tonic-gate fdio_read, 1557c478bd9Sstevel@tonic-gate fdio_write, 1567c478bd9Sstevel@tonic-gate fdio_seek, 1577c478bd9Sstevel@tonic-gate fdio_ctl, 1587c478bd9Sstevel@tonic-gate fdio_close, 1597c478bd9Sstevel@tonic-gate fdio_name, 1607c478bd9Sstevel@tonic-gate no_io_link, 1617c478bd9Sstevel@tonic-gate no_io_unlink, 1627c478bd9Sstevel@tonic-gate no_io_setattr, 1637c478bd9Sstevel@tonic-gate no_io_suspend, 1647c478bd9Sstevel@tonic-gate no_io_resume 1657c478bd9Sstevel@tonic-gate }; 1667c478bd9Sstevel@tonic-gate 167*b55a30d7SToomas Soome /* 168*b55a30d7SToomas Soome * Read media logical block size. On error, return DEV_BSIZE. 169*b55a30d7SToomas Soome */ 170*b55a30d7SToomas Soome static uint_t 171*b55a30d7SToomas Soome fdio_bdev_info(int fd) 172*b55a30d7SToomas Soome { 173*b55a30d7SToomas Soome struct dk_minfo disk_info; 174*b55a30d7SToomas Soome 175*b55a30d7SToomas Soome if ((ioctl(fd, DKIOCGMEDIAINFO, (caddr_t)&disk_info)) == -1) 176*b55a30d7SToomas Soome return (DEV_BSIZE); 177*b55a30d7SToomas Soome 178*b55a30d7SToomas Soome return (disk_info.dki_lbsize); 179*b55a30d7SToomas Soome } 180*b55a30d7SToomas Soome 1817c478bd9Sstevel@tonic-gate /* 1827c478bd9Sstevel@tonic-gate * In order to read from a block-oriented device, we pick up the seek pointer, 1837c478bd9Sstevel@tonic-gate * read each containing block, and then copy the desired range of bytes back 184*b55a30d7SToomas Soome * into the caller's buffer. At the end of the transfer we reset the seek 185*b55a30d7SToomas Soome * pointer to where the caller thinks it should be. 1867c478bd9Sstevel@tonic-gate */ 1877c478bd9Sstevel@tonic-gate static ssize_t 1887c478bd9Sstevel@tonic-gate fdio_bdev_read(mdb_io_t *io, void *buf, size_t nbytes) 1897c478bd9Sstevel@tonic-gate { 1907c478bd9Sstevel@tonic-gate fd_data_t *fdp = io->io_data; 1917c478bd9Sstevel@tonic-gate ssize_t resid = nbytes; 192*b55a30d7SToomas Soome size_t blksize; 193*b55a30d7SToomas Soome uchar_t *blk; 1947c478bd9Sstevel@tonic-gate off64_t off; 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate if (io->io_next != NULL) 1977c478bd9Sstevel@tonic-gate return (IOP_READ(io->io_next, buf, nbytes)); 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate if ((off = lseek64(fdp->fd_fd, 0, SEEK_CUR)) == -1) 2007c478bd9Sstevel@tonic-gate return (-1); /* errno is set for us */ 2017c478bd9Sstevel@tonic-gate 202*b55a30d7SToomas Soome blksize = fdio_bdev_info(fdp->fd_fd); 203*b55a30d7SToomas Soome blk = mdb_zalloc(blksize, UM_SLEEP | UM_GC); 2047c478bd9Sstevel@tonic-gate while (resid != 0) { 205*b55a30d7SToomas Soome off64_t devoff = off & ~(blksize - 1); 206*b55a30d7SToomas Soome size_t blkoff = off & (blksize - 1); 207*b55a30d7SToomas Soome size_t len = MIN(resid, blksize - blkoff); 2087c478bd9Sstevel@tonic-gate 209*b55a30d7SToomas Soome if (pread64(fdp->fd_fd, blk, blksize, devoff) != blksize) 2107c478bd9Sstevel@tonic-gate break; /* errno is set for us, unless EOF */ 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate bcopy(&blk[blkoff], buf, len); 2137c478bd9Sstevel@tonic-gate resid -= len; 2147c478bd9Sstevel@tonic-gate off += len; 2157c478bd9Sstevel@tonic-gate buf = (char *)buf + len; 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate if (resid == nbytes && nbytes != 0) 2197c478bd9Sstevel@tonic-gate return (set_errno(EMDB_EOF)); 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate (void) lseek64(fdp->fd_fd, off, SEEK_SET); 2227c478bd9Sstevel@tonic-gate return (nbytes - resid); 2237c478bd9Sstevel@tonic-gate } 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate /* 2267c478bd9Sstevel@tonic-gate * To perform a write to a block-oriented device, we use the same basic 2277c478bd9Sstevel@tonic-gate * algorithm as fdio_bdev_read(), above. In the inner loop, we read an 2287c478bd9Sstevel@tonic-gate * entire block, modify it using the data from the caller's buffer, and 2297c478bd9Sstevel@tonic-gate * then write the entire block back to the device. 2307c478bd9Sstevel@tonic-gate */ 2317c478bd9Sstevel@tonic-gate static ssize_t 2327c478bd9Sstevel@tonic-gate fdio_bdev_write(mdb_io_t *io, const void *buf, size_t nbytes) 2337c478bd9Sstevel@tonic-gate { 2347c478bd9Sstevel@tonic-gate fd_data_t *fdp = io->io_data; 2357c478bd9Sstevel@tonic-gate ssize_t resid = nbytes; 236*b55a30d7SToomas Soome size_t blksize; 237*b55a30d7SToomas Soome uchar_t *blk; 2387c478bd9Sstevel@tonic-gate off64_t off; 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate if (io->io_next != NULL) 2417c478bd9Sstevel@tonic-gate return (IOP_WRITE(io->io_next, buf, nbytes)); 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate if ((off = lseek64(fdp->fd_fd, 0, SEEK_CUR)) == -1) 2447c478bd9Sstevel@tonic-gate return (-1); /* errno is set for us */ 2457c478bd9Sstevel@tonic-gate 246*b55a30d7SToomas Soome blksize = fdio_bdev_info(fdp->fd_fd); 247*b55a30d7SToomas Soome blk = mdb_zalloc(blksize, UM_SLEEP | UM_GC); 2487c478bd9Sstevel@tonic-gate while (resid != 0) { 249*b55a30d7SToomas Soome off64_t devoff = off & ~(blksize - 1); 250*b55a30d7SToomas Soome size_t blkoff = off & (blksize - 1); 251*b55a30d7SToomas Soome size_t len = MIN(resid, blksize - blkoff); 2527c478bd9Sstevel@tonic-gate 253*b55a30d7SToomas Soome if (pread64(fdp->fd_fd, blk, blksize, devoff) != blksize) 2547c478bd9Sstevel@tonic-gate break; /* errno is set for us, unless EOF */ 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate bcopy(buf, &blk[blkoff], len); 2577c478bd9Sstevel@tonic-gate 258*b55a30d7SToomas Soome if (pwrite64(fdp->fd_fd, blk, blksize, devoff) != blksize) 2597c478bd9Sstevel@tonic-gate break; /* errno is set for us, unless EOF */ 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate resid -= len; 2627c478bd9Sstevel@tonic-gate off += len; 2637c478bd9Sstevel@tonic-gate buf = (char *)buf + len; 2647c478bd9Sstevel@tonic-gate } 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate if (resid == nbytes && nbytes != 0) 2677c478bd9Sstevel@tonic-gate return (set_errno(EMDB_EOF)); 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate (void) lseek64(fdp->fd_fd, off, SEEK_SET); 2707c478bd9Sstevel@tonic-gate return (nbytes - resid); 2717c478bd9Sstevel@tonic-gate } 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate static const mdb_io_ops_t fdio_bdev_ops = { 2747c478bd9Sstevel@tonic-gate fdio_bdev_read, 2757c478bd9Sstevel@tonic-gate fdio_bdev_write, 2767c478bd9Sstevel@tonic-gate fdio_seek, 2777c478bd9Sstevel@tonic-gate fdio_ctl, 2787c478bd9Sstevel@tonic-gate fdio_close, 2797c478bd9Sstevel@tonic-gate fdio_name, 2807c478bd9Sstevel@tonic-gate no_io_link, 2817c478bd9Sstevel@tonic-gate no_io_unlink, 2827c478bd9Sstevel@tonic-gate no_io_setattr, 2837c478bd9Sstevel@tonic-gate no_io_suspend, 2847c478bd9Sstevel@tonic-gate no_io_resume 2857c478bd9Sstevel@tonic-gate }; 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate mdb_io_t * 2887c478bd9Sstevel@tonic-gate mdb_fdio_create(int fd) 2897c478bd9Sstevel@tonic-gate { 2907c478bd9Sstevel@tonic-gate mdb_io_t *io = mdb_alloc(sizeof (mdb_io_t), UM_SLEEP); 2917c478bd9Sstevel@tonic-gate fd_data_t *fdp = mdb_alloc(sizeof (fd_data_t), UM_SLEEP); 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate struct dk_cinfo info; 2947c478bd9Sstevel@tonic-gate struct stat64 st; 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate switch (fd) { 2977c478bd9Sstevel@tonic-gate case STDIN_FILENO: 2987c478bd9Sstevel@tonic-gate (void) strcpy(fdp->fd_name, "(stdin)"); 2997c478bd9Sstevel@tonic-gate break; 3007c478bd9Sstevel@tonic-gate case STDOUT_FILENO: 3017c478bd9Sstevel@tonic-gate (void) strcpy(fdp->fd_name, "(stdout)"); 3027c478bd9Sstevel@tonic-gate break; 3037c478bd9Sstevel@tonic-gate case STDERR_FILENO: 3047c478bd9Sstevel@tonic-gate (void) strcpy(fdp->fd_name, "(stderr)"); 3057c478bd9Sstevel@tonic-gate break; 3067c478bd9Sstevel@tonic-gate default: 3077c478bd9Sstevel@tonic-gate (void) mdb_iob_snprintf(fdp->fd_name, MAXPATHLEN, "fd %d", fd); 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate fdp->fd_fd = fd; 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate /* 3137c478bd9Sstevel@tonic-gate * We determine if something is a raw block-oriented disk device by 3147c478bd9Sstevel@tonic-gate * testing to see if it is a character device that supports DKIOCINFO. 3157c478bd9Sstevel@tonic-gate * If we are operating on a disk in raw mode, we must do our own 3167c478bd9Sstevel@tonic-gate * block-oriented i/o; otherwise we can just use read() and write(). 3177c478bd9Sstevel@tonic-gate */ 3187c478bd9Sstevel@tonic-gate if (fstat64(fd, &st) == 0 && S_ISCHR(st.st_mode) && 3197c478bd9Sstevel@tonic-gate ioctl(fd, DKIOCINFO, &info) == 0) 3207c478bd9Sstevel@tonic-gate io->io_ops = &fdio_bdev_ops; 3217c478bd9Sstevel@tonic-gate else 3227c478bd9Sstevel@tonic-gate io->io_ops = &fdio_file_ops; 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate io->io_data = fdp; 3257c478bd9Sstevel@tonic-gate io->io_next = NULL; 3267c478bd9Sstevel@tonic-gate io->io_refcnt = 0; 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate return (io); 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate mdb_io_t * 3327c478bd9Sstevel@tonic-gate mdb_fdio_create_named(int fd, const char *name) 3337c478bd9Sstevel@tonic-gate { 3347c478bd9Sstevel@tonic-gate mdb_io_t *io = mdb_fdio_create(fd); 3357c478bd9Sstevel@tonic-gate fd_data_t *fdp = io->io_data; 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate (void) strncpy(fdp->fd_name, name, MAXPATHLEN); 3387c478bd9Sstevel@tonic-gate fdp->fd_name[MAXPATHLEN - 1] = '\0'; 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate return (io); 3417c478bd9Sstevel@tonic-gate } 342a576ab5bSrab 343a576ab5bSrab int 344a576ab5bSrab mdb_fdio_fileno(mdb_io_t *io) 345a576ab5bSrab { 346a576ab5bSrab fd_data_t *fdp = io->io_data; 347a576ab5bSrab return (fdp->fd_fd); 348a576ab5bSrab } 349