strio.c revision 141858
1239278Sgonzo/* 2239278Sgonzo * Copyright (c) 2000-2002, 2004 Sendmail, Inc. and its suppliers. 3239278Sgonzo * All rights reserved. 4239278Sgonzo * Copyright (c) 1990, 1993 5239278Sgonzo * The Regents of the University of California. All rights reserved. 6239278Sgonzo * 7239278Sgonzo * This code is derived from software contributed to Berkeley by 8239278Sgonzo * Chris Torek. 9239278Sgonzo * 10239278Sgonzo * By using this file, you agree to the terms and conditions set 11239278Sgonzo * forth in the LICENSE file which can be found at the top level of 12239278Sgonzo * the sendmail distribution. 13239278Sgonzo */ 14239278Sgonzo 15239278Sgonzo#include <sm/gen.h> 16239278SgonzoSM_IDSTR(id, "@(#)$Id: strio.c,v 1.43 2004/08/03 20:48:30 ca Exp $") 17239278Sgonzo#include <stdlib.h> 18239278Sgonzo#include <unistd.h> 19239278Sgonzo#include <fcntl.h> 20239278Sgonzo#include <string.h> 21239278Sgonzo#include <errno.h> 22239278Sgonzo#include <sm/rpool.h> 23239278Sgonzo#include <sm/io.h> 24239278Sgonzo#include <sm/heap.h> 25239278Sgonzo#include <sm/conf.h> 26239278Sgonzo#include "local.h" 27239278Sgonzo 28239278Sgonzostatic int sm_strsetmode __P((SM_FILE_T*, const int *)); 29239278Sgonzostatic int sm_strgetmode __P((SM_FILE_T*, int *)); 30239278Sgonzo 31239278Sgonzo/* 32239278Sgonzo** Cookie structure for the "strio" file type 33239278Sgonzo*/ 34239278Sgonzo 35239278Sgonzostruct sm_str_obj 36239278Sgonzo{ 37239278Sgonzo char *strio_base; 38239278Sgonzo char *strio_end; 39239278Sgonzo size_t strio_size; 40239278Sgonzo size_t strio_offset; 41239278Sgonzo int strio_flags; 42239278Sgonzo const void *strio_rpool; 43239278Sgonzo}; 44239278Sgonzo 45239278Sgonzotypedef struct sm_str_obj SM_STR_OBJ_T; 46239278Sgonzo 47239278Sgonzo/* 48239278Sgonzo** SM_STRGROW -- increase storage space for string 49239278Sgonzo** 50239278Sgonzo** Parameters: 51239278Sgonzo** s -- current cookie 52239278Sgonzo** size -- new storage size request 53239278Sgonzo** 54239278Sgonzo** Returns: 55239278Sgonzo** true iff successful. 56239278Sgonzo*/ 57239278Sgonzo 58239278Sgonzostatic bool sm_strgrow __P((SM_STR_OBJ_T *, size_t)); 59239278Sgonzo 60239278Sgonzostatic bool 61239278Sgonzosm_strgrow(s, size) 62239278Sgonzo SM_STR_OBJ_T *s; 63239278Sgonzo size_t size; 64239278Sgonzo{ 65239278Sgonzo register void *p; 66239278Sgonzo 67239278Sgonzo if (s->strio_size >= size) 68239278Sgonzo return true; 69239278Sgonzo p = sm_realloc(s->strio_base, size); 70239278Sgonzo if (p == NULL) 71239278Sgonzo return false; 72239278Sgonzo s->strio_base = p; 73239278Sgonzo s->strio_end = s->strio_base + size; 74239278Sgonzo s->strio_size = size; 75239278Sgonzo return true; 76239278Sgonzo} 77239278Sgonzo 78239278Sgonzo/* 79239278Sgonzo** SM_STRREAD -- read a portion of the string 80239278Sgonzo** 81239278Sgonzo** Parameters: 82239278Sgonzo** fp -- the file pointer 83239278Sgonzo** buf -- location to place read data 84239278Sgonzo** n -- number of bytes to read 85239278Sgonzo** 86239278Sgonzo** Returns: 87239278Sgonzo** Failure: -1 and sets errno 88239278Sgonzo** Success: >=0, number of bytes read 89239278Sgonzo*/ 90239278Sgonzo 91239278Sgonzossize_t 92239278Sgonzosm_strread(fp, buf, n) 93239278Sgonzo SM_FILE_T *fp; 94239278Sgonzo char *buf; 95239278Sgonzo size_t n; 96239278Sgonzo{ 97239278Sgonzo register SM_STR_OBJ_T *s = fp->f_cookie; 98239278Sgonzo int len; 99239278Sgonzo 100239278Sgonzo if (!(s->strio_flags & SMRD) && !(s->strio_flags & SMRW)) 101239278Sgonzo { 102239278Sgonzo errno = EBADF; 103239278Sgonzo return -1; 104239278Sgonzo } 105239278Sgonzo len = SM_MIN(s->strio_size - s->strio_offset, n); 106239278Sgonzo (void) memmove(buf, s->strio_base + s->strio_offset, len); 107239278Sgonzo s->strio_offset += len; 108239278Sgonzo return len; 109239278Sgonzo} 110239278Sgonzo 111239278Sgonzo/* 112239278Sgonzo** SM_STRWRITE -- write a portion of the string 113239278Sgonzo** 114239278Sgonzo** Parameters: 115239278Sgonzo** fp -- the file pointer 116239278Sgonzo** buf -- location of data for writing 117239278Sgonzo** n -- number of bytes to write 118239278Sgonzo** 119239278Sgonzo** Returns: 120239278Sgonzo** Failure: -1 and sets errno 121239278Sgonzo** Success: >=0, number of bytes written 122239278Sgonzo*/ 123239278Sgonzo 124239278Sgonzossize_t 125239278Sgonzosm_strwrite(fp, buf, n) 126239278Sgonzo SM_FILE_T *fp; 127239278Sgonzo char const *buf; 128239278Sgonzo size_t n; 129239278Sgonzo{ 130239278Sgonzo register SM_STR_OBJ_T *s = fp->f_cookie; 131239278Sgonzo 132239278Sgonzo if (!(s->strio_flags & SMWR) && !(s->strio_flags & SMRW)) 133239278Sgonzo { 134239278Sgonzo errno = EBADF; 135239278Sgonzo return -1; 136239278Sgonzo } 137239278Sgonzo if (n + s->strio_offset > s->strio_size) 138239278Sgonzo { 139239278Sgonzo if (!sm_strgrow(s, n + s->strio_offset)) 140239278Sgonzo return 0; 141239278Sgonzo } 142239278Sgonzo (void) memmove(s->strio_base + s->strio_offset, buf, n); 143239278Sgonzo s->strio_offset += n; 144239278Sgonzo return n; 145239278Sgonzo} 146239278Sgonzo 147239278Sgonzo/* 148239278Sgonzo** SM_STRSEEK -- position the offset pointer for the string 149239278Sgonzo** 150239278Sgonzo** Only SM_IO_SEEK_SET, SM_IO_SEEK_CUR and SM_IO_SEEK_END are valid 151239278Sgonzo** values for whence. 152239278Sgonzo** 153239278Sgonzo** Parameters: 154239278Sgonzo** fp -- the file pointer 155239278Sgonzo** offset -- number of bytes offset from "base" 156239278Sgonzo** whence -- determines "base" for 'offset' 157239278Sgonzo** 158239278Sgonzo** Returns: 159239278Sgonzo** Failure: -1 and sets errno 160239278Sgonzo** Success: >=0, number of bytes read 161239278Sgonzo*/ 162239278Sgonzo 163239278Sgonzooff_t 164239278Sgonzosm_strseek(fp, offset, whence) 165239278Sgonzo SM_FILE_T *fp; 166239278Sgonzo off_t offset; 167239278Sgonzo int whence; 168239278Sgonzo{ 169261410Sian register off_t ret; 170261410Sian register SM_STR_OBJ_T *s = fp->f_cookie; 171261410Sian 172261410Sianreseek: 173239278Sgonzo switch (whence) 174239278Sgonzo { 175239278Sgonzo case SM_IO_SEEK_SET: 176239278Sgonzo ret = offset; 177239278Sgonzo break; 178239278Sgonzo case SM_IO_SEEK_CUR: 179239278Sgonzo ret = s->strio_offset + offset; 180239278Sgonzo break; 181239278Sgonzo case SM_IO_SEEK_END: 182239278Sgonzo ret = s->strio_size; 183239278Sgonzo break; 184239278Sgonzo default: 185239278Sgonzo errno = EINVAL; 186239278Sgonzo return -1; 187239278Sgonzo } 188239278Sgonzo if (ret < 0 || ret > (off_t)(size_t)(-1)) /* XXX ugly */ 189239278Sgonzo return -1; 190239278Sgonzo if ((size_t) ret > s->strio_size) 191239278Sgonzo { 192239278Sgonzo if (sm_strgrow(s, (size_t)ret)) 193239278Sgonzo goto reseek; 194239278Sgonzo 195239278Sgonzo /* errno set by sm_strgrow */ 196239278Sgonzo return -1; 197239278Sgonzo } 198239278Sgonzo s->strio_offset = (size_t) ret; 199239278Sgonzo return ret; 200239278Sgonzo} 201239278Sgonzo 202239278Sgonzo/* 203239278Sgonzo** SM_STROPEN -- open a string file type 204239278Sgonzo** 205239278Sgonzo** Parameters: 206239278Sgonzo** fp -- file pointer open to be associated with 207239278Sgonzo** info -- initial contents (NULL for none) 208239278Sgonzo** flags -- flags for methods of access (was mode) 209239278Sgonzo** rpool -- resource pool to use memory from (if applicable) 210239278Sgonzo** 211239278Sgonzo** Results: 212239278Sgonzo** Success: 0 (zero) 213239278Sgonzo** Failure: -1 and sets errno 214239278Sgonzo*/ 215239278Sgonzo 216239278Sgonzoint 217239278Sgonzosm_stropen(fp, info, flags, rpool) 218239278Sgonzo SM_FILE_T *fp; 219239278Sgonzo const void *info; 220239278Sgonzo int flags; 221239278Sgonzo const void *rpool; 222239278Sgonzo{ 223239278Sgonzo register SM_STR_OBJ_T *s; 224239278Sgonzo 225239278Sgonzo#if SM_RPOOL 226239278Sgonzo s = sm_rpool_malloc_x(rpool, sizeof(SM_STR_OBJ_T)); 227239278Sgonzo#else /* SM_RPOOL */ 228239278Sgonzo s = sm_malloc(sizeof(SM_STR_OBJ_T)); 229239278Sgonzo if (s == NULL) 230239278Sgonzo return -1; 231239278Sgonzo#endif /* SM_RPOOL */ 232239278Sgonzo 233239278Sgonzo fp->f_cookie = s; 234239278Sgonzo s->strio_rpool = rpool; 235239278Sgonzo s->strio_offset = 0; 236239278Sgonzo s->strio_size = 0; 237239278Sgonzo s->strio_base = NULL; 238239278Sgonzo s->strio_end = 0; 239239278Sgonzo 240239278Sgonzo switch (flags) 241239278Sgonzo { 242239278Sgonzo case SM_IO_RDWR: 243239278Sgonzo s->strio_flags = SMRW; 244239278Sgonzo break; 245239278Sgonzo case SM_IO_RDONLY: 246239278Sgonzo s->strio_flags = SMRD; 247239278Sgonzo break; 248239278Sgonzo case SM_IO_WRONLY: 249239278Sgonzo s->strio_flags = SMWR; 250239278Sgonzo break; 251239278Sgonzo case SM_IO_APPEND: 252239278Sgonzo if (s->strio_rpool == NULL) 253239278Sgonzo sm_free(s); 254239278Sgonzo errno = EINVAL; 255239278Sgonzo return -1; 256239278Sgonzo default: 257239278Sgonzo if (s->strio_rpool == NULL) 258239278Sgonzo sm_free(s); 259239278Sgonzo errno = EINVAL; 260239278Sgonzo return -1; 261239278Sgonzo } 262239278Sgonzo 263239278Sgonzo if (info != NULL) 264239278Sgonzo { 265239278Sgonzo s->strio_base = sm_strdup_x(info); 266239278Sgonzo if (s->strio_base == NULL) 267239278Sgonzo { 268239278Sgonzo int save_errno = errno; 269239278Sgonzo 270239278Sgonzo if (s->strio_rpool == NULL) 271239278Sgonzo sm_free(s); 272239278Sgonzo errno = save_errno; 273239278Sgonzo return -1; 274239278Sgonzo } 275239278Sgonzo s->strio_size = strlen(info); 276239278Sgonzo s->strio_end = s->strio_base + s->strio_size; 277239278Sgonzo } 278239278Sgonzo return 0; 279239278Sgonzo} 280239278Sgonzo 281239278Sgonzo/* 282239278Sgonzo** SM_STRCLOSE -- close the string file type and free resources 283239278Sgonzo** 284239278Sgonzo** Parameters: 285239278Sgonzo** fp -- file pointer 286239278Sgonzo** 287239278Sgonzo** Results: 288239278Sgonzo** Success: 0 (zero) 289239278Sgonzo*/ 290239278Sgonzo 291239278Sgonzoint 292239278Sgonzosm_strclose(fp) 293239278Sgonzo SM_FILE_T *fp; 294239278Sgonzo{ 295239278Sgonzo SM_STR_OBJ_T *s = fp->f_cookie; 296239278Sgonzo 297239278Sgonzo#if !SM_RPOOL 298239278Sgonzo sm_free(s->strio_base); 299239278Sgonzo s->strio_base = NULL; 300239278Sgonzo#endif /* !SM_RPOOL */ 301239278Sgonzo return 0; 302239278Sgonzo} 303239278Sgonzo 304239278Sgonzo/* 305239278Sgonzo** SM_STRSETMODE -- set mode info for the file 306239278Sgonzo** 307239278Sgonzo** Note: changing the mode can be a safe way to have the "parent" 308239278Sgonzo** set up a string that the "child" is not to modify 309239278Sgonzo** 310239278Sgonzo** Parameters: 311239278Sgonzo** fp -- the file pointer 312239278Sgonzo** mode -- location of new mode to set 313239278Sgonzo** 314239278Sgonzo** Results: 315239278Sgonzo** Success: 0 (zero) 316239278Sgonzo** Failure: -1 and sets errno 317239278Sgonzo*/ 318239278Sgonzo 319239278Sgonzostatic int 320239278Sgonzosm_strsetmode(fp, mode) 321239278Sgonzo SM_FILE_T *fp; 322239278Sgonzo const int *mode; 323239278Sgonzo{ 324239278Sgonzo register SM_STR_OBJ_T *s = fp->f_cookie; 325239278Sgonzo int flags; 326239278Sgonzo 327239278Sgonzo switch (*mode) 328239278Sgonzo { 329239278Sgonzo case SM_IO_RDWR: 330239278Sgonzo flags = SMRW; 331239278Sgonzo break; 332239278Sgonzo case SM_IO_RDONLY: 333239278Sgonzo flags = SMRD; 334239278Sgonzo break; 335239278Sgonzo case SM_IO_WRONLY: 336239278Sgonzo flags = SMWR; 337239278Sgonzo break; 338239278Sgonzo case SM_IO_APPEND: 339239278Sgonzo errno = EINVAL; 340239278Sgonzo return -1; 341239278Sgonzo default: 342239278Sgonzo errno = EINVAL; 343239278Sgonzo return -1; 344239278Sgonzo } 345239278Sgonzo s->strio_flags &= ~SMMODEMASK; 346239278Sgonzo s->strio_flags |= flags; 347239278Sgonzo return 0; 348239278Sgonzo} 349239278Sgonzo 350239278Sgonzo/* 351239278Sgonzo** SM_STRGETMODE -- get mode info for the file 352239278Sgonzo** 353239278Sgonzo** Parameters: 354239278Sgonzo** fp -- the file pointer 355239278Sgonzo** mode -- location to store current mode 356239278Sgonzo** 357239278Sgonzo** Results: 358239278Sgonzo** Success: 0 (zero) 359239278Sgonzo** Failure: -1 and sets errno 360239278Sgonzo*/ 361239278Sgonzo 362239278Sgonzoint 363239278Sgonzosm_strgetmode(fp, mode) 364239278Sgonzo SM_FILE_T *fp; 365239278Sgonzo int *mode; 366239278Sgonzo{ 367239278Sgonzo register SM_STR_OBJ_T *s = fp->f_cookie; 368239278Sgonzo 369239278Sgonzo switch (s->strio_flags & SMMODEMASK) 370239278Sgonzo { 371239278Sgonzo case SMRW: 372239278Sgonzo *mode = SM_IO_RDWR; 373239278Sgonzo break; 374239278Sgonzo case SMRD: 375239278Sgonzo *mode = SM_IO_RDONLY; 376239278Sgonzo break; 377239278Sgonzo case SMWR: 378239278Sgonzo *mode = SM_IO_WRONLY; 379239278Sgonzo break; 380239278Sgonzo default: 381239278Sgonzo errno = EINVAL; 382239278Sgonzo return -1; 383239278Sgonzo } 384239278Sgonzo return 0; 385239278Sgonzo} 386239278Sgonzo 387239278Sgonzo/* 388239278Sgonzo** SM_STRSETINFO -- set info for the file 389239278Sgonzo** 390239278Sgonzo** Currently only SM_IO_WHAT_MODE is supported for 'what'. 391239278Sgonzo** 392239278Sgonzo** Parameters: 393239278Sgonzo** fp -- the file pointer 394239278Sgonzo** what -- type of information to set 395239278Sgonzo** valp -- location to data for doing set 396239278Sgonzo** 397239278Sgonzo** Results: 398239278Sgonzo** Failure: -1 and sets errno 399239278Sgonzo** Success: sm_strsetmode() return [0 (zero)] 400239278Sgonzo*/ 401239278Sgonzo 402239278Sgonzoint 403239278Sgonzosm_strsetinfo(fp, what, valp) 404239278Sgonzo SM_FILE_T *fp; 405239278Sgonzo int what; 406239278Sgonzo void *valp; 407239278Sgonzo{ 408239278Sgonzo switch(what) 409239278Sgonzo { 410239278Sgonzo case SM_IO_WHAT_MODE: 411239278Sgonzo return sm_strsetmode(fp, (int *) valp); 412239278Sgonzo default: 413239278Sgonzo errno = EINVAL; 414239278Sgonzo return -1; 415239278Sgonzo } 416239278Sgonzo} 417239278Sgonzo 418239278Sgonzo/* 419239278Sgonzo** SM_STRGETINFO -- get info for the file 420239278Sgonzo** 421239278Sgonzo** Currently only SM_IO_WHAT_MODE is supported for 'what'. 422239278Sgonzo** 423239278Sgonzo** Parameters: 424239278Sgonzo** fp -- the file pointer 425239278Sgonzo** what -- type of information requested 426239278Sgonzo** valp -- location to return information in 427239278Sgonzo** 428239278Sgonzo** Results: 429239278Sgonzo** Failure: -1 and sets errno 430239278Sgonzo** Success: sm_strgetmode() return [0 (zero)] 431239278Sgonzo*/ 432239278Sgonzo 433239278Sgonzoint 434239278Sgonzosm_strgetinfo(fp, what, valp) 435239278Sgonzo SM_FILE_T *fp; 436239278Sgonzo int what; 437239278Sgonzo void *valp; 438239278Sgonzo{ 439239278Sgonzo switch(what) 440239278Sgonzo { 441239278Sgonzo case SM_IO_WHAT_MODE: 442239278Sgonzo return sm_strgetmode(fp, (int *) valp); 443239278Sgonzo default: 444239278Sgonzo errno = EINVAL; 445239278Sgonzo return -1; 446239278Sgonzo } 447239278Sgonzo} 448239278Sgonzo 449239278Sgonzo/* 450239278Sgonzo** SM_STRIO_INIT -- initializes a write-only string type 451239278Sgonzo** 452239278Sgonzo** Original comments below. This function does not appear to be used anywhere. 453239278Sgonzo** The same functionality can be done by changing the mode of the file. 454239278Sgonzo** ------------ 455239278Sgonzo** sm_strio_init initializes an SM_FILE_T structure as a write-only file 456239278Sgonzo** that writes into the specified buffer: 457239278Sgonzo** - Use sm_io_putc, sm_io_fprintf, etc, to write into the buffer. 458239278Sgonzo** Attempts to write more than size-1 characters into the buffer will fail 459239278Sgonzo** silently (no error is reported). 460239278Sgonzo** - Use sm_io_fflush to nul terminate the string in the buffer 461239278Sgonzo** (the write pointer is not advanced). 462239278Sgonzo** No memory is allocated either by sm_strio_init or by sm_io_{putc,write} etc. 463239278Sgonzo** 464239278Sgonzo** Parameters: 465239278Sgonzo** fp -- file pointer 466239278Sgonzo** buf -- memory location for stored data 467239278Sgonzo** size -- size of 'buf' 468239278Sgonzo** 469239278Sgonzo** Results: 470239278Sgonzo** none. 471239278Sgonzo*/ 472239278Sgonzo 473239278Sgonzovoid 474239278Sgonzosm_strio_init(fp, buf, size) 475239278Sgonzo SM_FILE_T *fp; 476239278Sgonzo char *buf; 477239278Sgonzo size_t size; 478239278Sgonzo{ 479239278Sgonzo fp->sm_magic = SmFileMagic; 480239278Sgonzo fp->f_flags = SMWR | SMSTR; 481239278Sgonzo fp->f_file = -1; 482239278Sgonzo fp->f_bf.smb_base = fp->f_p = (unsigned char *) buf; 483239278Sgonzo fp->f_bf.smb_size = fp->f_w = (size ? size - 1 : 0); 484239278Sgonzo fp->f_lbfsize = 0; 485239278Sgonzo fp->f_r = 0; 486239278Sgonzo fp->f_read = NULL; 487239278Sgonzo fp->f_seek = NULL; 488239278Sgonzo fp->f_getinfo = NULL; 489239278Sgonzo fp->f_setinfo = NULL; 490239278Sgonzo} 491239278Sgonzo