1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright (c) 2000-2004 Sendmail, Inc. and its suppliers. 3*7c478bd9Sstevel@tonic-gate * All rights reserved. 4*7c478bd9Sstevel@tonic-gate * Copyright (c) 1990, 1993 5*7c478bd9Sstevel@tonic-gate * The Regents of the University of California. All rights reserved. 6*7c478bd9Sstevel@tonic-gate * 7*7c478bd9Sstevel@tonic-gate * This code is derived from software contributed to Berkeley by 8*7c478bd9Sstevel@tonic-gate * Chris Torek. 9*7c478bd9Sstevel@tonic-gate * 10*7c478bd9Sstevel@tonic-gate * By using this file, you agree to the terms and conditions set 11*7c478bd9Sstevel@tonic-gate * forth in the LICENSE file which can be found at the top level of 12*7c478bd9Sstevel@tonic-gate * the sendmail distribution. 13*7c478bd9Sstevel@tonic-gate */ 14*7c478bd9Sstevel@tonic-gate 15*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 16*7c478bd9Sstevel@tonic-gate 17*7c478bd9Sstevel@tonic-gate #include <sm/gen.h> 18*7c478bd9Sstevel@tonic-gate SM_RCSID("@(#)$Id: stdio.c,v 1.69 2004/08/03 20:46:34 ca Exp $") 19*7c478bd9Sstevel@tonic-gate #include <unistd.h> 20*7c478bd9Sstevel@tonic-gate #include <errno.h> 21*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 22*7c478bd9Sstevel@tonic-gate #include <string.h> /* FreeBSD: FD_ZERO needs <string.h> */ 23*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 24*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 25*7c478bd9Sstevel@tonic-gate #include <sm/heap.h> 26*7c478bd9Sstevel@tonic-gate #include <sm/assert.h> 27*7c478bd9Sstevel@tonic-gate #include <sm/varargs.h> 28*7c478bd9Sstevel@tonic-gate #include <sm/io.h> 29*7c478bd9Sstevel@tonic-gate #include <sm/setjmp.h> 30*7c478bd9Sstevel@tonic-gate #include <sm/conf.h> 31*7c478bd9Sstevel@tonic-gate #include <sm/fdset.h> 32*7c478bd9Sstevel@tonic-gate #include "local.h" 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate static int sm_stdsetmode __P((SM_FILE_T *, const int *)); 35*7c478bd9Sstevel@tonic-gate static int sm_stdgetmode __P((SM_FILE_T *, int *)); 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate /* 38*7c478bd9Sstevel@tonic-gate ** Overall: 39*7c478bd9Sstevel@tonic-gate ** Small standard I/O/seek/close functions. 40*7c478bd9Sstevel@tonic-gate ** These maintain the `known seek offset' for seek optimization. 41*7c478bd9Sstevel@tonic-gate */ 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate /* 44*7c478bd9Sstevel@tonic-gate ** SM_STDOPEN -- open a file with stdio behavior 45*7c478bd9Sstevel@tonic-gate ** 46*7c478bd9Sstevel@tonic-gate ** Not associated with the system's stdio in libc. 47*7c478bd9Sstevel@tonic-gate ** 48*7c478bd9Sstevel@tonic-gate ** Parameters: 49*7c478bd9Sstevel@tonic-gate ** fp -- file pointer to be associated with the open 50*7c478bd9Sstevel@tonic-gate ** info -- pathname of the file to be opened 51*7c478bd9Sstevel@tonic-gate ** flags -- indicates type of access methods 52*7c478bd9Sstevel@tonic-gate ** rpool -- ignored 53*7c478bd9Sstevel@tonic-gate ** 54*7c478bd9Sstevel@tonic-gate ** Returns: 55*7c478bd9Sstevel@tonic-gate ** Failure: -1 and set errno 56*7c478bd9Sstevel@tonic-gate ** Success: 0 or greater (fd of file from open(2)). 57*7c478bd9Sstevel@tonic-gate ** 58*7c478bd9Sstevel@tonic-gate */ 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate /* ARGSUSED3 */ 61*7c478bd9Sstevel@tonic-gate int 62*7c478bd9Sstevel@tonic-gate sm_stdopen(fp, info, flags, rpool) 63*7c478bd9Sstevel@tonic-gate SM_FILE_T *fp; 64*7c478bd9Sstevel@tonic-gate const void *info; 65*7c478bd9Sstevel@tonic-gate int flags; 66*7c478bd9Sstevel@tonic-gate const void *rpool; 67*7c478bd9Sstevel@tonic-gate { 68*7c478bd9Sstevel@tonic-gate char *path = (char *) info; 69*7c478bd9Sstevel@tonic-gate int oflags; 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate switch (SM_IO_MODE(flags)) 72*7c478bd9Sstevel@tonic-gate { 73*7c478bd9Sstevel@tonic-gate case SM_IO_RDWR: 74*7c478bd9Sstevel@tonic-gate oflags = O_RDWR; 75*7c478bd9Sstevel@tonic-gate break; 76*7c478bd9Sstevel@tonic-gate case SM_IO_RDWRTR: 77*7c478bd9Sstevel@tonic-gate oflags = O_RDWR | O_CREAT | O_TRUNC; 78*7c478bd9Sstevel@tonic-gate break; 79*7c478bd9Sstevel@tonic-gate case SM_IO_RDONLY: 80*7c478bd9Sstevel@tonic-gate oflags = O_RDONLY; 81*7c478bd9Sstevel@tonic-gate break; 82*7c478bd9Sstevel@tonic-gate case SM_IO_WRONLY: 83*7c478bd9Sstevel@tonic-gate oflags = O_WRONLY | O_CREAT | O_TRUNC; 84*7c478bd9Sstevel@tonic-gate break; 85*7c478bd9Sstevel@tonic-gate case SM_IO_APPEND: 86*7c478bd9Sstevel@tonic-gate oflags = O_APPEND | O_WRONLY | O_CREAT; 87*7c478bd9Sstevel@tonic-gate break; 88*7c478bd9Sstevel@tonic-gate case SM_IO_APPENDRW: 89*7c478bd9Sstevel@tonic-gate oflags = O_APPEND | O_RDWR | O_CREAT; 90*7c478bd9Sstevel@tonic-gate break; 91*7c478bd9Sstevel@tonic-gate default: 92*7c478bd9Sstevel@tonic-gate errno = EINVAL; 93*7c478bd9Sstevel@tonic-gate return -1; 94*7c478bd9Sstevel@tonic-gate } 95*7c478bd9Sstevel@tonic-gate #ifdef O_BINARY 96*7c478bd9Sstevel@tonic-gate if (SM_IS_BINARY(flags)) 97*7c478bd9Sstevel@tonic-gate oflags |= O_BINARY; 98*7c478bd9Sstevel@tonic-gate #endif /* O_BINARY */ 99*7c478bd9Sstevel@tonic-gate fp->f_file = open(path, oflags, 100*7c478bd9Sstevel@tonic-gate S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); 101*7c478bd9Sstevel@tonic-gate if (fp->f_file < 0) 102*7c478bd9Sstevel@tonic-gate return -1; /* errno set by open() */ 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate if (oflags & O_APPEND) 105*7c478bd9Sstevel@tonic-gate (void) (*fp->f_seek)((void *)fp, (off_t)0, SEEK_END); 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate return fp->f_file; 108*7c478bd9Sstevel@tonic-gate } 109*7c478bd9Sstevel@tonic-gate 110*7c478bd9Sstevel@tonic-gate /* 111*7c478bd9Sstevel@tonic-gate ** SM_STDREAD -- read from the file 112*7c478bd9Sstevel@tonic-gate ** 113*7c478bd9Sstevel@tonic-gate ** Parameters: 114*7c478bd9Sstevel@tonic-gate ** fp -- file pointer to read from 115*7c478bd9Sstevel@tonic-gate ** buf -- location to place read data 116*7c478bd9Sstevel@tonic-gate ** n -- number of bytes to read 117*7c478bd9Sstevel@tonic-gate ** 118*7c478bd9Sstevel@tonic-gate ** Returns: 119*7c478bd9Sstevel@tonic-gate ** Failure: -1 and sets errno 120*7c478bd9Sstevel@tonic-gate ** Success: number of bytes read 121*7c478bd9Sstevel@tonic-gate ** 122*7c478bd9Sstevel@tonic-gate ** Side Effects: 123*7c478bd9Sstevel@tonic-gate ** Updates internal offset into file. 124*7c478bd9Sstevel@tonic-gate */ 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate ssize_t 127*7c478bd9Sstevel@tonic-gate sm_stdread(fp, buf, n) 128*7c478bd9Sstevel@tonic-gate SM_FILE_T *fp; 129*7c478bd9Sstevel@tonic-gate char *buf; 130*7c478bd9Sstevel@tonic-gate size_t n; 131*7c478bd9Sstevel@tonic-gate { 132*7c478bd9Sstevel@tonic-gate register int ret; 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate ret = read(fp->f_file, buf, n); 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate /* if the read succeeded, update the current offset */ 137*7c478bd9Sstevel@tonic-gate if (ret > 0) 138*7c478bd9Sstevel@tonic-gate fp->f_lseekoff += ret; 139*7c478bd9Sstevel@tonic-gate return ret; 140*7c478bd9Sstevel@tonic-gate } 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate /* 143*7c478bd9Sstevel@tonic-gate ** SM_STDWRITE -- write to the file 144*7c478bd9Sstevel@tonic-gate ** 145*7c478bd9Sstevel@tonic-gate ** Parameters: 146*7c478bd9Sstevel@tonic-gate ** fp -- file pointer ro write to 147*7c478bd9Sstevel@tonic-gate ** buf -- location of data to be written 148*7c478bd9Sstevel@tonic-gate ** n - number of bytes to write 149*7c478bd9Sstevel@tonic-gate ** 150*7c478bd9Sstevel@tonic-gate ** Returns: 151*7c478bd9Sstevel@tonic-gate ** Failure: -1 and sets errno 152*7c478bd9Sstevel@tonic-gate ** Success: number of bytes written 153*7c478bd9Sstevel@tonic-gate */ 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate ssize_t 156*7c478bd9Sstevel@tonic-gate sm_stdwrite(fp, buf, n) 157*7c478bd9Sstevel@tonic-gate SM_FILE_T *fp; 158*7c478bd9Sstevel@tonic-gate char const *buf; 159*7c478bd9Sstevel@tonic-gate size_t n; 160*7c478bd9Sstevel@tonic-gate { 161*7c478bd9Sstevel@tonic-gate return write(fp->f_file, buf, n); 162*7c478bd9Sstevel@tonic-gate } 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate /* 165*7c478bd9Sstevel@tonic-gate ** SM_STDSEEK -- set the file offset position 166*7c478bd9Sstevel@tonic-gate ** 167*7c478bd9Sstevel@tonic-gate ** Parmeters: 168*7c478bd9Sstevel@tonic-gate ** fp -- file pointer to position 169*7c478bd9Sstevel@tonic-gate ** offset -- how far to position from "base" (set by 'whence') 170*7c478bd9Sstevel@tonic-gate ** whence -- indicates where the "base" of the 'offset' to start 171*7c478bd9Sstevel@tonic-gate ** 172*7c478bd9Sstevel@tonic-gate ** Results: 173*7c478bd9Sstevel@tonic-gate ** Failure: -1 and sets errno 174*7c478bd9Sstevel@tonic-gate ** Success: the current offset 175*7c478bd9Sstevel@tonic-gate ** 176*7c478bd9Sstevel@tonic-gate ** Side Effects: 177*7c478bd9Sstevel@tonic-gate ** Updates the internal value of the offset. 178*7c478bd9Sstevel@tonic-gate */ 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate off_t 181*7c478bd9Sstevel@tonic-gate sm_stdseek(fp, offset, whence) 182*7c478bd9Sstevel@tonic-gate SM_FILE_T *fp; 183*7c478bd9Sstevel@tonic-gate off_t offset; 184*7c478bd9Sstevel@tonic-gate int whence; 185*7c478bd9Sstevel@tonic-gate { 186*7c478bd9Sstevel@tonic-gate register off_t ret; 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate ret = lseek(fp->f_file, (off_t) offset, whence); 189*7c478bd9Sstevel@tonic-gate if (ret != (off_t) -1) 190*7c478bd9Sstevel@tonic-gate fp->f_lseekoff = ret; 191*7c478bd9Sstevel@tonic-gate return ret; 192*7c478bd9Sstevel@tonic-gate } 193*7c478bd9Sstevel@tonic-gate 194*7c478bd9Sstevel@tonic-gate /* 195*7c478bd9Sstevel@tonic-gate ** SM_STDCLOSE -- close the file 196*7c478bd9Sstevel@tonic-gate ** 197*7c478bd9Sstevel@tonic-gate ** Parameters: 198*7c478bd9Sstevel@tonic-gate ** fp -- the file pointer to close 199*7c478bd9Sstevel@tonic-gate ** 200*7c478bd9Sstevel@tonic-gate ** Returns: 201*7c478bd9Sstevel@tonic-gate ** Success: 0 (zero) 202*7c478bd9Sstevel@tonic-gate ** Failure: -1 and sets errno 203*7c478bd9Sstevel@tonic-gate */ 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate int 206*7c478bd9Sstevel@tonic-gate sm_stdclose(fp) 207*7c478bd9Sstevel@tonic-gate SM_FILE_T *fp; 208*7c478bd9Sstevel@tonic-gate { 209*7c478bd9Sstevel@tonic-gate return close(fp->f_file); 210*7c478bd9Sstevel@tonic-gate } 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate /* 213*7c478bd9Sstevel@tonic-gate ** SM_STDSETMODE -- set the access mode for the file 214*7c478bd9Sstevel@tonic-gate ** 215*7c478bd9Sstevel@tonic-gate ** Called by sm_stdsetinfo(). 216*7c478bd9Sstevel@tonic-gate ** 217*7c478bd9Sstevel@tonic-gate ** Parameters: 218*7c478bd9Sstevel@tonic-gate ** fp -- file pointer 219*7c478bd9Sstevel@tonic-gate ** mode -- new mode to set the file access to 220*7c478bd9Sstevel@tonic-gate ** 221*7c478bd9Sstevel@tonic-gate ** Results: 222*7c478bd9Sstevel@tonic-gate ** Success: 0 (zero); 223*7c478bd9Sstevel@tonic-gate ** Failure: -1 and sets errno 224*7c478bd9Sstevel@tonic-gate */ 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate int 227*7c478bd9Sstevel@tonic-gate sm_stdsetmode(fp, mode) 228*7c478bd9Sstevel@tonic-gate SM_FILE_T *fp; 229*7c478bd9Sstevel@tonic-gate const int *mode; 230*7c478bd9Sstevel@tonic-gate { 231*7c478bd9Sstevel@tonic-gate int flags = 0; 232*7c478bd9Sstevel@tonic-gate 233*7c478bd9Sstevel@tonic-gate switch (SM_IO_MODE(*mode)) 234*7c478bd9Sstevel@tonic-gate { 235*7c478bd9Sstevel@tonic-gate case SM_IO_RDWR: 236*7c478bd9Sstevel@tonic-gate flags |= SMRW; 237*7c478bd9Sstevel@tonic-gate break; 238*7c478bd9Sstevel@tonic-gate case SM_IO_RDONLY: 239*7c478bd9Sstevel@tonic-gate flags |= SMRD; 240*7c478bd9Sstevel@tonic-gate break; 241*7c478bd9Sstevel@tonic-gate case SM_IO_WRONLY: 242*7c478bd9Sstevel@tonic-gate flags |= SMWR; 243*7c478bd9Sstevel@tonic-gate break; 244*7c478bd9Sstevel@tonic-gate case SM_IO_APPEND: 245*7c478bd9Sstevel@tonic-gate default: 246*7c478bd9Sstevel@tonic-gate errno = EINVAL; 247*7c478bd9Sstevel@tonic-gate return -1; 248*7c478bd9Sstevel@tonic-gate } 249*7c478bd9Sstevel@tonic-gate fp->f_flags = fp->f_flags & ~SMMODEMASK; 250*7c478bd9Sstevel@tonic-gate fp->f_flags |= flags; 251*7c478bd9Sstevel@tonic-gate return 0; 252*7c478bd9Sstevel@tonic-gate } 253*7c478bd9Sstevel@tonic-gate 254*7c478bd9Sstevel@tonic-gate /* 255*7c478bd9Sstevel@tonic-gate ** SM_STDGETMODE -- for getinfo determine open mode 256*7c478bd9Sstevel@tonic-gate ** 257*7c478bd9Sstevel@tonic-gate ** Called by sm_stdgetinfo(). 258*7c478bd9Sstevel@tonic-gate ** 259*7c478bd9Sstevel@tonic-gate ** Parameters: 260*7c478bd9Sstevel@tonic-gate ** fp -- the file mode being determined 261*7c478bd9Sstevel@tonic-gate ** mode -- internal mode to map to external value 262*7c478bd9Sstevel@tonic-gate ** 263*7c478bd9Sstevel@tonic-gate ** Results: 264*7c478bd9Sstevel@tonic-gate ** Failure: -1 and sets errno 265*7c478bd9Sstevel@tonic-gate ** Success: external mode value 266*7c478bd9Sstevel@tonic-gate */ 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate static int 269*7c478bd9Sstevel@tonic-gate sm_stdgetmode(fp, mode) 270*7c478bd9Sstevel@tonic-gate SM_FILE_T *fp; 271*7c478bd9Sstevel@tonic-gate int *mode; 272*7c478bd9Sstevel@tonic-gate { 273*7c478bd9Sstevel@tonic-gate switch (fp->f_flags & SMMODEMASK) 274*7c478bd9Sstevel@tonic-gate { 275*7c478bd9Sstevel@tonic-gate case SMRW: 276*7c478bd9Sstevel@tonic-gate *mode = SM_IO_RDWR; 277*7c478bd9Sstevel@tonic-gate break; 278*7c478bd9Sstevel@tonic-gate case SMRD: 279*7c478bd9Sstevel@tonic-gate *mode = SM_IO_RDONLY; 280*7c478bd9Sstevel@tonic-gate break; 281*7c478bd9Sstevel@tonic-gate case SMWR: 282*7c478bd9Sstevel@tonic-gate *mode = SM_IO_WRONLY; 283*7c478bd9Sstevel@tonic-gate break; 284*7c478bd9Sstevel@tonic-gate default: 285*7c478bd9Sstevel@tonic-gate errno = EINVAL; 286*7c478bd9Sstevel@tonic-gate return -1; 287*7c478bd9Sstevel@tonic-gate } 288*7c478bd9Sstevel@tonic-gate return 0; 289*7c478bd9Sstevel@tonic-gate } 290*7c478bd9Sstevel@tonic-gate 291*7c478bd9Sstevel@tonic-gate /* 292*7c478bd9Sstevel@tonic-gate ** SM_STDSETINFO -- set/modify information for a file 293*7c478bd9Sstevel@tonic-gate ** 294*7c478bd9Sstevel@tonic-gate ** Parameters: 295*7c478bd9Sstevel@tonic-gate ** fp -- file to set info for 296*7c478bd9Sstevel@tonic-gate ** what -- type of info to set 297*7c478bd9Sstevel@tonic-gate ** valp -- location of data used for setting 298*7c478bd9Sstevel@tonic-gate ** 299*7c478bd9Sstevel@tonic-gate ** Returns: 300*7c478bd9Sstevel@tonic-gate ** Failure: -1 and sets errno 301*7c478bd9Sstevel@tonic-gate ** Success: >=0 302*7c478bd9Sstevel@tonic-gate */ 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate int 305*7c478bd9Sstevel@tonic-gate sm_stdsetinfo(fp, what, valp) 306*7c478bd9Sstevel@tonic-gate SM_FILE_T *fp; 307*7c478bd9Sstevel@tonic-gate int what; 308*7c478bd9Sstevel@tonic-gate void *valp; 309*7c478bd9Sstevel@tonic-gate { 310*7c478bd9Sstevel@tonic-gate switch (what) 311*7c478bd9Sstevel@tonic-gate { 312*7c478bd9Sstevel@tonic-gate case SM_IO_WHAT_MODE: 313*7c478bd9Sstevel@tonic-gate return sm_stdsetmode(fp, (const int *)valp); 314*7c478bd9Sstevel@tonic-gate 315*7c478bd9Sstevel@tonic-gate default: 316*7c478bd9Sstevel@tonic-gate errno = EINVAL; 317*7c478bd9Sstevel@tonic-gate return -1; 318*7c478bd9Sstevel@tonic-gate } 319*7c478bd9Sstevel@tonic-gate } 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate /* 322*7c478bd9Sstevel@tonic-gate ** SM_GETINFO -- get information about the open file 323*7c478bd9Sstevel@tonic-gate ** 324*7c478bd9Sstevel@tonic-gate ** Parameters: 325*7c478bd9Sstevel@tonic-gate ** fp -- file to get info for 326*7c478bd9Sstevel@tonic-gate ** what -- type of info to get 327*7c478bd9Sstevel@tonic-gate ** valp -- location to place found info 328*7c478bd9Sstevel@tonic-gate ** 329*7c478bd9Sstevel@tonic-gate ** Returns: 330*7c478bd9Sstevel@tonic-gate ** Success: may or may not place info in 'valp' depending 331*7c478bd9Sstevel@tonic-gate ** on 'what' value, and returns values >=0. Return 332*7c478bd9Sstevel@tonic-gate ** value may be the obtained info 333*7c478bd9Sstevel@tonic-gate ** Failure: -1 and sets errno 334*7c478bd9Sstevel@tonic-gate */ 335*7c478bd9Sstevel@tonic-gate 336*7c478bd9Sstevel@tonic-gate int 337*7c478bd9Sstevel@tonic-gate sm_stdgetinfo(fp, what, valp) 338*7c478bd9Sstevel@tonic-gate SM_FILE_T *fp; 339*7c478bd9Sstevel@tonic-gate int what; 340*7c478bd9Sstevel@tonic-gate void *valp; 341*7c478bd9Sstevel@tonic-gate { 342*7c478bd9Sstevel@tonic-gate switch (what) 343*7c478bd9Sstevel@tonic-gate { 344*7c478bd9Sstevel@tonic-gate case SM_IO_WHAT_MODE: 345*7c478bd9Sstevel@tonic-gate return sm_stdgetmode(fp, (int *)valp); 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate case SM_IO_WHAT_FD: 348*7c478bd9Sstevel@tonic-gate return fp->f_file; 349*7c478bd9Sstevel@tonic-gate 350*7c478bd9Sstevel@tonic-gate case SM_IO_WHAT_SIZE: 351*7c478bd9Sstevel@tonic-gate { 352*7c478bd9Sstevel@tonic-gate struct stat st; 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate if (fstat(fp->f_file, &st) == 0) 355*7c478bd9Sstevel@tonic-gate return st.st_size; 356*7c478bd9Sstevel@tonic-gate else 357*7c478bd9Sstevel@tonic-gate return -1; 358*7c478bd9Sstevel@tonic-gate } 359*7c478bd9Sstevel@tonic-gate 360*7c478bd9Sstevel@tonic-gate case SM_IO_IS_READABLE: 361*7c478bd9Sstevel@tonic-gate { 362*7c478bd9Sstevel@tonic-gate fd_set readfds; 363*7c478bd9Sstevel@tonic-gate struct timeval timeout; 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate if (SM_FD_SETSIZE > 0 && fp->f_file >= SM_FD_SETSIZE) 366*7c478bd9Sstevel@tonic-gate { 367*7c478bd9Sstevel@tonic-gate errno = EINVAL; 368*7c478bd9Sstevel@tonic-gate return -1; 369*7c478bd9Sstevel@tonic-gate } 370*7c478bd9Sstevel@tonic-gate FD_ZERO(&readfds); 371*7c478bd9Sstevel@tonic-gate SM_FD_SET(fp->f_file, &readfds); 372*7c478bd9Sstevel@tonic-gate timeout.tv_sec = 0; 373*7c478bd9Sstevel@tonic-gate timeout.tv_usec = 0; 374*7c478bd9Sstevel@tonic-gate if (select(fp->f_file + 1, FDSET_CAST &readfds, 375*7c478bd9Sstevel@tonic-gate NULL, NULL, &timeout) > 0 && 376*7c478bd9Sstevel@tonic-gate SM_FD_ISSET(fp->f_file, &readfds)) 377*7c478bd9Sstevel@tonic-gate return 1; 378*7c478bd9Sstevel@tonic-gate return 0; 379*7c478bd9Sstevel@tonic-gate } 380*7c478bd9Sstevel@tonic-gate 381*7c478bd9Sstevel@tonic-gate default: 382*7c478bd9Sstevel@tonic-gate errno = EINVAL; 383*7c478bd9Sstevel@tonic-gate return -1; 384*7c478bd9Sstevel@tonic-gate } 385*7c478bd9Sstevel@tonic-gate } 386*7c478bd9Sstevel@tonic-gate 387*7c478bd9Sstevel@tonic-gate /* 388*7c478bd9Sstevel@tonic-gate ** SM_STDFDOPEN -- open file by primitive 'fd' rather than pathname 389*7c478bd9Sstevel@tonic-gate ** 390*7c478bd9Sstevel@tonic-gate ** I/O function to handle fdopen() stdio equivalence. The rest of 391*7c478bd9Sstevel@tonic-gate ** the functions are the same as the sm_stdopen() above. 392*7c478bd9Sstevel@tonic-gate ** 393*7c478bd9Sstevel@tonic-gate ** Parameters: 394*7c478bd9Sstevel@tonic-gate ** fp -- the file pointer to be associated with the open 395*7c478bd9Sstevel@tonic-gate ** name -- the primitive file descriptor for association 396*7c478bd9Sstevel@tonic-gate ** flags -- indicates type of access methods 397*7c478bd9Sstevel@tonic-gate ** rpool -- ignored 398*7c478bd9Sstevel@tonic-gate ** 399*7c478bd9Sstevel@tonic-gate ** Results: 400*7c478bd9Sstevel@tonic-gate ** Success: primitive file descriptor value 401*7c478bd9Sstevel@tonic-gate ** Failure: -1 and sets errno 402*7c478bd9Sstevel@tonic-gate */ 403*7c478bd9Sstevel@tonic-gate 404*7c478bd9Sstevel@tonic-gate /* ARGSUSED3 */ 405*7c478bd9Sstevel@tonic-gate int 406*7c478bd9Sstevel@tonic-gate sm_stdfdopen(fp, info, flags, rpool) 407*7c478bd9Sstevel@tonic-gate SM_FILE_T *fp; 408*7c478bd9Sstevel@tonic-gate const void *info; 409*7c478bd9Sstevel@tonic-gate int flags; 410*7c478bd9Sstevel@tonic-gate const void *rpool; 411*7c478bd9Sstevel@tonic-gate { 412*7c478bd9Sstevel@tonic-gate int oflags, tmp, fdflags, fd = *((int *) info); 413*7c478bd9Sstevel@tonic-gate 414*7c478bd9Sstevel@tonic-gate switch (SM_IO_MODE(flags)) 415*7c478bd9Sstevel@tonic-gate { 416*7c478bd9Sstevel@tonic-gate case SM_IO_RDWR: 417*7c478bd9Sstevel@tonic-gate oflags = O_RDWR | O_CREAT; 418*7c478bd9Sstevel@tonic-gate break; 419*7c478bd9Sstevel@tonic-gate case SM_IO_RDONLY: 420*7c478bd9Sstevel@tonic-gate oflags = O_RDONLY; 421*7c478bd9Sstevel@tonic-gate break; 422*7c478bd9Sstevel@tonic-gate case SM_IO_WRONLY: 423*7c478bd9Sstevel@tonic-gate oflags = O_WRONLY | O_CREAT | O_TRUNC; 424*7c478bd9Sstevel@tonic-gate break; 425*7c478bd9Sstevel@tonic-gate case SM_IO_APPEND: 426*7c478bd9Sstevel@tonic-gate oflags = O_APPEND | O_WRONLY | O_CREAT; 427*7c478bd9Sstevel@tonic-gate break; 428*7c478bd9Sstevel@tonic-gate case SM_IO_APPENDRW: 429*7c478bd9Sstevel@tonic-gate oflags = O_APPEND | O_RDWR | O_CREAT; 430*7c478bd9Sstevel@tonic-gate break; 431*7c478bd9Sstevel@tonic-gate default: 432*7c478bd9Sstevel@tonic-gate errno = EINVAL; 433*7c478bd9Sstevel@tonic-gate return -1; 434*7c478bd9Sstevel@tonic-gate } 435*7c478bd9Sstevel@tonic-gate #ifdef O_BINARY 436*7c478bd9Sstevel@tonic-gate if (SM_IS_BINARY(flags)) 437*7c478bd9Sstevel@tonic-gate oflags |= O_BINARY; 438*7c478bd9Sstevel@tonic-gate #endif /* O_BINARY */ 439*7c478bd9Sstevel@tonic-gate 440*7c478bd9Sstevel@tonic-gate /* Make sure the mode the user wants is a subset of the actual mode. */ 441*7c478bd9Sstevel@tonic-gate if ((fdflags = fcntl(fd, F_GETFL, 0)) < 0) 442*7c478bd9Sstevel@tonic-gate return -1; 443*7c478bd9Sstevel@tonic-gate tmp = fdflags & O_ACCMODE; 444*7c478bd9Sstevel@tonic-gate if (tmp != O_RDWR && (tmp != (oflags & O_ACCMODE))) 445*7c478bd9Sstevel@tonic-gate { 446*7c478bd9Sstevel@tonic-gate errno = EINVAL; 447*7c478bd9Sstevel@tonic-gate return -1; 448*7c478bd9Sstevel@tonic-gate } 449*7c478bd9Sstevel@tonic-gate fp->f_file = fd; 450*7c478bd9Sstevel@tonic-gate if (oflags & O_APPEND) 451*7c478bd9Sstevel@tonic-gate (void) (*fp->f_seek)(fp, (off_t)0, SEEK_END); 452*7c478bd9Sstevel@tonic-gate return fp->f_file; 453*7c478bd9Sstevel@tonic-gate } 454*7c478bd9Sstevel@tonic-gate 455*7c478bd9Sstevel@tonic-gate /* 456*7c478bd9Sstevel@tonic-gate ** SM_IO_FOPEN -- open a file 457*7c478bd9Sstevel@tonic-gate ** 458*7c478bd9Sstevel@tonic-gate ** Same interface and semantics as the open() system call, 459*7c478bd9Sstevel@tonic-gate ** except that it returns SM_FILE_T* instead of a file descriptor. 460*7c478bd9Sstevel@tonic-gate ** 461*7c478bd9Sstevel@tonic-gate ** Parameters: 462*7c478bd9Sstevel@tonic-gate ** pathname -- path of file to open 463*7c478bd9Sstevel@tonic-gate ** flags -- flags controlling the open 464*7c478bd9Sstevel@tonic-gate ** ... -- option "mode" for opening the file 465*7c478bd9Sstevel@tonic-gate ** 466*7c478bd9Sstevel@tonic-gate ** Returns: 467*7c478bd9Sstevel@tonic-gate ** Raises an exception on heap exhaustion. 468*7c478bd9Sstevel@tonic-gate ** Returns NULL and sets errno if open() fails. 469*7c478bd9Sstevel@tonic-gate ** Returns an SM_FILE_T pointer on success. 470*7c478bd9Sstevel@tonic-gate */ 471*7c478bd9Sstevel@tonic-gate 472*7c478bd9Sstevel@tonic-gate SM_FILE_T * 473*7c478bd9Sstevel@tonic-gate #if SM_VA_STD 474*7c478bd9Sstevel@tonic-gate sm_io_fopen(char *pathname, int flags, ...) 475*7c478bd9Sstevel@tonic-gate #else /* SM_VA_STD */ 476*7c478bd9Sstevel@tonic-gate sm_io_fopen(pathname, flags, va_alist) 477*7c478bd9Sstevel@tonic-gate char *pathname; 478*7c478bd9Sstevel@tonic-gate int flags; 479*7c478bd9Sstevel@tonic-gate va_dcl 480*7c478bd9Sstevel@tonic-gate #endif /* SM_VA_STD */ 481*7c478bd9Sstevel@tonic-gate { 482*7c478bd9Sstevel@tonic-gate MODE_T mode; 483*7c478bd9Sstevel@tonic-gate SM_FILE_T *fp; 484*7c478bd9Sstevel@tonic-gate int ioflags; 485*7c478bd9Sstevel@tonic-gate 486*7c478bd9Sstevel@tonic-gate if (flags & O_CREAT) 487*7c478bd9Sstevel@tonic-gate { 488*7c478bd9Sstevel@tonic-gate SM_VA_LOCAL_DECL 489*7c478bd9Sstevel@tonic-gate 490*7c478bd9Sstevel@tonic-gate SM_VA_START(ap, flags); 491*7c478bd9Sstevel@tonic-gate mode = (MODE_T) SM_VA_ARG(ap, int); 492*7c478bd9Sstevel@tonic-gate SM_VA_END(ap); 493*7c478bd9Sstevel@tonic-gate } 494*7c478bd9Sstevel@tonic-gate else 495*7c478bd9Sstevel@tonic-gate mode = 0; 496*7c478bd9Sstevel@tonic-gate 497*7c478bd9Sstevel@tonic-gate switch (flags & O_ACCMODE) 498*7c478bd9Sstevel@tonic-gate { 499*7c478bd9Sstevel@tonic-gate case O_RDONLY: 500*7c478bd9Sstevel@tonic-gate ioflags = SMRD; 501*7c478bd9Sstevel@tonic-gate break; 502*7c478bd9Sstevel@tonic-gate case O_WRONLY: 503*7c478bd9Sstevel@tonic-gate ioflags = SMWR; 504*7c478bd9Sstevel@tonic-gate break; 505*7c478bd9Sstevel@tonic-gate case O_RDWR: 506*7c478bd9Sstevel@tonic-gate ioflags = SMRW; 507*7c478bd9Sstevel@tonic-gate break; 508*7c478bd9Sstevel@tonic-gate default: 509*7c478bd9Sstevel@tonic-gate sm_abort("sm_io_fopen: bad flags 0%o", flags); 510*7c478bd9Sstevel@tonic-gate } 511*7c478bd9Sstevel@tonic-gate 512*7c478bd9Sstevel@tonic-gate fp = sm_fp(SmFtStdio, ioflags, NULL); 513*7c478bd9Sstevel@tonic-gate fp->f_file = open(pathname, flags, mode); 514*7c478bd9Sstevel@tonic-gate if (fp->f_file == -1) 515*7c478bd9Sstevel@tonic-gate { 516*7c478bd9Sstevel@tonic-gate fp->f_flags = 0; 517*7c478bd9Sstevel@tonic-gate fp->sm_magic = NULL; 518*7c478bd9Sstevel@tonic-gate return NULL; 519*7c478bd9Sstevel@tonic-gate } 520*7c478bd9Sstevel@tonic-gate return fp; 521*7c478bd9Sstevel@tonic-gate } 522