2 * Copyright (c) 2000-2005 Sendmail, Inc. and its suppliers.
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
10 * By using this file, you agree to the terms and conditions set
11 * forth in the LICENSE file which can be found at the top level of
12 * the sendmail distribution.
15 #pragma ident "%Z%%M% %I% %E% SMI"
18 SM_RCSID("@(#)$Id: stdio.c,v 1.71 2005/06/14 23:07:20 ca Exp $")
22 #include <string.h> /* FreeBSD: FD_ZERO needs <string.h> */
26 #include <sm/assert.h>
27 #include <sm/varargs.h>
29 #include <sm/setjmp.h>
34 static int sm_stdsetmode
__P((SM_FILE_T
*, const int *));
35 static int sm_stdgetmode
__P((SM_FILE_T
*, int *));
39 ** Small standard I/O/seek/close functions.
40 ** These maintain the `known seek offset' for seek optimization.
44 ** SM_STDOPEN -- open a file with stdio behavior
46 ** Not associated with the system's stdio in libc.
49 ** fp -- file pointer to be associated with the open
50 ** info -- pathname of the file to be opened
51 ** flags -- indicates type of access methods
55 ** Failure: -1 and set errno
56 ** Success: 0 or greater (fd of file from open(2)).
62 sm_stdopen(fp
, info
, flags
, rpool
)
68 char *path
= (char *) info
;
71 switch (SM_IO_MODE(flags
))
77 oflags
= O_RDWR
| O_CREAT
| O_TRUNC
;
83 oflags
= O_WRONLY
| O_CREAT
| O_TRUNC
;
86 oflags
= O_APPEND
| O_WRONLY
| O_CREAT
;
89 oflags
= O_APPEND
| O_RDWR
| O_CREAT
;
96 if (SM_IS_BINARY(flags
))
99 fp
->f_file
= open(path
, oflags
,
100 S_IRUSR
|S_IWUSR
|S_IRGRP
|S_IWGRP
|S_IROTH
|S_IWOTH
);
102 return -1; /* errno set by open() */
104 if (oflags
& O_APPEND
)
105 (void) (*fp
->f_seek
)((void *)fp
, (off_t
)0, SEEK_END
);
111 ** SM_STDREAD -- read from the file
114 ** fp -- file pointer to read from
115 ** buf -- location to place read data
116 ** n -- number of bytes to read
119 ** Failure: -1 and sets errno
120 ** Success: number of bytes read
123 ** Updates internal offset into file.
127 sm_stdread(fp
, buf
, n
)
134 ret
= read(fp
->f_file
, buf
, n
);
136 /* if the read succeeded, update the current offset */
138 fp
->f_lseekoff
+= ret
;
143 ** SM_STDWRITE -- write to the file
146 ** fp -- file pointer ro write to
147 ** buf -- location of data to be written
148 ** n - number of bytes to write
151 ** Failure: -1 and sets errno
152 ** Success: number of bytes written
156 sm_stdwrite(fp
, buf
, n
)
161 return write(fp
->f_file
, buf
, n
);
165 ** SM_STDSEEK -- set the file offset position
168 ** fp -- file pointer to position
169 ** offset -- how far to position from "base" (set by 'whence')
170 ** whence -- indicates where the "base" of the 'offset' to start
173 ** Failure: -1 and sets errno
174 ** Success: the current offset
177 ** Updates the internal value of the offset.
181 sm_stdseek(fp
, offset
, whence
)
188 ret
= lseek(fp
->f_file
, (off_t
) offset
, whence
);
189 if (ret
!= (off_t
) -1)
190 fp
->f_lseekoff
= ret
;
195 ** SM_STDCLOSE -- close the file
198 ** fp -- the file pointer to close
202 ** Failure: -1 and sets errno
209 return close(fp
->f_file
);
213 ** SM_STDSETMODE -- set the access mode for the file
215 ** Called by sm_stdsetinfo().
218 ** fp -- file pointer
219 ** mode -- new mode to set the file access to
222 ** Success: 0 (zero);
223 ** Failure: -1 and sets errno
227 sm_stdsetmode(fp
, mode
)
233 switch (SM_IO_MODE(*mode
))
249 fp
->f_flags
= fp
->f_flags
& ~SMMODEMASK
;
250 fp
->f_flags
|= flags
;
255 ** SM_STDGETMODE -- for getinfo determine open mode
257 ** Called by sm_stdgetinfo().
260 ** fp -- the file mode being determined
261 ** mode -- internal mode to map to external value
264 ** Failure: -1 and sets errno
265 ** Success: external mode value
269 sm_stdgetmode(fp
, mode
)
273 switch (fp
->f_flags
& SMMODEMASK
)
279 *mode
= SM_IO_RDONLY
;
282 *mode
= SM_IO_WRONLY
;
292 ** SM_STDSETINFO -- set/modify information for a file
295 ** fp -- file to set info for
296 ** what -- type of info to set
297 ** valp -- location of data used for setting
300 ** Failure: -1 and sets errno
305 sm_stdsetinfo(fp
, what
, valp
)
312 case SM_IO_WHAT_MODE
:
313 return sm_stdsetmode(fp
, (const int *)valp
);
322 ** SM_GETINFO -- get information about the open file
325 ** fp -- file to get info for
326 ** what -- type of info to get
327 ** valp -- location to place found info
330 ** Success: may or may not place info in 'valp' depending
331 ** on 'what' value, and returns values >=0. Return
332 ** value may be the obtained info
333 ** Failure: -1 and sets errno
337 sm_stdgetinfo(fp
, what
, valp
)
344 case SM_IO_WHAT_MODE
:
345 return sm_stdgetmode(fp
, (int *)valp
);
350 case SM_IO_WHAT_SIZE
:
354 if (fstat(fp
->f_file
, &st
) == 0)
360 case SM_IO_IS_READABLE
:
363 struct timeval timeout
;
365 if (SM_FD_SETSIZE
> 0 && fp
->f_file
>= SM_FD_SETSIZE
)
371 SM_FD_SET(fp
->f_file
, &readfds
);
374 if (select(fp
->f_file
+ 1, FDSET_CAST
&readfds
,
375 NULL
, NULL
, &timeout
) > 0 &&
376 SM_FD_ISSET(fp
->f_file
, &readfds
))
388 ** SM_STDFDOPEN -- open file by primitive 'fd' rather than pathname
390 ** I/O function to handle fdopen() stdio equivalence. The rest of
391 ** the functions are the same as the sm_stdopen() above.
394 ** fp -- the file pointer to be associated with the open
395 ** name -- the primitive file descriptor for association
396 ** flags -- indicates type of access methods
400 ** Success: primitive file descriptor value
401 ** Failure: -1 and sets errno
406 sm_stdfdopen(fp
, info
, flags
, rpool
)
412 int oflags
, tmp
, fdflags
, fd
= *((int *) info
);
414 switch (SM_IO_MODE(flags
))
417 oflags
= O_RDWR
| O_CREAT
;
423 oflags
= O_WRONLY
| O_CREAT
| O_TRUNC
;
426 oflags
= O_APPEND
| O_WRONLY
| O_CREAT
;
429 oflags
= O_APPEND
| O_RDWR
| O_CREAT
;
436 if (SM_IS_BINARY(flags
))
438 #endif /* O_BINARY */
440 /* Make sure the mode the user wants is a subset of the actual mode. */
441 if ((fdflags
= fcntl(fd
, F_GETFL
, 0)) < 0)
443 tmp
= fdflags
& O_ACCMODE
;
444 if (tmp
!= O_RDWR
&& (tmp
!= (oflags
& O_ACCMODE
)))
450 if (oflags
& O_APPEND
)
451 (void) (*fp
->f_seek
)(fp
, (off_t
)0, SEEK_END
);
456 ** SM_IO_FOPEN -- open a file
458 ** Same interface and semantics as the open() system call,
459 ** except that it returns SM_FILE_T* instead of a file descriptor.
462 ** pathname -- path of file to open
463 ** flags -- flags controlling the open
464 ** ... -- option "mode" for opening the file
467 ** Raises an exception on heap exhaustion.
468 ** Returns NULL and sets errno if open() fails.
469 ** Returns an SM_FILE_T pointer on success.
474 sm_io_fopen(char *pathname
, int flags
, ...)
475 #else /* SM_VA_STD */
476 sm_io_fopen(pathname
, flags
, va_alist
)
480 #endif /* SM_VA_STD */
490 SM_VA_START(ap
, flags
);
491 mode
= (MODE_T
) SM_VA_ARG(ap
, int);
497 switch (flags
& O_ACCMODE
)
509 sm_abort("sm_io_fopen: bad flags 0%o", flags
);
512 fp
= sm_fp(SmFtStdio
, ioflags
, NULL
);
513 fp
->f_file
= open(pathname
, flags
, mode
);
514 if (fp
->f_file
== -1)