strio.c revision 157002
1260684Skaiw/* 2260684Skaiw * Copyright (c) 2000-2002, 2004, 2005 Sendmail, Inc. and its suppliers. 3260684Skaiw * All rights reserved. 4260684Skaiw * Copyright (c) 1990, 1993 5260684Skaiw * The Regents of the University of California. All rights reserved. 6260684Skaiw * 7260684Skaiw * This code is derived from software contributed to Berkeley by 8260684Skaiw * Chris Torek. 9260684Skaiw * 10260684Skaiw * By using this file, you agree to the terms and conditions set 11260684Skaiw * forth in the LICENSE file which can be found at the top level of 12260684Skaiw * the sendmail distribution. 13260684Skaiw */ 14260684Skaiw 15260684Skaiw#include <sm/gen.h> 16260684SkaiwSM_IDSTR(id, "@(#)$Id: strio.c,v 1.44 2005/06/09 21:40:19 ca Exp $") 17260684Skaiw#include <stdlib.h> 18260684Skaiw#include <unistd.h> 19260684Skaiw#include <fcntl.h> 20260684Skaiw#include <string.h> 21260684Skaiw#include <errno.h> 22260684Skaiw#include <sm/rpool.h> 23260684Skaiw#include <sm/io.h> 24260684Skaiw#include <sm/heap.h> 25260684Skaiw#include <sm/conf.h> 26260684Skaiw#include "local.h" 27260684Skaiw 28260684Skaiwstatic int sm_strsetmode __P((SM_FILE_T*, const int *)); 29260684Skaiwstatic int sm_strgetmode __P((SM_FILE_T*, int *)); 30295577Semaste 31260684Skaiw/* 32260684Skaiw** Cookie structure for the "strio" file type 33260684Skaiw*/ 34260684Skaiw 35260684Skaiwstruct sm_str_obj 36260684Skaiw{ 37260684Skaiw char *strio_base; 38260684Skaiw char *strio_end; 39260684Skaiw size_t strio_size; 40260684Skaiw size_t strio_offset; 41260684Skaiw int strio_flags; 42260684Skaiw const void *strio_rpool; 43260684Skaiw}; 44260684Skaiw 45295577Semastetypedef struct sm_str_obj SM_STR_OBJ_T; 46260684Skaiw 47260684Skaiw/* 48295577Semaste** SM_STRGROW -- increase storage space for string 49260684Skaiw** 50260684Skaiw** Parameters: 51295577Semaste** s -- current cookie 52260684Skaiw** size -- new storage size request 53260684Skaiw** 54260684Skaiw** Returns: 55260684Skaiw** true iff successful. 56260684Skaiw*/ 57260684Skaiw 58260684Skaiwstatic bool sm_strgrow __P((SM_STR_OBJ_T *, size_t)); 59260684Skaiw 60260684Skaiwstatic bool 61260684Skaiwsm_strgrow(s, size) 62260684Skaiw SM_STR_OBJ_T *s; 63260684Skaiw size_t size; 64260684Skaiw{ 65260684Skaiw register void *p; 66260684Skaiw 67260684Skaiw if (s->strio_size >= size) 68260684Skaiw return true; 69260684Skaiw p = sm_realloc(s->strio_base, size); 70260684Skaiw if (p == NULL) 71260684Skaiw return false; 72260684Skaiw s->strio_base = p; 73260684Skaiw s->strio_end = s->strio_base + size; 74260684Skaiw s->strio_size = size; 75260684Skaiw return true; 76260684Skaiw} 77295577Semaste 78260684Skaiw/* 79260684Skaiw** SM_STRREAD -- read a portion of the string 80295577Semaste** 81260684Skaiw** Parameters: 82260684Skaiw** fp -- the file pointer 83295577Semaste** buf -- location to place read data 84260684Skaiw** n -- number of bytes to read 85260684Skaiw** 86260684Skaiw** Returns: 87260684Skaiw** Failure: -1 and sets errno 88260684Skaiw** Success: >=0, number of bytes read 89260684Skaiw*/ 90260684Skaiw 91260684Skaiwssize_t 92260684Skaiwsm_strread(fp, buf, n) 93260684Skaiw SM_FILE_T *fp; 94260684Skaiw char *buf; 95260684Skaiw size_t n; 96260684Skaiw{ 97260684Skaiw register SM_STR_OBJ_T *s = fp->f_cookie; 98260684Skaiw int len; 99260684Skaiw 100260684Skaiw if (!(s->strio_flags & SMRD) && !(s->strio_flags & SMRW)) 101260684Skaiw { 102260684Skaiw errno = EBADF; 103260684Skaiw return -1; 104260684Skaiw } 105260684Skaiw len = SM_MIN(s->strio_size - s->strio_offset, n); 106260684Skaiw (void) memmove(buf, s->strio_base + s->strio_offset, len); 107260684Skaiw s->strio_offset += len; 108260684Skaiw return len; 109260684Skaiw} 110260684Skaiw 111260684Skaiw/* 112260684Skaiw** SM_STRWRITE -- write a portion of the string 113260684Skaiw** 114260684Skaiw** Parameters: 115260684Skaiw** fp -- the file pointer 116260684Skaiw** buf -- location of data for writing 117260684Skaiw** n -- number of bytes to write 118260684Skaiw** 119260684Skaiw** Returns: 120260684Skaiw** Failure: -1 and sets errno 121260684Skaiw** Success: >=0, number of bytes written 122260684Skaiw*/ 123260684Skaiw 124260684Skaiwssize_t 125260684Skaiwsm_strwrite(fp, buf, n) 126260684Skaiw SM_FILE_T *fp; 127260684Skaiw char const *buf; 128260684Skaiw size_t n; 129260684Skaiw{ 130260684Skaiw register SM_STR_OBJ_T *s = fp->f_cookie; 131260684Skaiw 132260684Skaiw if (!(s->strio_flags & SMWR) && !(s->strio_flags & SMRW)) 133260684Skaiw { 134260684Skaiw errno = EBADF; 135260684Skaiw return -1; 136260684Skaiw } 137260684Skaiw if (n + s->strio_offset > s->strio_size) 138260684Skaiw { 139260684Skaiw if (!sm_strgrow(s, n + s->strio_offset)) 140260684Skaiw return 0; 141260684Skaiw } 142260684Skaiw (void) memmove(s->strio_base + s->strio_offset, buf, n); 143260684Skaiw s->strio_offset += n; 144260684Skaiw return n; 145260684Skaiw} 146260684Skaiw 147260684Skaiw/* 148260684Skaiw** SM_STRSEEK -- position the offset pointer for the string 149260684Skaiw** 150260684Skaiw** Only SM_IO_SEEK_SET, SM_IO_SEEK_CUR and SM_IO_SEEK_END are valid 151260684Skaiw** values for whence. 152260684Skaiw** 153260684Skaiw** Parameters: 154260684Skaiw** fp -- the file pointer 155260684Skaiw** offset -- number of bytes offset from "base" 156260684Skaiw** whence -- determines "base" for 'offset' 157260684Skaiw** 158260684Skaiw** Returns: 159260684Skaiw** Failure: -1 and sets errno 160260684Skaiw** Success: >=0, number of bytes read 161260684Skaiw*/ 162260684Skaiw 163260684Skaiwoff_t 164260684Skaiwsm_strseek(fp, offset, whence) 165260684Skaiw SM_FILE_T *fp; 166260684Skaiw off_t offset; 167260684Skaiw int whence; 168260684Skaiw{ 169260684Skaiw register off_t ret; 170260684Skaiw register SM_STR_OBJ_T *s = fp->f_cookie; 171260684Skaiw 172260684Skaiwreseek: 173260684Skaiw switch (whence) 174260684Skaiw { 175260684Skaiw case SM_IO_SEEK_SET: 176260684Skaiw ret = offset; 177260684Skaiw break; 178260684Skaiw case SM_IO_SEEK_CUR: 179260684Skaiw ret = s->strio_offset + offset; 180295577Semaste break; 181260684Skaiw case SM_IO_SEEK_END: 182260684Skaiw ret = s->strio_size; 183260684Skaiw break; 184295577Semaste default: 185260684Skaiw errno = EINVAL; 186260684Skaiw return -1; 187295577Semaste } 188260684Skaiw if (ret < 0 || ret > (off_t)(size_t)(-1)) /* XXX ugly */ 189260684Skaiw return -1; 190260684Skaiw if ((size_t) ret > s->strio_size) 191260684Skaiw { 192260684Skaiw if (sm_strgrow(s, (size_t)ret)) 193260684Skaiw goto reseek; 194260684Skaiw 195260684Skaiw /* errno set by sm_strgrow */ 196260684Skaiw return -1; 197260684Skaiw } 198260684Skaiw s->strio_offset = (size_t) ret; 199260684Skaiw return ret; 200260684Skaiw} 201260684Skaiw 202260684Skaiw/* 203260684Skaiw** SM_STROPEN -- open a string file type 204260684Skaiw** 205260684Skaiw** Parameters: 206260684Skaiw** fp -- file pointer open to be associated with 207260684Skaiw** info -- initial contents (NULL for none) 208260684Skaiw** flags -- flags for methods of access (was mode) 209260684Skaiw** rpool -- resource pool to use memory from (if applicable) 210260684Skaiw** 211260684Skaiw** Results: 212260684Skaiw** Success: 0 (zero) 213260684Skaiw** Failure: -1 and sets errno 214260684Skaiw*/ 215260684Skaiw 216260684Skaiwint 217260684Skaiwsm_stropen(fp, info, flags, rpool) 218260684Skaiw SM_FILE_T *fp; 219260684Skaiw const void *info; 220260684Skaiw int flags; 221260684Skaiw const void *rpool; 222260684Skaiw{ 223260684Skaiw register SM_STR_OBJ_T *s; 224260684Skaiw 225260684Skaiw#if SM_RPOOL 226260684Skaiw s = sm_rpool_malloc_x(rpool, sizeof(SM_STR_OBJ_T)); 227260684Skaiw#else /* SM_RPOOL */ 228260684Skaiw s = sm_malloc(sizeof(SM_STR_OBJ_T)); 229260684Skaiw if (s == NULL) 230260684Skaiw return -1; 231260684Skaiw#endif /* SM_RPOOL */ 232260684Skaiw 233260684Skaiw fp->f_cookie = s; 234295577Semaste s->strio_rpool = rpool; 235260684Skaiw s->strio_offset = 0; 236260684Skaiw s->strio_size = 0; 237260684Skaiw s->strio_base = NULL; 238260684Skaiw s->strio_end = 0; 239295577Semaste 240260684Skaiw switch (flags) 241260684Skaiw { 242260684Skaiw case SM_IO_RDWR: 243295577Semaste s->strio_flags = SMRW; 244260684Skaiw break; 245260684Skaiw case SM_IO_RDONLY: 246260684Skaiw s->strio_flags = SMRD; 247260684Skaiw break; 248260684Skaiw case SM_IO_WRONLY: 249260684Skaiw s->strio_flags = SMWR; 250260684Skaiw break; 251260684Skaiw case SM_IO_APPEND: 252260684Skaiw if (s->strio_rpool == NULL) 253260684Skaiw sm_free(s); 254260684Skaiw errno = EINVAL; 255260684Skaiw return -1; 256260684Skaiw default: 257260684Skaiw if (s->strio_rpool == NULL) 258260684Skaiw sm_free(s); 259260684Skaiw errno = EINVAL; 260260684Skaiw return -1; 261260684Skaiw } 262260684Skaiw 263260684Skaiw if (info != NULL) 264260684Skaiw { 265260684Skaiw s->strio_base = sm_strdup_x(info); 266260684Skaiw if (s->strio_base == NULL) 267260684Skaiw { 268260684Skaiw int save_errno = errno; 269260684Skaiw 270260684Skaiw if (s->strio_rpool == NULL) 271260684Skaiw sm_free(s); 272260684Skaiw errno = save_errno; 273260684Skaiw return -1; 274260684Skaiw } 275260684Skaiw s->strio_size = strlen(info); 276260684Skaiw s->strio_end = s->strio_base + s->strio_size; 277260684Skaiw } 278260684Skaiw return 0; 279260684Skaiw} 280260684Skaiw 281260684Skaiw/* 282260684Skaiw** SM_STRCLOSE -- close the string file type and free resources 283260684Skaiw** 284260684Skaiw** Parameters: 285260684Skaiw** fp -- file pointer 286260684Skaiw** 287260684Skaiw** Results: 288260684Skaiw** Success: 0 (zero) 289260684Skaiw*/ 290260684Skaiw 291260684Skaiwint 292260684Skaiwsm_strclose(fp) 293260684Skaiw SM_FILE_T *fp; 294260684Skaiw{ 295260684Skaiw SM_STR_OBJ_T *s = fp->f_cookie; 296260684Skaiw 297260684Skaiw#if !SM_RPOOL 298260684Skaiw sm_free(s->strio_base); 299260684Skaiw s->strio_base = NULL; 300260684Skaiw#endif /* !SM_RPOOL */ 301260684Skaiw return 0; 302260684Skaiw} 303260684Skaiw 304260684Skaiw/* 305260684Skaiw** SM_STRSETMODE -- set mode info for the file 306260684Skaiw** 307260684Skaiw** Note: changing the mode can be a safe way to have the "parent" 308260684Skaiw** set up a string that the "child" is not to modify 309260684Skaiw** 310260684Skaiw** Parameters: 311260684Skaiw** fp -- the file pointer 312260684Skaiw** mode -- location of new mode to set 313260684Skaiw** 314260684Skaiw** Results: 315260684Skaiw** Success: 0 (zero) 316260684Skaiw** Failure: -1 and sets errno 317260684Skaiw*/ 318260684Skaiw 319260684Skaiwstatic int 320260684Skaiwsm_strsetmode(fp, mode) 321260684Skaiw SM_FILE_T *fp; 322260684Skaiw const int *mode; 323260684Skaiw{ 324260684Skaiw register SM_STR_OBJ_T *s = fp->f_cookie; 325260684Skaiw int flags; 326260684Skaiw 327260684Skaiw switch (*mode) 328260684Skaiw { 329260684Skaiw case SM_IO_RDWR: 330260684Skaiw flags = SMRW; 331260684Skaiw break; 332260684Skaiw case SM_IO_RDONLY: 333260684Skaiw flags = SMRD; 334260684Skaiw break; 335260684Skaiw case SM_IO_WRONLY: 336260684Skaiw flags = SMWR; 337260684Skaiw break; 338260684Skaiw case SM_IO_APPEND: 339260684Skaiw errno = EINVAL; 340260684Skaiw return -1; 341260684Skaiw default: 342260684Skaiw errno = EINVAL; 343260684Skaiw return -1; 344260684Skaiw } 345260684Skaiw s->strio_flags &= ~SMMODEMASK; 346260684Skaiw s->strio_flags |= flags; 347260684Skaiw return 0; 348260684Skaiw} 349260684Skaiw 350260684Skaiw/* 351260684Skaiw** SM_STRGETMODE -- get mode info for the file 352260684Skaiw** 353260684Skaiw** Parameters: 354260684Skaiw** fp -- the file pointer 355260684Skaiw** mode -- location to store current mode 356260684Skaiw** 357260684Skaiw** Results: 358260684Skaiw** Success: 0 (zero) 359260684Skaiw** Failure: -1 and sets errno 360260684Skaiw*/ 361260684Skaiw 362260684Skaiwstatic int 363260684Skaiwsm_strgetmode(fp, mode) 364260684Skaiw SM_FILE_T *fp; 365260684Skaiw int *mode; 366260684Skaiw{ 367260684Skaiw register SM_STR_OBJ_T *s = fp->f_cookie; 368260684Skaiw 369260684Skaiw switch (s->strio_flags & SMMODEMASK) 370260684Skaiw { 371260684Skaiw case SMRW: 372260684Skaiw *mode = SM_IO_RDWR; 373260684Skaiw break; 374260684Skaiw case SMRD: 375260684Skaiw *mode = SM_IO_RDONLY; 376260684Skaiw break; 377260684Skaiw case SMWR: 378260684Skaiw *mode = SM_IO_WRONLY; 379260684Skaiw break; 380260684Skaiw default: 381260684Skaiw errno = EINVAL; 382260684Skaiw return -1; 383260684Skaiw } 384260684Skaiw return 0; 385260684Skaiw} 386260684Skaiw 387260684Skaiw/* 388260684Skaiw** SM_STRSETINFO -- set info for the file 389260684Skaiw** 390260684Skaiw** Currently only SM_IO_WHAT_MODE is supported for 'what'. 391260684Skaiw** 392260684Skaiw** Parameters: 393260684Skaiw** fp -- the file pointer 394260684Skaiw** what -- type of information to set 395260684Skaiw** valp -- location to data for doing set 396260684Skaiw** 397260684Skaiw** Results: 398260684Skaiw** Failure: -1 and sets errno 399260684Skaiw** Success: sm_strsetmode() return [0 (zero)] 400260684Skaiw*/ 401260684Skaiw 402260684Skaiwint 403260684Skaiwsm_strsetinfo(fp, what, valp) 404260684Skaiw SM_FILE_T *fp; 405260684Skaiw int what; 406260684Skaiw void *valp; 407260684Skaiw{ 408260684Skaiw switch(what) 409260684Skaiw { 410260684Skaiw case SM_IO_WHAT_MODE: 411260684Skaiw return sm_strsetmode(fp, (int *) valp); 412260684Skaiw default: 413260684Skaiw errno = EINVAL; 414260684Skaiw return -1; 415260684Skaiw } 416260684Skaiw} 417260684Skaiw 418260684Skaiw/* 419260684Skaiw** SM_STRGETINFO -- get info for the file 420260684Skaiw** 421260684Skaiw** Currently only SM_IO_WHAT_MODE is supported for 'what'. 422260684Skaiw** 423260684Skaiw** Parameters: 424260684Skaiw** fp -- the file pointer 425260684Skaiw** what -- type of information requested 426260684Skaiw** valp -- location to return information in 427260684Skaiw** 428260684Skaiw** Results: 429260684Skaiw** Failure: -1 and sets errno 430260684Skaiw** Success: sm_strgetmode() return [0 (zero)] 431260684Skaiw*/ 432260684Skaiw 433260684Skaiwint 434260684Skaiwsm_strgetinfo(fp, what, valp) 435260684Skaiw SM_FILE_T *fp; 436260684Skaiw int what; 437260684Skaiw void *valp; 438260684Skaiw{ 439260684Skaiw switch(what) 440260684Skaiw { 441260684Skaiw case SM_IO_WHAT_MODE: 442260684Skaiw return sm_strgetmode(fp, (int *) valp); 443260684Skaiw default: 444260684Skaiw errno = EINVAL; 445260684Skaiw return -1; 446260684Skaiw } 447260684Skaiw} 448260684Skaiw 449260684Skaiw/* 450260684Skaiw** SM_STRIO_INIT -- initializes a write-only string type 451260684Skaiw** 452260684Skaiw** Original comments below. This function does not appear to be used anywhere. 453260684Skaiw** The same functionality can be done by changing the mode of the file. 454260684Skaiw** ------------ 455260684Skaiw** sm_strio_init initializes an SM_FILE_T structure as a write-only file 456260684Skaiw** that writes into the specified buffer: 457260684Skaiw** - Use sm_io_putc, sm_io_fprintf, etc, to write into the buffer. 458260684Skaiw** Attempts to write more than size-1 characters into the buffer will fail 459260684Skaiw** silently (no error is reported). 460260684Skaiw** - Use sm_io_fflush to nul terminate the string in the buffer 461260684Skaiw** (the write pointer is not advanced). 462260684Skaiw** No memory is allocated either by sm_strio_init or by sm_io_{putc,write} etc. 463260684Skaiw** 464260684Skaiw** Parameters: 465260684Skaiw** fp -- file pointer 466260684Skaiw** buf -- memory location for stored data 467260684Skaiw** size -- size of 'buf' 468260684Skaiw** 469260684Skaiw** Results: 470260684Skaiw** none. 471260684Skaiw*/ 472260684Skaiw 473260684Skaiwvoid 474260684Skaiwsm_strio_init(fp, buf, size) 475260684Skaiw SM_FILE_T *fp; 476260684Skaiw char *buf; 477260684Skaiw size_t size; 478260684Skaiw{ 479260684Skaiw fp->sm_magic = SmFileMagic; 480260684Skaiw fp->f_flags = SMWR | SMSTR; 481260684Skaiw fp->f_file = -1; 482260684Skaiw fp->f_bf.smb_base = fp->f_p = (unsigned char *) buf; 483260684Skaiw fp->f_bf.smb_size = fp->f_w = (size ? size - 1 : 0); 484260684Skaiw fp->f_lbfsize = 0; 485260684Skaiw fp->f_r = 0; 486260684Skaiw fp->f_read = NULL; 487260684Skaiw fp->f_seek = NULL; 488260684Skaiw fp->f_getinfo = NULL; 489260684Skaiw fp->f_setinfo = NULL; 490260684Skaiw} 491260684Skaiw